Can one use RenderScript's rsForEach on a non-root kernel?

痴心易碎 提交于 2019-12-04 03:42:42

问题


Can one invoke a non-root RenderScript kernel using rsForEach? There are many examples of using rsForEach to call the root kernel from within an invokable RenderScript function:

  • Documentation for Androids Renderscript advanced rsForEach call
  • How to write a convolution multiplication in Android Renderscript?
  • Passing Array to rsForEach in Renderscript Compute

These bind the script itself to a variable in the RenderScript context, then invoke the root kernel from within RenderScript. For example, in the Activity class:

...
mScript = new ScriptC_gradient(mRS);
// bind Allocations and mScript to variables in the RenderScript context:
mScript.set_gIn(mImageAllocation);
mScript.set_gOut(mGradientAllocation);
mScript.set_gScript(mScript);
// invoke gradient function:
mScript.invoke_gradient();
...

And in gradient.rs:

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

rs_allocation gOut;
rs_allocation gIn;
rs_script gScript;

void gradient() {
  rsForEach(gScript, gIn, gOut);
}
void root(const uchar4 *v_in, uchar4 *v_out, ...

But if I have another kernel gray could I invoke it after root, inside gradient?

// I thought it would look like this:
void gradient() {
  rsForEach(gScript, gIn, gOut);
  rsForEach(gScript, gIn, gOut, NULL, NULL, gExportForEachIdx_gray);
}
// Or:
void gradient() {
  rsForEach(gScript, gIn, gOut);
  rsSetMainKernel(&gScript, "gray");
  rsForEach(gScript, gIn, gOut);
}

But the documentation for rsForEach seems to indicate that it doesn't support anything like this. Perhaps it can be accomplished by setting something in a rs_script_call_t, but the doc is rather terse about that type: (Retrieved 20 September 2013)

typedef struct rs_script_call rs_script_call_t**

Structure to provide extra information to a rsForEach call. Primarly used to restrict the call to a subset of cells in the allocation.

This question is mostly out of curiosity- I expect the preferred method is to call them from Java:

...
mScript = new ScriptC_gradient(mRS);
// bind Allocations and mScript to variables in the RenderScript context:
mScript.forEach_root(mImageAllocation, mGradientAllocation);
mScript.forEach_gray(mGradientAllocation, mGrayGradientAllocation);
...

These seem to be synchronized. If one defines root and gray as follows:

void root(...) { rsDebug("root", 0,0);  }
void gray(...) { rsDebug("gray", 1,1);  }

then calling forEach_root then forEach_gray causes "root, {0,0}" to be logged NxM times before it starts logging "gray, {1,1}" - I haven't found documentation that guarantees that, though. Anybody know where that is?


回答1:


Unfortunately we don't currrently have a way to invoke a non-root RenderScript kernel using rsForEach() from the script. You will have to call into it from Java directly. You could also put the second kernel in another Script as root() and then bind that rs_script as well (e.g. you can have gScriptGradient and gScriptGray and execute them sequentially from a single invoke in your primary Script).

I initially missed your second question about synchronization between parallel kernels. They are indeed ordered. Although kernels are launched asynchronously, the second kernel will not run until the first kernel is complete.



来源:https://stackoverflow.com/questions/18924176/can-one-use-renderscripts-rsforeach-on-a-non-root-kernel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!