blob: fe686547fe6c896422f63d667d0263c000fc6798 [file] [log] [blame]
page.title=RenderScript
parent.title=Computation
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a></li>
<li><a href="#access-rs-apis">Accessing RenderScript APIs</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>
</ol>
<h2>Related Samples</h2>
<ol>
<li><a class="external-link"href="https://github.com/android/platform_development/tree/master/samples/RenderScript/HelloCompute">Hello
Compute</a></li>
</ol>
</div>
</div>
<p>RenderScript is a framework for running computationally intensive tasks at high performance on
Android. RenderScript is primarily oriented for use with data-parallel computation, although serial
computationally intensive workloads can benefit as well. The RenderScript runtime will parallelize
work across all processors available on a device, such as multi-core CPUs, GPUs, or DSPs, allowing
you to focus on expressing algorithms rather than scheduling work or load balancing. RenderScript is
especially useful for applications performing image processing, computational photography, or
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.</li>
<li>A Java API is used for managing the lifetime of RenderScript resources and controlling kernel
execution.</li>
</ul>
<h2 id="writing-an-rs-kernel">Writing a RenderScript Kernel</h2>
<p>A RenderScript kernel typically resides in a <code>.rs</code> file in the
<code>&lt;project_root&gt;/src/</code> directory; each <code>.rs</code> file is called a
script. Every script contains its own set of kernels, functions, and variables. A script can
contain:</p>
<ul>
<li>A pragma declaration (<code>#pragma version(1)</code>) that declares the version of the
RenderScript kernel language used in this script. Currently, 1 is the only valid value.</li>
<li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
declares the package name of the Java classes reflected from this script.
Note that your .rs file must be part of your application package, and not in a
library project.</li>
<li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
function that you can call from your Java code with arbitrary arguments. These are often useful for
initial setup or serial computations within a larger processing pipeline.</li>
<li>Some number of script globals. A script global is equivalent to a global variable in C. You can
access script globals from Java code, and these are often used for parameter passing to RenderScript
kernels.</li>
<li>Some number of compute kernels. A kernel is a parallel function that executes across every
{@link android.renderscript.Element} within an {@link android.renderscript.Allocation}.
<p>A simple kernel may look like the following:</p>
<pre>uchar4 __attribute__((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;
}</pre>
<p>In most respects, this is identical to a standard C function. The first notable feature is the
<code>__attribute__((kernel))</code> applied to the function prototype. This denotes that the
function is a RenderScript kernel instead of an invokable function. The next feature is the
<code>in</code> argument and its type. In a RenderScript kernel, this is a special argument that is
automatically filled in based on the input {@link android.renderscript.Allocation} passed to the
kernel launch. By default, the kernel is run across an entire {@link
android.renderscript.Allocation}, with one execution of the kernel body per {@link
android.renderscript.Element} in the {@link android.renderscript.Allocation}. The third notable
feature is the return type of the kernel. The value returned from the kernel is automatically
written to the appropriate location in the output {@link android.renderscript.Allocation}. The
RenderScript runtime checks to ensure that the {@link android.renderscript.Element} types of the
input and output Allocations match the kernel's prototype; if they do not match, an exception is
thrown.</p>
<p>A kernel may have an input {@link android.renderscript.Allocation}, an output {@link
android.renderscript.Allocation}, or both. A kernel may not have more than one input or one output
{@link android.renderscript.Allocation}. If more than one input or output is required, those objects
should be bound to <code>rs_allocation</code> script globals and accessed from a kernel or invokable
function via <code>rsGetElementAt_<em>type</em>()</code> or
<code>rsSetElementAt_<em>type</em>()</code>.</p>
<p>A kernel may access the coordinates of the current execution using the <code>x</code>,
<code>y</code>, and <code>z</code> arguments. These arguments are optional, but the type of the
coordinate arguments must be <code>uint32_t</code>.</p></li>
<li>An optional <code>init()</code> function. An <code>init()</code> function is a special type of
invokable function that is run when the script is first instantiated. This allows for some
computation to occur automatically at script creation.</li>
<li>Some number of static script globals and functions. A static script global is equivalent to a
script global except that it cannot be set from Java code. A static function is a standard C
function that can be called from any kernel or invokable function in the script but is not exposed
to the Java API. If a script global or function does not need to be called from Java code, it is
highly recommended that those be declared <code>static</code>.</li> </ul>
<h4>Setting floating point precision</h4>
<p>You can control the required level of floating point precision in a script. This is useful if
full IEEE 754-2008 standard (used by default) is not required. The following pragmas can set a
different level of floating point precision:</p>
<ul>
<li><code>#pragma rs_fp_full</code> (default if nothing is specified): For apps that require
floating point precision as outlined by the IEEE 754-2008 standard.
</li>
<li><code>#pragma rs_fp_relaxed</code> - For apps that don’t require strict IEEE 754-2008
compliance and can tolerate less precision. This mode enables flush-to-zero for denorms and
round-towards-zero.
</li>
<li><code>#pragma rs_fp_imprecise</code> - For apps that don’t have stringent precision
requirements. This mode enables everything in <code>rs_fp_relaxed</code> along with the
following:
<ul>
<li>Operations resulting in -0.0 can return +0.0 instead.</li>
<li>Operations on INF and NAN are undefined.</li>
</ul>
</li>
</ul>
<p>Most applications can use <code>rs_fp_relaxed</code> without any side effects. This may be very
beneficial on some architectures due to additional optimizations only available with relaxed
precision (such as SIMD CPU instructions).</p>
<h2 id="access-rs-apis">Accessing RenderScript APIs</h2>
<p>When developing an Android application that uses RenderScript, you can access its API in
one of two ways:</p>
<ul>
<li><strong>{@link android.renderscript}</strong> - The APIs in this class package are
available on devices running Android 3.0 (API level 11) and higher. </li>
<li><strong>{@link android.support.v8.renderscript}</strong> - The APIs in this package are
available through a <a href="{@docRoot}tools/support-library/features.html#v8">Support
Library</a>, which allows you to use them on devices running Android 2.2 (API level 8) and
higher.</li>
</ul>
<p>We strongly recommend using the Support Library APIs for accessing RenderScript because they
provide a wider range of device compatibility. Developers targeting specific versions of
Android can use {@link android.renderscript} if necessary.</p>
<h3 id="ide-setup">Using the RenderScript Support Library APIs</h3>
<p>In order to use the Support Library RenderScript APIs, you must configure your development
environment to be able to access them. The following Android SDK tools are required for using
these APIs:</p>
<ul>
<li>Android SDK Tools revision 22.2 or higher</li>
<li>Android SDK Build-tools revision 18.1.0 or higher</li>
</ul>
<p>You can check and update the installed version of these tools in the
<a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a>.</p>
<p>To use the Support Library RenderScript APIs:</p>
<ol>
<li>Make sure you have the required Android SDK version and Build Tools version installed.</li>
<li> Update the settings for the Android build process to include the RenderScript settings:
<ul>
<li>Open the {@code build.gradle} file in the app folder of your application module. </li>
<li>Add the following RenderScript settings to the file:
<pre>
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
minSdkVersion 8
targetSdkVersion 19
<strong>
renderscriptTargetApi 18
renderscriptSupportModeEnabled true
</strong>
}
}
</pre>
<p>The settings listed above control specific behavior in the Android build process:</p>
<ul>
<li>{@code renderscriptTargetApi} - Specifies the bytecode version to be generated. We
recommend you set this value to the lowest API level able to provide all the functionality
you are using and set {@code renderscriptSupportModeEnabled} to {@code true}.
Valid values for this setting are any integer value
from 11 to the most recently released API level. If your minimum SDK version specified in your
application manifest is set to a different value, that value is ignored and the target value
in the build file is used to set the minimum SDK version.</li>
<li>{@code renderscriptSupportModeEnabled} - Specifies that the generated bytecode should fall
back to a compatible version if the device it is running on does not support the target
version.
</li>
<li>{@code buildToolsVersion} - The version of the Android SDK build tools to use. This value
should be set to {@code 18.1.0} or higher. If this option is not specified, the highest
installed build tools version is used. You should always set this value to ensure the
consistency of builds across development machines with different configurations.</li>
</ul>
</li>
</ul>
<li>In your application classes that use RenderScript, add an import for the Support Library
classes:
<pre>
import android.support.v8.renderscript.*;
</pre>
</li>
</ol>
<h2 id="using-rs-from-java">Using RenderScript from Java Code</h2>
<p>Using RenderScript from Java code relies on the API classes located in the
{@link android.renderscript} or the {@link android.support.v8.renderscript} package. Most
applications follow the same basic usage patterns:</p>
<ol>
<li><strong>Initialize a RenderScript context.</strong> The {@link
android.renderscript.RenderScript} context, created with {@link
android.renderscript.RenderScript#create}, ensures that RenderScript can be used and provides an
object to control the lifetime of all subsequent RenderScript objects. You should consider context
creation to be a potentially long-running operation, since it may create resources on different
pieces of hardware; it should not be in an application's critical path if at all
possible. Typically, an application will have only a single RenderScript context at a time.</li>
<li><strong>Create at least one {@link android.renderscript.Allocation} to be passed to a
script.</strong> An {@link android.renderscript.Allocation} is a RenderScript object that provides
storage for a fixed amount of data. Kernels in scripts take {@link android.renderscript.Allocation}
objects as their input and output, and {@link android.renderscript.Allocation} objects can be
accessed in kernels using <code>rsGetElementAt_<em>type</em>()</code> and
<code>rsSetElementAt_<em>type</em>()</code> when bound as script globals. {@link
android.renderscript.Allocation} objects allow arrays to be passed from Java code to RenderScript
code and vice-versa. {@link android.renderscript.Allocation} objects are typically created using
{@link android.renderscript.Allocation#createTyped} or {@link
android.renderscript.Allocation#createFromBitmap}.</li>
<li><strong>Create whatever scripts are necessary.</strong> There are two types of scripts available
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
reflected by the RenderScript compiler in order to make it easy to access the script from Java code;
this class will have the name <code>ScriptC_<em>filename</em></code>. For example, if the kernel
above was located in <code>invert.rs</code> and a RenderScript context was already located in
<code>mRS</code>, the Java code to instantiate the script would be:
<pre>ScriptC_invert invert = new ScriptC_invert(mRenderScript);</pre></li>
<li><strong>ScriptIntrinsic</strong>: These are built-in RenderScript kernels for common operations,
such as Gaussian blur, convolution, and image blending. For more information, see the subclasses of
{@link android.renderscript.ScriptIntrinsic}.</li>
</ul></li>
<li><strong>Populate Allocations with data.</strong> Except for Allocations created with {@link
android.renderscript.Allocation#createFromBitmap}, an Allocation will be populated with empty data when it is
first created. To populate an Allocation, use one of the <code>copy</code> methods in {@link
android.renderscript.Allocation}.</li>
<li><strong>Set any necessary script globals.</strong> Globals may be set using methods in the same
<code>ScriptC_<em>filename</em></code> class with methods named
<code>set_<em>globalname</em></code>. For example, in order to set an <code>int</code> named
<code>elements</code>, use the Java method <code>set_elements(int)</code>. RenderScript objects can
also be set in kernels; for example, the <code>rs_allocation</code> variable named
<code>lookup</code> can be set with the method <code>set_lookup(Allocation)</code>.</li>
<li><strong>Launch the appropriate kernels.</strong> Methods to launch a given kernel will be
reflected in the same <code>ScriptC_<em>filename</em></code> class with methods named
<code>forEach_<em>kernelname</em>()</code>. These launches are asynchronous, and launches will be
serialized in the order in which they are launched. Depending on the arguments to the kernel, the
method will take either one or two Allocations. By default, a kernel will execute over the entire
input or output Allocation; to execute over a subset of that Allocation, pass an appropriate {@link
android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> method.
<p>Invoked functions can be launched using the <code>invoke_<em>functionname</em></code> methods
reflected in the same <code>ScriptC_<em>filename</em></code> class.</p></li>
<li><strong>Copy data out of {@link android.renderscript.Allocation} objects.</strong> In order to
access data from an {@link android.renderscript.Allocation} from Java code, that data must be copied
back to Java buffers using one of the <code>copy</code> methods in {@link
android.renderscript.Allocation}. These functions will synchronize with asynchronous kernel and
function launches as necessary.</li>
<li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
object to be garbage collected. This will cause any further use of any object belonging to that
context to throw an exception.</li> </ol>