summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Ni <yangni@google.com>2016-11-11 12:30:09 -0800
committerYang Ni <yangni@google.com>2016-12-06 09:24:52 -0800
commit75f0d3110b04346b901771f96ce15cdbe907278f (patch)
treea13ce3211bfb37b0d3088c5f5ff83e247c4167b2
parent6babd9ca03e1379380af0c1cfde6f6d3e92ccd29 (diff)
downloadrs-75f0d3110b04346b901771f96ce15cdbe907278f.tar.gz
Initial driver for RSoV (RenderScript over Vulkan/SPIR-V)
Bug: 30964317 Supports the following: * Allocations of 32-bit integers and floating point numbers and vectors * Single-input single-output kernels * Co-existence of RSoV scripts and CPU intrinsics Added default .clang-format for driver code using Google C++ code style. The RSoV driver is loaded, if and only if the property debug.rs.rsov is set to non-zero. Test: RSTest and CTS with debug.rs.rsov set to 0; and RSoVTest with debug.rs.rsov set to 1. Change-Id: If63370a502d499e8fc5f4bbd2e90ce84b167c331
-rw-r--r--rsContext.cpp8
-rw-r--r--rsContext.h6
-rw-r--r--rsDriverLoader.cpp15
-rw-r--r--rsov/compiler/Android.mk19
-rwxr-xr-xrsov/compiler/bcc_rsov.sh65
-rw-r--r--rsov/driver/.clang-format95
-rw-r--r--rsov/driver/Android.mk56
-rw-r--r--rsov/driver/rsovAllocation.cpp790
-rw-r--r--rsov/driver/rsovAllocation.h216
-rw-r--r--rsov/driver/rsovContext.cpp167
-rw-r--r--rsov/driver/rsovContext.h62
-rw-r--r--rsov/driver/rsovCore.cpp322
-rw-r--r--rsov/driver/rsovCore.h40
-rw-r--r--rsov/driver/rsovElement.cpp36
-rw-r--r--rsov/driver/rsovElement.h33
-rw-r--r--rsov/driver/rsovRuntimeStubs.cpp1150
-rw-r--r--rsov/driver/rsovSampler.cpp41
-rw-r--r--rsov/driver/rsovSampler.h33
-rw-r--r--rsov/driver/rsovScript.cpp675
-rw-r--r--rsov/driver/rsovScript.h208
-rw-r--r--rsov/driver/rsovScriptGroup.cpp57
-rw-r--r--rsov/driver/rsovScriptGroup.h37
-rw-r--r--rsov/driver/rsovType.cpp36
-rw-r--r--rsov/driver/rsovType.h32
-rw-r--r--rsov/tests/RSoVTest/Android.mk29
-rw-r--r--rsov/tests/RSoVTest/AndroidManifest.xml20
-rw-r--r--rsov/tests/RSoVTest/res/drawable-nodpi/test_pattern.pngbin0 -> 308 bytes
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTest.java49
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTestCore.java153
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_invert.java101
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_modulo.java86
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UnitTest.java148
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/invert.rs23
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/modulo.rs23
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/rslist.rs25
-rw-r--r--rsov/tests/RSoVTest/src/com/android/rs/rsov/test/shared.rsh116
36 files changed, 4964 insertions, 8 deletions
diff --git a/rsContext.cpp b/rsContext.cpp
index a706a8bc..0c25d04d 100644
--- a/rsContext.cpp
+++ b/rsContext.cpp
@@ -270,6 +270,12 @@ void * Context::threadProc(void *vrsc) {
rsc->mForceCpu = true;
}
+ bool forceRSoV = getProp("debug.rs.rsov") != 0;
+ if (forceRSoV) {
+ ALOGD("Force the use of RSoV driver");
+ rsc->mForceRSoV = true;
+ }
+
bool forceCpu = getProp("debug.rs.default-CPU-driver") != 0;
if (forceCpu) {
ALOGD("Skipping hardware driver and loading default CPU driver");
@@ -277,7 +283,7 @@ void * Context::threadProc(void *vrsc) {
}
rsc->mForceCpu |= rsc->mIsGraphicsContext;
- rsc->loadDriver(rsc->mForceCpu);
+ rsc->loadDriver(rsc->mForceCpu, rsc->mForceRSoV);
if (!rsc->isSynchronous()) {
// Due to legacy we default to normal_graphics
diff --git a/rsContext.h b/rsContext.h
index fe771ec5..e36eddb7 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -312,6 +312,7 @@ protected:
int32_t mThreadPriority;
bool mIsGraphicsContext;
+ bool mForceRSoV;
bool mForceCpu;
RsContextType mContextType;
@@ -349,7 +350,10 @@ private:
uint32_t runRootScript();
bool loadRuntime(const char* filename);
- bool loadDriver(bool forceDefault);
+ // Loads the driver.
+ // forceDefault: If true, loads the default CPU driver.
+ // forceRSoV: If true, overrides forceDefault and loads the RSoV driver.
+ bool loadDriver(bool forceDefault, bool forceRSoV);
static void * threadProc(void *);
static void * helperThreadProc(void *);
diff --git a/rsDriverLoader.cpp b/rsDriverLoader.cpp
index 16efa0d7..9e3c39da 100644
--- a/rsDriverLoader.cpp
+++ b/rsDriverLoader.cpp
@@ -232,16 +232,27 @@ error:
-bool Context::loadDriver(bool forceDefault) {
+bool Context::loadDriver(bool forceDefault, bool forceRSoV) {
bool loadDefault = true;
// Provide a mechanism for dropping in a different RS driver.
#ifndef RS_COMPATIBILITY_LIB
+
+ if (forceRSoV) {
+ // If the debug property is set to use the RSoV driver, load it and fail
+ // if it does not load.
+ if (loadRuntime("libRSDriver_RSoV.so")) {
+ ALOGV("Successfully loaded the RSoV driver!");
+ return true;
+ }
+ ALOGE("Failed to load the RSoV driver!");
+ return false;
+ }
+
#ifdef OVERRIDE_RS_DRIVER
#define XSTR(S) #S
#define STR(S) XSTR(S)
#define OVERRIDE_RS_DRIVER_STRING STR(OVERRIDE_RS_DRIVER)
-
if (!forceDefault) {
if (loadRuntime(OVERRIDE_RS_DRIVER_STRING)) {
ALOGV("Successfully loaded runtime: %s", OVERRIDE_RS_DRIVER_STRING);
diff --git a/rsov/compiler/Android.mk b/rsov/compiler/Android.mk
index 7f31d67c..477f1d9d 100644
--- a/rsov/compiler/Android.mk
+++ b/rsov/compiler/Android.mk
@@ -59,12 +59,9 @@ LOCAL_C_INCLUDES := \
LOCAL_MODULE := rs2spirv
LOCAL_MODULE_CLASS := EXECUTABLES
-# TODO: handle windows and darwin
-
-LOCAL_MODULE_HOST_OS := linux
LOCAL_IS_HOST_MODULE := true
-LOCAL_SHARED_LIBRARIES_linux += libLLVM libbcinfo libSPIRV
+LOCAL_SHARED_LIBRARIES += libLLVM libbcinfo libSPIRV
# TODO: fix the remaining warnings
@@ -132,6 +129,20 @@ include $(BUILD_EXECUTABLE)
endif # Don't build in unbundled branches
#=====================================================================
+# Device executable bcc_rsov
+#=====================================================================
+
+include $(CLEAR_VARS)
+include $(CLEAR_TBLGEN_VARS)
+
+LOCAL_MODULE:= bcc_rsov
+LOCAL_MULTILIB := first
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES := bcc_rsov.sh
+
+include $(BUILD_PREBUILT)
+
+#=====================================================================
# Include Subdirectories
#=====================================================================
diff --git a/rsov/compiler/bcc_rsov.sh b/rsov/compiler/bcc_rsov.sh
new file mode 100755
index 00000000..c2cb2196
--- /dev/null
+++ b/rsov/compiler/bcc_rsov.sh
@@ -0,0 +1,65 @@
+#! /system/bin/sh
+#
+# Copyright 2016, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+function help() {
+ echo "USAGE: $0 [options] <input>"
+ echo
+ echo "OPTIONS:"
+ echo " -h Show this help message."
+ echo " -o <file> Write output to file."
+}
+
+OUTPUT_FILE=""
+
+while getopts "ho:" opt; do
+ case "$opt" in
+ h)
+ help
+ exit 0
+ ;;
+ o)
+ OUTPUT_FILE=$OPTARG
+ ;;
+ esac
+done
+
+shift $((OPTIND-1))
+
+if [[ "$#" -ne 1 ]]; then
+ help
+ exit -1
+fi
+
+INPUT_FILE=$1
+
+if [[ -z "$OUTPUT_FILE" ]]; then
+ OUTPUT_FILE="${INPUT_FILE%.*}.spv"
+fi
+
+KERNEL="${INPUT_FILE%.*}_k.spv"
+KERNEL_TXT="${INPUT_FILE%.*}_k.spt"
+WRAPPER="${INPUT_FILE%.*}_w.spt"
+OUTPUT_TXT="${INPUT_FILE%.*}.spt"
+
+eval rs2spirv $INPUT_FILE -o $KERNEL -wo $WRAPPER &&
+eval spirv-dis $KERNEL --no-color -o $KERNEL_TXT &&
+eval rs2spirv -o $OUTPUT_TXT -lk $KERNEL_TXT -lw $WRAPPER &&
+eval spirv-as $OUTPUT_TXT -o $OUTPUT_FILE
+
+#rm -f $INPUT_FILE $KERNEL $KERNEL_TXT $WRAPPER $OUTPUT_TXT
+
+exit $?
diff --git a/rsov/driver/.clang-format b/rsov/driver/.clang-format
new file mode 100644
index 00000000..e8b6a2d9
--- /dev/null
+++ b/rsov/driver/.clang-format
@@ -0,0 +1,95 @@
+---
+Language: Cpp
+# BasedOnStyle: Google
+AccessModifierOffset: -1
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlinesLeft: true
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: true
+AllowShortLoopsOnASingleLine: true
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakAfterReturnType: None
+AlwaysBreakBeforeMultilineStrings: true
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Attach
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: true
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IncludeCategories:
+ - Regex: '^<.*\.h>'
+ Priority: 1
+ - Regex: '^<.*'
+ Priority: 2
+ - Regex: '.*'
+ Priority: 3
+IncludeIsMainRegex: '([-_](test|unittest))?$'
+IndentCaseLabels: true
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Left
+ReflowComments: true
+SortIncludes: true
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Auto
+TabWidth: 8
+UseTab: Never
+...
+
diff --git a/rsov/driver/Android.mk b/rsov/driver/Android.mk
new file mode 100644
index 00000000..5309ba8e
--- /dev/null
+++ b/rsov/driver/Android.mk
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH :=$(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libRSDriver_RSoV
+
+LOCAL_SRC_FILES := \
+ rsovAllocation.cpp \
+ rsovContext.cpp \
+ rsovCore.cpp \
+ rsovElement.cpp \
+ rsovRuntimeStubs.cpp \
+ rsovSampler.cpp \
+ rsovScript.cpp \
+ rsovScriptGroup.cpp \
+ rsovType.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libRS_internal \
+ libRSCpuRef \
+ libc++ \
+ libcutils \
+ libdl \
+ liblog \
+ libsync \
+ libutils \
+ libvulkan
+
+LOCAL_C_INCLUDES := \
+ frameworks/native/vulkan/include \
+ frameworks/rs \
+ frameworks/rs/cpu_ref \
+
+LOCAL_C_INCLUDES += \
+
+LOCAL_CFLAGS := -Werror -Wall -Wextra -fno-exceptions
+# TODO: remove warnings on unused variables and parameters
+LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-parameter
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/rsov/driver/rsovAllocation.cpp b/rsov/driver/rsovAllocation.cpp
new file mode 100644
index 00000000..fdb477d1
--- /dev/null
+++ b/rsov/driver/rsovAllocation.cpp
@@ -0,0 +1,790 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovAllocation.h"
+
+#include <map>
+
+#include "rsAllocation.h"
+#include "rsContext.h"
+#include "rsCppUtils.h"
+#include "rsElement.h"
+#include "rsType.h"
+#include "rsovContext.h"
+#include "rsovCore.h"
+
+namespace android {
+namespace renderscript {
+namespace rsov {
+
+namespace {
+
+using std::make_pair;
+
+// TODO: handle 8-bit, 16-bit, and 64-bit integers and floating point numbers
+const std::map<std::pair<RsDataType, uint32_t>, VkFormat> mapElementToFormat{
+ make_pair(make_pair(RS_TYPE_FLOAT_32, 1), VK_FORMAT_R32_SFLOAT),
+ make_pair(make_pair(RS_TYPE_FLOAT_32, 2), VK_FORMAT_R32G32_SFLOAT),
+ make_pair(make_pair(RS_TYPE_FLOAT_32, 3), VK_FORMAT_R32G32B32_SFLOAT),
+ make_pair(make_pair(RS_TYPE_FLOAT_32, 4), VK_FORMAT_R32G32B32A32_SFLOAT),
+
+ make_pair(make_pair(RS_TYPE_SIGNED_32, 1), VK_FORMAT_R32_SINT),
+ make_pair(make_pair(RS_TYPE_SIGNED_32, 2), VK_FORMAT_R32G32_SINT),
+ make_pair(make_pair(RS_TYPE_SIGNED_32, 3), VK_FORMAT_R32G32B32_SINT),
+ make_pair(make_pair(RS_TYPE_SIGNED_32, 4), VK_FORMAT_R32G32B32A32_SINT),
+
+ make_pair(make_pair(RS_TYPE_UNSIGNED_32, 1), VK_FORMAT_R32_UINT),
+ make_pair(make_pair(RS_TYPE_UNSIGNED_32, 2), VK_FORMAT_R32G32_UINT),
+ make_pair(make_pair(RS_TYPE_UNSIGNED_32, 3), VK_FORMAT_R32G32B32_UINT),
+ make_pair(make_pair(RS_TYPE_UNSIGNED_32, 4), VK_FORMAT_R32G32B32A32_UINT),
+};
+
+VkFormat VkFormatFromRSElement(const Element &elem) {
+ // TODO: reject struct, allocation, and other non-numeric element
+ rsAssert(!elem.getFieldCount());
+
+ RsDataType dataType = elem.getType();
+ uint32_t vectorWidth = elem.getVectorSize();
+
+ auto it = mapElementToFormat.find(make_pair(dataType, vectorWidth));
+ if (it != mapElementToFormat.end()) {
+ return it->second;
+ }
+
+ rsAssert(0 && "Unexpected RS Element to map to VkFormat");
+
+ return VK_FORMAT_R32G32B32A32_SFLOAT;
+}
+
+size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) {
+ // For the flexible YCbCr format, layout is initialized during call to
+ // Allocation::ioReceive. Return early and avoid clobberring any
+ // pre-existing layout.
+ if (yuv == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ return 0;
+ }
+
+ // YUV only supports basic 2d
+ // so we can stash the plane pointers in the mipmap levels.
+ size_t uvSize = 0;
+ state->lod[1].dimX = state->lod[0].dimX / 2;
+ state->lod[1].dimY = state->lod[0].dimY / 2;
+ state->lod[2].dimX = state->lod[0].dimX / 2;
+ state->lod[2].dimY = state->lod[0].dimY / 2;
+ state->yuv.shift = 1;
+ state->yuv.step = 1;
+ state->lodCount = 3;
+
+ switch (yuv) {
+ case HAL_PIXEL_FORMAT_YV12:
+ state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16);
+ state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
+ (state->lod[0].stride * state->lod[0].dimY);
+ uvSize += state->lod[2].stride * state->lod[2].dimY;
+
+ state->lod[1].stride = state->lod[2].stride;
+ state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) +
+ (state->lod[2].stride * state->lod[2].dimY);
+ uvSize += state->lod[1].stride * state->lod[2].dimY;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
+ // state->lod[1].dimX = state->lod[0].dimX;
+ state->lod[1].stride = state->lod[0].stride;
+ state->lod[2].stride = state->lod[0].stride;
+ state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
+ (state->lod[0].stride * state->lod[0].dimY);
+ state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) + 1;
+ uvSize += state->lod[1].stride * state->lod[1].dimY;
+ state->yuv.step = 2;
+ break;
+ default:
+ rsAssert(0);
+ }
+
+ return uvSize;
+}
+
+// TODO: Dedup this with the same code under frameworks/rs/driver
+size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
+ const Type *type, uint8_t *ptr,
+ size_t requiredAlignment) {
+ alloc->mHal.drvState.lod[0].dimX = type->getDimX();
+ alloc->mHal.drvState.lod[0].dimY = type->getDimY();
+ alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
+ alloc->mHal.drvState.lod[0].mallocPtr = 0;
+ // Stride needs to be aligned to a boundary defined by requiredAlignment!
+ size_t stride =
+ alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
+ alloc->mHal.drvState.lod[0].stride = rsRound(stride, requiredAlignment);
+ alloc->mHal.drvState.lodCount = type->getLODCount();
+ alloc->mHal.drvState.faceCount = type->getDimFaces();
+
+ size_t offsets[Allocation::MAX_LOD];
+ memset(offsets, 0, sizeof(offsets));
+
+ size_t o = alloc->mHal.drvState.lod[0].stride *
+ rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) *
+ rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u);
+ if (alloc->mHal.state.yuv) {
+ o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
+
+ for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) {
+ offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr;
+ }
+ } else if (alloc->mHal.drvState.lodCount > 1) {
+ uint32_t tx = alloc->mHal.drvState.lod[0].dimX;
+ uint32_t ty = alloc->mHal.drvState.lod[0].dimY;
+ uint32_t tz = alloc->mHal.drvState.lod[0].dimZ;
+ for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) {
+ alloc->mHal.drvState.lod[lod].dimX = tx;
+ alloc->mHal.drvState.lod[lod].dimY = ty;
+ alloc->mHal.drvState.lod[lod].dimZ = tz;
+ alloc->mHal.drvState.lod[lod].stride =
+ rsRound(tx * type->getElementSizeBytes(), requiredAlignment);
+ offsets[lod] = o;
+ o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
+ if (tx > 1) tx >>= 1;
+ if (ty > 1) ty >>= 1;
+ if (tz > 1) tz >>= 1;
+ }
+ }
+
+ alloc->mHal.drvState.faceOffset = o;
+
+ alloc->mHal.drvState.lod[0].mallocPtr = ptr;
+ for (uint32_t lod = 1; lod < alloc->mHal.drvState.lodCount; lod++) {
+ alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod];
+ }
+
+ size_t allocSize = alloc->mHal.drvState.faceOffset;
+ if (alloc->mHal.drvState.faceCount) {
+ allocSize *= 6;
+ }
+
+ return allocSize;
+}
+
+size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
+ const Type *type, uint8_t *ptr) {
+ return AllocationBuildPointerTable(rsc, alloc, type, ptr,
+ Allocation::kMinimumRSAlignment);
+}
+
+uint8_t *GetOffsetPtr(const Allocation *alloc, uint32_t xoff, uint32_t yoff,
+ uint32_t zoff, uint32_t lod,
+ RsAllocationCubemapFace face) {
+ uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr;
+ ptr += face * alloc->mHal.drvState.faceOffset;
+ ptr += zoff * alloc->mHal.drvState.lod[lod].dimY *
+ alloc->mHal.drvState.lod[lod].stride;
+ ptr += yoff * alloc->mHal.drvState.lod[lod].stride;
+ ptr += xoff * alloc->mHal.state.elementSizeBytes;
+ return ptr;
+}
+
+void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
+ uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
+ uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
+
+ for (uint32_t y = 0; y < h; y++) {
+ uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
+ const uint16_t *i1 =
+ (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2, lod, face);
+ const uint16_t *i2 =
+ (uint16_t *)GetOffsetPtr(alloc, 0, 0, y * 2 + 1, lod, face);
+
+ for (uint32_t x = 0; x < w; x++) {
+ *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
+ oPtr++;
+ i1 += 2;
+ i2 += 2;
+ }
+ }
+}
+
+void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
+ uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
+ uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
+
+ for (uint32_t y = 0; y < h; y++) {
+ uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
+ const uint32_t *i1 =
+ (uint32_t *)GetOffsetPtr(alloc, 0, y * 2, 0, lod, face);
+ const uint32_t *i2 =
+ (uint32_t *)GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face);
+
+ for (uint32_t x = 0; x < w; x++) {
+ *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
+ oPtr++;
+ i1 += 2;
+ i2 += 2;
+ }
+ }
+}
+
+void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
+ uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
+ uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
+
+ for (uint32_t y = 0; y < h; y++) {
+ uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
+ const uint8_t *i1 = GetOffsetPtr(alloc, 0, y * 2, 0, lod, face);
+ const uint8_t *i2 = GetOffsetPtr(alloc, 0, y * 2 + 1, 0, lod, face);
+
+ for (uint32_t x = 0; x < w; x++) {
+ *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
+ oPtr++;
+ i1 += 2;
+ i2 += 2;
+ }
+ }
+}
+
+} // anonymous namespace
+
+RSoVAllocation::RSoVAllocation(RSoVContext *context, const Type *type)
+ : mRSoV(context),
+ mDevice(context->getDevice()),
+ mType(type),
+ mWidth(type->getDimX()),
+ mHeight(type->getDimY()),
+ mDepth(type->getDimZ()) {
+ InitImage();
+}
+
+RSoVAllocation::~RSoVAllocation() {
+ vkDestroyImageView(mDevice, mImageView, nullptr);
+ vkDestroyImage(mDevice, mImage, nullptr);
+ vkFreeMemory(mDevice, mMem, nullptr);
+}
+
+void RSoVAllocation::InitImage() {
+ VkResult res;
+
+ mFormat = VkFormatFromRSElement(*mType->getElement());
+
+ const uint32_t width = mWidth;
+ const uint32_t height = mHeight;
+ const uint32_t depth = mDepth;
+
+ VkImageType imageType =
+ depth > 0 ? VK_IMAGE_TYPE_3D
+ : (height > 0 ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_1D);
+
+ VkImageCreateInfo createInfo = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .imageType = imageType,
+ .format = mFormat,
+ .extent = {width, rsMax(height, 1U), rsMax(depth, 1U)},
+ .mipLevels = 1,
+ .arrayLayers = 1,
+ .samples = VK_SAMPLE_COUNT_1_BIT,
+ .tiling = VK_IMAGE_TILING_LINEAR,
+ .usage = VK_IMAGE_USAGE_STORAGE_BIT,
+ .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+ .queueFamilyIndexCount = 0,
+ .pQueueFamilyIndices = nullptr,
+ .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
+ };
+
+ res = vkCreateImage(mDevice, &createInfo, nullptr, &mImage);
+ rsAssert(res == VK_SUCCESS);
+
+ VkMemoryRequirements mem_reqs;
+ vkGetImageMemoryRequirements(mDevice, mImage, &mem_reqs);
+
+ ALOGI("size of memory needed = %u", (uint)mem_reqs.size);
+
+ VkMemoryAllocateInfo allocateInfo = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .allocationSize = mem_reqs.size,
+ };
+
+ /* Use the memory properties to determine the type of memory required */
+ bool pass;
+ pass = mRSoV->MemoryTypeFromProperties(
+ mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+ &allocateInfo.memoryTypeIndex);
+ ALOGI("TypeBits = 0x%08X", mem_reqs.memoryTypeBits);
+ rsAssert(pass);
+
+ // TODO: Make this aligned
+ res = vkAllocateMemory(mDevice, &allocateInfo, nullptr, &mMem);
+ rsAssert(res == VK_SUCCESS);
+
+ res = vkBindImageMemory(mDevice, mImage, mMem, 0);
+ rsAssert(res == VK_SUCCESS);
+
+ VkImageViewType viewType =
+ depth > 0 ? VK_IMAGE_VIEW_TYPE_3D
+ : (height > 0 ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_1D);
+
+ VkImageViewCreateInfo view_info = {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .pNext = nullptr,
+ .image = mImage,
+ .viewType = viewType,
+ .format = mFormat,
+ .components =
+ {
+ .r = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .g = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .b = VK_COMPONENT_SWIZZLE_IDENTITY,
+ .a = VK_COMPONENT_SWIZZLE_IDENTITY,
+ },
+ .subresourceRange =
+ {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ },
+ };
+
+ res = vkCreateImageView(mDevice, &view_info, nullptr, &mImageView);
+ rsAssert(res == VK_SUCCESS);
+
+ mImageLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+ mImageInfo = {
+ .imageView = mImageView, .imageLayout = mImageLayout,
+ };
+
+ res = vkMapMemory(mDevice, mMem, 0, mem_reqs.size, 0, (void **)&mPtr);
+ rsAssert(res == VK_SUCCESS);
+}
+
+} // namespace rsov
+} // namespace renderscript
+} // namespace android
+
+using android::renderscript::Allocation;
+using android::renderscript::Context;
+using android::renderscript::Element;
+using android::renderscript::Type;
+using android::renderscript::rs_allocation;
+using android::renderscript::rsMax;
+using namespace android::renderscript::rsov;
+
+bool rsovAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
+ RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv);
+ RSoVContext *rsov = hal->mRSoV;
+ const Type *type = alloc->getType();
+
+ RSoVAllocation *rsovAlloc = new RSoVAllocation(rsov, type);
+ alloc->mHal.drv = rsovAlloc;
+ AllocationBuildPointerTable(rsc, alloc, type,
+ (uint8_t *)rsovAlloc->getHostPtr());
+ return true;
+}
+
+void rsovAllocationDestroy(const Context *rsc, Allocation *alloc) {
+ RSoVAllocation *rsovAlloc = static_cast<RSoVAllocation *>(alloc->mHal.drv);
+ delete rsovAlloc;
+ alloc->mHal.drv = nullptr;
+}
+
+void rsovAllocationData1D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t lod, size_t count,
+ const void *data, size_t sizeBytes) {
+ const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
+ uint8_t *ptr =
+ GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+ size_t size = count * eSize;
+ if (ptr != data) {
+ // Skip the copy if we are the same allocation. This can arise from
+ // our Bitmap optimization, where we share the same storage.
+ if (alloc->mHal.state.hasReferences) {
+ alloc->incRefs(data, count);
+ alloc->decRefs(ptr, count);
+ }
+ memcpy(ptr, data, size);
+ }
+}
+
+void rsovAllocationData2D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t lod,
+ RsAllocationCubemapFace face, uint32_t w, uint32_t h,
+ const void *data, size_t sizeBytes, size_t stride) {
+ size_t eSize = alloc->mHal.state.elementSizeBytes;
+ size_t lineSize = eSize * w;
+ if (!stride) {
+ stride = lineSize;
+ }
+
+ if (alloc->mHal.drvState.lod[0].mallocPtr) {
+ const uint8_t *src = static_cast<const uint8_t *>(data);
+ uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
+
+ for (uint32_t line = yoff; line < (yoff + h); line++) {
+ if (alloc->mHal.state.hasReferences) {
+ alloc->incRefs(src, w);
+ alloc->decRefs(dst, w);
+ }
+ memcpy(dst, src, lineSize);
+ src += stride;
+ dst += alloc->mHal.drvState.lod[lod].stride;
+ }
+ // TODO: handle YUV Allocations
+ if (alloc->mHal.state.yuv) {
+ size_t clineSize = lineSize;
+ int lod = 1;
+ int maxLod = 2;
+ if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YV12) {
+ maxLod = 3;
+ clineSize >>= 1;
+ } else if (alloc->mHal.state.yuv == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+ lod = 2;
+ maxLod = 3;
+ }
+
+ while (lod < maxLod) {
+ uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
+
+ for (uint32_t line = (yoff >> 1); line < ((yoff + h) >> 1); line++) {
+ memcpy(dst, src, clineSize);
+ // When copying from an array to an Allocation, the src pointer
+ // to the array should just move by the number of bytes copied.
+ src += clineSize;
+ dst += alloc->mHal.drvState.lod[lod].stride;
+ }
+ lod++;
+ }
+ }
+ }
+}
+
+void rsovAllocationData3D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t zoff,
+ uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
+ const void *data, size_t sizeBytes, size_t stride) {
+ uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+ uint32_t lineSize = eSize * w;
+ if (!stride) {
+ stride = lineSize;
+ }
+
+ if (alloc->mHal.drvState.lod[0].mallocPtr) {
+ const uint8_t *src = static_cast<const uint8_t *>(data);
+ for (uint32_t z = zoff; z < (d + zoff); z++) {
+ uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+ for (uint32_t line = yoff; line < (yoff + h); line++) {
+ if (alloc->mHal.state.hasReferences) {
+ alloc->incRefs(src, w);
+ alloc->decRefs(dst, w);
+ }
+ memcpy(dst, src, lineSize);
+ src += stride;
+ dst += alloc->mHal.drvState.lod[lod].stride;
+ }
+ }
+ }
+}
+
+void rsovAllocationRead1D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t lod, size_t count, void *data,
+ size_t sizeBytes) {
+ const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
+ const uint8_t *ptr =
+ GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+ if (data != ptr) {
+ // Skip the copy if we are the same allocation. This can arise from
+ // our Bitmap optimization, where we share the same storage.
+ memcpy(data, ptr, count * eSize);
+ }
+}
+
+void rsovAllocationRead2D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t lod,
+ RsAllocationCubemapFace face, uint32_t w, uint32_t h,
+ void *data, size_t sizeBytes, size_t stride) {
+ size_t eSize = alloc->mHal.state.elementSizeBytes;
+ size_t lineSize = eSize * w;
+ if (!stride) {
+ stride = lineSize;
+ }
+
+ if (alloc->mHal.drvState.lod[0].mallocPtr) {
+ uint8_t *dst = static_cast<uint8_t *>(data);
+ const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
+ if (dst == src) {
+ // Skip the copy if we are the same allocation. This can arise from
+ // our Bitmap optimization, where we share the same storage.
+ return;
+ }
+
+ for (uint32_t line = yoff; line < (yoff + h); line++) {
+ memcpy(dst, src, lineSize);
+ dst += stride;
+ src += alloc->mHal.drvState.lod[lod].stride;
+ }
+ } else {
+ ALOGE("Add code to readback from non-script memory");
+ }
+}
+
+void rsovAllocationRead3D(const Context *rsc, const Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t zoff,
+ uint32_t lod, uint32_t w, uint32_t h, uint32_t d,
+ void *data, size_t sizeBytes, size_t stride) {
+ uint32_t eSize = alloc->mHal.state.elementSizeBytes;
+ uint32_t lineSize = eSize * w;
+ if (!stride) {
+ stride = lineSize;
+ }
+
+ if (alloc->mHal.drvState.lod[0].mallocPtr) {
+ uint8_t *dst = static_cast<uint8_t *>(data);
+ for (uint32_t z = zoff; z < (d + zoff); z++) {
+ const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+ if (dst == src) {
+ // Skip the copy if we are the same allocation. This can arise from
+ // our Bitmap optimization, where we share the same storage.
+ return;
+ }
+
+ for (uint32_t line = yoff; line < (yoff + h); line++) {
+ memcpy(dst, src, lineSize);
+ dst += stride;
+ src += alloc->mHal.drvState.lod[lod].stride;
+ }
+ }
+ }
+}
+
+void *rsovAllocationLock1D(const Context *rsc, const Allocation *alloc) {
+ return alloc->mHal.drvState.lod[0].mallocPtr;
+}
+
+void rsovAllocationUnlock1D(const Context *rsc, const Allocation *alloc) {}
+
+void rsovAllocationData1D_alloc(const Context *rsc, const Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstLod, size_t count,
+ const Allocation *srcAlloc, uint32_t srcXoff,
+ uint32_t srcLod) {}
+
+void rsovAllocationData2D_alloc_script(
+ const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+ uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
+ uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
+ size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
+ for (uint32_t i = 0; i < h; i++) {
+ uint8_t *dstPtr =
+ GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
+ uint8_t *srcPtr =
+ GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
+ memcpy(dstPtr, srcPtr, w * elementSize);
+ }
+}
+
+void rsovAllocationData3D_alloc_script(
+ const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
+ uint32_t d, const Allocation *srcAlloc, uint32_t srcXoff, uint32_t srcYoff,
+ uint32_t srcZoff, uint32_t srcLod) {
+ uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
+ for (uint32_t j = 0; j < d; j++) {
+ for (uint32_t i = 0; i < h; i++) {
+ uint8_t *dstPtr =
+ GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j, dstLod,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+ uint8_t *srcPtr =
+ GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j, srcLod,
+ RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+ memcpy(dstPtr, srcPtr, w * elementSize);
+ }
+ }
+}
+
+void rsovAllocationData2D_alloc(
+ const Context *rsc, const Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+ uint32_t w, uint32_t h, const Allocation *srcAlloc, uint32_t srcXoff,
+ uint32_t srcYoff, uint32_t srcLod, RsAllocationCubemapFace srcFace) {
+ if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER,
+ "Non-script allocation copies not "
+ "yet implemented.");
+ return;
+ }
+ rsovAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstLod,
+ dstFace, w, h, srcAlloc, srcXoff, srcYoff,
+ srcLod, srcFace);
+}
+
+void rsovAllocationData3D_alloc(const Context *rsc, const Allocation *dstAlloc,
+ uint32_t dstXoff, uint32_t dstYoff,
+ uint32_t dstZoff, uint32_t dstLod, uint32_t w,
+ uint32_t h, uint32_t d,
+ const Allocation *srcAlloc, uint32_t srcXoff,
+ uint32_t srcYoff, uint32_t srcZoff,
+ uint32_t srcLod) {
+ if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
+ rsc->setError(RS_ERROR_FATAL_DRIVER,
+ "Non-script allocation copies not "
+ "yet implemented.");
+ return;
+ }
+ rsovAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
+ dstLod, w, h, d, srcAlloc, srcXoff, srcYoff,
+ srcZoff, srcLod);
+}
+
+void rsovAllocationAdapterOffset(const Context *rsc, const Allocation *alloc) {
+ // Get a base pointer to the new LOD
+ const Allocation *base = alloc->mHal.state.baseAlloc;
+ const Type *type = alloc->mHal.state.type;
+ if (base == nullptr) {
+ return;
+ }
+
+ const int lodBias = alloc->mHal.state.originLOD;
+ uint32_t lodCount = rsMax(alloc->mHal.drvState.lodCount, (uint32_t)1);
+ for (uint32_t lod = 0; lod < lodCount; lod++) {
+ alloc->mHal.drvState.lod[lod] = base->mHal.drvState.lod[lod + lodBias];
+ alloc->mHal.drvState.lod[lod].mallocPtr = GetOffsetPtr(
+ alloc, alloc->mHal.state.originX, alloc->mHal.state.originY,
+ alloc->mHal.state.originZ, lodBias,
+ (RsAllocationCubemapFace)alloc->mHal.state.originFace);
+ }
+}
+
+bool rsovAllocationAdapterInit(const Context *rsc, Allocation *alloc) {
+// TODO: may need a RSoV Allocation here
+#if 0
+ DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
+ if (!drv) {
+ return false;
+ }
+ alloc->mHal.drv = drv;
+#endif
+ // We need to build an allocation that looks like a subset of the parent
+ // allocation
+ rsovAllocationAdapterOffset(rsc, alloc);
+
+ return true;
+}
+
+void rsovAllocationSyncAll(const Context *rsc, const Allocation *alloc,
+ RsAllocationUsageType src) {
+ // TODO: anything to do here?
+}
+
+void rsovAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
+ // TODO: anything to do here?
+}
+
+void rsovAllocationResize(const Context *rsc, const Allocation *alloc,
+ const Type *newType, bool zeroNew) {
+ // TODO: implement this
+ // can this be done without copying, if the new size is greater than the
+ // original?
+}
+
+void rsovAllocationGenerateMipmaps(const Context *rsc,
+ const Allocation *alloc) {
+ if (!alloc->mHal.drvState.lod[0].mallocPtr) {
+ return;
+ }
+ uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
+ for (uint32_t face = 0; face < numFaces; face++) {
+ for (uint32_t lod = 0; lod < (alloc->getType()->getLODCount() - 1); lod++) {
+ switch (alloc->getType()->getElement()->getSizeBits()) {
+ case 32:
+ mip8888(alloc, lod, (RsAllocationCubemapFace)face);
+ break;
+ case 16:
+ mip565(alloc, lod, (RsAllocationCubemapFace)face);
+ break;
+ case 8:
+ mip8(alloc, lod, (RsAllocationCubemapFace)face);
+ break;
+ }
+ }
+ }
+}
+
+uint32_t rsovAllocationGrallocBits(const Context *rsc, Allocation *alloc) {
+ return 0;
+}
+
+void rsovAllocationUpdateCachedObject(const Context *rsc,
+ const Allocation *alloc,
+ rs_allocation *obj) {
+ obj->p = alloc;
+#ifdef __LP64__
+ if (alloc != nullptr) {
+ obj->r = alloc->mHal.drvState.lod[0].mallocPtr;
+ obj->v1 = alloc->mHal.drv;
+ obj->v2 = (void *)alloc->mHal.drvState.lod[0].stride;
+ } else {
+ obj->r = nullptr;
+ obj->v1 = nullptr;
+ obj->v2 = nullptr;
+ }
+#endif
+}
+
+void rsovAllocationSetSurface(const Context *rsc, Allocation *alloc,
+ ANativeWindow *nw) {
+ // TODO: implement this
+}
+
+void rsovAllocationIoSend(const Context *rsc, Allocation *alloc) {
+ // TODO: implement this
+}
+
+void rsovAllocationIoReceive(const Context *rsc, Allocation *alloc) {
+ // TODO: implement this
+}
+
+void rsovAllocationElementData(const Context *rsc, const Allocation *alloc,
+ uint32_t x, uint32_t y, uint32_t z,
+ const void *data, uint32_t cIdx,
+ size_t sizeBytes) {
+ uint8_t *ptr =
+ GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+
+ const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
+ ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
+
+ if (alloc->mHal.state.hasReferences) {
+ e->incRefs(data);
+ e->decRefs(ptr);
+ }
+
+ memcpy(ptr, data, sizeBytes);
+}
+
+void rsovAllocationElementRead(const Context *rsc, const Allocation *alloc,
+ uint32_t x, uint32_t y, uint32_t z, void *data,
+ uint32_t cIdx, size_t sizeBytes) {
+ uint8_t *ptr =
+ GetOffsetPtr(alloc, x, y, z, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
+
+ const Element *e = alloc->mHal.state.type->getElement()->getField(cIdx);
+ ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
+
+ memcpy(data, ptr, sizeBytes);
+}
diff --git a/rsov/driver/rsovAllocation.h b/rsov/driver/rsovAllocation.h
new file mode 100644
index 00000000..24f4cf0a
--- /dev/null
+++ b/rsov/driver/rsovAllocation.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_ALLOCATION_H
+#define RSOV_ALLOCATION_H
+
+#include <vulkan/vulkan.h>
+
+#include "rsDefines.h"
+#include "rs_hal.h"
+#include "system/window.h"
+
+namespace android {
+namespace renderscript {
+
+class Allocation;
+class Context;
+class Type;
+
+namespace rsov {
+
+class RSoVContext;
+
+class RSoVAllocation {
+ public:
+ RSoVAllocation(RSoVContext *context, const Type *type);
+ ~RSoVAllocation();
+
+ uint32_t getWidth() const { return mWidth; }
+ uint32_t getHeight() const { return mHeight; }
+ uint32_t getDepth() const { return mDepth; }
+ const VkDescriptorImageInfo *getImageInfo() const { return &mImageInfo; }
+ char *getHostPtr() const { return mPtr; }
+
+ private:
+ void InitImage();
+
+ char *mPtr; // Host pointer to mmapped device memory for the Allocation
+ RSoVContext *mRSoV;
+ VkDevice mDevice;
+ const Type *mType;
+ const uint32_t mWidth;
+ const uint32_t mHeight;
+ const uint32_t mDepth;
+
+ VkFormat mFormat;
+ VkDescriptorImageInfo mImageInfo;
+ VkDeviceMemory mMem;
+ VkImage mImage;
+ VkImageView mImageView;
+ VkImageLayout mImageLayout;
+
+ // TODO: add an underneath buffer too
+};
+
+} // namespace rsov
+} // namespace renderscript
+} // namespace android
+
+extern bool rsovAllocationInit(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc,
+ bool forceZero);
+
+extern void rsovAllocationDestroy(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationData1D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t lod, size_t count,
+ const void *data, size_t sizeBytes);
+
+extern void rsovAllocationData2D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t lod,
+ RsAllocationCubemapFace face, uint32_t w,
+ uint32_t h, const void *data, size_t sizeBytes,
+ size_t stride);
+
+extern void rsovAllocationData3D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t zoff,
+ uint32_t lod, uint32_t w, uint32_t h,
+ uint32_t d, const void *data, size_t sizeBytes,
+ size_t stride);
+
+extern void rsovAllocationRead1D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t lod, size_t count,
+ void *data, size_t sizeBytes);
+
+extern void rsovAllocationRead2D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t lod,
+ RsAllocationCubemapFace face, uint32_t w,
+ uint32_t h, void *data, size_t sizeBytes,
+ size_t stride);
+
+extern void rsovAllocationRead3D(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ uint32_t xoff, uint32_t yoff, uint32_t zoff,
+ uint32_t lod, uint32_t w, uint32_t h,
+ uint32_t d, void *data, size_t sizeBytes,
+ size_t stride);
+
+extern void *rsovAllocationLock1D(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationUnlock1D(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationData1D_alloc(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstLod, size_t count,
+ const android::renderscript::Allocation *srcAlloc, uint32_t srcXoff,
+ uint32_t srcLod);
+
+extern void rsovAllocationData2D_alloc_script(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+ uint32_t w, uint32_t h, const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+ RsAllocationCubemapFace srcFace);
+
+extern void rsovAllocationData2D_alloc(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstLod, RsAllocationCubemapFace dstFace,
+ uint32_t w, uint32_t h, const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
+ RsAllocationCubemapFace srcFace);
+
+extern void rsovAllocationData3D_alloc_script(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
+ uint32_t d, const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod);
+
+extern void rsovAllocationData3D_alloc(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod, uint32_t w, uint32_t h,
+ uint32_t d, const android::renderscript::Allocation *srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod);
+
+extern void rsovAllocationAdapterOffset(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc);
+
+extern bool rsovAllocationAdapterInit(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationSyncAll(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc, RsAllocationUsageType src);
+
+extern void rsovAllocationMarkDirty(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationResize(const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ const android::renderscript::Type *newType,
+ bool zeroNew);
+
+extern void rsovAllocationGenerateMipmaps(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc);
+
+extern uint32_t rsovAllocationGrallocBits(
+ const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationUpdateCachedObject(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc,
+ android::renderscript::rs_allocation *obj);
+
+extern void rsovAllocationSetSurface(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc,
+ ANativeWindow *nw);
+
+extern void rsovAllocationIoSend(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationIoReceive(const android::renderscript::Context *rsc,
+ android::renderscript::Allocation *alloc);
+
+extern void rsovAllocationElementData(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc, uint32_t x, uint32_t y,
+ uint32_t z, const void *data, uint32_t cIdx, size_t sizeBytes);
+
+extern void rsovAllocationElementRead(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Allocation *alloc, uint32_t x, uint32_t y,
+ uint32_t z, void *data, uint32_t cIdx, size_t sizeBytes);
+
+#endif // RSOV_ALLOCATION_H
diff --git a/rsov/driver/rsovContext.cpp b/rsov/driver/rsovContext.cpp
new file mode 100644
index 00000000..f1bfc66e
--- /dev/null
+++ b/rsov/driver/rsovContext.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovContext.h"
+
+#include <vector>
+
+#include "rsUtils.h"
+
+namespace android {
+namespace renderscript {
+namespace rsov {
+
+RSoVContext* RSoVContext::mContext = nullptr;
+std::once_flag RSoVContext::mInitFlag;
+
+void RSoVContext::Initialize(char const* const name) {
+ // Initialize instance
+ VkApplicationInfo appInfo = {
+ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ .pNext = nullptr,
+ .pApplicationName = name, // TODO: set to app name
+ .applicationVersion = 1,
+ .pEngineName = name,
+ .engineVersion = 1,
+ .apiVersion = VK_API_VERSION_1_0};
+
+ VkInstanceCreateInfo instInfo = {
+ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .pApplicationInfo = &appInfo,
+ };
+
+ VkResult res;
+ res = vkCreateInstance(&instInfo, nullptr, &mInstance);
+ rsAssert(res == VK_SUCCESS);
+
+ // Enumerate devices
+ uint32_t gpu_count;
+
+ res = vkEnumeratePhysicalDevices(mInstance, &gpu_count, nullptr);
+ rsAssert(gpu_count > 0);
+
+ std::vector<VkPhysicalDevice> GPUs(gpu_count);
+
+ res = vkEnumeratePhysicalDevices(mInstance, &gpu_count, GPUs.data());
+ rsAssert(res == VK_SUCCESS && gpu_count > 0);
+
+ mGPU = GPUs[0];
+
+ // Get device memory properties
+ vkGetPhysicalDeviceMemoryProperties(mGPU, &mMemoryProperties);
+
+ // Initialize device
+
+ float queuePriorities[] = {0.0};
+
+ VkDeviceQueueCreateInfo queueInfo = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ .pNext = nullptr,
+ .queueCount = 1,
+ .pQueuePriorities = queuePriorities,
+ };
+
+ VkDeviceCreateInfo deviceInfo = {
+ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ .pNext = nullptr,
+ .queueCreateInfoCount = 1,
+ .pQueueCreateInfos = &queueInfo,
+ .pEnabledFeatures = nullptr,
+ };
+
+ res = vkCreateDevice(mGPU, &deviceInfo, nullptr, &mDevice);
+ rsAssert(res == VK_SUCCESS);
+
+ // Initialize queue family index
+ uint32_t queueCount;
+
+ vkGetPhysicalDeviceQueueFamilyProperties(mGPU, &queueCount, nullptr);
+ rsAssert(queueCount > 0);
+
+ std::vector<VkQueueFamilyProperties> queueProps(queueCount);
+
+ vkGetPhysicalDeviceQueueFamilyProperties(mGPU, &queueCount,
+ queueProps.data());
+ rsAssert(queueCount > 0);
+
+ uint32_t queueFamilyIndex = UINT_MAX;
+ bool found = false;
+ for (unsigned int i = 0; i < queueCount; i++) {
+ if (queueProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
+ queueFamilyIndex = i;
+ found = true;
+ break;
+ }
+ }
+
+ rsAssert(found);
+
+ // Create a device queue
+
+ vkGetDeviceQueue(mDevice, queueFamilyIndex, 0, &mQueue);
+
+ // Create command pool
+
+ VkCommandPoolCreateInfo cmd_pool_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ .pNext = nullptr,
+ .queueFamilyIndex = queueFamilyIndex,
+ .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
+ };
+
+ res = vkCreateCommandPool(mDevice, &cmd_pool_info, nullptr, &mCmdPool);
+ rsAssert(res == VK_SUCCESS);
+}
+
+bool RSoVContext::MemoryTypeFromProperties(uint32_t typeBits,
+ VkFlags requirements_mask,
+ uint32_t* typeIndex) {
+ for (uint32_t i = 0; i < 32; i++) {
+ if ((typeBits & 1) == 1) {
+ const uint32_t prop = mMemoryProperties.memoryTypes[i].propertyFlags;
+ if ((prop & requirements_mask) == requirements_mask) {
+ *typeIndex = i;
+ return true;
+ }
+ }
+ typeBits >>= 1;
+ }
+
+ return false;
+}
+
+RSoVContext::RSoVContext() {
+ char engineName[] = "RSoV";
+
+ Initialize(engineName);
+}
+
+RSoVContext::~RSoVContext() {
+ vkDestroyCommandPool(mDevice, mCmdPool, nullptr);
+ vkDestroyDevice(mDevice, nullptr);
+ vkDestroyInstance(mInstance, nullptr);
+}
+
+RSoVContext* RSoVContext::create() {
+ std::call_once(mInitFlag, []() { mContext = new RSoVContext(); });
+ return mContext;
+}
+
+} // namespace rsov
+} // namespace renderscript
+} // namespace android
diff --git a/rsov/driver/rsovContext.h b/rsov/driver/rsovContext.h
new file mode 100644
index 00000000..cf8e30bd
--- /dev/null
+++ b/rsov/driver/rsovContext.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_CONTEXT_H
+#define RSOV_CONTEXT_H
+
+#include <vulkan/vulkan.h>
+#include <mutex>
+
+namespace android {
+namespace renderscript {
+
+class RsdCpuReference;
+
+namespace rsov {
+
+class RSoVContext {
+ public:
+ static RSoVContext* create();
+ ~RSoVContext();
+
+ VkDevice getDevice() const { return mDevice; }
+ VkQueue getQueue() const { return mQueue; }
+ VkCommandPool getCmdPool() const { return mCmdPool; }
+
+ bool MemoryTypeFromProperties(uint32_t typeBits, VkFlags requirements_mask,
+ uint32_t* typeIndex);
+
+ private:
+ RSoVContext();
+
+ void Initialize(char const* const name);
+
+ static RSoVContext* mContext;
+ static std::once_flag mInitFlag;
+
+ VkInstance mInstance;
+ VkPhysicalDevice mGPU;
+ VkDevice mDevice;
+ VkPhysicalDeviceMemoryProperties mMemoryProperties;
+ VkQueue mQueue;
+ VkCommandPool mCmdPool;
+};
+
+} // namespace rsov
+} // namespace renderscript
+} // namespace android
+
+#endif // RSOV_CONTEXT_H
diff --git a/rsov/driver/rsovCore.cpp b/rsov/driver/rsovCore.cpp
new file mode 100644
index 00000000..b51fa391
--- /dev/null
+++ b/rsov/driver/rsovCore.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovCore.h"
+
+#include <malloc.h>
+#include <sched.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+
+#include "cpu_ref/rsd_cpu.h"
+#include "rsContext.h"
+#include "rsovAllocation.h"
+#include "rsovContext.h"
+#include "rsovElement.h"
+#include "rsovSampler.h"
+#include "rsovScript.h"
+#include "rsovScriptGroup.h"
+#include "rsovType.h"
+
+namespace android {
+namespace renderscript {
+
+namespace {
+void SetPriority(const Context *rsc, int32_t priority) {
+ RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+
+ dc->mCpuRef->setPriority(priority);
+}
+
+void Shutdown(Context *rsc) {
+ RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+ delete dc->mCpuRef;
+ free(dc);
+ rsc->mHal.drv = nullptr;
+}
+
+void *AllocRuntimeMem(size_t size, uint32_t flags) {
+ void* buffer = calloc(size, sizeof(char));
+ return buffer;
+}
+
+void FreeRuntimeMem(void* ptr) {
+ free(ptr);
+}
+
+const RsdCpuReference::CpuSymbol *rsdLookupRuntimeStub(
+ Context *pContext, char const *name) {
+ return nullptr;
+}
+
+RsdCpuReference::CpuScript *LookupScript(Context *, const Script *s) {
+ return (RsdCpuReference::CpuScript *)s->mHal.drv;
+}
+
+} // anonymous namespace
+
+extern "C" bool rsdHalQueryHal(RsHalInitEnums entry, void **fnPtr) {
+ switch (entry) {
+ case RS_HAL_ALLOCATION_INIT:
+ fnPtr[0] = (void *)rsovAllocationInit;
+ break;
+ case RS_HAL_ALLOCATION_INIT_OEM:
+ fnPtr[0] = (void *)nullptr;
+ break;
+ case RS_HAL_ALLOCATION_INIT_ADAPTER:
+ fnPtr[0] = (void *)rsovAllocationAdapterInit;
+ break;
+ case RS_HAL_ALLOCATION_DESTROY:
+ fnPtr[0] = (void *)rsovAllocationDestroy;
+ break;
+ case RS_HAL_ALLOCATION_GET_GRALLOC_BITS:
+ fnPtr[0] = (void *)rsovAllocationGrallocBits;
+ break;
+ case RS_HAL_ALLOCATION_DATA_1D:
+ fnPtr[0] = (void *)rsovAllocationData1D;
+ break;
+ case RS_HAL_ALLOCATION_DATA_2D:
+ fnPtr[0] = (void *)rsovAllocationData2D;
+ break;
+ case RS_HAL_ALLOCATION_DATA_3D:
+ fnPtr[0] = (void *)rsovAllocationData3D;
+ break;
+ case RS_HAL_ALLOCATION_READ_1D:
+ fnPtr[0] = (void *)rsovAllocationRead1D;
+ break;
+ case RS_HAL_ALLOCATION_READ_2D:
+ fnPtr[0] = (void *)rsovAllocationRead2D;
+ break;
+ case RS_HAL_ALLOCATION_READ_3D:
+ fnPtr[0] = (void *)rsovAllocationRead3D;
+ break;
+ case RS_HAL_ALLOCATION_LOCK_1D:
+ fnPtr[0] = (void *)rsovAllocationLock1D;
+ break;
+ case RS_HAL_ALLOCATION_UNLOCK_1D:
+ fnPtr[0] = (void *)rsovAllocationUnlock1D;
+ break;
+ case RS_HAL_ALLOCATION_COPY_1D:
+ fnPtr[0] = (void *)rsovAllocationData1D_alloc;
+ break;
+ case RS_HAL_ALLOCATION_COPY_2D:
+ fnPtr[0] = (void *)rsovAllocationData2D_alloc;
+ break;
+ case RS_HAL_ALLOCATION_COPY_3D:
+ fnPtr[0] = (void *)rsovAllocationData3D_alloc;
+ break;
+ case RS_HAL_ALLOCATION_ADAPTER_OFFSET:
+ fnPtr[0] = (void *)rsovAllocationAdapterOffset;
+ break;
+ case RS_HAL_ALLOCATION_RESIZE:
+ fnPtr[0] = (void *)rsovAllocationResize;
+ break;
+ case RS_HAL_ALLOCATION_SYNC_ALL:
+ fnPtr[0] = (void *)rsovAllocationSyncAll;
+ break;
+ case RS_HAL_ALLOCATION_MARK_DIRTY:
+ fnPtr[0] = (void *)rsovAllocationMarkDirty;
+ break;
+ case RS_HAL_ALLOCATION_GENERATE_MIPMAPS:
+ fnPtr[0] = (void *)rsovAllocationGenerateMipmaps;
+ break;
+ case RS_HAL_ALLOCATION_UPDATE_CACHED_OBJECT:
+ fnPtr[0] = (void *)rsovAllocationUpdateCachedObject;
+ break;
+ case RS_HAL_ALLOCATION_GET_POINTER:
+ fnPtr[0] = (void *)nullptr;
+ break;
+ case RS_HAL_ALLOCATION_SET_SURFACE:
+ fnPtr[0] = (void *)rsovAllocationSetSurface;
+ break;
+ case RS_HAL_ALLOCATION_IO_SEND:
+ fnPtr[0] = (void *)rsovAllocationIoSend;
+ break;
+ case RS_HAL_ALLOCATION_IO_RECEIVE:
+ fnPtr[0] = (void *)rsovAllocationIoReceive;
+ break;
+ case RS_HAL_ALLOCATION_ELEMENT_DATA:
+ fnPtr[0] = (void *)rsovAllocationElementData;
+ break;
+ case RS_HAL_ALLOCATION_ELEMENT_READ:
+ fnPtr[0] = (void *)rsovAllocationElementRead;
+ break;
+
+ case RS_HAL_CORE_SHUTDOWN:
+ fnPtr[0] = (void *)Shutdown;
+ break;
+ case RS_HAL_CORE_SET_PRIORITY:
+ fnPtr[0] = (void *)SetPriority;
+ break;
+ case RS_HAL_CORE_ALLOC_RUNTIME_MEM:
+ fnPtr[0] = (void *)AllocRuntimeMem;
+ break;
+ case RS_HAL_CORE_FREE_RUNTIME_MEM:
+ fnPtr[0] = (void *)FreeRuntimeMem;
+ break;
+ case RS_HAL_CORE_FINISH:
+ fnPtr[0] = (void *)nullptr;
+ break;
+
+ case RS_HAL_SCRIPT_INIT:
+ fnPtr[0] = (void *)rsovScriptInit;
+ break;
+ case RS_HAL_SCRIPT_INIT_INTRINSIC:
+ fnPtr[0] = (void *)rsovInitIntrinsic;
+ break;
+ case RS_HAL_SCRIPT_INVOKE_FUNCTION:
+ fnPtr[0] = (void *)rsovScriptInvokeFunction;
+ break;
+ case RS_HAL_SCRIPT_INVOKE_ROOT:
+ fnPtr[0] = (void *)rsovScriptInvokeRoot;
+ break;
+ case RS_HAL_SCRIPT_INVOKE_FOR_EACH:
+ fnPtr[0] = (void *)rsovScriptInvokeForEach;
+ break;
+ case RS_HAL_SCRIPT_INVOKE_INIT:
+ fnPtr[0] = (void *)rsovScriptInvokeInit;
+ break;
+ case RS_HAL_SCRIPT_INVOKE_FREE_CHILDREN:
+ fnPtr[0] = (void *)rsovScriptInvokeFreeChildren;
+ break;
+ case RS_HAL_SCRIPT_DESTROY:
+ fnPtr[0] = (void *)rsovScriptDestroy;
+ break;
+ case RS_HAL_SCRIPT_SET_GLOBAL_VAR:
+ fnPtr[0] = (void *)rsovScriptSetGlobalVar;
+ break;
+ case RS_HAL_SCRIPT_GET_GLOBAL_VAR:
+ fnPtr[0] = (void *)rsovScriptGetGlobalVar;
+ break;
+ case RS_HAL_SCRIPT_SET_GLOBAL_VAR_WITH_ELEMENT_DIM:
+ fnPtr[0] = (void *)rsovScriptSetGlobalVarWithElemDims;
+ break;
+ case RS_HAL_SCRIPT_SET_GLOBAL_BIND:
+ fnPtr[0] = (void *)rsovScriptSetGlobalBind;
+ break;
+ case RS_HAL_SCRIPT_SET_GLOBAL_OBJECT:
+ fnPtr[0] = (void *)rsovScriptSetGlobalObj;
+ break;
+ case RS_HAL_SCRIPT_INVOKE_FOR_EACH_MULTI:
+ fnPtr[0] = (void *)rsovScriptInvokeForEachMulti;
+ break;
+ case RS_HAL_SCRIPT_UPDATE_CACHED_OBJECT:
+ fnPtr[0] = (void *)rsovScriptUpdateCachedObject;
+ break;
+ case RS_HAL_SCRIPT_INVOKE_REDUCE:
+ fnPtr[0] = (void *)rsovScriptInvokeReduce;
+ break;
+
+ case RS_HAL_SAMPLER_INIT:
+ fnPtr[0] = (void *)rsovSamplerInit;
+ break;
+ case RS_HAL_SAMPLER_DESTROY:
+ fnPtr[0] = (void *)rsovSamplerDestroy;
+ break;
+ case RS_HAL_SAMPLER_UPDATE_CACHED_OBJECT:
+ fnPtr[0] = (void *)rsovSamplerUpdateCachedObject;
+ break;
+
+ case RS_HAL_TYPE_INIT:
+ fnPtr[0] = (void *)rsovTypeInit;
+ break;
+ case RS_HAL_TYPE_DESTROY:
+ fnPtr[0] = (void *)rsovTypeDestroy;
+ break;
+ case RS_HAL_TYPE_UPDATE_CACHED_OBJECT:
+ fnPtr[0] = (void *)rsovTypeUpdateCachedObject;
+ break;
+
+ case RS_HAL_ELEMENT_INIT:
+ fnPtr[0] = (void *)rsovElementInit;
+ break;
+ case RS_HAL_ELEMENT_DESTROY:
+ fnPtr[0] = (void *)rsovElementDestroy;
+ break;
+ case RS_HAL_ELEMENT_UPDATE_CACHED_OBJECT:
+ fnPtr[0] = (void *)rsovElementUpdateCachedObject;
+ break;
+
+ case RS_HAL_SCRIPT_GROUP_INIT:
+ fnPtr[0] = (void *)rsovScriptGroupInit;
+ break;
+ case RS_HAL_SCRIPT_GROUP_DESTROY:
+ fnPtr[0] = (void *)rsovScriptGroupDestroy;
+ break;
+ case RS_HAL_SCRIPT_GROUP_UPDATE_CACHED_OBJECT:
+ fnPtr[0] = (void *)nullptr;
+ break;
+ case RS_HAL_SCRIPT_GROUP_SET_INPUT:
+ fnPtr[0] = (void *)rsovScriptGroupSetInput;
+ break;
+ case RS_HAL_SCRIPT_GROUP_SET_OUTPUT:
+ fnPtr[0] = (void *)rsovScriptGroupSetOutput;
+ break;
+ case RS_HAL_SCRIPT_GROUP_EXECUTE:
+ fnPtr[0] = (void *)rsovScriptGroupExecute;
+ break;
+
+ // Ignore entries for the legacy graphics api,
+
+ default:
+ ALOGE("ERROR: unknown RenderScript HAL API query, %i", entry);
+ return false;
+ }
+
+ return true;
+}
+
+extern "C" void rsdHalAbort(RsContext) {}
+
+extern "C" bool rsdHalQueryVersion(uint32_t *major, uint32_t *minor) {
+ *major = RS_HAL_VERSION;
+ *minor = 0;
+ return true;
+}
+
+extern "C" bool rsdHalInit(RsContext c, uint32_t version_major,
+ uint32_t version_minor) {
+ Context *rsc = (Context *)c;
+
+ RSoVHal *hal = new RSoVHal();
+ if (!hal) {
+ ALOGE("Failed creating RSoV driver hal.");
+ return false;
+ }
+ rsc->mHal.drv = hal;
+
+ hal->mCpuRef = RsdCpuReference::create(rsc, version_major, version_minor,
+ &rsdLookupRuntimeStub, &LookupScript);
+ if (!hal->mCpuRef) {
+ ALOGE("RsdCpuReference::create for driver hal failed.");
+ rsc->mHal.drv = nullptr;
+ return false;
+ }
+
+ hal->mRSoV = android::renderscript::rsov::RSoVContext::create();
+ if (!hal->mRSoV) {
+ ALOGE("RsdCpuReference::create for driver hal failed.");
+ rsc->mHal.drv = nullptr;
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace renderscript
+} // namespace android
diff --git a/rsov/driver/rsovCore.h b/rsov/driver/rsovCore.h
new file mode 100644
index 00000000..d0c160d5
--- /dev/null
+++ b/rsov/driver/rsovCore.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_CORE_H
+#define RSOV_CORE_H
+
+namespace android {
+namespace renderscript {
+
+class RsdCpuReference;
+
+namespace rsov {
+
+class RSoVContext;
+
+} // namespace rsov
+} // namespace renderscript
+} // namespace android
+
+struct RSoVHal {
+ android::renderscript::rsov::RSoVContext* mRSoV;
+ android::renderscript::RsdCpuReference *mCpuRef;
+};
+
+#define NELEM(x) (sizeof(x) / sizeof((x)[0]))
+
+#endif
diff --git a/rsov/driver/rsovElement.cpp b/rsov/driver/rsovElement.cpp
new file mode 100644
index 00000000..d6321b34
--- /dev/null
+++ b/rsov/driver/rsovElement.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsElement.h"
+
+using android::renderscript::Context;
+using android::renderscript::Element;
+using android::renderscript::rs_element;
+
+bool rsovElementInit(const Context *rsc, const Element *e) { return true; }
+
+void rsovElementDestroy(const Context *rsc, const Element *e) {}
+
+void rsovElementUpdateCachedObject(const Context *rsc, const Element *element,
+ rs_element *obj) {
+ obj->p = element;
+#ifdef __LP64__
+ obj->r = nullptr;
+ obj->v1 = nullptr;
+ obj->v2 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovElement.h b/rsov/driver/rsovElement.h
new file mode 100644
index 00000000..e3d46bcd
--- /dev/null
+++ b/rsov/driver/rsovElement.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_ELEMENT_H
+#define RSOV_ELEMENT_H
+
+#include "rs_hal.h"
+
+extern bool rsovElementInit(const android::renderscript::Context *rsc,
+ const android::renderscript::Element *);
+
+extern void rsovElementDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Element *);
+
+extern void rsovElementUpdateCachedObject(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Element *,
+ android::renderscript::rs_element *obj);
+
+#endif // RSOV_ELEMENT_H
diff --git a/rsov/driver/rsovRuntimeStubs.cpp b/rsov/driver/rsovRuntimeStubs.cpp
new file mode 100644
index 00000000..308c0a53
--- /dev/null
+++ b/rsov/driver/rsovRuntimeStubs.cpp
@@ -0,0 +1,1150 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <time.h>
+
+#include "rsContext.h"
+#include "rsElement.h"
+#include "rsMatrix2x2.h"
+#include "rsMatrix3x3.h"
+#include "rsMatrix4x4.h"
+#include "rsRuntime.h"
+#include "rsScriptC.h"
+#include "rsType.h"
+#include "rsovAllocation.h"
+#include "rsovCore.h"
+#include "rsovScript.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+typedef __fp16 half;
+typedef half half2 __attribute__((ext_vector_type(2)));
+typedef half half3 __attribute__((ext_vector_type(3)));
+typedef half half4 __attribute__((ext_vector_type(4)));
+
+typedef float float2 __attribute__((ext_vector_type(2)));
+typedef float float3 __attribute__((ext_vector_type(3)));
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef double double3 __attribute__((ext_vector_type(3)));
+typedef double double4 __attribute__((ext_vector_type(4)));
+typedef char char2 __attribute__((ext_vector_type(2)));
+typedef char char3 __attribute__((ext_vector_type(3)));
+typedef char char4 __attribute__((ext_vector_type(4)));
+typedef unsigned char uchar2 __attribute__((ext_vector_type(2)));
+typedef unsigned char uchar3 __attribute__((ext_vector_type(3)));
+typedef unsigned char uchar4 __attribute__((ext_vector_type(4)));
+typedef int16_t short2 __attribute__((ext_vector_type(2)));
+typedef int16_t short3 __attribute__((ext_vector_type(3)));
+typedef int16_t short4 __attribute__((ext_vector_type(4)));
+typedef uint16_t ushort2 __attribute__((ext_vector_type(2)));
+typedef uint16_t ushort3 __attribute__((ext_vector_type(3)));
+typedef uint16_t ushort4 __attribute__((ext_vector_type(4)));
+typedef int32_t int2 __attribute__((ext_vector_type(2)));
+typedef int32_t int3 __attribute__((ext_vector_type(3)));
+typedef int32_t int4 __attribute__((ext_vector_type(4)));
+typedef uint32_t uint2 __attribute__((ext_vector_type(2)));
+typedef uint32_t uint3 __attribute__((ext_vector_type(3)));
+typedef uint32_t uint4 __attribute__((ext_vector_type(4)));
+typedef int64_t long2 __attribute__((ext_vector_type(2)));
+typedef int64_t long3 __attribute__((ext_vector_type(3)));
+typedef int64_t long4 __attribute__((ext_vector_type(4)));
+typedef uint64_t ulong2 __attribute__((ext_vector_type(2)));
+typedef uint64_t ulong3 __attribute__((ext_vector_type(3)));
+typedef uint64_t ulong4 __attribute__((ext_vector_type(4)));
+
+typedef uint8_t uchar;
+typedef uint16_t ushort;
+typedef uint32_t uint;
+#ifndef RS_SERVER
+typedef uint64_t ulong;
+#endif
+
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#ifndef __LP64__
+#define OPAQUETYPE(t) \
+ typedef struct { \
+ const int *const p; \
+ } __attribute__((packed, aligned(4))) t; /*NOLINT*/
+#else
+#define OPAQUETYPE(t) \
+ typedef struct { \
+ const void *p; \
+ const void *r; \
+ const void *v1; \
+ const void *v2; \
+ } t; /*NOLINT*/
+#endif
+
+OPAQUETYPE(rs_element)
+OPAQUETYPE(rs_type)
+OPAQUETYPE(rs_allocation)
+OPAQUETYPE(rs_sampler)
+OPAQUETYPE(rs_script)
+OPAQUETYPE(rs_script_call)
+
+OPAQUETYPE(rs_program_fragment);
+OPAQUETYPE(rs_program_store);
+OPAQUETYPE(rs_program_vertex);
+OPAQUETYPE(rs_program_raster);
+OPAQUETYPE(rs_mesh);
+OPAQUETYPE(rs_font);
+
+#undef OPAQUETYPE
+
+typedef enum {
+ // Empty to avoid conflicting definitions with RsAllocationCubemapFace
+} rs_allocation_cubemap_face;
+
+typedef enum {
+ // Empty to avoid conflicting definitions with RsYuvFormat
+} rs_yuv_format;
+
+typedef enum {
+ // Empty to avoid conflicting definitions with RsAllocationMipmapControl
+} rs_allocation_mipmap_control;
+
+typedef struct { unsigned int val; } rs_allocation_usage_type;
+
+typedef struct {
+ int tm_sec; ///< seconds
+ int tm_min; ///< minutes
+ int tm_hour; ///< hours
+ int tm_mday; ///< day of the month
+ int tm_mon; ///< month
+ int tm_year; ///< year
+ int tm_wday; ///< day of the week
+ int tm_yday; ///< day of the year
+ int tm_isdst; ///< daylight savings time
+} rs_tm;
+
+// Some RS functions are not threadsafe but can be called from an invoke
+// function. Instead of summarily marking scripts that call these functions as
+// not-threadable we detect calls to them in the driver and sends a fatal error
+// message.
+static bool failIfInKernel(Context *rsc, const char *funcName) {
+ RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+ RsdCpuReference *impl = (RsdCpuReference *)dc->mCpuRef;
+
+ if (impl->getInKernel()) {
+ char buf[256];
+ snprintf(buf, sizeof(buf),
+ "Error: Call to unsupported function %s "
+ "in kernel",
+ funcName);
+ rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
+ return true;
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Allocation routines
+//////////////////////////////////////////////////////////////////////////////
+#if defined(__i386__) || (defined(__mips__) && __mips == 32)
+// i386 and MIPS32 have different struct return passing to ARM; emulate with a
+// pointer
+const Allocation *rsGetAllocation(const void *ptr) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ const Script *sc = RsdCpuReference::getTlsScript();
+ Allocation *alloc = rsovScriptGetAllocationForPointer(rsc, sc, ptr);
+ android::renderscript::rs_allocation obj = {0};
+ alloc->callUpdateCacheObject(rsc, &obj);
+ return (Allocation *)obj.p;
+}
+#else
+const android::renderscript::rs_allocation rsGetAllocation(const void *ptr) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ const Script *sc = RsdCpuReference::getTlsScript();
+ Allocation *alloc = rsovScriptGetAllocationForPointer(rsc, sc, ptr);
+
+#ifndef __LP64__ // ARMv7
+ android::renderscript::rs_allocation obj = {0};
+#else // AArch64/x86_64/MIPS64
+ android::renderscript::rs_allocation obj = {0, 0, 0, 0};
+#endif
+ alloc->callUpdateCacheObject(rsc, &obj);
+ return obj;
+}
+#endif
+
+void __attribute__((overloadable)) rsAllocationIoSend(::rs_allocation a) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ if (failIfInKernel(rsc, "rsAllocationIoSend")) return;
+ rsrAllocationIoSend(rsc, (Allocation *)a.p);
+}
+
+void __attribute__((overloadable)) rsAllocationIoReceive(::rs_allocation a) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ if (failIfInKernel(rsc, "rsAllocationIoReceive")) return;
+ rsrAllocationIoReceive(rsc, (Allocation *)a.p);
+}
+
+void __attribute__((overloadable))
+rsAllocationCopy1DRange(::rs_allocation dstAlloc, uint32_t dstOff,
+ uint32_t dstMip, uint32_t count,
+ ::rs_allocation srcAlloc, uint32_t srcOff,
+ uint32_t srcMip) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ if (failIfInKernel(rsc, "rsAllocationCopy1DRange")) return;
+ rsrAllocationCopy1DRange(rsc, (Allocation *)dstAlloc.p, dstOff, dstMip, count,
+ (Allocation *)srcAlloc.p, srcOff, srcMip);
+}
+
+void __attribute__((overloadable))
+rsAllocationCopy2DRange(::rs_allocation dstAlloc, uint32_t dstXoff,
+ uint32_t dstYoff, uint32_t dstMip,
+ rs_allocation_cubemap_face dstFace, uint32_t width,
+ uint32_t height, ::rs_allocation srcAlloc,
+ uint32_t srcXoff, uint32_t srcYoff, uint32_t srcMip,
+ rs_allocation_cubemap_face srcFace) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ if (failIfInKernel(rsc, "rsAllocationCopy2DRange")) return;
+ rsrAllocationCopy2DRange(
+ rsc, (Allocation *)dstAlloc.p, dstXoff, dstYoff, dstMip, dstFace, width,
+ height, (Allocation *)srcAlloc.p, srcXoff, srcYoff, srcMip, srcFace);
+}
+
+static android::renderscript::rs_element CreateElement(RsDataType dt,
+ RsDataKind dk,
+ bool isNormalized,
+ uint32_t vecSize) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+
+ // No need for validation here. The rsCreateElement overload below is not
+ // exposed to the Script. The Element-creation APIs call this function in a
+ // consistent manner and rsComponent.cpp asserts on any inconsistency.
+ Element *element =
+ (Element *)rsrElementCreate(rsc, dt, dk, isNormalized, vecSize);
+ android::renderscript::rs_element obj = {};
+ if (element == nullptr) return obj;
+ element->callUpdateCacheObject(rsc, &obj);
+
+ // Any new rsObject created from inside a script should have the usrRefCount
+ // initialized to 0 and the sysRefCount initialized to 1.
+ element->incSysRef();
+ element->decUserRef();
+
+ return obj;
+}
+
+static android::renderscript::rs_type CreateType(RsElement element,
+ uint32_t dimX, uint32_t dimY,
+ uint32_t dimZ, bool mipmaps,
+ bool faces,
+ uint32_t yuv_format) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ android::renderscript::rs_type obj = {};
+
+ if (element == nullptr) {
+ ALOGE("rs_type creation error: Invalid element");
+ return obj;
+ }
+
+ // validate yuv_format
+ RsYuvFormat yuv = (RsYuvFormat)yuv_format;
+ if (yuv != RS_YUV_NONE && yuv != RS_YUV_YV12 && yuv != RS_YUV_NV21 &&
+ yuv != RS_YUV_420_888) {
+ ALOGE("rs_type creation error: Invalid yuv_format %d\n", yuv_format);
+ return obj;
+ }
+
+ // validate consistency of shape parameters
+ if (dimZ > 0) {
+ if (dimX < 1 || dimY < 1) {
+ ALOGE(
+ "rs_type creation error: Both X and Y dimension required "
+ "when Z is present.");
+ return obj;
+ }
+ if (mipmaps) {
+ ALOGE("rs_type creation error: mipmap control requires 2D types");
+ return obj;
+ }
+ if (faces) {
+ ALOGE("rs_type creation error: Cube maps require 2D types");
+ return obj;
+ }
+ }
+ if (dimY > 0 && dimX < 1) {
+ ALOGE(
+ "rs_type creation error: X dimension required when Y is "
+ "present.");
+ return obj;
+ }
+ if (mipmaps && dimY < 1) {
+ ALOGE("rs_type creation error: mipmap control require 2D Types.");
+ return obj;
+ }
+ if (faces && dimY < 1) {
+ ALOGE("rs_type creation error: Cube maps require 2D Types.");
+ return obj;
+ }
+ if (yuv_format != RS_YUV_NONE) {
+ if (dimZ != 0 || dimY == 0 || faces || mipmaps) {
+ ALOGE("rs_type creation error: YUV only supports basic 2D.");
+ return obj;
+ }
+ }
+
+ Type *type = (Type *)rsrTypeCreate(rsc, element, dimX, dimY, dimZ, mipmaps,
+ faces, yuv_format);
+ if (type == nullptr) return obj;
+ type->callUpdateCacheObject(rsc, &obj);
+
+ // Any new rsObject created from inside a script should have the usrRefCount
+ // initialized to 0 and the sysRefCount initialized to 1.
+ type->incSysRef();
+ type->decUserRef();
+
+ return obj;
+}
+
+static android::renderscript::rs_allocation CreateAllocation(
+ RsType type, RsAllocationMipmapControl mipmaps, uint32_t usages,
+ void *ptr) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ android::renderscript::rs_allocation obj = {};
+
+ if (type == nullptr) {
+ ALOGE("rs_allocation creation error: Invalid type");
+ return obj;
+ }
+
+ uint32_t validUsages =
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE;
+ if (usages & ~validUsages) {
+ ALOGE("rs_allocation creation error: Invalid usage flag");
+ return obj;
+ }
+
+ Allocation *alloc = (Allocation *)rsrAllocationCreateTyped(
+ rsc, type, mipmaps, usages, (uintptr_t)ptr);
+ if (alloc == nullptr) return obj;
+ alloc->callUpdateCacheObject(rsc, &obj);
+
+ // Any new rsObject created from inside a script should have the usrRefCount
+ // initialized to 0 and the sysRefCount initialized to 1.
+ alloc->incSysRef();
+ alloc->decUserRef();
+
+ return obj;
+}
+
+// Define rsCreateElement, rsCreateType and rsCreateAllocation entry points
+// differently for 32-bit x86 and Mips. The definitions for ARM32 and all
+// 64-bit architectures is further below.
+#if defined(__i386__) || (defined(__mips__) && __mips == 32)
+
+// The calling convention for the driver on 32-bit x86 and Mips returns
+// rs_element etc. as a stack-return parameter. The Script uses ARM32 calling
+// conventions that return the structs in a register. To match this convention,
+// emulate the return value using a pointer.
+Element *rsCreateElement(int32_t dt, int32_t dk, bool isNormalized,
+ uint32_t vecSize) {
+ android::renderscript::rs_element obj =
+ CreateElement((RsDataType)dt, (RsDataKind)dk, isNormalized, vecSize);
+ return (Element *)obj.p;
+}
+
+Type *rsCreateType(::rs_element element, uint32_t dimX, uint32_t dimY,
+ uint32_t dimZ, bool mipmaps, bool faces,
+ rs_yuv_format yuv_format) {
+ android::renderscript::rs_type obj =
+ CreateType((RsElement)element.p, dimX, dimY, dimZ, mipmaps, faces,
+ (RsYuvFormat)yuv_format);
+ return (Type *)obj.p;
+}
+
+Allocation *rsCreateAllocation(::rs_type type,
+ rs_allocation_mipmap_control mipmaps,
+ uint32_t usages, void *ptr) {
+ android::renderscript::rs_allocation obj;
+ obj = CreateAllocation((RsType)type.p, (RsAllocationMipmapControl)mipmaps,
+ usages, ptr);
+ return (Allocation *)obj.p;
+}
+
+#else
+android::renderscript::rs_element rsCreateElement(int32_t dt, int32_t dk,
+ bool isNormalized,
+ uint32_t vecSize) {
+ return CreateElement((RsDataType)dt, (RsDataKind)dk, isNormalized, vecSize);
+}
+
+android::renderscript::rs_type rsCreateType(::rs_element element, uint32_t dimX,
+ uint32_t dimY, uint32_t dimZ,
+ bool mipmaps, bool faces,
+ rs_yuv_format yuv_format) {
+ return CreateType((RsElement)element.p, dimX, dimY, dimZ, mipmaps, faces,
+ yuv_format);
+}
+
+android::renderscript::rs_allocation rsCreateAllocation(
+ ::rs_type type, rs_allocation_mipmap_control mipmaps, uint32_t usages,
+ void *ptr) {
+ return CreateAllocation((RsType)type.p, (RsAllocationMipmapControl)mipmaps,
+ usages, ptr);
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Object routines
+//////////////////////////////////////////////////////////////////////////////
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#define IS_CLEAR_SET_OBJ(t) \
+ bool rsIsObject(t src) { return src.p != nullptr; } \
+ void __attribute__((overloadable)) rsClearObject(t *dst) { /*NOLINT*/ \
+ rsrClearObject(reinterpret_cast<rs_object_base *>(dst)); \
+ } \
+ void __attribute__((overloadable)) rsSetObject(t *dst, t src) { /*NOLINT*/ \
+ Context *rsc = RsdCpuReference::getTlsContext(); \
+ rsrSetObject(rsc, reinterpret_cast<rs_object_base *>(dst), \
+ (ObjectBase *)src.p); \
+ }
+
+IS_CLEAR_SET_OBJ(::rs_element)
+IS_CLEAR_SET_OBJ(::rs_type)
+IS_CLEAR_SET_OBJ(::rs_allocation)
+IS_CLEAR_SET_OBJ(::rs_sampler)
+IS_CLEAR_SET_OBJ(::rs_script)
+
+IS_CLEAR_SET_OBJ(::rs_mesh)
+IS_CLEAR_SET_OBJ(::rs_program_fragment)
+IS_CLEAR_SET_OBJ(::rs_program_vertex)
+IS_CLEAR_SET_OBJ(::rs_program_raster)
+IS_CLEAR_SET_OBJ(::rs_program_store)
+IS_CLEAR_SET_OBJ(::rs_font)
+
+#undef IS_CLEAR_SET_OBJ
+
+//////////////////////////////////////////////////////////////////////////////
+// Element routines
+//////////////////////////////////////////////////////////////////////////////
+static void *ElementAt(Allocation *a, RsDataType dt, uint32_t vecSize,
+ uint32_t x, uint32_t y, uint32_t z) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ const Type *t = a->getType();
+ const Element *e = t->getElement();
+
+ char buf[256];
+ if (x && (x >= t->getLODDimX(0))) {
+ snprintf(buf, sizeof(buf), "Out range ElementAt X %i of %i", x,
+ t->getLODDimX(0));
+ rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+ return nullptr;
+ }
+
+ if (y && (y >= t->getLODDimY(0))) {
+ snprintf(buf, sizeof(buf), "Out range ElementAt Y %i of %i", y,
+ t->getLODDimY(0));
+ rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+ return nullptr;
+ }
+
+ if (z && (z >= t->getLODDimZ(0))) {
+ snprintf(buf, sizeof(buf), "Out range ElementAt Z %i of %i", z,
+ t->getLODDimZ(0));
+ rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+ return nullptr;
+ }
+
+ if (vecSize > 0) {
+ if (vecSize != e->getVectorSize()) {
+ snprintf(buf, sizeof(buf), "Vector size mismatch for ElementAt %i of %i",
+ vecSize, e->getVectorSize());
+ rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+ return nullptr;
+ }
+
+ if (dt != e->getType()) {
+ snprintf(buf, sizeof(buf), "Data type mismatch for ElementAt %i of %i",
+ dt, e->getType());
+ rsc->setError(RS_ERROR_FATAL_DEBUG, buf);
+ return nullptr;
+ }
+ }
+
+ uint8_t *p = (uint8_t *)a->mHal.drvState.lod[0].mallocPtr;
+ const uint32_t eSize = e->getSizeBytes();
+ const uint32_t stride = a->mHal.drvState.lod[0].stride;
+ const uint32_t dimY = a->mHal.drvState.lod[0].dimY;
+ return &p[(x * eSize) + (y * stride) + (z * stride * dimY)];
+}
+
+void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x, uint32_t y,
+ uint32_t z) {
+ const Type *t = const_cast<Allocation *>((Allocation *)a.p)->getType();
+ const Element *e = t->getElement();
+ void *tmp = ElementAt((Allocation *)a.p, RS_TYPE_UNSIGNED_8, 0, x, y, z);
+ if (tmp != nullptr) memcpy(tmp, ptr, e->getSizeBytes());
+}
+
+void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x,
+ uint32_t y) {
+ rsSetElementAt(a, ptr, x, y, 0);
+}
+
+void rsSetElementAt(::rs_allocation a, const void *ptr, uint32_t x) {
+ rsSetElementAt(a, ptr, x, 0, 0);
+}
+
+const void *rsGetElementAt(::rs_allocation a, uint32_t x, uint32_t y,
+ uint32_t z) {
+ return ElementAt((Allocation *)a.p, RS_TYPE_UNSIGNED_8, 0, x, y, z);
+}
+
+const void *rsGetElementAt(::rs_allocation a, uint32_t x, uint32_t y) {
+ return rsGetElementAt(a, x, y, 0);
+}
+
+const void *rsGetElementAt(::rs_allocation a, uint32_t x) {
+ return rsGetElementAt(a, x, 0, 0);
+}
+
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#define ELEMENT_AT(T, DT, VS) \
+ void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x, \
+ uint32_t y, uint32_t z) { \
+ void *r = ElementAt((Allocation *)a.p, DT, VS, x, y, z); \
+ if (r != nullptr) \
+ ((T *)r)[0] = *val; \
+ else \
+ ALOGE("Error from %s", __PRETTY_FUNCTION__); \
+ } \
+ void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x, \
+ uint32_t y) { \
+ rsSetElementAt_##T(a, val, x, y, 0); \
+ } \
+ void rsSetElementAt_##T(::rs_allocation a, const T *val, uint32_t x) { \
+ rsSetElementAt_##T(a, val, x, 0, 0); \
+ } \
+ void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x, uint32_t y, \
+ uint32_t z) { /*NOLINT*/ \
+ void *r = ElementAt((Allocation *)a.p, DT, VS, x, y, z); \
+ if (r != nullptr) \
+ *val = ((T *)r)[0]; \
+ else \
+ ALOGE("Error from %s", __PRETTY_FUNCTION__); \
+ } \
+ void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x, \
+ uint32_t y) { /*NOLINT*/ \
+ rsGetElementAt_##T(a, val, x, y, 0); \
+ } \
+ void rsGetElementAt_##T(::rs_allocation a, T *val, uint32_t x) { /*NOLINT*/ \
+ rsGetElementAt_##T(a, val, x, 0, 0); \
+ }
+
+ELEMENT_AT(char, RS_TYPE_SIGNED_8, 1)
+ELEMENT_AT(char2, RS_TYPE_SIGNED_8, 2)
+ELEMENT_AT(char3, RS_TYPE_SIGNED_8, 3)
+ELEMENT_AT(char4, RS_TYPE_SIGNED_8, 4)
+ELEMENT_AT(uchar, RS_TYPE_UNSIGNED_8, 1)
+ELEMENT_AT(uchar2, RS_TYPE_UNSIGNED_8, 2)
+ELEMENT_AT(uchar3, RS_TYPE_UNSIGNED_8, 3)
+ELEMENT_AT(uchar4, RS_TYPE_UNSIGNED_8, 4)
+ELEMENT_AT(short, RS_TYPE_SIGNED_16, 1)
+ELEMENT_AT(short2, RS_TYPE_SIGNED_16, 2)
+ELEMENT_AT(short3, RS_TYPE_SIGNED_16, 3)
+ELEMENT_AT(short4, RS_TYPE_SIGNED_16, 4)
+ELEMENT_AT(ushort, RS_TYPE_UNSIGNED_16, 1)
+ELEMENT_AT(ushort2, RS_TYPE_UNSIGNED_16, 2)
+ELEMENT_AT(ushort3, RS_TYPE_UNSIGNED_16, 3)
+ELEMENT_AT(ushort4, RS_TYPE_UNSIGNED_16, 4)
+ELEMENT_AT(int, RS_TYPE_SIGNED_32, 1)
+ELEMENT_AT(int2, RS_TYPE_SIGNED_32, 2)
+ELEMENT_AT(int3, RS_TYPE_SIGNED_32, 3)
+ELEMENT_AT(int4, RS_TYPE_SIGNED_32, 4)
+ELEMENT_AT(uint, RS_TYPE_UNSIGNED_32, 1)
+ELEMENT_AT(uint2, RS_TYPE_UNSIGNED_32, 2)
+ELEMENT_AT(uint3, RS_TYPE_UNSIGNED_32, 3)
+ELEMENT_AT(uint4, RS_TYPE_UNSIGNED_32, 4)
+ELEMENT_AT(long, RS_TYPE_SIGNED_64, 1)
+ELEMENT_AT(long2, RS_TYPE_SIGNED_64, 2)
+ELEMENT_AT(long3, RS_TYPE_SIGNED_64, 3)
+ELEMENT_AT(long4, RS_TYPE_SIGNED_64, 4)
+ELEMENT_AT(ulong, RS_TYPE_UNSIGNED_64, 1)
+ELEMENT_AT(ulong2, RS_TYPE_UNSIGNED_64, 2)
+ELEMENT_AT(ulong3, RS_TYPE_UNSIGNED_64, 3)
+ELEMENT_AT(ulong4, RS_TYPE_UNSIGNED_64, 4)
+ELEMENT_AT(half, RS_TYPE_FLOAT_16, 1)
+ELEMENT_AT(half2, RS_TYPE_FLOAT_16, 2)
+ELEMENT_AT(half3, RS_TYPE_FLOAT_16, 3)
+ELEMENT_AT(half4, RS_TYPE_FLOAT_16, 4)
+ELEMENT_AT(float, RS_TYPE_FLOAT_32, 1)
+ELEMENT_AT(float2, RS_TYPE_FLOAT_32, 2)
+ELEMENT_AT(float3, RS_TYPE_FLOAT_32, 3)
+ELEMENT_AT(float4, RS_TYPE_FLOAT_32, 4)
+ELEMENT_AT(double, RS_TYPE_FLOAT_64, 1)
+ELEMENT_AT(double2, RS_TYPE_FLOAT_64, 2)
+ELEMENT_AT(double3, RS_TYPE_FLOAT_64, 3)
+ELEMENT_AT(double4, RS_TYPE_FLOAT_64, 4)
+
+#undef ELEMENT_AT
+
+#ifndef __LP64__
+/*
+ * We miss some symbols for rs{Get,Set}Element_long,ulong variants because 64
+ * bit integer values are 'long' in RS-land but might be 'long long' in the
+ * driver. Define native_long* and native_ulong* types to be vectors of
+ * 'long' as seen by the driver and define overloaded versions of
+ * rsSetElementAt_* and rsGetElementAt_*. This should get us the correct
+ * mangled names in the driver.
+ */
+
+typedef long native_long2 __attribute__((ext_vector_type(2)));
+typedef long native_long3 __attribute__((ext_vector_type(3)));
+typedef long native_long4 __attribute__((ext_vector_type(4)));
+typedef unsigned long native_ulong2 __attribute__((ext_vector_type(2)));
+typedef unsigned long native_ulong3 __attribute__((ext_vector_type(3)));
+typedef unsigned long native_ulong4 __attribute__((ext_vector_type(4)));
+
+// Add NOLINT to suppress wrong warnings from clang-tidy.
+#define ELEMENT_AT_OVERLOADS(T, U) \
+ void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x, \
+ uint32_t y, uint32_t z) { \
+ rsSetElementAt_##T(a, (T *)val, x, y, z); \
+ } \
+ void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x, \
+ uint32_t y) { \
+ rsSetElementAt_##T(a, (T *)val, x, y, 0); \
+ } \
+ void rsSetElementAt_##T(::rs_allocation a, const U *val, uint32_t x) { \
+ rsSetElementAt_##T(a, (T *)val, x, 0, 0); \
+ } \
+ void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x, uint32_t y, \
+ uint32_t z) { /*NOLINT*/ \
+ rsGetElementAt_##T(a, (T *)val, x, y, z); \
+ } \
+ void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x, \
+ uint32_t y) { /*NOLINT*/ \
+ rsGetElementAt_##T(a, (T *)val, x, y, 0); \
+ } \
+ void rsGetElementAt_##T(::rs_allocation a, U *val, uint32_t x) { /*NOLINT*/ \
+ rsGetElementAt_##T(a, (T *)val, x, 0, 0); \
+ }
+
+ELEMENT_AT_OVERLOADS(long2, native_long2)
+ELEMENT_AT_OVERLOADS(long3, native_long3)
+ELEMENT_AT_OVERLOADS(long4, native_long4)
+ELEMENT_AT_OVERLOADS(ulong, unsigned long)
+ELEMENT_AT_OVERLOADS(ulong2, native_ulong2)
+ELEMENT_AT_OVERLOADS(ulong3, native_ulong3)
+ELEMENT_AT_OVERLOADS(ulong4, native_ulong4)
+
+// We also need variants of rs{Get,Set}ElementAt_long that take 'long long *' as
+// we might have this overloaded variant in old APKs.
+ELEMENT_AT_OVERLOADS(long, long long)
+
+#undef ELEMENT_AT_OVERLOADS
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// ForEach routines
+//////////////////////////////////////////////////////////////////////////////
+void rsForEachInternal(int slot, rs_script_call *options, int hasOutput,
+ int numInputs, ::rs_allocation *allocs) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ Script *s = const_cast<Script *>(RsdCpuReference::getTlsScript());
+ if (numInputs > RS_KERNEL_MAX_ARGUMENTS) {
+ rsc->setError(RS_ERROR_BAD_SCRIPT,
+ "rsForEachInternal: too many inputs to a kernel.");
+ return;
+ }
+ Allocation *inputs[RS_KERNEL_MAX_ARGUMENTS];
+ for (int i = 0; i < numInputs; i++) {
+ inputs[i] = (Allocation *)allocs[i].p;
+ }
+ Allocation *out = hasOutput ? (Allocation *)allocs[numInputs].p : nullptr;
+ rsrForEach(rsc, s, slot, numInputs, numInputs > 0 ? inputs : nullptr, out,
+ nullptr, 0, (RsScriptCall *)options);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+ const void *usr, const rs_script_call *call) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+ (Allocation *)out.p, usr, 0, (RsScriptCall *)call);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+ const void *usr) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+ (Allocation *)out.p, usr, 0, nullptr);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+ (Allocation *)out.p, nullptr, 0, nullptr);
+}
+
+// These functions are only supported in 32-bit.
+#ifndef __LP64__
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+ const void *usr, uint32_t usrLen) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+ (Allocation *)out.p, usr, usrLen, nullptr);
+}
+
+void __attribute__((overloadable))
+rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out,
+ const void *usr, uint32_t usrLen, const rs_script_call *call) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ rsrForEach(rsc, (Script *)script.p, 0, 1, (Allocation **)&in.p,
+ (Allocation *)out.p, usr, usrLen, (RsScriptCall *)call);
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Message routines
+//////////////////////////////////////////////////////////////////////////////
+uint32_t rsSendToClient(int cmdID) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return rsrToClient(rsc, cmdID, (const void *)nullptr, 0);
+}
+
+uint32_t rsSendToClient(int cmdID, const void *data, uint32_t len) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return rsrToClient(rsc, cmdID, data, len);
+}
+
+uint32_t rsSendToClientBlocking(int cmdID) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return rsrToClientBlocking(rsc, cmdID, (const void *)nullptr, 0);
+}
+
+uint32_t rsSendToClientBlocking(int cmdID, const void *data, uint32_t len) {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return rsrToClientBlocking(rsc, cmdID, data, len);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Time routines
+//////////////////////////////////////////////////////////////////////////////
+
+// time_t is int in 32-bit RenderScript. time_t is long in bionic. rsTime and
+// rsLocaltime are set to explicitly take 'const int *' so we generate the
+// correct mangled names.
+#ifndef __LP64__
+int rsTime(int *timer) {
+#else
+time_t rsTime(time_t *timer) {
+#endif
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return rsrTime(rsc, (time_t *)timer);
+}
+
+#ifndef __LP64__
+rs_tm *rsLocaltime(rs_tm *local, const int *timer) {
+#else
+rs_tm *rsLocaltime(rs_tm *local, const time_t *timer) {
+#endif
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return (rs_tm *)rsrLocalTime(rsc, (tm *)local, (time_t *)timer);
+}
+
+int64_t rsUptimeMillis() {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return rsrUptimeMillis(rsc);
+}
+
+int64_t rsUptimeNanos() {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ return rsrUptimeNanos(rsc);
+}
+
+float rsGetDt() {
+ Context *rsc = RsdCpuReference::getTlsContext();
+ const Script *sc = RsdCpuReference::getTlsScript();
+ return rsrGetDt(rsc, sc);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Debug routines
+//////////////////////////////////////////////////////////////////////////////
+void rsDebug(const char *s, float f) {
+ ALOGD("%s %f, 0x%08x", s, f, *((int *)(&f)));
+}
+
+void rsDebug(const char *s, float f1, float f2) {
+ ALOGD("%s {%f, %f}", s, f1, f2);
+}
+
+void rsDebug(const char *s, float f1, float f2, float f3) {
+ ALOGD("%s {%f, %f, %f}", s, f1, f2, f3);
+}
+
+void rsDebug(const char *s, float f1, float f2, float f3, float f4) {
+ ALOGD("%s {%f, %f, %f, %f}", s, f1, f2, f3, f4);
+}
+
+void rsDebug(const char *s, const float2 *f2) {
+ float2 f = *f2;
+ ALOGD("%s {%f, %f}", s, f.x, f.y);
+}
+
+void rsDebug(const char *s, const float3 *f3) {
+ float3 f = *f3;
+ ALOGD("%s {%f, %f, %f}", s, f.x, f.y, f.z);
+}
+
+void rsDebug(const char *s, const float4 *f4) {
+ float4 f = *f4;
+ ALOGD("%s {%f, %f, %f, %f}", s, f.x, f.y, f.z, f.w);
+}
+
+// Accept a half value converted to float. This eliminates the need in the
+// driver to properly support the half datatype (either by adding compiler flags
+// for half or link against compiler_rt).
+void rsDebug(const char *s, float f, ushort us) {
+ ALOGD("%s {%f} {0x%hx}", s, f, us);
+}
+
+void rsDebug(const char *s, const float2 *f2, const ushort2 *us2) {
+ float2 f = *f2;
+ ushort2 us = *us2;
+ ALOGD("%s {%f %f} {0x%hx 0x%hx}", s, f.x, f.y, us.x, us.y);
+}
+
+void rsDebug(const char *s, const float3 *f3, const ushort3 *us3) {
+ float3 f = *f3;
+ ushort3 us = *us3;
+ ALOGD("%s {%f %f %f} {0x%hx 0x%hx 0x%hx}", s, f.x, f.y, f.z, us.x, us.y,
+ us.z);
+}
+
+void rsDebug(const char *s, const float4 *f4, const ushort4 *us4) {
+ float4 f = *f4;
+ ushort4 us = *us4;
+ ALOGD("%s {%f %f %f %f} {0x%hx 0x%hx 0x%hx 0x%hx}", s, f.x, f.y, f.z, f.w,
+ us.x, us.y, us.z, us.w);
+}
+
+void rsDebug(const char *s, double d) {
+ ALOGD("%s %f, 0x%08llx", s, d, *((long long *)(&d)));
+}
+
+void rsDebug(const char *s, const double2 *d2) {
+ double2 d = *d2;
+ ALOGD("%s {%f, %f}", s, d.x, d.y);
+}
+
+void rsDebug(const char *s, const double3 *d3) {
+ double3 d = *d3;
+ ALOGD("%s {%f, %f, %f}", s, d.x, d.y, d.z);
+}
+
+void rsDebug(const char *s, const double4 *d4) {
+ double4 d = *d4;
+ ALOGD("%s {%f, %f, %f, %f}", s, d.x, d.y, d.z, d.w);
+}
+
+void rsDebug(const char *s, const rs_matrix4x4 *m) {
+ float *f = (float *)m;
+ ALOGD("%s {%f, %f, %f, %f", s, f[0], f[4], f[8], f[12]);
+ ALOGD("%s %f, %f, %f, %f", s, f[1], f[5], f[9], f[13]);
+ ALOGD("%s %f, %f, %f, %f", s, f[2], f[6], f[10], f[14]);
+ ALOGD("%s %f, %f, %f, %f}", s, f[3], f[7], f[11], f[15]);
+}
+
+void rsDebug(const char *s, const rs_matrix3x3 *m) {
+ float *f = (float *)m;
+ ALOGD("%s {%f, %f, %f", s, f[0], f[3], f[6]);
+ ALOGD("%s %f, %f, %f", s, f[1], f[4], f[7]);
+ ALOGD("%s %f, %f, %f}", s, f[2], f[5], f[8]);
+}
+
+void rsDebug(const char *s, const rs_matrix2x2 *m) {
+ float *f = (float *)m;
+ ALOGD("%s {%f, %f", s, f[0], f[2]);
+ ALOGD("%s %f, %f}", s, f[1], f[3]);
+}
+
+void rsDebug(const char *s, char c) {
+ ALOGD("%s %hhd 0x%hhx", s, c, (unsigned char)c);
+}
+
+void rsDebug(const char *s, const char2 *c2) {
+ char2 c = *c2;
+ ALOGD("%s {%hhd, %hhd} 0x%hhx 0x%hhx", s, c.x, c.y, (unsigned char)c.x,
+ (unsigned char)c.y);
+}
+
+void rsDebug(const char *s, const char3 *c3) {
+ char3 c = *c3;
+ ALOGD("%s {%hhd, %hhd, %hhd} 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y, c.z,
+ (unsigned char)c.x, (unsigned char)c.y, (unsigned char)c.z);
+}
+
+void rsDebug(const char *s, const char4 *c4) {
+ char4 c = *c4;
+ ALOGD("%s {%hhd, %hhd, %hhd, %hhd} 0x%hhx 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y,
+ c.z, c.w, (unsigned char)c.x, (unsigned char)c.y, (unsigned char)c.z,
+ (unsigned char)c.w);
+}
+
+void rsDebug(const char *s, unsigned char c) {
+ ALOGD("%s %hhu 0x%hhx", s, c, c);
+}
+
+void rsDebug(const char *s, const uchar2 *c2) {
+ uchar2 c = *c2;
+ ALOGD("%s {%hhu, %hhu} 0x%hhx 0x%hhx", s, c.x, c.y, c.x, c.y);
+}
+
+void rsDebug(const char *s, const uchar3 *c3) {
+ uchar3 c = *c3;
+ ALOGD("%s {%hhu, %hhu, %hhu} 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y, c.z, c.x,
+ c.y, c.z);
+}
+
+void rsDebug(const char *s, const uchar4 *c4) {
+ uchar4 c = *c4;
+ ALOGD("%s {%hhu, %hhu, %hhu, %hhu} 0x%hhx 0x%hhx 0x%hhx 0x%hhx", s, c.x, c.y,
+ c.z, c.w, c.x, c.y, c.z, c.w);
+}
+
+void rsDebug(const char *s, short c) { ALOGD("%s %hd 0x%hx", s, c, c); }
+
+void rsDebug(const char *s, const short2 *c2) {
+ short2 c = *c2;
+ ALOGD("%s {%hd, %hd} 0x%hx 0x%hx", s, c.x, c.y, c.x, c.y);
+}
+
+void rsDebug(const char *s, const short3 *c3) {
+ short3 c = *c3;
+ ALOGD("%s {%hd, %hd, %hd} 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z, c.x, c.y,
+ c.z);
+}
+
+void rsDebug(const char *s, const short4 *c4) {
+ short4 c = *c4;
+ ALOGD("%s {%hd, %hd, %hd, %hd} 0x%hx 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z,
+ c.w, c.x, c.y, c.z, c.w);
+}
+
+void rsDebug(const char *s, unsigned short c) {
+ ALOGD("%s %hu 0x%hx", s, c, c);
+}
+
+void rsDebug(const char *s, const ushort2 *c2) {
+ ushort2 c = *c2;
+ ALOGD("%s {%hu, %hu} 0x%hx 0x%hx", s, c.x, c.y, c.x, c.y);
+}
+
+void rsDebug(const char *s, const ushort3 *c3) {
+ ushort3 c = *c3;
+ ALOGD("%s {%hu, %hu, %hu} 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z, c.x, c.y,
+ c.z);
+}
+
+void rsDebug(const char *s, const ushort4 *c4) {
+ ushort4 c = *c4;
+ ALOGD("%s {%hu, %hu, %hu, %hu} 0x%hx 0x%hx 0x%hx 0x%hx", s, c.x, c.y, c.z,
+ c.w, c.x, c.y, c.z, c.w);
+}
+
+void rsDebug(const char *s, int i) { ALOGD("%s %d 0x%x", s, i, i); }
+
+void rsDebug(const char *s, const int2 *i2) {
+ int2 i = *i2;
+ ALOGD("%s {%d, %d} 0x%x 0x%x", s, i.x, i.y, i.x, i.y);
+}
+
+void rsDebug(const char *s, const int3 *i3) {
+ int3 i = *i3;
+ ALOGD("%s {%d, %d, %d} 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.x, i.y, i.z);
+}
+
+void rsDebug(const char *s, const int4 *i4) {
+ int4 i = *i4;
+ ALOGD("%s {%d, %d, %d, %d} 0x%x 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.w, i.x,
+ i.y, i.z, i.w);
+}
+
+void rsDebug(const char *s, unsigned int i) { ALOGD("%s %u 0x%x", s, i, i); }
+
+void rsDebug(const char *s, const uint2 *i2) {
+ uint2 i = *i2;
+ ALOGD("%s {%u, %u} 0x%x 0x%x", s, i.x, i.y, i.x, i.y);
+}
+
+void rsDebug(const char *s, const uint3 *i3) {
+ uint3 i = *i3;
+ ALOGD("%s {%u, %u, %u} 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.x, i.y, i.z);
+}
+
+void rsDebug(const char *s, const uint4 *i4) {
+ uint4 i = *i4;
+ ALOGD("%s {%u, %u, %u, %u} 0x%x 0x%x 0x%x 0x%x", s, i.x, i.y, i.z, i.w, i.x,
+ i.y, i.z, i.w);
+}
+
+template <typename T>
+static inline long long LL(const T &x) {
+ return static_cast<long long>(x);
+}
+
+template <typename T>
+static inline unsigned long long LLu(const T &x) {
+ return static_cast<unsigned long long>(x);
+}
+
+void rsDebug(const char *s, long l) {
+ ALOGD("%s %lld 0x%llx", s, LL(l), LL(l));
+}
+
+void rsDebug(const char *s, long long ll) {
+ ALOGD("%s %lld 0x%llx", s, LL(ll), LL(ll));
+}
+
+void rsDebug(const char *s, const long2 *c) {
+ long2 ll = *c;
+ ALOGD("%s {%lld, %lld} 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
+ LL(ll.y));
+}
+
+void rsDebug(const char *s, const long3 *c) {
+ long3 ll = *c;
+ ALOGD("%s {%lld, %lld, %lld} 0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
+ LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
+}
+
+void rsDebug(const char *s, const long4 *c) {
+ long4 ll = *c;
+ ALOGD("%s {%lld, %lld, %lld, %lld} 0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
+ LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
+}
+
+void rsDebug(const char *s, unsigned long l) {
+ unsigned long long ll = l;
+ ALOGD("%s %llu 0x%llx", s, ll, ll);
+}
+
+void rsDebug(const char *s, unsigned long long ll) {
+ ALOGD("%s %llu 0x%llx", s, ll, ll);
+}
+
+void rsDebug(const char *s, const ulong2 *c) {
+ ulong2 ll = *c;
+ ALOGD("%s {%llu, %llu} 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
+ LLu(ll.y));
+}
+
+void rsDebug(const char *s, const ulong3 *c) {
+ ulong3 ll = *c;
+ ALOGD("%s {%llu, %llu, %llu} 0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
+ LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
+}
+
+void rsDebug(const char *s, const ulong4 *c) {
+ ulong4 ll = *c;
+ ALOGD("%s {%llu, %llu, %llu, %llu} 0x%llx 0x%llx 0x%llx 0x%llx", s,
+ LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
+ LLu(ll.z), LLu(ll.w));
+}
+
+// FIXME: We need to export these function signatures for the compatibility
+// library. The C++ name mangling that LLVM uses for ext_vector_type requires
+// different versions for "long" vs. "long long". Note that the called
+// functions are still using the appropriate 64-bit sizes.
+
+#ifndef __LP64__
+typedef long l2 __attribute__((ext_vector_type(2)));
+typedef long l3 __attribute__((ext_vector_type(3)));
+typedef long l4 __attribute__((ext_vector_type(4)));
+typedef unsigned long ul2 __attribute__((ext_vector_type(2)));
+typedef unsigned long ul3 __attribute__((ext_vector_type(3)));
+typedef unsigned long ul4 __attribute__((ext_vector_type(4)));
+
+void rsDebug(const char *s, const l2 *c) {
+ long2 ll = *(const long2 *)c;
+ ALOGD("%s {%lld, %lld} 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
+ LL(ll.y));
+}
+
+void rsDebug(const char *s, const l3 *c) {
+ long3 ll = *(const long3 *)c;
+ ALOGD("%s {%lld, %lld, %lld} 0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
+ LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
+}
+
+void rsDebug(const char *s, const l4 *c) {
+ long4 ll = *(const long4 *)c;
+ ALOGD("%s {%lld, %lld, %lld, %lld} 0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
+ LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
+}
+
+void rsDebug(const char *s, const ul2 *c) {
+ ulong2 ll = *(const ulong2 *)c;
+ ALOGD("%s {%llu, %llu} 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
+ LLu(ll.y));
+}
+
+void rsDebug(const char *s, const ul3 *c) {
+ ulong3 ll = *(const ulong3 *)c;
+ ALOGD("%s {%llu, %llu, %llu} 0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
+ LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
+}
+
+void rsDebug(const char *s, const ul4 *c) {
+ ulong4 ll = *(const ulong4 *)c;
+ ALOGD("%s {%llu, %llu, %llu, %llu} 0x%llx 0x%llx 0x%llx 0x%llx", s,
+ LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
+ LLu(ll.z), LLu(ll.w));
+}
+#endif
+
+void rsDebug(const char *s, const long2 ll) {
+ ALOGD("%s {%lld, %lld} 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y), LL(ll.x),
+ LL(ll.y));
+}
+
+void rsDebug(const char *s, const long3 ll) {
+ ALOGD("%s {%lld, %lld, %lld} 0x%llx 0x%llx 0x%llx", s, LL(ll.x), LL(ll.y),
+ LL(ll.z), LL(ll.x), LL(ll.y), LL(ll.z));
+}
+
+void rsDebug(const char *s, const long4 ll) {
+ ALOGD("%s {%lld, %lld, %lld, %lld} 0x%llx 0x%llx 0x%llx 0x%llx", s, LL(ll.x),
+ LL(ll.y), LL(ll.z), LL(ll.w), LL(ll.x), LL(ll.y), LL(ll.z), LL(ll.w));
+}
+
+void rsDebug(const char *s, const ulong2 ll) {
+ ALOGD("%s {%llu, %llu} 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y), LLu(ll.x),
+ LLu(ll.y));
+}
+
+void rsDebug(const char *s, const ulong3 ll) {
+ ALOGD("%s {%llu, %llu, %llu} 0x%llx 0x%llx 0x%llx", s, LLu(ll.x), LLu(ll.y),
+ LLu(ll.z), LLu(ll.x), LLu(ll.y), LLu(ll.z));
+}
+
+void rsDebug(const char *s, const ulong4 ll) {
+ ALOGD("%s {%llu, %llu, %llu, %llu} 0x%llx 0x%llx 0x%llx 0x%llx", s,
+ LLu(ll.x), LLu(ll.y), LLu(ll.z), LLu(ll.w), LLu(ll.x), LLu(ll.y),
+ LLu(ll.z), LLu(ll.w));
+}
+
+void rsDebug(const char *s, const void *p) { ALOGD("%s %p", s, p); }
diff --git a/rsov/driver/rsovSampler.cpp b/rsov/driver/rsovSampler.cpp
new file mode 100644
index 00000000..0857c6ee
--- /dev/null
+++ b/rsov/driver/rsovSampler.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovSampler.h"
+
+#include "rsContext.h"
+
+using android::renderscript::Context;
+using android::renderscript::Sampler;
+using android::renderscript::rs_sampler;
+
+bool rsovSamplerInit(const Context *rsc, const Sampler *s) { return true; }
+
+void rsovSamplerDestroy(const Context *rsc, const Sampler *s) {}
+
+void rsovSamplerUpdateCachedObject(const Context *rsc, const Sampler *alloc,
+ rs_sampler *obj) {
+ obj->p = alloc;
+#ifdef __LP64__
+ obj->r = nullptr;
+ if (alloc != nullptr) {
+ obj->v1 = alloc->mHal.drv;
+ } else {
+ obj->v1 = nullptr;
+ }
+ obj->v2 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovSampler.h b/rsov/driver/rsovSampler.h
new file mode 100644
index 00000000..9b8112ca
--- /dev/null
+++ b/rsov/driver/rsovSampler.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_SAMPLER_H
+#define RSOV_SAMPLER_H
+
+#include "rs_hal.h"
+
+extern bool rsovSamplerInit(const android::renderscript::Context *rsc,
+ const android::renderscript::Sampler *);
+
+extern void rsovSamplerDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Sampler *);
+
+extern void rsovSamplerUpdateCachedObject(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Sampler *,
+ android::renderscript::rs_sampler *obj);
+
+#endif // RSD_SAMPLER_H
diff --git a/rsov/driver/rsovScript.cpp b/rsov/driver/rsovScript.cpp
new file mode 100644
index 00000000..2d0fa250
--- /dev/null
+++ b/rsov/driver/rsovScript.cpp
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovScript.h"
+
+#include <fstream>
+
+#include "rsContext.h"
+#include "rsType.h"
+#include "rsUtils.h"
+#include "rsovAllocation.h"
+#include "rsovContext.h"
+#include "rsovCore.h"
+
+namespace android {
+namespace renderscript {
+namespace rsov {
+
+namespace {
+
+const char *COMPILER_EXE_PATH = "/system/bin/bcc_rsov";
+
+std::vector<const char *> setCompilerArgs(const char *bcFileName,
+ const char *cacheDir) {
+ rsAssert(bcFileName && cacheDir);
+
+ std::vector<const char *> args;
+
+ args.push_back(COMPILER_EXE_PATH);
+ args.push_back(bcFileName);
+
+ args.push_back(nullptr);
+ return args;
+}
+
+void writeBytes(const char *filename, const char *bytes, size_t size) {
+ std::ofstream ofs(filename, std::ios::binary);
+ ofs.write(bytes, size);
+ ofs.close();
+}
+
+std::vector<uint32_t> readWords(const char *filename) {
+ std::ifstream ifs(filename, std::ios::binary);
+
+ ifs.seekg(0, ifs.end);
+ int length = ifs.tellg();
+ ifs.seekg(0, ifs.beg);
+
+ rsAssert(((length & 3) == 0) && "File size expected to be multiples of 4");
+
+ std::vector<uint32_t> spvWords(length / sizeof(uint32_t));
+
+ ifs.read((char *)(spvWords.data()), length);
+
+ ifs.close();
+
+ return spvWords;
+}
+
+std::vector<uint32_t> compileBitcode(const char *resName, const char *cacheDir,
+ const char *bitcode, size_t bitcodeSize) {
+ rsAssert(bitcode && bitcodeSize);
+
+ // TODO: Cache the generated code
+
+ std::string bcFileName(cacheDir);
+ bcFileName.append("/");
+ bcFileName.append(resName);
+ bcFileName.append(".bc");
+
+ writeBytes(bcFileName.c_str(), bitcode, bitcodeSize);
+
+ auto args = setCompilerArgs(bcFileName.c_str(), cacheDir);
+
+ if (!rsuExecuteCommand(COMPILER_EXE_PATH, args.size() - 1, args.data())) {
+ ALOGE("compiler command line failed");
+ return std::vector<uint32_t>();
+ }
+
+ ALOGV("compiler command line succeeded");
+
+ std::string spvFileName(cacheDir);
+ spvFileName.append("/");
+ spvFileName.append(resName);
+ spvFileName.append(".spv");
+
+ return readWords(spvFileName.c_str());
+}
+
+} // anonymous namespace
+
+RSoVScript::RSoVScript(RSoVContext *context, std::vector<uint32_t> &&spvWords)
+ : mRSoV(context),
+ mDevice(context->getDevice()),
+ mSPIRVWords(std::move(spvWords)) {}
+
+RSoVScript::~RSoVScript() {
+ delete mCpuScript;
+ // TODO: destroy shader
+}
+
+void RSoVScript::populateScript(Script *) {
+ // TODO: implement this
+}
+
+void RSoVScript::invokeFunction(uint32_t slot, const void *params,
+ size_t paramLength) {
+ // TODO: implement this
+}
+
+int RSoVScript::invokeRoot() {
+ // TODO: implement this
+ return 0;
+}
+
+void RSoVScript::invokeForEach(uint32_t slot, const Allocation **ains,
+ uint32_t inLen, Allocation *aout,
+ const void *usr, uint32_t usrLen,
+ const RsScriptCall *sc) {
+ // TODO: Handle kernel without input Allocation
+ // TODO: Handle multi-input kernel
+ rsAssert(ains && inLen == 1);
+
+ RSoVAllocation *inputAllocation =
+ static_cast<RSoVAllocation *>(ains[0]->mHal.drv);
+ RSoVAllocation *outputAllocation =
+ static_cast<RSoVAllocation *>(aout->mHal.drv);
+ runForEach(inputAllocation, outputAllocation);
+}
+
+void RSoVScript::invokeReduce(uint32_t slot, const Allocation **ains,
+ uint32_t inLen, Allocation *aout,
+ const RsScriptCall *sc) {
+ // TODO: implement this
+}
+
+void RSoVScript::invokeInit() {
+ // TODO: implement this
+}
+
+void RSoVScript::invokeFreeChildren() {
+ // TODO: implement this
+}
+
+void RSoVScript::setGlobalVar(uint32_t slot, const void *data,
+ size_t dataLength) {
+ // TODO: implement this
+}
+
+void RSoVScript::getGlobalVar(uint32_t slot, void *data, size_t dataLength) {
+ // TODO: implement this
+}
+
+void RSoVScript::setGlobalVarWithElemDims(uint32_t slot, const void *data,
+ size_t dataLength, const Element *e,
+ const uint32_t *dims,
+ size_t dimLength) {
+ // TODO: implement this
+}
+
+void RSoVScript::setGlobalBind(uint32_t slot, Allocation *data) {
+ // TODO: implement this
+}
+
+void RSoVScript::setGlobalObj(uint32_t slot, ObjectBase *obj) {
+ // TODO: implement this
+}
+
+Allocation *RSoVScript::getAllocationForPointer(const void *ptr) const {
+ // TODO: implement this
+ return nullptr;
+}
+
+int RSoVScript::getGlobalEntries() const {
+ // TODO: implement this
+ return 0;
+}
+
+const char *RSoVScript::getGlobalName(int i) const {
+ // TODO: implement this
+ return nullptr;
+}
+
+const void *RSoVScript::getGlobalAddress(int i) const {
+ // TODO: implement this
+ return nullptr;
+}
+
+size_t RSoVScript::getGlobalSize(int i) const {
+ // TODO: implement this
+ return 0;
+}
+
+uint32_t RSoVScript::getGlobalProperties(int i) const {
+ // TODO: implement this
+ return 0;
+}
+
+void RSoVScript::InitDescriptorAndPipelineLayouts() {
+ VkDescriptorSetLayoutBinding layout_bindings[] = {
+ {
+ // In the current implementation, these are all STORAGE_IMAGEs
+ // TODO:
+ // 1) replace all images with buffers
+ // 2) based on usage, select either images or buffers
+ .binding = 0,
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ .descriptorCount = 1,
+ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
+ .pImmutableSamplers = nullptr,
+ },
+ {
+ .binding = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ .descriptorCount = 1,
+ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
+ .pImmutableSamplers = nullptr,
+ },
+#ifdef SUPPORT_GLOBAL_VARIABLES
+ {
+ .binding = 2,
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ .descriptorCount = 1,
+ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
+ .pImmutableSamplers = nullptr,
+ }
+#endif
+ };
+
+ VkDescriptorSetLayoutCreateInfo descriptor_layout = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .bindingCount = NELEM(layout_bindings),
+ .pBindings = layout_bindings,
+ };
+
+ VkResult res;
+
+ mDescLayout.resize(NUM_DESCRIPTOR_SETS);
+ res = vkCreateDescriptorSetLayout(mDevice, &descriptor_layout, NULL,
+ mDescLayout.data());
+ if (res != VK_SUCCESS) {
+ __android_log_print(ANDROID_LOG_ERROR, "ComputeTest",
+ "vkCreateDescriptorSetLayout() returns %d", res);
+ }
+ rsAssert(res == VK_SUCCESS);
+ /*
+ VkPushConstantRange pushConstantRange[] = { {
+ .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
+ .offset = 0,
+ .size = 16
+ } };
+ */
+ /* Now use the descriptor layout to create a pipeline layout */
+ VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {
+ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ .pNext = nullptr,
+ .pushConstantRangeCount = 0,
+ .pPushConstantRanges = nullptr,
+ .setLayoutCount = NUM_DESCRIPTOR_SETS,
+ .pSetLayouts = mDescLayout.data(),
+ };
+
+ res = vkCreatePipelineLayout(mDevice, &pPipelineLayoutCreateInfo, NULL,
+ &mPipelineLayout);
+ rsAssert(res == VK_SUCCESS);
+
+ ALOGV("%s succeeded.", __FUNCTION__);
+}
+
+void RSoVScript::InitShader() {
+ VkResult res;
+
+ mShaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ mShaderStage.pNext = nullptr;
+ mShaderStage.pSpecializationInfo = nullptr;
+ mShaderStage.flags = 0;
+ mShaderStage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
+ mShaderStage.pName = "main";
+
+ VkShaderModuleCreateInfo moduleCreateInfo = {
+ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .codeSize = mSPIRVWords.size() * sizeof(unsigned int),
+ .pCode = mSPIRVWords.data(),
+ };
+ res = vkCreateShaderModule(mDevice, &moduleCreateInfo, NULL,
+ &mShaderStage.module);
+ rsAssert(res == VK_SUCCESS);
+
+ ALOGV("%s succeeded.", __FUNCTION__);
+}
+
+void RSoVScript::InitDescriptorPool() {
+ /* DEPENDS on InitDescriptorAndPipelineLayouts() */
+
+ VkResult res;
+ VkDescriptorPoolSize type_count[] = {
+ // The current implementation uses STORAGE_IMAGE for all allocations
+ {
+ .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = 1,
+ },
+ {
+ .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = 1,
+ },
+#ifdef SUPPORT_GLOBAL_VARIABLES
+ {
+ .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .descriptorCount = 1,
+ }
+#endif
+ };
+
+ VkDescriptorPoolCreateInfo descriptor_pool = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ .pNext = nullptr,
+ .maxSets = 1,
+ .poolSizeCount = NELEM(type_count),
+ .pPoolSizes = type_count,
+ };
+
+ res = vkCreateDescriptorPool(mDevice, &descriptor_pool, NULL, &mDescPool);
+ rsAssert(res == VK_SUCCESS);
+
+ ALOGV("%s succeeded.", __FUNCTION__);
+}
+
+void RSoVScript::InitDescriptorSet(const RSoVAllocation *inputAllocation,
+ RSoVAllocation *outputAllocation) {
+ VkResult res;
+
+ VkDescriptorSetAllocateInfo alloc_info = {
+ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ .pNext = NULL,
+ .descriptorPool = mDescPool,
+ .descriptorSetCount = NUM_DESCRIPTOR_SETS,
+ .pSetLayouts = mDescLayout.data(),
+ };
+
+ mDescSet.resize(NUM_DESCRIPTOR_SETS);
+ res = vkAllocateDescriptorSets(mDevice, &alloc_info, mDescSet.data());
+ rsAssert(res == VK_SUCCESS);
+
+ const VkWriteDescriptorSet writes[] = {
+ {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = mDescSet[0],
+ .dstBinding = 0,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ .pImageInfo = inputAllocation->getImageInfo(),
+ },
+ {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = mDescSet[0],
+ .dstBinding = 1,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ .pImageInfo = outputAllocation->getImageInfo(),
+ },
+#ifdef SUPPORT_GLOBAL_VARIABLES
+ {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = mDescSet[0],
+ .dstBinding = 2,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ .pBufferInfo = somebuffer_info,
+ },
+#endif
+ };
+
+ vkUpdateDescriptorSets(mDevice, NELEM(writes), writes, 0, NULL);
+
+ ALOGV("%s succeeded.", __FUNCTION__);
+}
+
+void RSoVScript::InitPipeline() {
+ // DEPENDS on mShaderStage, i.e., InitShader()
+
+ VkResult res;
+
+ VkComputePipelineCreateInfo pipeline_info = {
+ .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ .pNext = nullptr,
+ .layout = mPipelineLayout,
+ .basePipelineHandle = VK_NULL_HANDLE,
+ .basePipelineIndex = 0,
+ .flags = 0,
+ .stage = mShaderStage,
+ };
+ res = vkCreateComputePipelines(mDevice, VK_NULL_HANDLE, 1, &pipeline_info,
+ NULL, &mComputePipeline);
+ rsAssert(res == VK_SUCCESS);
+
+ ALOGV("%s succeeded.", __FUNCTION__);
+}
+
+void RSoVScript::runForEach(const RSoVAllocation *inputAllocation,
+ RSoVAllocation *outputAllocation) {
+ VkResult res;
+
+ InitDescriptorAndPipelineLayouts();
+ InitShader();
+ InitDescriptorPool();
+ InitDescriptorSet(inputAllocation, outputAllocation);
+ // InitPipelineCache();
+ InitPipeline();
+
+ VkCommandBuffer cmd;
+
+ VkCommandBufferAllocateInfo cmd_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .commandPool = mRSoV->getCmdPool(),
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ .commandBufferCount = 1,
+ };
+
+ res = vkAllocateCommandBuffers(mDevice, &cmd_info, &cmd);
+ rsAssert(res == VK_SUCCESS);
+
+ VkCommandBufferBeginInfo cmd_buf_info = {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ .pInheritanceInfo = nullptr,
+ };
+
+ res = vkBeginCommandBuffer(cmd, &cmd_buf_info);
+ rsAssert(res == VK_SUCCESS);
+
+ vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, mComputePipeline);
+
+ vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, mPipelineLayout,
+ 0, mDescSet.size(), mDescSet.data(), 0, nullptr);
+
+ const uint32_t width = inputAllocation->getWidth();
+ const uint32_t height = rsMax(inputAllocation->getHeight(), 1U);
+ const uint32_t depth = rsMax(inputAllocation->getDepth(), 1U);
+ vkCmdDispatch(cmd, width, height, depth);
+
+ res = vkEndCommandBuffer(cmd);
+ assert(res == VK_SUCCESS);
+
+ VkSubmitInfo submit_info = {
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .commandBufferCount = 1,
+ .pCommandBuffers = &cmd,
+ };
+
+ VkFence fence;
+
+ VkFenceCreateInfo fenceInfo = {
+ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ .pNext = nullptr,
+ .flags = 0,
+ };
+
+ vkCreateFence(mDevice, &fenceInfo, NULL, &fence);
+
+ vkQueueSubmit(mRSoV->getQueue(), 1, &submit_info, fence);
+
+ // Make sure command buffer is finished
+ do {
+ res = vkWaitForFences(mDevice, 1, &fence, VK_TRUE, 100000);
+ } while (res == VK_TIMEOUT);
+
+ rsAssert(res == VK_SUCCESS);
+
+ vkDestroyFence(mDevice, fence, NULL);
+
+ // TODO: shall we reuse command buffers?
+ VkCommandBuffer cmd_bufs[] = {cmd};
+ vkFreeCommandBuffers(mDevice, mRSoV->getCmdPool(), 1, cmd_bufs);
+
+ vkDestroyPipeline(mDevice, mComputePipeline, nullptr);
+ for (int i = 0; i < NUM_DESCRIPTOR_SETS; i++)
+ vkDestroyDescriptorSetLayout(mDevice, mDescLayout[i], nullptr);
+ vkDestroyPipelineLayout(mDevice, mPipelineLayout, nullptr);
+ vkDestroyDescriptorPool(mDevice, mDescPool, nullptr);
+ vkDestroyShaderModule(mDevice, mShaderStage.module, nullptr);
+
+ ALOGV("%s succeeded.", __FUNCTION__);
+}
+
+} // namespace rsov
+} // namespace renderscript
+} // namespace android
+
+using android::renderscript::Allocation;
+using android::renderscript::Context;
+using android::renderscript::Element;
+using android::renderscript::ObjectBase;
+using android::renderscript::RsdCpuReference;
+using android::renderscript::Script;
+using android::renderscript::ScriptC;
+using android::renderscript::rs_script;
+using android::renderscript::rsov::RSoVContext;
+using android::renderscript::rsov::RSoVScript;
+using android::renderscript::rsov::compileBitcode;
+
+bool rsovScriptInit(const Context *rsc, ScriptC *script, char const *resName,
+ char const *cacheDir, uint8_t const *bitcode,
+ size_t bitcodeSize, uint32_t flags) {
+ std::vector<uint32_t> &&spvWords =
+ compileBitcode(resName, cacheDir, (const char *)bitcode, bitcodeSize);
+
+ if (spvWords.empty()) {
+ ALOGE("compilation failed for script %s", resName);
+ return false;
+ }
+
+ RSoVHal *hal = static_cast<RSoVHal *>(rsc->mHal.drv);
+ RSoVContext *rsov = hal->mRSoV;
+
+ std::unique_ptr<RsdCpuReference::CpuScript> cs(hal->mCpuRef->createScript(
+ script, resName, cacheDir, bitcode, bitcodeSize, flags));
+ if (cs == nullptr) {
+ return false;
+ }
+ cs->populateScript(script);
+
+ RSoVScript *rsovScript = new RSoVScript(rsov, std::move(spvWords));
+
+ if (!rsovScript) {
+ ALOGV("Failed creating a RSoV script");
+ // Uncomment below to choose CPU driver instead
+ // script->mHal.drv = cs;
+ return false;
+ }
+
+ rsovScript->setCpuScript(cs.release());
+ script->mHal.drv = rsovScript;
+
+ return true;
+}
+
+bool rsovInitIntrinsic(const Context *rsc, Script *s, RsScriptIntrinsicID iid,
+ Element *e) {
+ RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+ RsdCpuReference::CpuScript *cs = dc->mCpuRef->createIntrinsic(s, iid, e);
+ if (cs == nullptr) {
+ return false;
+ }
+ s->mHal.drv = cs;
+ cs->populateScript(s);
+ return true;
+}
+
+void rsovScriptInvokeForEach(const Context *rsc, Script *s, uint32_t slot,
+ const Allocation *ain, Allocation *aout,
+ const void *usr, size_t usrLen,
+ const RsScriptCall *sc) {
+ if (ain == nullptr) {
+ rsovScriptInvokeForEachMulti(rsc, s, slot, nullptr, 0, aout, usr, usrLen,
+ sc);
+ } else {
+ const Allocation *ains[1] = {ain};
+
+ rsovScriptInvokeForEachMulti(rsc, s, slot, ains, 1, aout, usr, usrLen, sc);
+ }
+}
+
+void rsovScriptInvokeForEachMulti(const Context *rsc, Script *s, uint32_t slot,
+ const Allocation **ains, size_t inLen,
+ Allocation *aout, const void *usr,
+ size_t usrLen, const RsScriptCall *sc) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->invokeForEach(slot, ains, inLen, aout, usr, usrLen, sc);
+}
+
+int rsovScriptInvokeRoot(const Context *dc, Script *s) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ return cs->invokeRoot();
+}
+
+void rsovScriptInvokeInit(const Context *dc, Script *s) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->invokeInit();
+}
+
+void rsovScriptInvokeFreeChildren(const Context *dc, Script *s) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->invokeFreeChildren();
+}
+
+void rsovScriptInvokeFunction(const Context *dc, Script *s, uint32_t slot,
+ const void *params, size_t paramLength) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->invokeFunction(slot, params, paramLength);
+}
+
+void rsovScriptInvokeReduce(const Context *dc, Script *s, uint32_t slot,
+ const Allocation **ains, size_t inLen,
+ Allocation *aout, const RsScriptCall *sc) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->invokeReduce(slot, ains, inLen, aout, sc);
+}
+
+void rsovScriptSetGlobalVar(const Context *dc, const Script *s, uint32_t slot,
+ void *data, size_t dataLength) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->setGlobalVar(slot, data, dataLength);
+}
+
+void rsovScriptGetGlobalVar(const Context *dc, const Script *s, uint32_t slot,
+ void *data, size_t dataLength) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->getGlobalVar(slot, data, dataLength);
+}
+
+void rsovScriptSetGlobalVarWithElemDims(
+ const Context *dc, const Script *s, uint32_t slot, void *data,
+ size_t dataLength, const android::renderscript::Element *elem,
+ const uint32_t *dims, size_t dimLength) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->setGlobalVarWithElemDims(slot, data, dataLength, elem, dims, dimLength);
+}
+
+void rsovScriptSetGlobalBind(const Context *dc, const Script *s, uint32_t slot,
+ Allocation *data) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->setGlobalBind(slot, data);
+}
+
+void rsovScriptSetGlobalObj(const Context *dc, const Script *s, uint32_t slot,
+ ObjectBase *data) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ cs->setGlobalObj(slot, data);
+}
+
+void rsovScriptDestroy(const Context *dc, Script *s) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)s->mHal.drv;
+ delete cs;
+ s->mHal.drv = nullptr;
+}
+
+Allocation *rsovScriptGetAllocationForPointer(
+ const android::renderscript::Context *dc,
+ const android::renderscript::Script *sc, const void *ptr) {
+ RsdCpuReference::CpuScript *cs = (RsdCpuReference::CpuScript *)sc->mHal.drv;
+ return cs->getAllocationForPointer(ptr);
+}
+
+void rsovScriptUpdateCachedObject(const Context *rsc, const Script *script,
+ rs_script *obj) {
+ obj->p = script;
+#ifdef __LP64__
+ obj->r = nullptr;
+ if (script != nullptr) {
+ obj->v1 = script->mHal.drv;
+ } else {
+ obj->v1 = nullptr;
+ }
+ obj->v2 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovScript.h b/rsov/driver/rsovScript.h
new file mode 100644
index 00000000..e9030d1c
--- /dev/null
+++ b/rsov/driver/rsovScript.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_SCRIPT_H
+#define RSOV_SCRIPT_H
+
+#include <vulkan/vulkan.h>
+
+#include <vector>
+
+#include "rsDefines.h"
+#include "rs_hal.h"
+#include "rsd_cpu.h"
+
+namespace android {
+namespace renderscript {
+
+class Allocation;
+class Context;
+class Element;
+class Script;
+class ScriptC;
+
+namespace rsov {
+
+class RSoVAllocation;
+class RSoVContext;
+
+// TODO: CpuScript is a bad name for the base class. Fix with a refactoring.
+class RSoVScript : RsdCpuReference::CpuScript {
+ public:
+ RSoVScript(RSoVContext *context, std::vector<uint32_t> &&spvWords);
+ RSoVScript(RSoVContext *context,
+ const std::vector<uint32_t> &spvWords) = delete;
+
+ virtual ~RSoVScript();
+
+ void populateScript(Script *) override;
+ void invokeFunction(uint32_t slot, const void *params,
+ size_t paramLength) override;
+ int invokeRoot() override;
+
+ void invokeForEach(uint32_t slot, const Allocation **ains, uint32_t inLen,
+ Allocation *aout, const void *usr, uint32_t usrLen,
+ const RsScriptCall *sc) override;
+
+ void invokeReduce(uint32_t slot, const Allocation **ains, uint32_t inLen,
+ Allocation *aout, const RsScriptCall *sc) override;
+
+ void invokeInit() override;
+ void invokeFreeChildren() override;
+
+ void setGlobalVar(uint32_t slot, const void *data,
+ size_t dataLength) override;
+ void getGlobalVar(uint32_t slot, void *data, size_t dataLength) override;
+ void setGlobalVarWithElemDims(uint32_t slot, const void *data,
+ size_t dataLength, const Element *e,
+ const uint32_t *dims,
+ size_t dimLength) override;
+
+ void setGlobalBind(uint32_t slot, Allocation *data) override;
+ void setGlobalObj(uint32_t slot, ObjectBase *obj) override;
+
+ Allocation *getAllocationForPointer(const void *ptr) const override;
+
+ // Returns number of global variables in this Script (may be 0 if
+ // compiler is not configured to emit this information).
+ int getGlobalEntries() const override;
+ // Returns the name of the global variable at index i.
+ const char *getGlobalName(int i) const override;
+ // Returns the CPU address of the global variable at index i.
+ const void *getGlobalAddress(int i) const override;
+ // Returns the size (in bytes) of the global variable at index i.
+ size_t getGlobalSize(int i) const override;
+ // Returns the properties of the global variable at index i.
+ uint32_t getGlobalProperties(int i) const override;
+
+ void setCpuScript(RsdCpuReference::CpuScript *cs) { mCpuScript = cs; }
+
+ RsdCpuReference::CpuScript *getCpuScript() const { return mCpuScript; }
+
+ private:
+ void InitDescriptorAndPipelineLayouts();
+ void InitShader();
+ void InitDescriptorPool();
+ void InitDescriptorSet(const RSoVAllocation *inputAllocation,
+ RSoVAllocation *outputAllocation);
+ void InitPipelineCache();
+ void InitPipeline();
+ void runForEach(const RSoVAllocation *input, RSoVAllocation *output);
+
+ RSoVContext *mRSoV;
+ VkDevice mDevice;
+ std::vector<uint32_t> mSPIRVWords;
+ RsdCpuReference::CpuScript *mCpuScript;
+
+ static constexpr int NUM_DESCRIPTOR_SETS = 1;
+ std::vector<VkDescriptorSetLayout> mDescLayout;
+ VkPipelineLayout mPipelineLayout;
+ VkPipeline mComputePipeline;
+ // TODO: Multiple stages for multiple kernels
+ VkPipelineShaderStageCreateInfo mShaderStage;
+ VkDescriptorPool mDescPool;
+ std::vector<VkDescriptorSet> mDescSet;
+};
+
+} // namespace rsov
+} // namespace renderscript
+} // namespace android
+
+extern bool rsovScriptInit(const android::renderscript::Context *rsc,
+ android::renderscript::ScriptC *script,
+ char const *resName, char const *cacheDir,
+ uint8_t const *bitcode, size_t bitcodeSize,
+ uint32_t flags);
+
+extern bool rsovInitIntrinsic(const android::renderscript::Context *rsc,
+ android::renderscript::Script *s,
+ RsScriptIntrinsicID iid,
+ android::renderscript::Element *e);
+
+extern void rsovScriptInvokeFunction(const android::renderscript::Context *dc,
+ android::renderscript::Script *script,
+ uint32_t slot, const void *params,
+ size_t paramLength);
+
+extern void rsovScriptInvokeForEach(
+ const android::renderscript::Context *rsc, android::renderscript::Script *s,
+ uint32_t slot, const android::renderscript::Allocation *ain,
+ android::renderscript::Allocation *aout, const void *usr, size_t usrLen,
+ const RsScriptCall *sc);
+
+extern void rsovScriptInvokeReduce(
+ const android::renderscript::Context *rsc, android::renderscript::Script *s,
+ uint32_t slot, const android::renderscript::Allocation **ains, size_t inLen,
+ android::renderscript::Allocation *aout, const RsScriptCall *sc);
+
+extern void rsovScriptInvokeForEachMulti(
+ const android::renderscript::Context *rsc, android::renderscript::Script *s,
+ uint32_t slot, const android::renderscript::Allocation **ains, size_t inLen,
+ android::renderscript::Allocation *aout, const void *usr, size_t usrLen,
+ const RsScriptCall *sc);
+
+extern int rsovScriptInvokeRoot(const android::renderscript::Context *dc,
+ android::renderscript::Script *script);
+
+extern void rsovScriptInvokeInit(const android::renderscript::Context *dc,
+ android::renderscript::Script *script);
+
+extern void rsovScriptInvokeFreeChildren(
+ const android::renderscript::Context *dc,
+ android::renderscript::Script *script);
+
+extern void rsovScriptSetGlobalVar(const android::renderscript::Context *,
+ const android::renderscript::Script *,
+ uint32_t slot, void *data, size_t dataLen);
+
+extern void rsovScriptGetGlobalVar(const android::renderscript::Context *,
+ const android::renderscript::Script *,
+ uint32_t slot, void *data, size_t dataLen);
+
+extern void rsovScriptSetGlobalVarWithElemDims(
+ const android::renderscript::Context *,
+ const android::renderscript::Script *, uint32_t slot, void *data,
+ size_t dataLength, const android::renderscript::Element *,
+ const uint32_t *dims, size_t dimLength);
+extern void rsovScriptSetGlobalBind(const android::renderscript::Context *,
+ const android::renderscript::Script *,
+ uint32_t slot,
+ android::renderscript::Allocation *data);
+
+extern void rsovScriptSetGlobalObj(const android::renderscript::Context *,
+ const android::renderscript::Script *,
+ uint32_t slot,
+ android::renderscript::ObjectBase *data);
+
+extern void rsovScriptSetGlobal(const android::renderscript::Context *dc,
+ const android::renderscript::Script *script,
+ uint32_t slot, void *data, size_t dataLength);
+extern void rsovScriptGetGlobal(const android::renderscript::Context *dc,
+ const android::renderscript::Script *script,
+ uint32_t slot, void *data, size_t dataLength);
+extern void rsovScriptDestroy(const android::renderscript::Context *dc,
+ android::renderscript::Script *script);
+
+extern android::renderscript::Allocation *rsovScriptGetAllocationForPointer(
+ const android::renderscript::Context *dc,
+ const android::renderscript::Script *script, const void *);
+
+extern void rsovScriptUpdateCachedObject(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Script *script,
+ android::renderscript::rs_script *obj);
+
+#endif // RSOV_SCRIPT_H
diff --git a/rsov/driver/rsovScriptGroup.cpp b/rsov/driver/rsovScriptGroup.cpp
new file mode 100644
index 00000000..3603c04b
--- /dev/null
+++ b/rsov/driver/rsovScriptGroup.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsovCore.h"
+
+#include "rsAllocation.h"
+#include "rsContext.h"
+#include "rsScript.h"
+#include "rsScriptGroup.h"
+#include "rsd_cpu.h"
+
+using android::renderscript::Allocation;
+using android::renderscript::Context;
+using android::renderscript::RsdCpuReference;
+using android::renderscript::ScriptGroup;
+using android::renderscript::ScriptGroupBase;
+using android::renderscript::ScriptKernelID;
+using android::renderscript::rs_script_group;
+
+bool rsovScriptGroupInit(const Context *rsc, ScriptGroupBase *sg) {
+ // Always falls back to CPU implmentation of ScriptGroup
+ RSoVHal *dc = (RSoVHal *)rsc->mHal.drv;
+
+ sg->mHal.drv = dc->mCpuRef->createScriptGroup(sg);
+ return sg->mHal.drv != nullptr;
+}
+
+void rsovScriptGroupSetInput(const Context *rsc, const ScriptGroup *sg,
+ const ScriptKernelID *kid, Allocation *) {}
+
+void rsovScriptGroupSetOutput(const Context *rsc, const ScriptGroup *sg,
+ const ScriptKernelID *kid, Allocation *) {}
+
+void rsovScriptGroupExecute(const Context *rsc, const ScriptGroupBase *sg) {
+ RsdCpuReference::CpuScriptGroupBase *sgi =
+ (RsdCpuReference::CpuScriptGroupBase *)sg->mHal.drv;
+ sgi->execute();
+}
+
+void rsovScriptGroupDestroy(const Context *rsc, const ScriptGroupBase *sg) {
+ RsdCpuReference::CpuScriptGroupBase *sgi =
+ (RsdCpuReference::CpuScriptGroupBase *)sg->mHal.drv;
+ delete sgi;
+}
diff --git a/rsov/driver/rsovScriptGroup.h b/rsov/driver/rsovScriptGroup.h
new file mode 100644
index 00000000..1a16136e
--- /dev/null
+++ b/rsov/driver/rsovScriptGroup.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_SCRIPT_GROUP_H
+#define RSOV_SCRIPT_GROUP_H
+
+#include "rs_hal.h"
+
+bool rsovScriptGroupInit(const android::renderscript::Context *rsc,
+ android::renderscript::ScriptGroupBase *sg);
+void rsovScriptGroupSetInput(const android::renderscript::Context *rsc,
+ const android::renderscript::ScriptGroup *sg,
+ const android::renderscript::ScriptKernelID *kid,
+ android::renderscript::Allocation *);
+void rsovScriptGroupSetOutput(const android::renderscript::Context *rsc,
+ const android::renderscript::ScriptGroup *sg,
+ const android::renderscript::ScriptKernelID *kid,
+ android::renderscript::Allocation *);
+void rsovScriptGroupExecute(const android::renderscript::Context *rsc,
+ const android::renderscript::ScriptGroupBase *sg);
+void rsovScriptGroupDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::ScriptGroupBase *sg);
+
+#endif // RSOV_SCRIPT_GROUP_H
diff --git a/rsov/driver/rsovType.cpp b/rsov/driver/rsovType.cpp
new file mode 100644
index 00000000..e18400a8
--- /dev/null
+++ b/rsov/driver/rsovType.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsType.h"
+
+using android::renderscript::Context;
+using android::renderscript::Type;
+using android::renderscript::rs_type;
+
+bool rsovTypeInit(const Context *, const Type *t) { return true; }
+
+void rsovTypeDestroy(const Context *rsc, const Type *t) {}
+
+void rsovTypeUpdateCachedObject(const Context *rsc, const Type *t,
+ rs_type *obj) {
+ obj->p = t;
+#ifdef __LP64__
+ obj->r = nullptr;
+ obj->v1 = nullptr;
+ obj->v2 = nullptr;
+#endif
+}
diff --git a/rsov/driver/rsovType.h b/rsov/driver/rsovType.h
new file mode 100644
index 00000000..39f31dc7
--- /dev/null
+++ b/rsov/driver/rsovType.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSOV_TYPE_H
+#define RSOV_TYPE_H
+
+#include "rs_hal.h"
+
+extern bool rsovTypeInit(const android::renderscript::Context *rsc,
+ const android::renderscript::Type *);
+
+extern void rsovTypeDestroy(const android::renderscript::Context *rsc,
+ const android::renderscript::Type *);
+
+extern void rsovTypeUpdateCachedObject(
+ const android::renderscript::Context *rsc,
+ const android::renderscript::Type *, android::renderscript::rs_type *obj);
+
+#endif // RSD_TYPE_H
diff --git a/rsov/tests/RSoVTest/Android.mk b/rsov/tests/RSoVTest/Android.mk
new file mode 100644
index 00000000..882de995
--- /dev/null
+++ b/rsov/tests/RSoVTest/Android.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_RENDERSCRIPT_FLAGS := -target-api 0
+
+LOCAL_PACKAGE_NAME := RSoVTest
+
+include $(BUILD_PACKAGE)
diff --git a/rsov/tests/RSoVTest/AndroidManifest.xml b/rsov/tests/RSoVTest/AndroidManifest.xml
new file mode 100644
index 00000000..23a4e5c2
--- /dev/null
+++ b/rsov/tests/RSoVTest/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.rs.rsov.test">
+ <application
+ android:largeHeap="true"
+ android:label="_RSoV_Test"
+ android:icon="@drawable/test_pattern">
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="RSoVTest"
+ android:screenOrientation="portrait">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.rs.rsov.test"/>
+</manifest>
diff --git a/rsov/tests/RSoVTest/res/drawable-nodpi/test_pattern.png b/rsov/tests/RSoVTest/res/drawable-nodpi/test_pattern.png
new file mode 100644
index 00000000..7b344380
--- /dev/null
+++ b/rsov/tests/RSoVTest/res/drawable-nodpi/test_pattern.png
Binary files differ
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTest.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTest.java
new file mode 100644
index 00000000..f9035d29
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+public class RSoVTest extends ListActivity {
+
+ private static final String LOG_TAG = "RSTest";
+ private static final boolean DEBUG = false;
+ private static final boolean LOG_ENABLED = false;
+
+ private RenderScript mRS;
+ private RSoVTestCore RSTC;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mRS = RenderScript.create(this);
+
+ RSTC = new RSoVTestCore(this);
+ RSTC.init(mRS);
+ }
+
+ static void log(String message) {
+ if (LOG_ENABLED) {
+ Log.v(LOG_TAG, message);
+ }
+ }
+
+
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTestCore.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTestCore.java
new file mode 100644
index 00000000..e3d80233
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/RSoVTestCore.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.app.ListActivity;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.widget.ArrayAdapter;
+
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class RSoVTestCore {
+ ListActivity mCtx;
+
+ public RSoVTestCore(ListActivity ctx) {
+ mCtx = ctx;
+ }
+
+ private RenderScript mRS;
+
+ private ArrayList<UnitTest> unitTests;
+ private ListIterator<UnitTest> test_iter;
+ private UnitTest activeTest;
+ private boolean stopTesting;
+
+ private ScriptField_ListAllocs_s mListAllocs;
+
+ private ArrayAdapter<UnitTest> testAdapter;
+
+ /* Periodic timer for ensuring future tests get scheduled */
+ private Timer mTimer;
+ public static final int RS_TIMER_PERIOD = 100;
+
+ public void init(RenderScript rs) {
+ mRS = rs;
+ stopTesting = false;
+
+ unitTests = new ArrayList<UnitTest>();
+
+ unitTests.add(new UT_invert(this, mCtx));
+ unitTests.add(new UT_modulo(this, mCtx));
+
+ UnitTest[] uta = new UnitTest[unitTests.size()];
+ uta = unitTests.toArray(uta);
+
+ /*
+ mListAllocs = new ScriptField_ListAllocs_s(mRS, uta.length);
+ for (int i = 0; i < uta.length; i++) {
+ ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
+ listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
+ listElem.result = uta[i].getResult();
+ mListAllocs.set(listElem, i, false);
+ uta[i].setItem(listElem);
+ }
+
+ mListAllocs.copyAll();
+ */
+ testAdapter = new ArrayAdapter<UnitTest>(mCtx, android.R.layout.simple_list_item_1, unitTests);
+ mCtx.setListAdapter(testAdapter);
+
+ test_iter = unitTests.listIterator();
+ refreshTestResults(); /* Kick off the first test */
+
+ TimerTask pTask = new TimerTask() {
+ public void run() {
+ refreshTestResults();
+ }
+ };
+
+ mTimer = new Timer();
+ mTimer.schedule(pTask, RS_TIMER_PERIOD, RS_TIMER_PERIOD);
+ }
+
+ public void checkAndRunNextTest() {
+ mCtx.runOnUiThread(new Runnable() {
+ public void run() {
+ if (testAdapter != null)
+ testAdapter.notifyDataSetChanged();
+ }
+ });
+
+ if (activeTest != null) {
+ if (!activeTest.isAlive()) {
+ /* Properly clean up on our last test */
+ try {
+ activeTest.join();
+ } catch (InterruptedException e) {
+ }
+ activeTest = null;
+ }
+ }
+
+ if (!stopTesting && activeTest == null) {
+ if (test_iter.hasNext()) {
+ activeTest = test_iter.next();
+ activeTest.start();
+ /* This routine will only get called once when a new test
+ * should start running. The message handler in UnitTest.java
+ * ensures this. */
+ } else {
+ if (mTimer != null) {
+ mTimer.cancel();
+ mTimer.purge();
+ mTimer = null;
+ }
+ }
+ }
+ }
+
+ public void refreshTestResults() {
+ checkAndRunNextTest();
+ }
+
+ public void cleanup() {
+ stopTesting = true;
+ UnitTest t = activeTest;
+
+ /* Stop periodic refresh of testing */
+ if (mTimer != null) {
+ mTimer.cancel();
+ mTimer.purge();
+ mTimer = null;
+ }
+
+ /* Wait to exit until we finish the current test */
+ if (t != null) {
+ try {
+ t.join();
+ } catch (InterruptedException e) {
+ }
+ t = null;
+ }
+
+ }
+
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_invert.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_invert.java
new file mode 100644
index 00000000..017aa061
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_invert.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class UT_invert extends UnitTest {
+ protected UT_invert(RSoVTestCore rstc, Context ctx) {
+ super(rstc, "invert", ctx);
+ }
+
+ private boolean Test(int width, int height, int depth) {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_invert s = new ScriptC_invert(pRS);
+
+ Type.Builder typeBuilder = new Type.Builder(pRS, Element.F32_4(pRS));
+ typeBuilder.setX(width);
+ if (height > 0) {
+ typeBuilder.setY(height);
+ if (depth > 0) {
+ typeBuilder.setZ(depth);
+ }
+ }
+
+ if (depth < 1) {
+ depth = 1;
+ }
+
+ if (height < 1) {
+ height = 1;
+ }
+
+ Allocation A = Allocation.createTyped(pRS, typeBuilder.create());
+ Allocation B = Allocation.createTyped(pRS, typeBuilder.create());
+
+ float a[] = new float[width * height * depth * 4];
+ float b[] = new float[width * height * depth * 4];
+
+ java.util.Random rand = new java.util.Random();
+
+ for (int i = 0; i < width * height * depth * 4; i++) {
+ a[i] = rand.nextFloat();
+ }
+
+ A.copyFrom(a);
+
+ s.forEach_invert(A, B);
+
+ B.copyTo(b);
+
+ B.destroy();
+ A.destroy();
+
+ pRS.finish();
+ pRS.destroy();
+
+ boolean failed = false;
+ for (int i = 0; i < width * height * depth * 4; i++) {
+ if (b[i] != 1.0f - a[i]) {
+ Log.e(name, "expects " + (1.0f - a[i]) + " for element " + i +
+ ". got " + b[i]);
+ failed = true;
+ break;
+ }
+ }
+
+ return !failed;
+ }
+
+ public void run() {
+ final int X = 96;
+ final int Y = 64;
+ final int Z = 32;
+
+ if (Test(X, 0, 0) && Test(X, Y, 0)) {
+ passTest();
+ return;
+ }
+
+ failTest();
+ }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_modulo.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_modulo.java
new file mode 100644
index 00000000..bb55612b
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UT_modulo.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class UT_modulo extends UnitTest {
+ private Allocation A;
+ private Allocation B;
+ private final int X = 96;
+ private final int Y = 64;
+
+ protected UT_modulo(RSoVTestCore rstc, Context ctx) {
+ super(rstc, "modulo", ctx);
+ }
+
+ private void initializeGlobals(RenderScript RS, ScriptC_modulo s) {
+ Type.Builder typeBuilder = new Type.Builder(RS, Element.I32(RS));
+ typeBuilder.setX(X);
+ typeBuilder.setY(Y);
+
+ A = Allocation.createTyped(RS, typeBuilder.create());
+ B = Allocation.createTyped(RS, typeBuilder.create());
+ return;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_modulo s = new ScriptC_modulo(pRS);
+
+ initializeGlobals(pRS, s);
+
+ int a[] = new int[X*Y];
+ int b[] = new int[X*Y];
+
+ java.util.Random rand = new java.util.Random();
+
+ for (int i = 0; i < X * Y; i++) {
+ a[i] = rand.nextInt(65536);
+ }
+
+ A.copyFrom(a);
+
+ s.forEach_modulo(A, B);
+
+ B.copyTo(b);
+
+ pRS.finish();
+ pRS.destroy();
+
+ boolean failed = false;
+ for (int i = 0; i < X * Y; i++) {
+ int expected = a[i] % 256;
+ if (b[i] != expected) {
+ Log.e(name, "expects " + expected + " got " + b[i]);
+ failed = true;
+ break;
+ }
+ }
+
+ if (failed) {
+ failTest();
+ } else {
+ passTest();
+ }
+ }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UnitTest.java b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UnitTest.java
new file mode 100644
index 00000000..f69a96af
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/UnitTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.rsov.test;
+
+import android.content.Context;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.util.Log;
+
+public class UnitTest extends Thread {
+ public String name;
+ private int result;
+ private ScriptField_ListAllocs_s.Item mItem;
+ private RSoVTestCore mRSTC;
+ private boolean msgHandled;
+ protected Context mCtx;
+
+ /* These constants must match those in shared.rsh */
+ public static final int RS_MSG_TEST_PASSED = 100;
+ public static final int RS_MSG_TEST_FAILED = 101;
+ public static final int TEST_PASSED = 1;
+ public static final int TEST_FAILED = -1;
+
+ private static int numTests = 0;
+ public int testID;
+
+ protected UnitTest(RSoVTestCore rstc, String n, int initResult, Context ctx) {
+ super();
+ mRSTC = rstc;
+ name = n;
+ msgHandled = false;
+ mCtx = ctx;
+ result = initResult;
+ testID = numTests++;
+ }
+
+ protected UnitTest(RSoVTestCore rstc, String n, Context ctx) {
+ this(rstc, n, 0, ctx);
+ }
+
+ protected UnitTest(RSoVTestCore rstc, Context ctx) {
+ this(rstc, "<Unknown>", ctx);
+ }
+
+ protected UnitTest(Context ctx) {
+ this(null, ctx);
+ }
+
+ protected void _RS_ASSERT(String message, boolean b) {
+ if (b == false) {
+ Log.e(name, message + " FAILED");
+ failTest();
+ }
+ }
+
+ private void updateUI() {
+ msgHandled = true;
+ if (mItem != null) {
+ mItem.result = result;
+ if (mRSTC != null) {
+ // Add null check for mRSTC, for instrumentation tests.
+ try {
+ mRSTC.refreshTestResults();
+ } catch (IllegalStateException e) {
+ /* Ignore the case where our message receiver has been
+ disconnected. This happens when we leave the application
+ before it finishes running all of the unit tests. */
+ }
+ }
+ }
+ }
+
+ protected RSMessageHandler mRsMessage = new RSMessageHandler() {
+ public void run() {
+ if (result == 0) {
+ switch (mID) {
+ case RS_MSG_TEST_PASSED:
+ result = TEST_PASSED;
+ break;
+ case RS_MSG_TEST_FAILED:
+ result = TEST_FAILED;
+ break;
+ default:
+ RSoVTest.log("Unit test got unexpected message");
+ return;
+ }
+ }
+
+ updateUI();
+ }
+ };
+
+ public void waitForMessage() {
+ while (!msgHandled) {
+ yield();
+ }
+ }
+
+ public int getResult() {
+ return result;
+ }
+
+ public void failTest() {
+ result = TEST_FAILED;
+ updateUI();
+ }
+
+ public void passTest() {
+ if (result != TEST_FAILED) {
+ result = TEST_PASSED;
+ }
+ updateUI();
+ }
+
+ public String toString() {
+ String out = name;
+ if (result == TEST_PASSED) {
+ out += " - PASSED";
+ } else if (result == TEST_FAILED) {
+ out += " - FAILED";
+ }
+ return out;
+ }
+
+ public void setItem(ScriptField_ListAllocs_s.Item item) {
+ mItem = item;
+ }
+
+ public void run() {
+ /* This method needs to be implemented for each subclass */
+ if (mRSTC != null) {
+ mRSTC.refreshTestResults();
+ }
+ }
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/invert.rs b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/invert.rs
new file mode 100644
index 00000000..eb89da24
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/invert.rs
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+float4 RS_KERNEL invert(float4 a) {
+ return 1.0f - a;
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/modulo.rs b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/modulo.rs
new file mode 100644
index 00000000..410dccf3
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/modulo.rs
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+int RS_KERNEL modulo(int a) {
+ return a % 256;
+}
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/rslist.rs b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/rslist.rs
new file mode 100644
index 00000000..2d5fa59a
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/rslist.rs
@@ -0,0 +1,25 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+typedef struct ListAllocs_s {
+ rs_allocation text;
+ int result;
+} ListAllocs;
+
+ListAllocs *gList;
+
diff --git a/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/shared.rsh b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/shared.rsh
new file mode 100644
index 00000000..481e874b
--- /dev/null
+++ b/rsov/tests/RSoVTest/src/com/android/rs/rsov/test/shared.rsh
@@ -0,0 +1,116 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.rs.rsov.test)
+
+typedef struct TestResult_s {
+ rs_allocation name;
+ bool pass;
+ float score;
+ int64_t time;
+} TestResult;
+//TestResult *g_results;
+
+static int64_t g_time;
+
+static inline void start(void) {
+ g_time = rsUptimeMillis();
+}
+
+static inline float end(uint32_t idx) {
+ int64_t t = rsUptimeMillis() - g_time;
+ //g_results[idx].time = t;
+ //rsDebug("test time", (int)t);
+ return ((float)t) / 1000.f;
+}
+
+#define _RS_ASSERT(b) \
+do { \
+ if (!(b)) { \
+ failed = true; \
+ rsDebug(#b " FAILED", 0); \
+ } \
+\
+} while (0)
+
+#define _RS_ASSERT_EQU(e1, e2) \
+ (((e1) != (e2)) ? (failed = true, rsDebug(#e1 " != " #e2, (e1), (e2)), false) : true)
+
+static const int iposinf = 0x7f800000;
+static const int ineginf = 0xff800000;
+
+static inline const float posinf() {
+ float f = *((float*)&iposinf);
+ return f;
+}
+
+static inline const float neginf() {
+ float f = *((float*)&ineginf);
+ return f;
+}
+
+static inline bool isposinf(float f) {
+ int i = *((int*)(void*)&f);
+ return (i == iposinf);
+}
+
+static inline bool isneginf(float f) {
+ int i = *((int*)(void*)&f);
+ return (i == ineginf);
+}
+
+static inline bool isnan(float f) {
+ int i = *((int*)(void*)&f);
+ return (((i & 0x7f800000) == 0x7f800000) && (i & 0x007fffff));
+}
+
+static inline bool isposzero(float f) {
+ int i = *((int*)(void*)&f);
+ return (i == 0x00000000);
+}
+
+static inline bool isnegzero(float f) {
+ int i = *((int*)(void*)&f);
+ return (i == 0x80000000);
+}
+
+static inline bool iszero(float f) {
+ return isposzero(f) || isnegzero(f);
+}
+
+/* Absolute epsilon used for floats. Value is similar to float.h. */
+#ifndef FLT_EPSILON
+#define FLT_EPSILON 1.19e7f
+#endif
+/* Max ULPs while still being considered "equal". Only used when this number
+ of ULPs is of a greater size than FLT_EPSILON. */
+#define FLT_MAX_ULP 1
+
+/* Calculate the difference in ULPs between the two values. (Return zero on
+ perfect equality.) */
+static inline int float_dist(float f1, float f2) {
+ return *((int *)(&f1)) - *((int *)(&f2));
+}
+
+/* Check if two floats are essentially equal. Will fail with some values
+ due to design. (Validate using FLT_EPSILON or similar if necessary.) */
+static inline bool float_almost_equal(float f1, float f2) {
+ int *i1 = (int*)(&f1);
+ int *i2 = (int*)(&f2);
+
+ // Check for sign equality
+ if ( ((*i1 >> 31) == 0) != ((*i2 >> 31) == 0) ) {
+ // Handle signed zeroes
+ if (f1 == f2)
+ return true;
+ return false;
+ }
+
+ // Check with ULP distance
+ if (float_dist(f1, f2) > FLT_MAX_ULP)
+ return false;
+ return true;
+}
+
+/* These constants must match those in UnitTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;