How to pass array values to and from Android RenderScript using Allocations

亡梦爱人 提交于 2019-11-30 23:55:52

问题


I've been working with RenderScript recently with the intent of creating an API that a programmer can use with ease, similar to the way that Microsoft Accelerator works.

The trouble I'm stuck with at the moment as that I want to pass values to and from the RenderScript layer and have everything run in the most efficient way possible, this is an extract of my source code so far:

    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);

This just creates two basic arrays and fills them with values and calls the functions that will send them to 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;
}

This will send a pair of values to the following RenderScript code:

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);
 }

But there are two problems with this, the first one is the Asynchronous nature of RenderScript means that when the Java layer requests the value, the script either hasn't done the operation yet, or it's already done it, destroyed the value of the output and started on the next one. And thanks to the low debugging visibility of RenderScript there's no way of telling.

The other problem is that it's not very efficient, the code is constantly calling the RenderScript function to add two numbers together. Ideally I'd want to pass the array to RenderScript and store it in a struct and have the entire operation done in one script call rather than many. But in order to get it back I reckon I'll need to user the rsSendtoClient function, but I've not found any material on how to use it. And preferably I'd like to use the rsForEach strategy, but again information is scare.

If anyone has any ideas I'd be very grateful. Thanks.

Will Scott-Jackson


回答1:


I'm not sure if this will be of help to you at this point but since I know how much of a pain it can be to work through RenderScript, here is the help I can offer. In order to use the rsSendToClient function, you need to instruct the RenderScript instance you created where to send messages to. This is accomplished by something such as:

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);
     }
}

It will be necessary to subclass RenderScript.RSMessageHandler and override the run() method. See http://developer.android.com/reference/android/renderscript/RenderScript.RSMessageHandler.html if you havn't already. Basically there is no way to get around the asynchronous nature which I find to be a double edged sword.

As for the inefficiency, I would consider creating a RenderScript instance, leave it running (you can pause it when not needed, will stay in memory but stop the threads, thus not incurring the construction cost each time you call a function). From here you can have your structures and then use invoke_myFunction(some arguments here) from the reflected Java layer.

Hopefully this helps at least a little bit.




回答2:


I had the same problem. The problem with your program is that doesn't know when the add function in rs file should run ,try this it should work

public void setNewValues(Script script, int A, int B) {
mScript.set_numberA(A);
mScript.set_numberB(B);
mscript.invoke_intAdd();

}



回答3:


I had the same problem with you. I think rsSendtoClient function is not useful and creates many bugs. Instead, using a pointer and allocate it a memory to bring result back to you is much easier.

I recommend the solution of your problem like this:

In rsintadd.rs use this snippet:

int32_t *a;
int32_t *b;
int32_t *c;

void intAdd() {
    for(int i = 0; i<10;i++){
    c[i] = a[i] + b[i];
}

In your JAVA code use this snippet:

    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]);
    }

And this is your result on Logcat:

Your first question is about Asynchronous, you can use thread to wait result. In this example, the function is fast enough and instantly gives the output to C array so result can show on logcat.

Your second question is about implement intAdd() function without recalling it. The code above is the answer. You can access any part of int array in Java until the method is done ( different from root() function ).

Hope this can help someone :)



来源:https://stackoverflow.com/questions/9655346/how-to-pass-array-values-to-and-from-android-renderscript-using-allocations

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