| 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> |