Question

I was wondering if it's possible to write/modify renderscript code when the android application is running. My main goal is to make an app where users can learn to work with renderscript without any java knowledge. The basic layout of the app would consist of an input and output image, with the possibility for code input. The basic functionality of this app is already working and this is an image of the interface. App layout

It would be useful to test renderscript code with direct feedback from the app.

I've already done research about the build process and came up with the following idea:

A basic "template" renderscript file, with the necessary global variables like in and out allocations.

My java code would create a script object of the generated java class and do the basic initialization of these global script variables. The root function of this template .rs file would be empty, and it should be possible to be implemented by the user at runtime.

When the user types in his code in the main view of the app, the code is written to my own .rs file which then is compiled by the llvm-rs-cc compiler, invoked by the application. The generated .bc would then be copied to the location of the original .bc file of the template. Because the only change of code happens inside the root function, it would not be necessary to make changes to the surrounding java code.

The problem I'm having at the moment is the fact that the .bc files are bundled within the final apk inside the res/raw folder, which is not accessible by the app. Overwriting old .bc files with the newly generated files is therefore not possible.

Is there a(nother) way to compile renderscript code at runtime?

Edit: Solution can be found in this github link. For more details, check this answer, read the last comment

Was it helpful?

Solution

You will have to alter the generated glue class (ScriptC_mono) and it's base (ScriptC) at the very least.

<ExtremeHax>

The .bc file is read and passed down to RenderScript's internals. So far as I can tell, that is done inside ScriptC.internalCreate(), which is wired to read a raw resource. You need it to instead read your file from a location you control. Possibly you will only need to modify internalCreate() but there will probably be complications requiring broader editing.

Once you implement RuntimeScriptC, you should modify ScriptC_mono to inherit from that base class instead of ScriptC.

As you noted, you will be very limited in the changes you can make to the rs code since you cannot modify the glue class at runtime. For example, you could not change the signature of a kernel. However you could take this hack a bit further: if you forgo the glue class, it is possible to make whatever changes you want.

Kernels are invoked in the glue class by index rather than by name, and type/element checks are done inside the glue class. Thus even if you changed the kernel's signature, so long as you knew its index and the types of its in and out allocations, you could still invoke it by using forEach() directly.

public class ScriptC_mono extends ScriptC {
  //...

  public void forEach_root(Allocation ain, Allocation aout) {
    // check ain
    if (!ain.getType().getElement().isCompatible(__U8_4)) {
        throw new RSRuntimeException("Type mismatch with U8_4!");
    }
    // check aout
    if (!aout.getType().getElement().isCompatible(__U8_4)) {
        throw new RSRuntimeException("Type mismatch with U8_4!");
            // Verify dimensions
    Type tIn = ain.getType();
    Type tOut = aout.getType();
    if ((tIn.getCount() != tOut.getCount()) ||
        (tIn.getX() != tOut.getX()) ||
        (tIn.getY() != tOut.getY()) ||
        (tIn.getZ() != tOut.getZ()) ||
        (tIn.hasFaces() != tOut.hasFaces()) ||
        (tIn.hasMipmaps() != tOut.hasMipmaps())) {
        throw new RSRuntimeException("Dimension mismatch between input and output parameters!");
    }
    forEach(mExportForEachIdx_root, ain, aout, null);
  }
}

</ExtremeHax>

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top