`

【翻译】(78)Renderscript

 
阅读更多

【翻译】(78)Renderscript

 

see

http://developer.android.com/guide/topics/renderscript/index.html

 

原文见

http://developer.android.com/guide/topics/renderscript/index.html

 

-------------------------------

 

Renderscript

 

Renderscript(注:虽然在官方示例代码中可能会被写成RenderScript,但文档中统一只有一个大写)

 

-------------------------------

 

In this document

 

本文目录

 

* Renderscript Overview Renderscript概览

* Renderscript Runtime Layer Renderscript运行时层

* Reflected Layer 反射层

* Functions 函数

* Variables 变量

* Pointers 指针

* Structs 结构体(注:在C语言中struct是指structure结构体,一种复合类型)

* Memory Allocation APIs 内存分配API

* Working with Memory 处理内存(注:使用内存工作)

* Allocating and binding memory to the Renderscript 分配和绑定内存到Renderscript

* Reading and writing to memory 读写内存

 

-------------------------------

 

Renderscript offers a high performance 3D graphics rendering and compute API at the native level that you write in C (C99 standard). The main advantages of Renderscript are:

 

Renderscript在原生层上提供一套高性能三维图形渲染和计算API,你用C(C99标准)语言编写它。Renderscript的主要优点有:

 

* Portability: Renderscript is designed to run on many types of devices with different processor (CPU, GPU, and DSP for instance) architectures. It supports all of these architectures without having to target each device, because the code is compiled and cached on the device at runtime.

 

* 可移植性:Renderscript被设计为运行在带不同处理器(例如CPU,GPU,和DSP)架构的多种类型设备上。(注:CPU是Central processing unit中央处理器的缩写,GPU是Graphics processing unit图形处理器的缩写,DSP是Digital signal processor数字信号处理器的缩写)。它支持所有这些架构而不必把目标定于每种设备,因为在运行时代码被编译和缓存在设备上。

 

* Performance: Renderscript provides similar performance to OpenGL with the NDK and also provides a high performance compute API that is not offered by OpenGL.

 

* 性能:Renderscript提供与使用NDK的OpenGL相似的性能,还提供OpenGL没有提供的一套高性能计算API。

 

* Usability: Renderscript simplifies development when possible, such as eliminating JNI glue code and simplifying mesh setup.

 

* 可用性:Renderscript简化开发,当可能的时候,诸如消除JNI胶水代码和简化网格配置。

 

The main disadvantages are:

 

主要的缺点有:

 

* Development complexity: Renderscript introduces a new set of APIs that you have to learn. Renderscript also allocates memory differently compared to OpenGL with the Android framework APIs. However, these issues are not hard to understand and Renderscript offers many features that make it easier than OpenGL to initialize rendering.

 

* 开发复杂性:Renderscript引入一套你不得不学习的新API。Renderscript还直接地分配内存,不同地对比使用Android框架API的OpenGL。然而,这些问题不难理解,而且Renderscript提供许多特性,使它比OpenGL更容易初始化渲染。

 

* Debugging visibility: Renderscript can potentially execute (planned feature for later releases) on processors other than the main CPU (such as the GPU), so if this occurs, debugging becomes more difficult.

 

* 调试可见性:Renderscript可以在处理器上而非主CPU(诸如GPU)上隐式地执行(以后发布版的计划特性),所以,如果它发生,调试变得更加困难。

 

For an example of Renderscript in action, install the Renderscript sample applications that are shipped with the SDK in <sdk_root>/samples/android-11/RenderScript. You can also see a typical use of Renderscript with the 3D carousel view in the Android 3.x versions of Google Books and YouTube.

 

想获得实战中Renderscript的一个示例,请安装Renderscript示例应用程序,它被停靠在SDK旁的<sdk_root>/samples/android-11/RenderScript中。你也可以在Android 3.x版本的Google Books和YouTube中用三维旋转木马视图看到Renderscript的一个典型使用。(注:Google Books是Google的图书搜索服务,而YouTube是Google的子公司,一个影片分享网站)

 

-------------------------------

 

Renderscript Overview

 

Renderscript概览

 

The Renderscript runtime operates at the native level and still needs to communicate with the Android VM, so the way a Renderscript application is setup is different from a pure VM application. An application that uses Renderscript is still a traditional Android application that runs in the VM, but you write Renderscript code for the parts of your program that require it. Using Renderscript can be as simple as offloading a few math calculations or as complicated as rendering an entire 3D game. No matter what you use it for, Renderscript remains platform independent, so you do not have to target multiple architectures (for example, ARM v5, ARM v7, x86).

 

Renderscript运行时操作在原生层,而且仍然需要与Android虚拟机通信,所以一个Renderscript应用程序的配置方式不同于一个纯虚拟机应用程序。一个使用Renderscript的应用程序仍然是一个运行在虚拟机中的传统Android应用程序,但你为你的需要它的程序部分而编写Renderscript代码。使用Renderscript可以简单到减轻一些数学运算或者复杂到渲染一个完整的三维游戏。不管你为了什么而使用它,Renderscript保持平台的独立,所以你不必把目标定于多个架构(例如,ARM v5,ARM v7,x86)。

 

The Renderscript system adopts a control and slave architecture where the low-level Renderscript runtime code is controlled by the higher level Android system that runs in a virtual machine (VM). The Android VM still retains all control of memory management and binds memory that it allocates to the Renderscript runtime, so the Renderscript code can access it. The Android framework makes asynchronous calls to Renderscript, and the calls are placed in a message queue and processed as soon as possible. Figure 1 shows how the Renderscript system is structured.

 

Renderscript系统采用一个控制和从(注:主从)架构,那里低层次Renderscript运行时代码被运行在虚拟机(VM)中的较高层次Android系统控制。Android虚拟机仍然维持内存管理的所有控制权并且绑定它分配给Renderscript运行时的内存,所以Renderscript代码可以反问它。Android框架对Renderscript作出异步调用,而调用被放置进一个消息队列并且尽快被处理。图1展示Renderscript系统是如何被构筑的。

 

-------------------------------

 

(图略:

1. Android框架层

Android应用程序代码->反射层类

 

2. Renderscript运行时

Renderscript代码->Renderscript图形和计算引擎

 

3. 内存

 

-----(连线)

 

1->2

1、3(圆圈):内存分配

1、2(圆圈)、3:内存绑定

1<-读/写->3

2<-读/写->3

 

Figure 1. Renderscript system overview

 

图1. Renderscript系统概览

 

-------------------------------

 

When using Renderscript, there are three layers of APIs that enable communication between the Renderscript runtime and Android framework code:

 

当使用Renderscript时,有三层API使能Renderscript运行时和Android框架代码之间的通信:

 

* The Renderscript runtime APIs allow you to do the computation or graphics rendering that is required by your application.

 

* Renderscript运行时API允许你执行你的应用程序所需的计算或图形渲染。

 

* The reflected layer APIs are a set of classes that are reflected from your Renderscript runtime code. It is basically a wrapper around the Renderscript code that allows the Android framework to interact with the Renderscript runtime. The Android build tools automatically generate the classes for this layer during the build process. These classes eliminate the need to write JNI glue code, like with the NDK.

 

* 反射层API是一组类,它们从你的Renderscript运行时代码中被反射。它基本上是一个围绕Renderscript代码的封装器,允许Android框架与Renderscript运行时交互。在构建处理中,Android构建工具为这个层自动地生成类。这些类消除像使用NDK那样编写JNI胶水代码的需要。

 

* The Android framework APIs, which include the android.renderscript package, allow you to build your application using traditional Android components such as activities and views. When using Renderscript, this layer calls the reflected layer to access the Renderscript runtime.

 

* Android框架API,包括android.renderscript包,允许你使用传统Android组件诸如活动和视图构建你的应用程序。当使用Renderscript时,这个层调用反射层以访问Renderscript运行时。

 

-------------------------------

 

Renderscript Runtime Layer

 

Renderscript运行时层

 

Your Renderscript code is compiled and executed in a compact and well-defined runtime layer. The Renderscript runtime APIs offer support for intensive computation and graphics rendering that is portable and automatically scalable to the amount of cores available on a processor.

 

你的Renderscript代码在一个紧凑的和被良好定义的运行时层中被编译和执行。Renderscript运行时API提供对密集计算和图形渲染的支持,它是可移植的和自动可伸展至一个处理器上的可用核数。

 

-------------------------------

 

Note: 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.

 

注意:NDK中的标准C函数必须保证(注:保证一定)运行在一个CPU上,所以Renderscript不可以访问这些库,因为Renderscript被设计为运行在不同类型的处理器上。

 

-------------------------------

 

You define your Renderscript code in .rs and .rsh files in the src/ directory of your Android project. The code is compiled to intermediate bytecode by the llvm 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 llvm 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.

 

你在你的Android工程src/目录下的.rs和.rsh文件中定义你的Renderscript代码。代码被作为Android构建的部分而运行的llvm编译器编译成中间字节码。当你的应用程序运行在一台设备上时,接着字节码被位于设备上的另一个llvm编译器编译(即时编译)(注:JIT)成机器代码。机器代码为设备而被优化和缓存,所以Renderscript使能的应用程序的随后使用并不重新编译字节码。

 

Some key features of the Renderscript runtime libraries include:

 

Renderscript运行时库的一些关键特性包括:

 

* Graphics rendering functions

 

* 图形渲染函数

 

* Memory allocation request features

 

* 内存分配请求特性

 

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

 

* 数学函数的一个大集合,带有标量和向量两种类型的过载版本的许多公共例程。一些操作诸如加、乘、点乘和叉乘,以及原子算术(注:这里可能是指原子操作)和比较函数。都是可用的。

 

* Conversion routines for primitive data types and vectors, matrix routines, date and time routines, and graphics routines.

 

* 原始数据类型和向量之间的转换例程,矩阵例程,日期和时间例程,以及图形例程。

 

* Data types and structures to support the Renderscript system such as Vector types for defining two-, three-, or four-vectors.

 

* 支持Renderscript的数据类型和结构,诸如Vector类型用于定义二维,三维或四维向量。

 

* Logging functions

 

* 日志函数

 

See the Renderscript runtime API reference for more information on the available functions. The Renderscript header files are automatically included for you, except for the Renderscript graphics header file, which you can include as follows:

 

请见Renderscript运行时API参考手册以获得关于可用函数的更多信息。Renderscript头文件为你自动地被包含,除了Renderscript图形头文件,你可以如下面那样包含它:

 

-------------------------------

 

#include "rs_graphics.rsh"

 

-------------------------------

 

-------------------------------

 

Reflected Layer

 

反射层

 

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:

 

反射层是一组类,Android构建工具生成以允许从Android框架对Renderscript运行时的访问。这个层还提供方法和构造函数,允许你分配和处理定义在你的Renderscript代码中的指针。以下列表描述被反射的主要组件:

 

* Every .rs file that you create is generated into a class named project_root/gen/package/name/ScriptC_renderscript_filename of type ScriptC. This file is the .java version of your .rs file, which you can call from the Android framework. This class contains the following items reflected from the .rs file:

 

* 你创建的每个.rs文件被生成进类型ScriptC(注:这里的意思是继承自ScriptC类)的名为project_root/gen/package/name/ScriptC_renderscript_filename的类。这个文件是你的.rs文件的.java版本,你可以从Android框架中调用它。这个类包含从.rs文件中反射的以下条目:

 

* Non-static functions

 

* 非静态函数

 

* 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 const, then a set method is not generated.

 

* 非静态,全局Renderscript变量。为每个变量生成访问器方法,所以你可以从Android框架中读写Renderscript变量。如果一个全局变量在Renderscript运行时层上被初始化,那么那些值被用于初始化Android框架层上相应的值。如果全局变量被标注为const,那么不会生成set方法。

 

* Global pointers

 

* 全局指针

 

* A struct is reflected into its own class named project_root/gen/package/name/ScriptField_struct_name, which extends Script.FieldBase. This class represents an array of the struct, which allows you to allocate memory for one or more instances of this struct.

 

* 一个struct被反射进它自己的名为project_root/gen/package/name/ScriptField_struct_name的类,它扩展自Script.FieldBase。这个类代表结构体的一个数组,允许你为这个结构体的一个或多个实例分配内存。

 

Functions

 

函数

 

Functions are reflected into the script class itself, located in project_root/gen/package/name/ScriptC_renderscript_filename. For example, if you declare the following function in your Renderscript code:

 

函数被反射进位于project_root/gen/package/name/ScriptC_renderscript_filename的脚本类自身。例如,如果你在你的Renderscript代码中声明以下函数:

 

-------------------------------

 

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;

}

 

-------------------------------

 

then the following code is generated:

 

那么以下代码被生成:

 

-------------------------------

 

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

}

 

-------------------------------

 

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.

 

函数不可以有一个返回值,因为Renderscript系统被设置为异步的。当你的Android框架代码调用进Renderscript时,该调用被队列并在可能的时候被执行。这个限制允许Renderscript系统在没有常量(注:恒定时间间隔)中断的情况下起作用并且提高效率。如果允许函数拥用返回值,调用将阻塞直至该值被返回。

 

If you want the Renderscript code to send a value back to the Android framework, use the rsSendToClient() function.

 

如果你想让Renderscript代码发送一个值回Android框架,请使用rsSendToClient()函数。

 

Variables

 

变量

 

Variables of supported types are reflected into the script class itself, located in project_root/gen/package/name/ScriptC_renderscript_filename. A set of accessor methods are generated for each variable. For example, if you declare the following variable in your Renderscript code:

 

支持类型的变量被反射进位于project_root/gen/package/name/ScriptC_renderscript_filename中的脚本类自身。为每个变量生成一组访问器方法。例如,如果你在你的Renderscript代码中声明以下变量:

 

-------------------------------

 

uint32_t unsignedInteger = 1;

 

-------------------------------

 

then the following code is generated:

 

那么以下代码被生成:

 

-------------------------------

 

private long mExportVar_unsignedInteger;

public void set_unsignedInteger(long v){

    mExportVar_unsignedInteger = v;

    setVar(mExportVarIdx_unsignedInteger, v);

}

 

public long get_unsignedInteger(){

    return mExportVar_unsignedInteger;

}

 

-------------------------------

 

Structs

 

结构体

 

Structs are reflected into their own classes, located in <project_root>/gen/com/example/renderscript/ScriptField_struct_name. This class represents an array of the struct and allows you to allocate memory for a specified number of structs. For example, if you declare the following struct:

 

struct被反射进它们自己的位于<project_root>/gen/com/example/renderscript/ScriptField_struct_name中的类,这个类代表一个结构体数组,并且允许你为指定数量的结构体分配内存。例如,如果你声明以下结构体:

 

-------------------------------

 

typedef struct Point {

    float2 position;

    float size;

} Point_t;

 

-------------------------------

 

then the following code is generated in ScriptField_Point.java:

 

那么在ScriptField_Point.java中生成以下代码:

 

-------------------------------

 

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 */);

    }

}

 

-------------------------------

 

The generated code is provided to you as a convenience to allocate memory for structs requested by the Renderscript runtime and to interact with structs in memory. Each struct's class defines the following methods and constructors:

 

提供被生成的代码给你作为为Renderscript运行时请求的struct分配内存,并且与内存中结构体交互的一种便利方法。每个结构体的类定义以下方法和构造函数:

 

* Overloaded constructors that allow you to allocate memory. The ScriptField_struct_name(RenderScript rs, int count) constructor allows you to define the number of structures that you want to allocate memory for with the count parameter. The ScriptField_struct_name(RenderScript rs, int count, int usages) constructor defines an extra parameter, usages, that lets you specify the memory space of this memory allocation. There are four memory space possibilities:

 

* 被重载的构造函数,允许你分配内存。ScriptField_struct_name(RenderScript rs, int count)构造函数允许你定义结构体的数量,而你想使用count参数对其分配内存。ScriptField_struct_name(RenderScript rs, int count, int usages)构造函数定义一个具体的参数usages,它让你指定这次内存分配的内存空间。有四个内存空间的可能性:

 

* USAGE_SCRIPT: Allocates in the script memory space. This is the default memory space if you do not specify a memory space.

 

* USAGE_SCRIPT:在脚本内存空间中分配。这是默认内存空间,如果你不指定一个内存空间。

 

* USAGE_GRAPHICS_TEXTURE: Allocates in the texture memory space of the GPU.

 

* USAGE_GRAPHICS_TEXTURE:在GPU的纹理内存空间中分配。

 

* USAGE_GRAPHICS_VERTEX: Allocates in the vertex memory space of the GPU.

 

* USAGE_GRAPHICS_VERTEX:在GPU的向量内存空间中分配。

 

* USAGE_GRAPHICS_CONSTANTS: Allocates in the constants memory space of the GPU that is used by the various program objects.

 

* USAGE_GRAPHICS_CONSTANTS:在GPU的常量内存空间中分配,它被不同的程序对象使用。

 

You can specify multiple memory spaces by using the bitwise OR 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:

 

你可以通过使用按位或操作来指定多个内存空间。做这件事通知Renderscript运行时你打算在指定的内存空间中访问数据。以下示例为一个自定义数据类型分配内存在脚本和顶点内存空间中:

 

-------------------------------

 

        ScriptField_Point touchPoints = new ScriptField_Point(glRenderer, 2,

        Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_VERTEX);

 

-------------------------------

 

If you modify the memory in one memory space and want to push the updates to the rest of the memory spaces, call rsgAllocationSyncAll() in your Renderscript code to synchronize the memory.

 

如果你在一个内存空间中修改内存并且想把更新推到剩余的内存空间,请在你的Renderscript代码中调用rsgAllocationSyncAll()以同步内存。

 

* A static nested class, Item, allows you to create an instance of the struct, in the form of an object. This nested class is useful if it makes more sense to work with the struct in your Android code. When you are done manipulating the object, you can push the object to the allocated memory by calling set(Item i, int index, boolean copyNow) and setting the Item to the desired position in the array. The Renderscript runtime automatically has access to the newly written memory.

 

* 一个static内嵌类,Item,允许你创建struct的一个实例,以一个对象的形式。这个内嵌类是有用的,如果在你的Android代码中处理struct会更有意义。当你已经完成对象的操作时,你可以通过调用set(Item i, int index, boolean copyNow)推数据到被分配的内存,并且设置Item到数组中理想的位置。Renderscript运行时自动地拥有对最近被写入内存的访问权。

 

* Accessor methods to get and set the values of each field in a struct. Each of these accessor methods have an index parameter to specify the struct in the array that you want to read or write to. Each setter method also has a copyNow 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 copyAll().

 

* 访问器方法以获取和设置一个struct中每个域的值。这些访问器方法的每一个拥有一个index参数以指定数组中你想读写的struct。每个set方法还拥有一个copyNow参数,它指定是否立刻同步这个内存到Renderscript运行时。为了同步还未曾被同步的任意内存,请调用copyAll()。

 

* The createElement() method creates a description of the struct in memory. This description is used to allocate memory consisting of one or many elements.

 

* createElement()方法创建内存中struct的一个描述。这个描述被用于分配由一个或多个元素组成的内存。

 

* resize() works much like a realloc() in C, allowing you to expand previously allocated memory, maintaining the current values that were previously created.

 

* resize()的工作非常像C中的realloc(),允许你扩展之前分配的内存,维护之前曾被创建的当前值。

 

* copyAll() 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 copyNow boolean parameter that you can specify. Specifying true synchronizes the memory when you call the method. If you specify false, you can call copyAll() once, and it synchronizes memory for all the properties that are not yet synchronized.

 

* copyAll()同步在框架层中被设置的内存到Renderscript运行时。当你在一个成员上调用一个set访问器方法时,你可以指定一个可选的copyNow布尔型参数。如果指定true,当你调用该方法时同步内存。如果你指定false,你可以调用copyAll()一次,而它为不曾被同步的所有属性同步内存。

 

Pointers

 

指针

 

Pointers are reflected into the script class itself, located in project_root/gen/package/name/ScriptC_renderscript_filename. You can declare pointers to a struct or any of the supported Renderscript types, but a struct cannot contain pointers or nested arrays. For example, if you declare the following pointers to a struct and int32_t

 

指针被反射进位于project_root/gen/package/name/ScriptC_renderscript_filename中的脚本类自身,你可以声明指向一个struct或任意被支持的Renderscript类型的指针,但一个struct不可以包含指针或嵌套的数组。例如,如果你声明一下指向一个struct和int32_t的指针

 

-------------------------------

 

typedef struct Point {

    float2 position;

    float size;

} Point_t;

 

Point_t *touchPoints;

int32_t *intPointer;

 

-------------------------------

 

then the following code is generated in:

 

然后以下代码被生成在(注:被生成):

 

-------------------------------

 

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;

}

 

-------------------------------

 

A get method and a special method named bind_pointer_name (instead of a set() 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 .rs file). For more information, see Working with Allocated Memory.

 

一个get方法和一个名为bind_pointer_name的特殊方法(取代一个set()方法)被生成。这个方法允许你绑定在Android虚拟机中分配的内存到Renderscript运行时(你不可以在你的.rs文件中分配内存)。想获得更多信息,请参见处理分配的内存。

 

-------------------------------

 

Memory Allocation APIs

 

内存分配API

 

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 malloc 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 Figure 1 for more information on how memory allocation occurs.

 

使用Renderscript的应用程序仍然运行在Android虚拟机中。然而,实际的Renderscript代码原生地运行,并且需要访问分配在Android虚拟机内的内存。为了实现这一点,你必须把在虚拟机中分配的内存依附到Renderscript运行时。这个处理,被称为绑定,允许Renderscript运行时无缝地处理它请求的内存,但不可以显式地分配。最后的结构本质上是相同的,如果你曾经在C中调用malloc。增加的好处是Android虚拟机可以解决垃圾回收(注:的问题)以及与Renderscript运行时层共享内存。绑定只对于动态分配的内存是必需的。静态分配的内存在编译期为你的Renderscript自动地被创建。见图1以获得关于内存分配如何发生的更多信息。

 

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 malloc 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 malloc call that can look like this:

 

为了支持这个内存分配系统,有一组API允许Android虚拟机分配内存和提供与一个malloc调用相似的功能。这些类本质上描述内存应该如何被分配以及执行分配。为了更好地理解这些类如何工作,把它们与一个简单的malloc调用关联起来想是有用的,malloc调用可能看起来像这样:

 

-------------------------------

 

array = (int *)malloc(sizeof(int)*10);

 

-------------------------------

 

The malloc call can be broken up into two parts: the size of the memory being allocated (sizeof(int)), 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 malloc itself.

 

malloc调用可以被分割成两部分:内存的大小正在被分配(sizeof(int)),伴随着那个内存的多少单元应该被分配(10)。Android框架为这两个部分提供类并且用一个类来代表malloc自身。

 

The Element class represents the (sizeof(int)) portion of the malloc call and encapsulates one cell of a memory allocation, such as a single float value or a struct. The Type class encapsulates the Element and the amount of elements to allocate (10 in our example). You can think of a Type as an array of Elements. The Allocation class does the actual memory allocation based on a given Type and represents the actual allocated memory.

 

Element类代表malloc对于的(sizeof(int))部分,并且封装内存分配的一个单元,诸如一个单一float值或一个struct。Type类封装元素和要分配的元素个数(在我们的示例中是10)。你可以认为一个Type是一个Element数组。Allocation类基于给定Type执行实际内存分配并且代表实际分配的内存。

 

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 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 Allocating and binding memory to the Renderscript section. The following table describes the three memory management classes in more detail:

 

在大多数情况下,你不需要直接地调用这些内存分配API。反射层的类生成代码以自动地使用这些API,而且你要分配内存而需要做的所有事情是调用被声明在反射层的类之一中的一个构造函数,然后绑定结果的内存Allocation到Renderscript。有一些情况,你将希望直接使用这些类自己分配内存,诸如从一个资源中加载一个位图或当你希望为指向原始类型的指针分配内存。你可以在分配和绑定内存到Renderscript的章节中看到如何做这件事。以下表格更详细地描述三个内存管理类。

 

-------------------------------

 

* Android Object Type Description

 

* Android对象类型 描述

 

* Element

 

* Element类

 

An element describes one cell of a memory allocation and can have two forms: basic or complex.

 

一个元素描述一次内存分配的一个单元,可以有两种形式:基本或复杂。

 

A basic element contains a single component of data of any valid Renderscript data type. Examples of basic element data types include a single float value, a float4 vector, or a single RGB-565 color.

 

一个基本元素包含任意可用Renderscript数据类型的数据的一个单一成分。示例的基本元素数据类型包括一个单一float值,一个float4向量,或一个单一RGB-565颜色(注:顾名思义,就是16位RGB颜色)。

 

Complex elements contain a list of basic elements and are created from structs that you declare in your Renderscript code. For instance an allocation can contain multiple structs arranged in order in memory. Each struct is considered as its own element, rather than each data type within that struct.

 

复杂元素包含一列基本元素,从你在你的Renderscript代码中声明的struct中创建。例如一次分配可以包含在内存中依次排列的多个结构体。每个结构体被认为是它自己的元素,而非在那个结构体中的每个数据类型。

 

* Type

 

* Type类

 

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 Elements) but does not allocate the memory for the data that it describes.

 

类型是一个内存分配模板,并且由一个元素和一个或多个维(注:一维是指某个元素的一维数组的下标大小,多维是指某个元素的多维数组的多个下标大小)组成。它描述内存的布局(基本上是Element的数组)但不为它描述的数据分配内存。

 

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.

 

类型由5个维组成(注:根据上文所述,类型还应该包含Element):X,Y,Z,LOD(细节层次)(注:level of detail,细节层次,在三维游戏渲染中常用于降低细节来提高性能),和Faces(一个立方映射的面)(注:cube map,立方映射,三维图形中用于渲染反射表面)。你可以在可用内存的约束内把X,Y,Z维赋值为任意正整数值。一个单一维的分配拥有一个大于0的X维,然而Y和Z维为0指示不存在(注:Y和Z维不存在)。例如,一个x=10,y=1的分配被认为是两个维而x=10,y=0被认为是一个维。LOD和Faces维是布尔值以指示存在或不存在。

 

* Allocation

 

* Allocation类

 

An allocation provides the memory for applications based on a description of the memory that is represented by a 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.

 

分配提供用于应用程序的内存,基于由一个Type对象代表的内存的描述。被分配的内存可以并发地(注:同时地)存在于许多内存空间中。如果内存被修改在一个空间中,你必须显式地同步内存,以致使它在它所存在的其它所有空间中被更新。

 

Allocation data is uploaded in one of two primary ways: type checked and type unchecked. For simple arrays there are copyFrom() 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 byte[n*4] array can be copied.

 

用两种主要方式之一来上传分配的数据:类型检查或未类型检查。对于简单数组,存在copyFrom()函数,它传入一个来自Android系统的数组并且复制它到原生层内存存储。未检查变种允许Android系统复制整个(注:越过?)结构体数组,因为它不支持结构体。例如,如果存在一次分配,它是n个浮点数数组,那么包含在float[n]数组中或一个byte[n*4]数组中的数据可以被复制。

 

-------------------------------

 

-------------------------------

 

Working with Memory

 

处理内存

 

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 set method is not generated.

 

你在你的Renderscript中声明的非静态、全局变量是在编译期分配的内存。你可以直接地在你的Renderscript代码中处理这些变量而不必在Android框架级(注:层)上为它们分配内存。Android框架层还使用提供的访问器方法拥有对这些变量的访问权,这些方法被生成在反射层类中。如果这些变量在Renderscript运行时层上被初始化,那些值被用于初始化在Android框架层中相应的值。如果全局变量被标注为const,那么不生成set方法。

 

-------------------------------

 

Note: If you are using certain Renderscript structures that contain pointers, such as rs_program_fragment and rs_allocation, you have to obtain an object of the corresponding Android framework class first and then call the set method for that structure to bind the memory to the Renderscript runtime. You cannot directly manipulate these structures at the Renderscript runtime layer. Keep in mind that user-defined structures cannot contain pointers, so this restriction only applies to certain structures that are provided by Renderscript.

 

注意:如果你正在使用某些包含指针的Renderscript结构体,诸如rs_program_fragment和rs_allocation,你不得不首先取出相应Android框架类的一个对象,然后调用那个结构体的set方法以绑定内存到Renderscript运行时。你不可以直接在Renderscript运行时层上操纵这些结构体。请谨记用户定义的结构体不可以包含指针,所以这个限制只适用于Renderscript提供的某些结构体。

 

-------------------------------

 

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

 

Renderscript还拥有对指针的支持,但你必须咋你的Android框架代码中显式地分配内存。当你在你的.rs文件中声明一个全局指针时,你通过合适的反射层类分配内存并且绑定那个内存到原生Renderscript层。你可以从Android框架层和Renderscript层与这个内存交互,这提供给你灵活性在最合适的层内修改变量。

 

Allocating and binding dynamic memory to the Renderscript

 

分配和绑定动态内存到Renderscript

 

To allocate dynamic memory, you need to call the constructor of a Script.FieldBase class, which is the most common way. An alternative is to create an Allocation manually, which is required for things such as primitive type pointers. You should use a Script.FieldBase class constructor whenever available for simplicity. After obtaining a memory allocation, call the reflected bind method of the pointer to bind the allocated memory to the Renderscript runtime.

 

为了分配动态内存,你需要调用一个Script.FieldBase类的构造函数,它是最一般的方法。一个替换方案是手工创建一个Allocation,它对于一些东西诸如原始类型指针是必需的。为了简化,你应该使用一个Script.FieldBase类构造函数,只要它是可用的。在获取一次内存分配后,调用该指针被反射的绑定方法以绑定被分配内存到Renderscript运行时。

 

The example below allocates memory for both a primitive type pointer, intPointer, and a pointer to a struct, touchPoints. It also binds the memory to the Renderscript:

 

下面的示例为一个原始类型的指针intPointer和指向一个struct的指针touchPoints都分配内存。它还绑定内存到Renderscript:

 

-------------------------------

 

private RenderScriptGL glRenderer;

private ScriptC_example script;

private Resources resources;

 

public void init(RenderScriptGL rs, Resources res) {

    //get the rendering context and resources from the calling method

    //从正在调用的方法中获得渲染上下文和资源

    glRenderer = rs;

    resources = res;

 

    //allocate memory for the struct pointer, calling the constructor

    //为struct指针分配内存,调用构造函数

    ScriptField_Point touchPoints = new ScriptField_Point(glRenderer, 2);

 

    //Create an element manually and allocate memory for the int pointer

    //手动创建一个元素并且为整型指针分配内存

    intPointer = Allocation.createSized(glRenderer, Element.I32(glRenderer), 2);

 

    //create an instance of the Renderscript, pointing it to the bytecode resource

    //创建Renderscript的一个实例,把它指向字节码资源

    mScript = new ScriptC_example(glRenderer, resources, R.raw.example);

 

    //bind the struct and int pointers to the Renderscript

    //绑定struct和int指针到Renderscript

    mScript.bind_touchPoints(touchPoints);

    script.bind_intPointer(intPointer);

 

   ...

}

 

-------------------------------

 

Reading and writing to memory

 

读写内存

 

You can read and write to statically and dynamically allocated memory both at the Renderscript runtime and Android framework layer.

 

你可以同时在Renderscript运行时和Android框架层上读写静态和动态分配的内存。

 

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 get 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 rsSendToClient() function to overcome this limitation.

 

静态分配内存伴随着Renderscript运行时层上的单向通信限制。当Renderscript代码改变变量的值时,它出于效率的目的而不通信回Android框架层。来自Android框架的被设置的最后值总是在对get方法的一次调用期间被返回。然而,当Android框架修改一个变量时,那个改变可以被自动地通信到Renderscript运行时或在稍后的时候被同步。如果你需要从Renderscript运行时发送数据到Android框架层,你可以使用rsSendToClient()函数以克服这个限制。

 

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.

 

当处理动态分配内存时,在Renderscript运行时层上的任意改变被传播回Android框架层,如果你曾使用它的关联指针修改内存分配。在Android框架层上修改一个对象立刻地传播那个改变回Renderscript运行时层。

 

Reading and writing to global variables

 

读写全局变量

 

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.

 

读写全局变量是一个直截了当的过程。你可以在Android框架层上使用访问器方法或直接地在Renderscript代码中设置它们。谨记你在你的Renderscript代码中作出的任意改变不被传播回Android框架层。

 

For example, given the following struct declared in a file named rsfile.rs:

 

例如,假设以下声明在一个名为rsfile.rs的文件中的一个struct:

 

-------------------------------

 

typedef struct Point {

    int x;

    int y;

} Point_t;

 

Point_t point;

 

-------------------------------

 

You can assign values to the struct like this directly in rsfile.rs. These values are not propagated back to the Android framework level:

 

你可以像这样直接在rsfile.rs中赋值到struct。这些值不被传播回Android框架层:

 

-------------------------------

 

point.x = 1;

point.y = 1;

 

-------------------------------

 

You can assign values to the struct at the Android framework layer like this. These values are propagated back to the Renderscript runtime level:

 

你可以在Android框架层上像这样赋值给struct。这些值被传播回Renderscript运行时层:

 

-------------------------------

 

ScriptC_rsfile mScript;

 

...

 

Item i = new ScriptField_Point.Item();

i.x = 1;

i.y = 1;

mScript.set_point(i);

 

-------------------------------

 

You can read the values in your Renderscript code like this:

 

你可以在你的Renderscript代码中像这样读取值:

 

-------------------------------

 

rsDebug("Printing out a Point", point.x, point.y);

 

-------------------------------

 

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:

 

你可以用以下代码在Android框架层读取值。谨记这段代码只返回一个值,如果它曾在Android框架层上被设置。你将得到一个空指针异常,如果你只在Renderscript运行时层上设置该值:

 

-------------------------------

 

Log.i("TAGNAME", "Printing out a Point: " + mScript.get_point().x + " " + mScript.get_point().y);

System.out.println(point.get_x() + " " + point.get_y());

 

-------------------------------

 

Reading and writing global pointers

 

读写全局指针

 

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 get and set 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.

 

假设内存已经在Android框架层中被分配,并且已经被绑定到Renderscript运行时,你可以从Android框架层中通过使用那个指针的get和set方法来读写内存。在Renderscript运行时层中,你可以如平常那样用指针读写内存,而改变被传播回Android框架层,不像使用静态分配内存那样。

 

For example, given the following pointer to a struct in a file named rsfile.rs:

 

例如,假设下面在一个名为rsfile.rs文件中有一个指向一个struct的指针:

 

-------------------------------

 

typedef struct Point {

    int x;

    int y;

} Point_t;

 

Point_t *point;

 

-------------------------------

 

Assuming you already allocated memory at the Android framework layer, you can access values in the struct as normal. Any changes you make to the struct via its pointer variable are automatically available to the Android framework layer:

 

假设你已经在Android框架层分配好内存,你可以如平常那样访问结构体中的值。你通过其指针值对struct作出的任何改变对于Android框架层是自动地可用的:

 

-------------------------------

 

point[index].x = 1;

point[index].y = 1;

 

-------------------------------

 

You can read and write values to the pointer at the Android framework layer as well:

 

你还可以在Android框架层上对指针读写值:

 

-------------------------------

 

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 从索引0开始读取x和y

    points.get_x(0);

 

-------------------------------

 

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.

 

一旦内存已经被绑定好,每当你对一个值作出改变时你不必重新绑定内存到Renderscript运行时。

 

Except as noted, this content is licensed under Apache 2.0. For details and restrictions, see the Content License.

 

除特别说明外,本文在Apache 2.0下许可。细节和限制请参考内容许可证。

 

Android 4.0 r1 - 29 Mar 2012 18:25

 

-------------------------------

 

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

 

此页部分内容,是基于Android开源项目所创建和共享的工作,并且根据知识共享2.5署名许可证描述的条款来使用的修改版。

 

(本人翻译质量欠佳,请以官方最新内容为准,或者参考其它翻译版本:

* ソフトウェア技術ドキュメントを勝手に翻訳

http://www.techdoctranslator.com/android

* Ley's Blog

http://leybreeze.com/blog/

* 农民伯伯

http://www.cnblogs.com/over140/

* Android中文翻译组

http://androidbox.sinaapp.com/


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics