731 lines
31 KiB
Plaintext
731 lines
31 KiB
Plaintext
page.title=Advanced 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="#native">RenderScript Runtime Layer</a></li>
|
|
<li><a href="#reflected">Reflected Layer</a>
|
|
<ol>
|
|
<li><a href="#func">Functions</a></li>
|
|
<li><a href="#var">Variables</a></li>
|
|
<li><a href="#pointer">Pointers</a></li>
|
|
<li><a href="#struct">Structs</a></li>
|
|
</ol>
|
|
</li>
|
|
|
|
<li>
|
|
<a href="#mem-allocation">Memory Allocation APIs</a>
|
|
</li>
|
|
<li>
|
|
<a href="#memory">Working with Memory</a>
|
|
<ol>
|
|
<li><a href="#allocating-mem">Allocating and binding memory to the RenderScript</a></li>
|
|
|
|
<li><a href="#read-write">Reading and writing to memory</a></li>
|
|
|
|
</ol>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
|
|
<p></p>
|
|
|
|
<p>Because applications that utilize RenderScript still run inside of the Android VM,
|
|
you have access to all of the framework APIs that you are familiar with, but can
|
|
utilize RenderScript when appropriate. To facilitate this interaction between
|
|
the framework and the RenderScript runtime, an intermediate layer of code is also
|
|
present to facilitate communication and memory management between the two levels of code.
|
|
This document goes into more detail about these
|
|
different layers of code as well as how memory is shared between the Android VM and
|
|
RenderScript runtime.</p>
|
|
|
|
<h2 id="native">RenderScript Runtime Layer</h2>
|
|
|
|
<p>Your RenderScript code is compiled and
|
|
executed in a compact and well-defined runtime layer. The RenderScript runtime APIs offer support for
|
|
intensive computation that is portable and automatically scalable to the
|
|
amount of cores available on a processor.
|
|
</p>
|
|
<p class="note"><strong>Note:</strong> The standard C functions in the NDK must be
|
|
guaranteed to run on a CPU, so RenderScript cannot access these libraries,
|
|
because RenderScript is designed to run on different types of processors.</p>
|
|
|
|
<p>You define your RenderScript code in <code>.rs</code>
|
|
and <code>.rsh</code> files in the <code>src/</code> directory of your Android project. The code
|
|
is compiled to intermediate bytecode by the
|
|
<code>llvm</code> compiler that runs as part of an Android build. When your application
|
|
runs on a device, the bytecode is then compiled (just-in-time) to machine code by another
|
|
<code>llvm</code> compiler that resides on the device. The machine code is optimized for the
|
|
device and also cached, so subsequent uses of the RenderScript enabled application does not
|
|
recompile the bytecode.</p>
|
|
|
|
<p>Some key features of the RenderScript runtime libraries include:</p>
|
|
|
|
<ul>
|
|
|
|
<li>Memory allocation request features</li>
|
|
|
|
<li>A large collection of math functions with both scalar and vector typed overloaded versions
|
|
of many common routines. Operations such as adding, multiplying, dot product, and cross product
|
|
are available as well as atomic arithmetic and comparison functions.</li>
|
|
|
|
<li>Conversion routines for primitive data types and vectors, matrix routines, and date and time
|
|
routines</li>
|
|
|
|
<li>Data types and structures to support the RenderScript system such as Vector types for
|
|
defining two-, three-, or four-vectors.</li>
|
|
|
|
<li>Logging functions</li>
|
|
</ul>
|
|
|
|
<p>See the RenderScript runtime API reference for more information on the available functions.
|
|
|
|
<h2 id="reflected">Reflected Layer</h2>
|
|
|
|
<p>The reflected layer is a set of classes that the Android build tools generate to allow access
|
|
to the RenderScript runtime from the Android framework. This layer also provides methods
|
|
and constructors that allow you to allocate and work with memory for pointers that are defined in
|
|
your RenderScript code. The following list describes the major
|
|
components that are reflected:</p>
|
|
|
|
<ul>
|
|
<li>Every <code>.rs</code> file that you create is generated into a class named
|
|
<code>project_root/gen/package/name/ScriptC_<em>renderscript_filename</em></code> of
|
|
type {@link android.renderscript.ScriptC}. This file is the <code>.java</code> version of your
|
|
<code>.rs</code> file, which you can call from the Android framework. This class contains the
|
|
following items reflected from the <code>.rs</code> file:
|
|
|
|
<ul>
|
|
<li>Non-static functions</li>
|
|
|
|
<li>Non-static, global RenderScript variables. Accessor methods are generated for each
|
|
variable, so you can read and write the RenderScript variables from the Android
|
|
framework. If a global variable is initialized at the RenderScript runtime layer, those
|
|
values are used to initialize the corresponding values in the Android framework layer. If global
|
|
variables are marked as <code>const</code>, then a <code>set</code> method is not
|
|
generated.</p></li>
|
|
|
|
<li>Global pointers</li>
|
|
</ul>
|
|
</li>
|
|
|
|
<li>A <code>struct</code> is reflected into its own class named
|
|
|
|
<code>project_root/gen/package/name/ScriptField_struct_name</em></code>, which extends {@link
|
|
android.renderscript.Script.FieldBase}. This class represents an array of the
|
|
<code>struct</code>, which allows you to allocate memory for one or more instances of this
|
|
<code>struct</code>.</li>
|
|
</ul>
|
|
|
|
|
|
<h3 id="func">Functions</h3>
|
|
<p>Functions are reflected into the script class itself, located in
|
|
<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. For
|
|
example, if you declare the following function in your RenderScript code:</p>
|
|
|
|
<pre>
|
|
void touch(float x, float y, float pressure, int id) {
|
|
if (id >= 10) {
|
|
return;
|
|
}
|
|
|
|
touchPos[id].x = x;
|
|
touchPos[id].y = y;
|
|
touchPressure[id] = pressure;
|
|
}
|
|
</pre>
|
|
|
|
<p>then the following code is generated:</p>
|
|
|
|
<pre>
|
|
public void invoke_touch(float x, float y, float pressure, int id) {
|
|
FieldPacker touch_fp = new FieldPacker(16);
|
|
touch_fp.addF32(x);
|
|
touch_fp.addF32(y);
|
|
touch_fp.addF32(pressure);
|
|
touch_fp.addI32(id);
|
|
invoke(mExportFuncIdx_touch, touch_fp);
|
|
}
|
|
</pre>
|
|
<p>
|
|
Functions cannot have a return value, because the RenderScript system is designed to be
|
|
asynchronous. When your Android framework code calls into RenderScript, the call is queued and is
|
|
executed when possible. This restriction allows the RenderScript system to function without constant
|
|
interruption and increases efficiency. If functions were allowed to have return values, the call
|
|
would block until the value was returned.</p>
|
|
|
|
<p>
|
|
If you want the RenderScript code to send a value back to the Android framework, use the
|
|
<a href="{@docRoot}reference/renderscript/rs__core_8rsh.html"><code>rsSendToClient()</code></a>
|
|
function.
|
|
</p>
|
|
|
|
<h3 id="var">Variables</h3>
|
|
|
|
<p>Variables of supported types are reflected into the script class itself, located in
|
|
<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. A set of accessor
|
|
methods are generated for each variable. For example, if you declare the following variable in
|
|
your RenderScript code:</p>
|
|
<pre>uint32_t unsignedInteger = 1;</pre>
|
|
|
|
<p>then the following code is generated:</p>
|
|
|
|
<pre>
|
|
private long mExportVar_unsignedInteger;
|
|
public void set_unsignedInteger(long v){
|
|
mExportVar_unsignedInteger = v;
|
|
setVar(mExportVarIdx_unsignedInteger, v);
|
|
}
|
|
|
|
public long get_unsignedInteger(){
|
|
return mExportVar_unsignedInteger;
|
|
}
|
|
</pre>
|
|
|
|
|
|
<h3 id="struct">Structs</h3>
|
|
<p>Structs are reflected into their own classes, located in
|
|
<code><project_root>/gen/com/example/renderscript/ScriptField_struct_name</code>. This
|
|
class represents an array of the <code>struct</code> and allows you to allocate memory for a
|
|
specified number of <code>struct</code>s. For example, if you declare the following struct:</p>
|
|
<pre>
|
|
typedef struct Point {
|
|
float2 position;
|
|
float size;
|
|
} Point_t;
|
|
</pre>
|
|
|
|
<p>then the following code is generated in <code>ScriptField_Point.java</code>:
|
|
<pre>
|
|
package com.example.android.rs.hellocompute;
|
|
|
|
import android.renderscript.*;
|
|
import android.content.res.Resources;
|
|
|
|
/**
|
|
* @hide
|
|
*/
|
|
public class ScriptField_Point extends android.renderscript.Script.FieldBase {
|
|
|
|
static public class Item {
|
|
public static final int sizeof = 12;
|
|
|
|
Float2 position;
|
|
float size;
|
|
|
|
Item() {
|
|
position = new Float2();
|
|
}
|
|
}
|
|
|
|
private Item mItemArray[];
|
|
private FieldPacker mIOBuffer;
|
|
public static Element createElement(RenderScript rs) {
|
|
Element.Builder eb = new Element.Builder(rs);
|
|
eb.add(Element.F32_2(rs), "position");
|
|
eb.add(Element.F32(rs), "size");
|
|
return eb.create();
|
|
}
|
|
|
|
public ScriptField_Point(RenderScript rs, int count) {
|
|
mItemArray = null;
|
|
mIOBuffer = null;
|
|
mElement = createElement(rs);
|
|
init(rs, count);
|
|
}
|
|
|
|
public ScriptField_Point(RenderScript rs, int count, int usages) {
|
|
mItemArray = null;
|
|
mIOBuffer = null;
|
|
mElement = createElement(rs);
|
|
init(rs, count, usages);
|
|
}
|
|
|
|
private void copyToArray(Item i, int index) {
|
|
if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count
|
|
*/);
|
|
mIOBuffer.reset(index * Item.sizeof);
|
|
mIOBuffer.addF32(i.position);
|
|
mIOBuffer.addF32(i.size);
|
|
}
|
|
|
|
public void set(Item i, int index, boolean copyNow) {
|
|
if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
|
|
mItemArray[index] = i;
|
|
if (copyNow) {
|
|
copyToArray(i, index);
|
|
mAllocation.setFromFieldPacker(index, mIOBuffer);
|
|
}
|
|
}
|
|
|
|
public Item get(int index) {
|
|
if (mItemArray == null) return null;
|
|
return mItemArray[index];
|
|
}
|
|
|
|
public void set_position(int index, Float2 v, boolean copyNow) {
|
|
if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);
|
|
if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
|
|
if (mItemArray[index] == null) mItemArray[index] = new Item();
|
|
mItemArray[index].position = v;
|
|
if (copyNow) {
|
|
mIOBuffer.reset(index * Item.sizeof);
|
|
mIOBuffer.addF32(v);
|
|
FieldPacker fp = new FieldPacker(8);
|
|
fp.addF32(v);
|
|
mAllocation.setFromFieldPacker(index, 0, fp);
|
|
}
|
|
}
|
|
|
|
public void set_size(int index, float v, boolean copyNow) {
|
|
if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);
|
|
if (mItemArray == null) mItemArray = new Item[getType().getX() /* count */];
|
|
if (mItemArray[index] == null) mItemArray[index] = new Item();
|
|
mItemArray[index].size = v;
|
|
if (copyNow) {
|
|
mIOBuffer.reset(index * Item.sizeof + 8);
|
|
mIOBuffer.addF32(v);
|
|
FieldPacker fp = new FieldPacker(4);
|
|
fp.addF32(v);
|
|
mAllocation.setFromFieldPacker(index, 1, fp);
|
|
}
|
|
}
|
|
|
|
public Float2 get_position(int index) {
|
|
if (mItemArray == null) return null;
|
|
return mItemArray[index].position;
|
|
}
|
|
|
|
public float get_size(int index) {
|
|
if (mItemArray == null) return 0;
|
|
return mItemArray[index].size;
|
|
}
|
|
|
|
public void copyAll() {
|
|
for (int ct = 0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
|
|
mAllocation.setFromFieldPacker(0, mIOBuffer);
|
|
}
|
|
|
|
public void resize(int newSize) {
|
|
if (mItemArray != null) {
|
|
int oldSize = mItemArray.length;
|
|
int copySize = Math.min(oldSize, newSize);
|
|
if (newSize == oldSize) return;
|
|
Item ni[] = new Item[newSize];
|
|
System.arraycopy(mItemArray, 0, ni, 0, copySize);
|
|
mItemArray = ni;
|
|
}
|
|
mAllocation.resize(newSize);
|
|
if (mIOBuffer != null) mIOBuffer = new FieldPacker(Item.sizeof * getType().getX()/* count */);
|
|
}
|
|
}
|
|
</pre>
|
|
|
|
<p>The generated code is provided to you as a convenience to allocate memory for structs requested
|
|
by the RenderScript runtime and to interact with <code>struct</code>s
|
|
in memory. Each <code>struct</code>'s class defines the following methods and constructors:</p>
|
|
|
|
<ul>
|
|
<li>Overloaded constructors that allow you to allocate memory. The
|
|
<code>ScriptField_<em>struct_name</em>(RenderScript rs, int count)</code> constructor allows
|
|
you to define the number of structures that you want to allocate memory for with the
|
|
<code>count</code> parameter. The <code>ScriptField_<em>struct_name</em>(RenderScript rs, int
|
|
count, int usages)</code> constructor defines an extra parameter, <code>usages</code>, that
|
|
lets you specify the memory space of this memory allocation. There are four memory space
|
|
possibilities:
|
|
|
|
<ul>
|
|
<li>{@link android.renderscript.Allocation#USAGE_SCRIPT}: Allocates in the script memory
|
|
space. This is the default memory space if you do not specify a memory space.</li>
|
|
|
|
<li>{@link android.renderscript.Allocation#USAGE_GRAPHICS_TEXTURE}: Allocates in the
|
|
texture memory space of the GPU.</li>
|
|
|
|
<li>{@link android.renderscript.Allocation#USAGE_GRAPHICS_VERTEX}: Allocates in the vertex
|
|
memory space of the GPU.</li>
|
|
|
|
<li>{@link android.renderscript.Allocation#USAGE_GRAPHICS_CONSTANTS}: Allocates in the
|
|
constants memory space of the GPU that is used by the various program objects.</li>
|
|
</ul>
|
|
|
|
<p>You can specify multiple memory spaces by using the bitwise <code>OR</code> operator. Doing so
|
|
notifies the RenderScript runtime that you intend on accessing the data in the
|
|
specified memory spaces. The following example allocates memory for a custom data type
|
|
in both the script and vertex memory spaces:</p>
|
|
<pre>
|
|
ScriptField_Point touchPoints = new ScriptField_Point(myRenderScript, 2,
|
|
Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_VERTEX);
|
|
</pre>
|
|
</li>
|
|
|
|
<li>A static nested class, <code>Item</code>, allows you to create an instance of the
|
|
<code>struct</code>, in the form of an object. This nested class is useful if it makes more sense to work
|
|
with the <code>struct</code> in your Android code. When you are done manipulating the object,
|
|
you can push the object to the allocated memory by calling <code>set(Item i, int index,
|
|
boolean copyNow)</code> and setting the <code>Item</code> to the desired position in
|
|
the array. The RenderScript runtime automatically has access to the newly written memory.
|
|
|
|
<li>Accessor methods to get and set the values of each field in a struct. Each of these
|
|
accessor methods have an <code>index</code> parameter to specify the <code>struct</code> in
|
|
the array that you want to read or write to. Each setter method also has a
|
|
<code>copyNow</code> parameter that specifies whether or not to immediately sync this memory
|
|
to the RenderScript runtime. To sync any memory that has not been synced, call
|
|
<code>copyAll()</code>.</li>
|
|
|
|
<li>The <code>createElement()</code> method creates a description of the struct in memory. This
|
|
description is used to allocate memory consisting of one or many elements.</li>
|
|
|
|
<li><code>resize()</code> works much like a <code>realloc()</code> in C, allowing you to
|
|
expand previously allocated memory, maintaining the current values that were previously
|
|
created.</li>
|
|
|
|
<li><code>copyAll()</code> synchronizes memory that was set on the framework level to the
|
|
RenderScript runtime. When you call a set accessor method on a member, there is an optional
|
|
<code>copyNow</code> boolean parameter that you can specify. Specifying
|
|
<code>true</code> synchronizes the memory when you call the method. If you specify false,
|
|
you can call <code>copyAll()</code> once, and it synchronizes memory for all the
|
|
properties that are not yet synchronized.</li>
|
|
</ul>
|
|
|
|
<h3 id="pointer">Pointers</h3>
|
|
<p>Pointers are reflected into the script class itself, located in
|
|
<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. You
|
|
can declare pointers to a <code>struct</code> or any of the supported RenderScript types, but a
|
|
<code>struct</code> cannot contain pointers or nested arrays. For example, if you declare the
|
|
following pointers to a <code>struct</code> and <code>int32_t</code></p>
|
|
|
|
<pre>
|
|
typedef struct Point {
|
|
float2 position;
|
|
float size;
|
|
} Point_t;
|
|
|
|
Point_t *touchPoints;
|
|
int32_t *intPointer;
|
|
</pre>
|
|
<p>then the following code is generated in:</p>
|
|
|
|
<pre>
|
|
private ScriptField_Point mExportVar_touchPoints;
|
|
public void bind_touchPoints(ScriptField_Point v) {
|
|
mExportVar_touchPoints = v;
|
|
if (v == null) bindAllocation(null, mExportVarIdx_touchPoints);
|
|
else bindAllocation(v.getAllocation(), mExportVarIdx_touchPoints);
|
|
}
|
|
|
|
public ScriptField_Point get_touchPoints() {
|
|
return mExportVar_touchPoints;
|
|
}
|
|
|
|
private Allocation mExportVar_intPointer;
|
|
public void bind_intPointer(Allocation v) {
|
|
mExportVar_intPointer = v;
|
|
if (v == null) bindAllocation(null, mExportVarIdx_intPointer);
|
|
else bindAllocation(v, mExportVarIdx_intPointer);
|
|
}
|
|
|
|
public Allocation get_intPointer() {
|
|
return mExportVar_intPointer;
|
|
}
|
|
</pre>
|
|
|
|
<p>A <code>get</code> method and a special method named <code>bind_<em>pointer_name</em></code>
|
|
(instead of a <code>set()</code> method) is generated. This method allows you to bind the memory
|
|
that is allocated in the Android VM to the RenderScript runtime (you cannot allocate
|
|
memory in your <code>.rs</code> file). For more information, see <a href="#memory">Working
|
|
with Allocated Memory</a>.
|
|
</p>
|
|
|
|
|
|
<h2 id="mem-allocation">Memory Allocation APIs</h2>
|
|
|
|
<p>Applications that use RenderScript still run in the Android VM. The actual RenderScript code, however, runs natively and
|
|
needs access to the memory allocated in the Android VM. To accomplish this, you must
|
|
attach the memory that is allocated in the VM to the RenderScript runtime. This
|
|
process, called binding, allows the RenderScript runtime to seamlessly work with memory that it
|
|
requests but cannot explicitly allocate. The end result is essentially the same as if you had
|
|
called <code>malloc</code> in C. The added benefit is that the Android VM can carry out garbage collection as well as
|
|
share memory with the RenderScript runtime layer. Binding is only necessary for dynamically allocated memory. Statically
|
|
allocated memory is automatically created for your RenderScript code at compile time. See <a href="#figure1">Figure 1</a>
|
|
for more information on how memory allocation occurs.
|
|
</p>
|
|
|
|
<p>To support this memory allocation system, there are a set of APIs that allow the Android VM to
|
|
allocate memory and offer similar functionality to a <code>malloc</code> call. These classes
|
|
essentially describe how memory should be allocated and also carry out the allocation. To better
|
|
understand how these classes work, it is useful to think of them in relation to a simple
|
|
<code>malloc</code> call that can look like this: </p>
|
|
|
|
<pre>array = (int *)malloc(sizeof(int)*10);</pre>
|
|
|
|
<p>The <code>malloc</code> call can be broken up into two parts: the size of the memory being allocated (<code>sizeof(int)</code>),
|
|
along with how many units of that memory should be allocated (10). The Android framework provides classes for these two parts as
|
|
well as a class to represent <code>malloc</code> itself.</p>
|
|
|
|
<p>The {@link android.renderscript.Element} class represents the (<code>sizeof(int)</code>) portion
|
|
of the <code>malloc</code> call and encapsulates one cell of a memory allocation, such as a single
|
|
float value or a struct. The {@link android.renderscript.Type} class encapsulates the {@link android.renderscript.Element}
|
|
and the amount of elements to allocate (10 in our example). You can think of a {@link android.renderscript.Type} as
|
|
an array of {@link android.renderscript.Element}s. The {@link android.renderscript.Allocation} class does the actual
|
|
memory allocation based on a given {@link android.renderscript.Type} and represents the actual allocated memory.</p>
|
|
|
|
<p>In most situations, you do not need to call these memory allocation APIs directly. The reflected layer
|
|
classes generate code to use these APIs automatically and all you need to do to allocate memory is call a
|
|
constructor that is declared in one of the reflected layer classes and then bind
|
|
the resulting memory {@link android.renderscript.Allocation} to the RenderScript.
|
|
There are some situations where you would want to use these classes directly to allocate memory on your
|
|
own, such as loading a bitmap from a resource or when you want to allocate memory for pointers to
|
|
primitive types. You can see how to do this in the
|
|
<a href="#allocating-mem">Allocating and binding memory to the RenderScript</a> section.
|
|
The following table describes the three memory management classes in more detail:</p>
|
|
|
|
<table id="mem-mgmt-table">
|
|
<tr>
|
|
<th>Android Object Type</th>
|
|
|
|
<th>Description</th>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>{@link android.renderscript.Element}</td>
|
|
|
|
<td>
|
|
<p>An element describes one cell of a memory allocation and can have two forms: basic or
|
|
complex.</p>
|
|
|
|
<p>A basic element contains a single component of data of any valid RenderScript data type.
|
|
Examples of basic element data types include a single <code>float</code> value, a <code>float4</code> vector, or a
|
|
single RGB-565 color.</p>
|
|
|
|
<p>Complex elements contain a list of basic elements and are created from
|
|
<code>struct</code>s that you declare in your RenderScript code. For instance an allocation
|
|
can contain multiple <code>struct</code>s arranged in order in memory. Each struct is considered as its
|
|
own element, rather than each data type within that struct.</p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>{@link android.renderscript.Type}</td>
|
|
|
|
<td>
|
|
<p>A type is a memory allocation template and consists of an element and one or more
|
|
dimensions. It describes the layout of the memory (basically an array of {@link
|
|
android.renderscript.Element}s) but does not allocate the memory for the data that it
|
|
describes.</p>
|
|
|
|
<p>A type consists of five dimensions: X, Y, Z, LOD (level of detail), and Faces (of a cube
|
|
map). You can assign the X,Y,Z dimensions to any positive integer value within the
|
|
constraints of available memory. A single dimension allocation has an X dimension of
|
|
greater than zero while the Y and Z dimensions are zero to indicate not present. For
|
|
example, an allocation of x=10, y=1 is considered two dimensional and x=10, y=0 is
|
|
considered one dimensional. The LOD and Faces dimensions are booleans to indicate present
|
|
or not present.</p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>{@link android.renderscript.Allocation}</td>
|
|
|
|
<td>
|
|
<p>An allocation provides the memory for applications based on a description of the memory
|
|
that is represented by a {@link android.renderscript.Type}. Allocated memory can exist in
|
|
many memory spaces concurrently. If memory is modified in one space, you must explicitly
|
|
synchronize the memory, so that it is updated in all the other spaces in which it exists.
|
|
</p>
|
|
|
|
<p>Allocation data is uploaded in one of two primary ways: type checked and type unchecked.
|
|
For simple arrays there are <code>copyFrom()</code> functions that take an array from the
|
|
Android system and copy it to the native layer memory store. The unchecked variants allow
|
|
the Android system to copy over arrays of structures because it does not support
|
|
structures. For example, if there is an allocation that is an array of n floats, the data
|
|
contained in a float[n] array or a <code>byte[n*4]</code> array can be copied.</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h2 id="memory">Working with Memory</h2>
|
|
|
|
<p>Non-static, global variables that you declare in your RenderScript are allocated memory at compile time.
|
|
You can work with these variables directly in your RenderScript code without having to allocate
|
|
memory for them at the Android framework level. The Android framework layer also has access to these variables
|
|
with the provided accessor methods that are generated in the reflected layer classes. If these variables are
|
|
initialized at the RenderScript runtime layer, those values are used to initialize the corresponding
|
|
values in the Android framework layer. If global variables are marked as const, then a <code>set</code> method is
|
|
not generated.</p>
|
|
|
|
|
|
<p class="note"><strong>Note:</strong> If you are using certain RenderScript structures that contain pointers, such as
|
|
<code>rs_program_fragment</code> and <code>rs_allocation</code>, you have to obtain an object of the
|
|
corresponding Android framework class first and then call the <code>set</code> method for that
|
|
structure to bind the memory to the RenderScript runtime. You cannot directly manipulate these structures
|
|
at the RenderScript runtime layer. This restriction is not applicable to user-defined structures
|
|
that contain pointers, because they cannot be exported to a reflected layer class
|
|
in the first place. A compiler error is generated if you try to declare a non-static, global
|
|
struct that contains a pointer.
|
|
</p>
|
|
|
|
<p>RenderScript also has support for pointers, but you must explicitly allocate the memory in your
|
|
Android framework code. When you declare a global pointer in your <code>.rs</code> file, you
|
|
allocate memory through the appropriate reflected layer class and bind that memory to the native
|
|
RenderScript layer. You can interact with this memory from the Android framework layer as well as
|
|
the RenderScript layer, which offers you the flexibility to modify variables in the most
|
|
appropriate layer.</p>
|
|
|
|
|
|
|
|
<h3 id="allocating-mem">Allocating and binding dynamic memory to the RenderScript</h3>
|
|
|
|
<p>To allocate dynamic memory, you need to call the constructor of a
|
|
{@link android.renderscript.Script.FieldBase} class, which is the most common way. An alternative is to create an
|
|
{@link android.renderscript.Allocation} manually, which is required for things such as primitive type pointers. You should
|
|
use a {@link android.renderscript.Script.FieldBase} class constructor whenever available for simplicity.
|
|
After obtaining a memory allocation, call the reflected <code>bind</code> method of the pointer to bind the allocated memory to the
|
|
RenderScript runtime.</p>
|
|
<p>The example below allocates memory for both a primitive type pointer,
|
|
<code>intPointer</code>, and a pointer to a struct, <code>touchPoints</code>. It also binds the memory to the
|
|
RenderScript:</p>
|
|
<pre>
|
|
private RenderScript myRenderScript;
|
|
private ScriptC_example script;
|
|
private Resources resources;
|
|
|
|
public void init(RenderScript rs, Resources res) {
|
|
myRenderScript = rs;
|
|
resources = res;
|
|
|
|
//allocate memory for the struct pointer, calling the constructor
|
|
ScriptField_Point touchPoints = new ScriptField_Point(myRenderScript, 2);
|
|
|
|
//Create an element manually and allocate memory for the int pointer
|
|
intPointer = Allocation.createSized(myRenderScript, Element.I32(myRenderScript), 2);
|
|
|
|
//create an instance of the RenderScript, pointing it to the bytecode resource
|
|
mScript = new ScriptC_example(myRenderScript, resources, R.raw.example);
|
|
|
|
//bind the struct and int pointers to the RenderScript
|
|
mScript.bind_touchPoints(touchPoints);
|
|
script.bind_intPointer(intPointer);
|
|
|
|
...
|
|
}
|
|
</pre>
|
|
|
|
<h3>Reading and writing to memory</h3>
|
|
<p>You can read and write to statically and dynamically allocated memory both at the RenderScript runtime
|
|
and Android framework layer.</p>
|
|
|
|
<p>Statically allocated memory comes with a one-way communication restriction
|
|
at the RenderScript runtime level. When RenderScript code changes the value of a variable, it is not
|
|
communicated back to the Android framework layer for efficiency purposes. The last value
|
|
that is set from the Android framework is always returned during a call to a <code>get</code>
|
|
method. However, when Android framework code modifies a variable, that change can be communicated to
|
|
the RenderScript runtime automatically or synchronized at a later time. If you need to send data
|
|
from the RenderScript runtime to the Android framework layer, you can use the
|
|
<a href="{@docRoot}reference/renderscript/rs__core_8rsh.html"><code>rsSendToClient()</code></a> function
|
|
to overcome this limitation.
|
|
</p>
|
|
<p>When working with dynamically allocated memory, any changes at the RenderScript runtime layer are propagated
|
|
back to the Android framework layer if you modified the memory allocation using its associated pointer.
|
|
Modifying an object at the Android framework layer immediately propagates that change back to the RenderScript
|
|
runtime layer.</p>
|
|
|
|
<h4>Reading and writing to global variables</h4>
|
|
|
|
<p>Reading and writing to global variables is a straightforward process. You can use the accessor methods
|
|
at the Android framework level or set them directly in the RenderScript code. Keep in mind that any
|
|
changes that you make in your RenderScript code are not propagated back to the Android framework layer.</p>
|
|
|
|
<p>For example, given the following struct declared in a file named <code>rsfile.rs</code>:</p>
|
|
<pre>
|
|
typedef struct Point {
|
|
int x;
|
|
int y;
|
|
} Point_t;
|
|
|
|
Point_t point;
|
|
|
|
</pre>
|
|
<p>You can assign values to the struct like this directly in <code>rsfile.rs</code>. These values are not
|
|
propagated back to the Android framework level:</p>
|
|
<pre>
|
|
point.x = 1;
|
|
point.y = 1;
|
|
</pre>
|
|
|
|
<p>You can assign values to the struct at the Android framework layer like this. These values are
|
|
propagated back to the RenderScript runtime level:</p>
|
|
<pre>
|
|
ScriptC_rsfile mScript;
|
|
|
|
...
|
|
|
|
Item i = new ScriptField_Point.Item();
|
|
i.x = 1;
|
|
i.y = 1;
|
|
mScript.set_point(i);
|
|
</pre>
|
|
|
|
<p>You can read the values in your RenderScript code like this:</p>
|
|
|
|
<pre>
|
|
rsDebug("Printing out a Point", point.x, point.y);
|
|
</pre>
|
|
|
|
<p>You can read the values in the Android framework layer with the following code. Keep in mind that this
|
|
code only returns a value if one was set at the Android framework level. You will get a null pointer
|
|
exception if you only set the value at the RenderScript runtime level:</p>
|
|
|
|
<pre>
|
|
Log.i("TAGNAME", "Printing out a Point: " + mScript.get_point().x + " " + mScript.get_point().y);
|
|
System.out.println(point.get_x() + " " + point.get_y());
|
|
</pre>
|
|
|
|
<h4>Reading and writing global pointers</h4>
|
|
|
|
<p>Assuming that memory has been allocated in the Android framework level and bound to the RenderScript runtime,
|
|
you can read and write memory from the Android framework level by using the <code>get</code> and <code>set</code> methods for that pointer.
|
|
In the RenderScript runtime layer, you can read and write to memory with pointers as normal and the changes are propagated
|
|
back to the Android framework layer, unlike with statically allocated memory.</p>
|
|
|
|
<p>For example, given the following pointer to a <code>struct</code> in a file named <code>rsfile.rs</code>:</p>
|
|
<pre>
|
|
typedef struct Point {
|
|
int x;
|
|
int y;
|
|
} Point_t;
|
|
|
|
Point_t *point;
|
|
</pre>
|
|
|
|
<p>Assuming you already allocated memory at the Android framework layer, you can access values in
|
|
the <code>struct</code> as normal. Any changes you make to the struct via its pointer variable
|
|
are automatically available to the Android framework layer:</p>
|
|
|
|
<pre>
|
|
point[index].x = 1;
|
|
point[index].y = 1;
|
|
</pre>
|
|
|
|
<p>You can read and write values to the pointer at the Android framework layer as well:
|
|
<pre>
|
|
ScriptField_Point p = new ScriptField_Point(mRS, 1);
|
|
Item i = new ScriptField_Point.Item();
|
|
i.x=100;
|
|
i.y = 100;
|
|
p.set(i, 0, true);
|
|
mScript.bind_point(p);
|
|
|
|
points.get_x(0); //read x and y from index 0
|
|
points.get_x(0);
|
|
</pre>
|
|
|
|
<p>Once memory is already bound, you do not have to rebind the memory to the RenderScript
|
|
runtime every time you make a change to a value.</p>
|