page.title=Compute parent.title=Renderscript parent.link=index.html @jd:body

In this document

  1. Creating a Compute Renderscript
    1. Creating the Renderscript file
    2. Calling the Renderscript code

Related Samples

  1. Hello Compute
  2. Balls

Renderscript exposes a set of compute APIs that you can use to do intensive computational operations. You can use the compute APIs in the context of a graphics Renderscript such as calculating the positions of many objects in a scene. You can also create standalone compute Renderscripts such as one that does image processing for a photo editor application.

Compute Renderscripts scale to the amount of processing cores available on the device. This is enabled through a function named rsForEach() (or the forEach_root() method at the Android framework level). that automatically partitions work across available processing cores on the device. For now, compute Renderscripts can only take advantage of CPU cores, but in the future, they can potentially run on other types of processors such as GPUs and DSPs.

Creating a Compute Renderscript

Implementing a compute Renderscript creating a .rs file that contains your Renderscript code and calling it at the Android framework level with the forEach_root() or at the Renderscript runtime level with the rsForEach() function. The following diagram describes how a typical compute Renderscript is set up:

Figure 1. Compute Renderscript overview

The following sections describe how to create a simple compute Renderscript and use it in an Android application. This example uses the HelloCompute Renderscript sample that is provided in the SDK as a guide (some code has been modified from its original form for simplicity).

Creating the Renderscript file

Your Renderscript code resides in .rs and .rsh files in the <project_root>/src/ directory. This code contains the compute logic and declares all necessary variables and pointers. Every compute .rs file generally contains the following items:

The following code shows how the mono.rs file is implemented:

#pragma version(1)
#pragma rs java_package_name(com.example.android.rs.hellocompute)

//multipliers to convert a RGB colors to black and white
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};

void root(const uchar4 *v_in, uchar4 *v_out) {
  //unpack a color to a float4
  float4 f4 = rsUnpackColor8888(*v_in);
  //take the dot product of the color and the multiplier
  float3 mono = dot(f4.rgb, gMonoMult);
  //repack the float to a color
  *v_out = rsPackColorTo8888(mono);
}

Calling the Renderscript code

You can do Renderscript to Renderscript calls with rsForEach in situations such as when a graphics Renderscript needs to do a lot of computational operations. The Renderscript Balls sample shows how this is setup. The balls.rs graphics Renderscript calls the balls_physics.rs compute Renderscript to calculate the location of the balls that are rendered to the screen.

Another way to use a compute Renderscript is to call it from your Android framework code by creating a Renderscript object by instantiating the (ScriptC_script_name) class. This class contains a method, forEach_root(), that lets you invoke rsForEach. You give it the same parameters that you would if you were invoking it at the Renderscript runtime level. This technique allows your Android application to offload intensive mathematical calculations to Renderscript. See the HelloCompute sample to see how a simple Android application can utilize a compute Renderscript.

To call a compute Renderscript at the Android framework level:

  1. Allocate memory that is needed by the compute Renderscript in your Android framework code. You need an input and output {@link android.renderscript.Allocation} for Android 3.2 (API level 13) platform versions and older. The Android 4.0 (API level 14) platform version requires only one or both {@link android.renderscript.Allocation}s.
  2. Create an instance of the ScriptC_script_name class.
  3. Call forEach_root(), passing in the allocations, the Renderscript, and any optional user-defined data. The output allocation will contain the output of the compute Renderscript.

In the following example, taken from the HelloCompute sample, processes a bitmap and outputs a black and white version of it. The createScript() method carries out the steps described previously. This method the compute Renderscript, mono.rs, passing in memory allocations that store the bitmap to be processed as well as the eventual output bitmap. It then displays the processed bitmap onto the screen:

package com.example.android.rs.hellocompute;

import android.app.Activity;
import android.os.Bundle;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.renderscript.RenderScript;
import android.renderscript.Allocation;
import android.widget.ImageView;

public class HelloCompute extends Activity {
  private Bitmap mBitmapIn;
  private Bitmap mBitmapOut;

  private RenderScript mRS;
  private Allocation mInAllocation;
  private Allocation mOutAllocation;
  private ScriptC_mono mScript;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);

      mBitmapIn = loadBitmap(R.drawable.data);
      mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
                                       mBitmapIn.getConfig());

      ImageView in = (ImageView) findViewById(R.id.displayin);
      in.setImageBitmap(mBitmapIn);

      ImageView out = (ImageView) findViewById(R.id.displayout);
      out.setImageBitmap(mBitmapOut);

      createScript();
  }
  private void createScript() {
      mRS = RenderScript.create(this);
      mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
          Allocation.MipmapControl.MIPMAP_NONE,
          Allocation.USAGE_SCRIPT);
      mOutAllocation = Allocation.createTyped(mRS, mInAllocation.getType());
      mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono);
      mScript.forEach_root(mInAllocation, mOutAllocation);
      mOutAllocation.copyTo(mBitmapOut);
  }

  private Bitmap loadBitmap(int resource) {
      final BitmapFactory.Options options = new BitmapFactory.Options();
      options.inPreferredConfig = Bitmap.Config.ARGB_8888;
      return BitmapFactory.decodeResource(getResources(), resource, options);
  }
}

To call a compute Renderscript from another Renderscript file:

  1. Allocate memory that is needed by the compute Renderscript in your Android framework code. You need an input and output {@link android.renderscript.Allocation} for Android 3.2 (API level 13) platform versions and older. The Android 4.0 (API level 14) platform version requires only one or both {@link android.renderscript.Allocation}s.
  2. Call rsForEach(), passing in the allocations and any optional user-defined data. The output allocation will contain the output of the compute Renderscript.

The following example, taken from the Renderscript Balls sample, demonstrates how to do make a script to script call:

rs_script script;
rs_allocation in_allocation;
rs_allocation out_allocation;
UserData_t data;
...
rsForEach(script, in_allocation, out_allocation, &data, sizeof(data));

In this example, assume that the script and memory allocations have already been allocated and bound at the Android framework level and that UserData_t is a struct declared previously. Passing a pointer to a struct and the size of the struct to rsForEach is optional, but useful if your compute Renderscript requires additional information other than the necessary memory allocations.