1
votes

In Java I have this code for creating the Allocation for the intPointer. But after the renderscript computation I can't get the value of the allocation back. There is no copyTo(int) method only byte[], short[], int[], float[], bitmap.

    //Create Allocation
    Allocation intPointer = Allocation.createSized(renderScript, Element.I32(renderScript), 2);

    convolution.bind_intPointer(intPointer);
    convolution.forEach_root(allocationOut);

    [...]
    //read Allocation, not working
    int[] ints = new int[]{0x01234567};
    intPointer.copyTo(ints);             //does not overwrite the ints the line above
    int i = (int)ints[0];
    Log.d("ints", String.valueOf(i));

renderscript:

#pragma version(1)
#pragma rs java_package_name(package com.ap.wificam)
#pragma rs_fp_imprecise

rs_allocation input;
rs_allocation mask;

int32_t *intPointer = 0;

void root(uchar4* out, uint32_t x, uint32_t y) {

    //do some stuff

    if((sum.x + sum.y + sum.z)/3 > *intPointer)
        *intPointer = (sum.x + sum.y + sum.z)/3;    //wirte data to intPointer

    *out = convert_uchar4(sum);
}

Log.d("ints", String.valueOf(i)); gives me D/intsīš• 19088743 and rsDebug("rs", *intPointer); 2045 0x7fd

How can I get my int value from the Allocation?

1
with this code I am able to read the int: int[] ints = new int[]{0x0,0x0}; intPointer = convolution.get_intPointer(); intPointer.copyTo(ints); the int[] array needs to have two elements. - Penta

1 Answers

0
votes

Your RenderScript setup seems to be correct, but I think you're having problems initializing the data in the allocation correctly.

Since you're reading the values of the allocation inside RenderScript when you compare if the sum average is greater than *intPointer, you'll want to make sure the starting value for that is what you're actually expecting. Otherwise it will have uninitialized data and the > comparison will fail most of the time.

I guess that's what you were trying to do with int32_t *intPointer = 0;, but that's not really the correct way to initialize the data of pointers in C. The easiest way to do this is to do a data copy from Java right after you create the allocation:

Allocation intPointer = Allocation.createSized(renderScript, Element.I32(renderScript), 2);
intPointer.copy1DRangeFrom(0, 2, new int[2]);
convolution.bind_intPointer(intPointer);

This will make sure all values are 0 at the start of your RS kernel (since in Java, new int[2] creates a 0-initialized array).

Furthermore, your code might not be entirely thread-safe. Since you will have many threads reading and writing simultaneously to that single *intPointer address, you might run into synchronization problems, where the final value you get out of that may or may not be the true global maximum from all your threads.

I would suggest that instead of doing this, you store all (sum.x + sum.y + sum.z)/3 values in an allocation that is as big as your input data, then copy that allocation back out to Java and from there, do a simple loop over its array to find the maximum value.

Properly parallelizing a maximum algorithm from inside a RenderScript kernel is actually a bit difficult to do (you can read this other answer I posted some time ago for more details if you're interested), so to keep things simple, you might be better off just finding the maximum from Java instead as I suggested above.