Search code examples
renderscript

Renderscript, forEach_root, and porting from OpenCL


1) How can I access in forEach_root() other elements except for the current one?

In OpenCL we have pointer to the first element and then can use get_global_id(0) to get current index. But we can still access all other elements. In Renderscript, do we only have pointer to the current element?

2) How can I loop through an Allocation in forEach_root()?

I have a code that uses nested (double) loop in java. Renderscript automates the outer loop, but I can't find any information on implementing the inner loop. Below is my best effort:

void root(const float3 *v_in, float3 *v_out) {
  rs_allocation alloc = rsGetAllocation(v_in);
  uint32_t cnt = rsAllocationGetDimX(alloc);
  *v_out = 0;
  for(int i=0; i<cnt; i++)  
    *v_out += v_in[i];
}

But here rsGetAllocation() fails when called from forEach_root().

05-11 21:31:29.639: E/RenderScript(17032): ScriptC::ptrToAllocation, failed to find 0x5beb1a40

Just in case I add my OpenCL code that works great under Windows. I'm trying to port it to Renderscript

typedef float4 wType;

__kernel void gravity_kernel(__global wType *src,__global wType *dst)
{
  int id = get_global_id(0);
  int count = get_global_size(0);
  double4 tmp = 0;
  for(int i=0;i<count;i++) {
    float4 diff = src[i] - src[id];
    float sq_dist = dot(diff, diff);
    float4 norm = normalize(diff);
    if (sq_dist<0.5/60)
      tmp += convert_double4(norm*sq_dist);
    else
      tmp += convert_double4(norm/sq_dist);
  }
  dst[id] = convert_float4(tmp);
}

Solution

  • You can provide data apart from your root function. In the current android version (4.2) you could do the following (It is an example from an image processing scenario):

    Renderscript snippet:

    #pragma version(1)
    #pragma rs java_package_name(com.example.renderscripttests)
    
    //Define global variables in your renderscript:
    rs_allocation pixels;
    int width;
    int height;
    
    // And access these in your root function via rsGetElementAt(pixels, px, py)
    void root(uchar4 *v_out, uint32_t x, uint32_t y)
    {
        for(int px = 0; px < width; ++px)
            for(int py = 0; py < height; ++py)
            {
                // unpack a color to a float4
                float4 f4 = rsUnpackColor8888(*(uchar*)rsGetElementAt(pixels, px, py));
                ...
    

    Java file snippet

    // In your java file, create a renderscript:
    RenderScript renderscript = RenderScript.create(this);
    
    ScriptC_myscript script = new ScriptC_myscript(renderscript);
    
    // Create Allocations for in- and output (As input the bitmap 'bitmapIn' should be used):
    Allocation pixelsIn = Allocation.createFromBitmap(renderscript, bitmapIn,
             Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
    Allocation pixelsOut = Allocation.createTyped(renderscript, pixelsIn.getType());
    
    // Set width, height and pixels in the script:
    script.set_width(640);
    script.set_height(480);
    script.set_pixels(pixelsIn);
    
    // Call the for each loop:
    script.forEach_root(pixelsOut);
    
    // Copy Allocation to the bitmap 'bitmapOut':
    pixelsOut.copyTo(bitmapOut);
    

    You can see, the input 'pixelsIn' is previously set and used inside the renderscript when calling the forEach_root function to calculate values for 'pixelsOut'. Also width and height are previously set.