我最近一直在使用RenderScript,目的是创建一个程序员可以轻松使用的API,类似于Microsoft Accelerator的工作方式。
此刻我遇到的麻烦是因为我想要在RenderScript层之间传递值并让所有内容以最有效的方式运行,这是我目前为止源代码的摘录:
int[] A = new int[10];
int[] B = new int[10];
for (int i = 0; i < 10; i++) {
A[i] = 2;
B[i] = i;
}
intAdd(A, B);
这只会创建两个基本数组,并用值填充它们并调用将它们发送到RenderScript的函数。
private void intAdd(int[] A, int[] B) {
RenderScript rs = RenderScript.create(this);
ScriptC_rsintadd intaddscript = new ScriptC_rsintadd(rs, getResources(), R.raw.rsintadd);
mScript = intaddscript;
for(int i = 0; i < A.length; i++) {
setNewValues(mScript, A[i], B[i]);
intaddscript.invoke_intAdd();
int C = getResult(mScript);
notifyUser.append(" " + C);
}
}
public void setNewValues(Script script, int A, int B) {
mScript.set_numberA(A);
mScript.set_numberB(B);
}
public int getResult(Script script) {
int C = mScript.get_numberC();
return C;
}
这会将一对值发送到以下RenderScript代码:
int numberA;
int numberB;
int numberC;
void intAdd() {
/*Add the two together*/
numberC = numberA + numberB;
/*Send their values to the logcat*/
rsDebug("Current Value", numberC);
}
但是这有两个问题,第一个是RenderScript的异步性质意味着当Java层请求值时,脚本还没有完成操作,或者它已经完成了操作,销毁了值输出并在下一个开始。由于RenderScript的调试可见性低,无法说清楚。
另一个问题是它效率不高,代码不断调用RenderScript函数将两个数字加在一起。理想情况下,我想将数组传递给RenderScript并将其存储在结构中,并在一个脚本调用中完成整个操作,而不是很多。但是为了得到它我认为我需要使用rsSendtoClient函数,但我没有找到任何关于如何使用它的材料。最好是我想使用rsForEach策略,但再次提供信息就是恐慌。
如果有人有任何想法,我会非常感激。感谢。
威尔斯 - 杰克逊答案 0 :(得分:2)
我不确定这对你是否有帮助,但是因为我知道通过RenderScript可以解决多少痛苦,所以我可以提供帮助。要使用rsSendToClient函数,您需要指示您创建的RenderScript实例将消息发送到的位置。这可以通过以下方式实现:
private void intAdd(int[] A, int[] B) {
RenderScript rs = RenderScript.create(this);
MySubclassedRSMessageHandler handler = new MySubclassedRSMessageHandler();
rs.setMessageHandler(handler);
ScriptC_rsintadd intaddscript = new ScriptC_rsintadd(rs, getResources(), R.raw.rsintadd);
mScript = intaddscript;
for(int i = 0; i < A.length; i++) {
setNewValues(mScript, A[i], B[i]);
intaddscript.invoke_intAdd();
int C = getResult(mScript);
notifyUser.append(" " + C);
}
}
有必要继承RenderScript.RSMessageHandler并覆盖run()方法。如果你还没有,请参见http://developer.android.com/reference/android/renderscript/RenderScript.RSMessageHandler.html。基本上没有办法绕过我认为是双刃剑的异步性质。
至于低效率,我会考虑创建一个RenderScript实例,让它保持运行(你可以在不需要时暂停它,将停留在内存中但停止线程,因此每次调用函数时都不会产生建设成本) 。从这里你可以拥有你的结构,然后从反射的Java层使用invoke_myFunction(这里的一些参数)。
希望这至少有一点帮助。
答案 1 :(得分:2)
我遇到了同样的问题。 程序的问题是不知道rs文件中的add函数何时应该运行 ,试试这应该工作
public void setNewValues(Script script, int A, int B) {
mScript.set_numberA(A);
mScript.set_numberB(B);
mscript.invoke_intAdd();
}
答案 2 :(得分:0)
我遇到了同样的问题。我认为rsSendtoClient函数没用,会产生很多错误。相反,使用指针并为其分配内存以将结果带回给您更容易。
我建议像这样解决你的问题:
在rsintadd.rs中使用此代码段:
int32_t *a;
int32_t *b;
int32_t *c;
void intAdd() {
for(int i = 0; i<10;i++){
c[i] = a[i] + b[i];
}
在您的JAVA代码中使用此代码段:
int[] B = new int[10];
int[] A = new int[10];
for (int i = 0; i < 10; i++) {
A[i] = 2;
B[i] = 1;
}
// provide memory for b using data in B
Allocation b = Allocation.createSized(rs, Element.I32(rs), B.length);
b.copyFrom(B);
inv.bind_b(b);
// provide memory for a using data in A
Allocation a = Allocation.createSized(rs, Element.I32(rs), A.length);
a.copyFrom(A);
inv.bind_a(a);
// create blank memory for c
inv.bind_c(Allocation.createSized(rs, Element.I32(rs), 10));
// call intAdd function
inv.invoke_intAdd();
// get result
int[] C = new int[10];
inv.get_c().copyTo(C);
for (int i = 0; i < C.length; i++) {
System.out.println(C[i]);
}
这是你在Logcat上的结果:
您的第一个问题是关于异步,您可以使用线程等待结果。在这个例子中,函数足够快,并立即将输出提供给C数组,因此结果可以显示在logcat上。
你的第二个问题是关于实现intAdd()函数而不回忆它。上面的代码就是答案。您可以在Java中访问int数组的任何部分,直到方法完成(与root()函数不同)。
希望这可以帮助某人:)