Loading docs/html/guide/topics/renderscript/compute.jd +127 −10 Original line number Diff line number Diff line Loading @@ -10,12 +10,13 @@ parent.link=index.html <ol> <li><a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a></li> <li><a href="#access-rs-apis">Accessing RenderScript APIs</a> <li><a href="#access-rs-apis">Accessing RenderScript APIs from Java</a> <ol> <li><a href="#ide-setup">Setting Up Your Development Environment</a></li> </ol> </li> <li><a href="#using-rs-from-java">Using RenderScript from Java Code</a></li> <li><a href="#single-source-rs">Single-Source RenderScript</a></li> <li><a href="#reduction-in-depth">Reduction Kernels in Depth</a> <ol> <li><a href="#writing-reduction-kernel">Writing a reduction kernel</a></li> Loading Loading @@ -45,12 +46,16 @@ computer vision.</p> <p>To begin with RenderScript, there are two main concepts you should understand:</p> <ul> <li>High-performance compute kernels are written in a C99-derived language. A <i>compute kernel</i> is a function or collection of functions that you can direct the RenderScript runtime to execute in parallel across a collection of data.</li> <li>The <em>language</em> itself is a C99-derived language for writing high-performance compute code. <a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> describes how to use it to write compute kernels.</li> <li>A Java API is used for managing the lifetime of RenderScript resources and controlling kernel execution.</li> <li>The <em>control API</em> is used for managing the lifetime of RenderScript resources and controlling kernel execution. It is available in three different languages: Java, C++ in Android NDK, and the C99-derived kernel language itself. <a href="#using-rs-from-java">Using RenderScript from Java Code</a> and <a href=#single-source-rs>Single-Source RenderScript</a> describe the first and the third options, respectively.</li> </ul> <h2 id="writing-an-rs-kernel">Writing a RenderScript Kernel</h2> Loading @@ -77,7 +82,9 @@ initial setup or serial computations within a larger processing pipeline.</li> access script globals from Java code, and these are often used for parameter passing to RenderScript kernels.</p></li> <li><p>Zero or more <strong><i>compute kernels</i></strong>. There are two kinds of compute <li><p>Zero or more <strong><i>compute kernels</i></strong>. 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: <i>mapping</i> kernels (also called <i>foreach</i> kernels) and <i>reduction</i> kernels.</p> Loading Loading @@ -243,9 +250,9 @@ beneficial on some architectures due to additional optimizations only available precision (such as SIMD CPU instructions).</p> <h2 id="access-rs-apis">Accessing RenderScript APIs</h2> <h2 id="access-rs-apis">Accessing RenderScript APIs from Java</h2> <p>When developing an Android application that uses RenderScript, you can access its API in <p>When developing an Android application that uses RenderScript, you can access its API from Java in one of two ways:</p> <ul> Loading Loading @@ -377,7 +384,7 @@ to you when using RenderScript: <ul> <li><strong>ScriptC</strong>: These are the user-defined scripts as described in <a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> above. Every script has a Java class href="#writing-an-rs-kernel"><i>Writing a RenderScript Kernel</i></a> above. Every script has a Java class reflected by the RenderScript compiler in order to make it easy to access the script from Java code; this class has the name <code>ScriptC_<i>filename</i></code>. For example, if the mapping kernel above were located in <code>invert.rs</code> and a RenderScript context were already located in Loading Loading @@ -448,6 +455,116 @@ context to throw an exception.</li> </ol> a <code>get()</code> method to obtain the result of a reduction. <code>get()</code> is synchronous, and is serialized with respect to the reduction (which is asynchronous).</p> <h2 id="single-source-rs">Single-Source RenderScript</h2> <p>Android 7.0 (API level 24) introduces a new programming feature called <em>Single-Source RenderScript</em>, 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 <a href={@docRoot}guide/topics/renderscript/reference/rs_object_types.html#android_rs:rs_allocation> <code>rs_allocation</code></a> 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.</p> <p>In Single-Source RenderScript, you write kernels as described in <a href="#writing-an-rs-kernel"> Writing a RenderScript Kernel</a>. You then write an invokable function that calls <a href="{@docRoot}guide/topics/renderscript/reference/rs_for_each.html#android_rs:rsForEach"> <code>rsForEach()</code></a> to launch them. That API takes a kernel function as the first parameter, followed by input and output allocations. A similar API <a href="{@docRoot}guide/topics/renderscript/reference/rs_for_each.html#android_rs:rsForEachWithOptions"> <code>rsForEachWithOptions()</code></a> takes an extra argument of type <a href="{@docRoot}guide/topics/renderscript/reference/rs_for_each.html#android_rs:rs_script_call_t"> <code>rs_script_call_t</code></a>, which specifies a subset of the elements from the input and output allocations for the kernel function to process.</p> <p>To start RenderScript computation, you call the invokable function from Java. Follow the steps in <a href="#using-rs-from-java">Using RenderScript from Java Code</a>. In the step <a href="#launching_kernels">launch the appropriate kernels</a>, call the invokable function using <code>invoke_<i>function_name</i>()</code>, which will start the whole computation, including launching kernels.</p> <p>Allocations are often needed to save and pass intermediate results from one kernel launch to another. You can create them using <a href="{@docRoot}guide/topics/renderscript/reference/rs_allocation_create.html#android_rs:rsCreateAllocation"> rsCreateAllocation()</a>. One easy-to-use form of that API is <code> rsCreateAllocation_<T><W>(…)</code>, where <i>T</i> is the data type for an element, and <i>W</i> 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, <code>rsCreateAllocation_uchar4(16384)</code> creates a 1D allocation of 16384 elements, each of which is of type <code>uchar4</code>.</p> <p>Allocations are managed by the system automatically. You do not have to explicitly release or free them. However, you can call <a href="{@docRoot}guide/topics/renderscript/reference/rs_object_info.html#android_rs:rsClearObject"> <code>rsClearObject(rs_allocation* alloc)</code></a> to indicate you no longer need the handle <code>alloc</code> to the underlying allocation, so that the system can free up resources as early as possible.</p> <p>The <a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> 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, <code>greyscale</code>, which turns a color image into black-and-white. An invokable function <code>process()</code> 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 <a href={@docRoot}guide/topics/renderscript/reference/rs_object_types.html#android_rs:rs_allocation> <code>rs_allocation</code></a>.</p> <pre> // 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); } </pre> <p>You can call the <code>process()</code> function from Java as follows:</p> <pre> // 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); </pre> <p>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.</p> <h2 id="reduction-in-depth">Reduction Kernels in Depth</h2> <p><i>Reduction</i> is the process of combining a collection of data into a single Loading Loading
docs/html/guide/topics/renderscript/compute.jd +127 −10 Original line number Diff line number Diff line Loading @@ -10,12 +10,13 @@ parent.link=index.html <ol> <li><a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a></li> <li><a href="#access-rs-apis">Accessing RenderScript APIs</a> <li><a href="#access-rs-apis">Accessing RenderScript APIs from Java</a> <ol> <li><a href="#ide-setup">Setting Up Your Development Environment</a></li> </ol> </li> <li><a href="#using-rs-from-java">Using RenderScript from Java Code</a></li> <li><a href="#single-source-rs">Single-Source RenderScript</a></li> <li><a href="#reduction-in-depth">Reduction Kernels in Depth</a> <ol> <li><a href="#writing-reduction-kernel">Writing a reduction kernel</a></li> Loading Loading @@ -45,12 +46,16 @@ computer vision.</p> <p>To begin with RenderScript, there are two main concepts you should understand:</p> <ul> <li>High-performance compute kernels are written in a C99-derived language. A <i>compute kernel</i> is a function or collection of functions that you can direct the RenderScript runtime to execute in parallel across a collection of data.</li> <li>The <em>language</em> itself is a C99-derived language for writing high-performance compute code. <a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> describes how to use it to write compute kernels.</li> <li>A Java API is used for managing the lifetime of RenderScript resources and controlling kernel execution.</li> <li>The <em>control API</em> is used for managing the lifetime of RenderScript resources and controlling kernel execution. It is available in three different languages: Java, C++ in Android NDK, and the C99-derived kernel language itself. <a href="#using-rs-from-java">Using RenderScript from Java Code</a> and <a href=#single-source-rs>Single-Source RenderScript</a> describe the first and the third options, respectively.</li> </ul> <h2 id="writing-an-rs-kernel">Writing a RenderScript Kernel</h2> Loading @@ -77,7 +82,9 @@ initial setup or serial computations within a larger processing pipeline.</li> access script globals from Java code, and these are often used for parameter passing to RenderScript kernels.</p></li> <li><p>Zero or more <strong><i>compute kernels</i></strong>. There are two kinds of compute <li><p>Zero or more <strong><i>compute kernels</i></strong>. 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: <i>mapping</i> kernels (also called <i>foreach</i> kernels) and <i>reduction</i> kernels.</p> Loading Loading @@ -243,9 +250,9 @@ beneficial on some architectures due to additional optimizations only available precision (such as SIMD CPU instructions).</p> <h2 id="access-rs-apis">Accessing RenderScript APIs</h2> <h2 id="access-rs-apis">Accessing RenderScript APIs from Java</h2> <p>When developing an Android application that uses RenderScript, you can access its API in <p>When developing an Android application that uses RenderScript, you can access its API from Java in one of two ways:</p> <ul> Loading Loading @@ -377,7 +384,7 @@ to you when using RenderScript: <ul> <li><strong>ScriptC</strong>: These are the user-defined scripts as described in <a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> above. Every script has a Java class href="#writing-an-rs-kernel"><i>Writing a RenderScript Kernel</i></a> above. Every script has a Java class reflected by the RenderScript compiler in order to make it easy to access the script from Java code; this class has the name <code>ScriptC_<i>filename</i></code>. For example, if the mapping kernel above were located in <code>invert.rs</code> and a RenderScript context were already located in Loading Loading @@ -448,6 +455,116 @@ context to throw an exception.</li> </ol> a <code>get()</code> method to obtain the result of a reduction. <code>get()</code> is synchronous, and is serialized with respect to the reduction (which is asynchronous).</p> <h2 id="single-source-rs">Single-Source RenderScript</h2> <p>Android 7.0 (API level 24) introduces a new programming feature called <em>Single-Source RenderScript</em>, 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 <a href={@docRoot}guide/topics/renderscript/reference/rs_object_types.html#android_rs:rs_allocation> <code>rs_allocation</code></a> 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.</p> <p>In Single-Source RenderScript, you write kernels as described in <a href="#writing-an-rs-kernel"> Writing a RenderScript Kernel</a>. You then write an invokable function that calls <a href="{@docRoot}guide/topics/renderscript/reference/rs_for_each.html#android_rs:rsForEach"> <code>rsForEach()</code></a> to launch them. That API takes a kernel function as the first parameter, followed by input and output allocations. A similar API <a href="{@docRoot}guide/topics/renderscript/reference/rs_for_each.html#android_rs:rsForEachWithOptions"> <code>rsForEachWithOptions()</code></a> takes an extra argument of type <a href="{@docRoot}guide/topics/renderscript/reference/rs_for_each.html#android_rs:rs_script_call_t"> <code>rs_script_call_t</code></a>, which specifies a subset of the elements from the input and output allocations for the kernel function to process.</p> <p>To start RenderScript computation, you call the invokable function from Java. Follow the steps in <a href="#using-rs-from-java">Using RenderScript from Java Code</a>. In the step <a href="#launching_kernels">launch the appropriate kernels</a>, call the invokable function using <code>invoke_<i>function_name</i>()</code>, which will start the whole computation, including launching kernels.</p> <p>Allocations are often needed to save and pass intermediate results from one kernel launch to another. You can create them using <a href="{@docRoot}guide/topics/renderscript/reference/rs_allocation_create.html#android_rs:rsCreateAllocation"> rsCreateAllocation()</a>. One easy-to-use form of that API is <code> rsCreateAllocation_<T><W>(…)</code>, where <i>T</i> is the data type for an element, and <i>W</i> 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, <code>rsCreateAllocation_uchar4(16384)</code> creates a 1D allocation of 16384 elements, each of which is of type <code>uchar4</code>.</p> <p>Allocations are managed by the system automatically. You do not have to explicitly release or free them. However, you can call <a href="{@docRoot}guide/topics/renderscript/reference/rs_object_info.html#android_rs:rsClearObject"> <code>rsClearObject(rs_allocation* alloc)</code></a> to indicate you no longer need the handle <code>alloc</code> to the underlying allocation, so that the system can free up resources as early as possible.</p> <p>The <a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> 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, <code>greyscale</code>, which turns a color image into black-and-white. An invokable function <code>process()</code> 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 <a href={@docRoot}guide/topics/renderscript/reference/rs_object_types.html#android_rs:rs_allocation> <code>rs_allocation</code></a>.</p> <pre> // 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); } </pre> <p>You can call the <code>process()</code> function from Java as follows:</p> <pre> // 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); </pre> <p>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.</p> <h2 id="reduction-in-depth">Reduction Kernels in Depth</h2> <p><i>Reduction</i> is the process of combining a collection of data into a single Loading