From c069ed7f8c3d307c9fed2c8d1a81e28152190b5a Mon Sep 17 00:00:00 2001
From: Yang Ni
To begin with RenderScript, there are two main concepts you should understand:
Zero or more compute kernels. There are two kinds of compute +
Zero or more compute kernels. A compute kernel is a function +or collection of functions that you can direct the RenderScript runtime to execute in parallel +across a collection of data. There are two kinds of compute kernels: mapping kernels (also called foreach kernels) and reduction kernels.
@@ -243,9 +250,9 @@ beneficial on some architectures due to additional optimizations only available precision (such as SIMD CPU instructions). -When developing an Android application that uses RenderScript, you can access its API in +
When developing an Android application that uses RenderScript, you can access its API from Java in one of two ways:
ScriptC_filename. For example, if the mapping kernel
above were located in invert.rs and a RenderScript context were already located in
@@ -448,6 +455,116 @@ context to throw an exception.get() method to obtain the result of a reduction. get() is
synchronous, and is serialized with respect to the reduction (which is asynchronous).
+Android 7.0 (API level 24) introduces a new programming feature called Single-Source
+RenderScript, in which kernels are launched from the script where they are defined, rather than
+from Java. This approach is currently limited to mapping kernels, which are simply referred to as "kernels"
+in this section for conciseness. This new feature also supports creating allocations of type
+
+rs_allocation from inside the script. It is now possible to
+implement a whole algorithm solely within a script, even if multiple kernel launches are required.
+The benefit is twofold: more readable code, because it keeps the implementation of an algorithm in
+one language; and potentially faster code, because of fewer transitions between Java and
+RenderScript across multiple kernel launches.
In Single-Source RenderScript, you write kernels as described in
+Writing a RenderScript Kernel. You then write an invokable function that calls
+
+rsForEach() to launch them. That API takes a kernel function as the first
+parameter, followed by input and output allocations. A similar API
+
+rsForEachWithOptions() takes an extra argument of type
+
+rs_script_call_t, which specifies a subset of the elements from the input and
+output allocations for the kernel function to process.
To start RenderScript computation, you call the invokable function from Java.
+Follow the steps in Using RenderScript from Java Code.
+In the step launch the appropriate kernels, call
+the invokable function using invoke_function_name(), which will start the
+whole computation, including launching kernels.
Allocations are often needed to save and pass
+intermediate results from one kernel launch to another. You can create them using
+
+rsCreateAllocation(). One easy-to-use form of that API is
+rsCreateAllocation_<T><W>(…), where T is the data type for an
+element, and W is the vector width for the element. The API takes the sizes in
+dimensions X, Y, and Z as arguments. For 1D or 2D allocations, the size for dimension Y or Z can
+be omitted. For example, rsCreateAllocation_uchar4(16384) creates a 1D allocation of
+16384 elements, each of which is of type uchar4.
Allocations are managed by the system automatically. You
+do not have to explicitly release or free them. However, you can call
+
+rsClearObject(rs_allocation* alloc) to indicate you no longer need the handle
+alloc to the underlying allocation,
+so that the system can free up resources as early as possible.
The Writing a RenderScript Kernel section contains an example
+kernel that inverts an image. The example below expands that to apply more than one effect to an image,
+using Single-Source RenderScript. It includes another kernel, greyscale, which turns a
+color image into black-and-white. An invokable function process() then applies those two kernels
+consecutively to an input image, and produces an output image. Allocations for both the input and
+the output are passed in as arguments of type
+
+rs_allocation.
+// File: singlesource.rs
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rssample)
+
+static const float4 weight = {0.299f, 0.587f, 0.114f, 0.0f};
+
+uchar4 RS_KERNEL invert(uchar4 in, uint32_t x, uint32_t y) {
+ uchar4 out = in;
+ out.r = 255 - in.r;
+ out.g = 255 - in.g;
+ out.b = 255 - in.b;
+ return out;
+}
+
+uchar4 RS_KERNEL greyscale(uchar4 in) {
+ const float4 inF = rsUnpackColor8888(in);
+ const float4 outF = (float4){ dot(inF, weight) };
+ return rsPackColorTo8888(outF);
+}
+
+void process(rs_allocation inputImage, rs_allocation outputImage) {
+ const uint32_t imageWidth = rsAllocationGetDimX(inputImage);
+ const uint32_t imageHeight = rsAllocationGetDimY(inputImage);
+ rs_allocation tmp = rsCreateAllocation_uchar4(imageWidth, imageHeight);
+ rsForEach(invert, inputImage, tmp);
+ rsForEach(greyscale, tmp, outputImage);
+}
+
+
+You can call the process() function from Java as follows:
+// File SingleSource.java + +RenderScript RS = RenderScript.create(context); +ScriptC_singlesource script = new ScriptC_singlesource(RS); +Allocation inputAllocation = Allocation.createFromBitmapResource( + RS, getResources(), R.drawable.image); +Allocation outputAllocation = Allocation.createTyped( + RS, inputAllocation.getType(), + Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT); +script.invoke_process(inputAllocation, outputAllocation); ++ +
This example shows how an algorithm that involves two kernel launches can be implemented completely +in the RenderScript language itself. Without Single-Source +RenderScript, you would have to launch both kernels from the Java code, separating kernel launches +from kernel definitions and making it harder to understand the whole algorithm. Not only is the +Single-Source RenderScript code easier to read, it also eliminates the transitioning +between Java and the script across kernel launches. Some iterative algorithms may launch kernels +hundreds of times, making the overhead of such transitioning considerable.
+Reduction is the process of combining a collection of data into a single -- cgit v1.2.3-59-g8ed1b