【问题标题】:How to retrieve a struct from Renderscript kernel [duplicate]如何从 Renderscript 内核中检索结构 [重复]
【发布时间】:2016-07-22 19:15:56
【问题描述】:

我有问题。我想从渲染脚本内核中检索结构。我想要的是我会得到一个结构元素的输入......我会修改它,然后将它修改后返回。但是反射层没有这种方式。我尝试手动反序列化缓冲区中的数据,但我什至无法将缓冲区复制到 ByteBuffer,因为分配在类型的 copyTo 中具有验证,所以我不知道我应该做什么......

【问题讨论】:

  • 嗯......“重复”中的答案不正确。答案是可以使用分配的copy1DRangeToUnchecked方法将其复制到一个ByteBuffer中,然后自己反序列化。后来才意识到

标签: java android renderscript android-renderscript


【解决方案1】:

RenderScript 支持自定义元素。要创建一个,请在 RS 脚本中声明一个自定义 typedef struct,如下所示:

typedef struct MyElement {

    int x;
    int y;
    bool simpleBool;

} MyElement_t;

在构建过程之后,将出现一个ScriptField_MyElement Java 类,镜像 RS 结构。您将能够使用此类创建使用您自己的元素的自定义分配:

// Declares a new Allocation, based upon the custom struct Element
Element myElement = ScriptField_MyElement.createElement(mRS);
Allocation myElementsAllocation = Allocation.createSized(mRS, myElement, 5);

// Or

Allocation myElementsAllocation = ScriptField_MyElement.create1D(mRS, sizeX).getAllocation();

您可以在CustomElementExample sample project 中找到此过程的示例。 此外,在SurfaceRenderExample sample project 中,您可以看到如何使用自定义元素来模拟数学结构(在本例中为粒子,以某种加速度下落)。

RenderScript 脚本内部:

  • 从分配中获取自定义元素:

    MyElement_t el = * (MyElement_t *) rsGetElementAt(aIn, index);
    
  • 更改自定义元素成员:

    el.x = 10;
    
  • 在分配中设置自定义元素:

    rsSetElementAt(myAlloc, (void *)&el);
    

参考:RenderScript: parallel computing on Android, the easy way

编辑:

目前,没有直接的方法可以将自定义结构元素复制到 Java 端。

CustomStructElementCopyToJava sample project 提供了该过程的示例。

例子的简短说明

注意:以下过程是实验性,根本没有性能!如果您打算大量使用此进程,请使用 Android NDK 访问分配。 此外,在 Android SDK 的未来版本中,此代码可能会因为它依赖于 Java 反射而中断;一些通常隐藏的方法可能会在 Android SDK 中更改,恕不另行通知。

假设使用以下自定义结构元素:

typedef struct Point {
    int x;
    int y;
} Point_t;

查看生成的结构代码时(可以看到,在 Android Studio 中,通过按下 CTRL+B 同时关注 Java 端的 ScriptField_Point 元素),以下元素可见:

public static Element createElement(RenderScript rs) {
        Element.Builder eb = new Element.Builder(rs);
        eb.add(Element.I32(rs), "x");
        eb.add(Element.I32(rs), "y");
        return eb.create();
    }

您可以用 hacky 方式映射自定义结构的内容:

1) 定义目标字节数组:

    byte destinationArray[] = new byte[allocationGrayPointOrdered.getBytesSize()];

2) 使用Java反射访问隐藏的Allocation.copyTo方法:

private static Method getCopyToWithoutValidationMethod(){
    // private void copyTo(Object array, Element.DataType dt, int arrayLen)
    Method allocationHiddenCopyToMethod = null;
    try {
        allocationHiddenCopyToMethod = Allocation.class.getDeclaredMethod("copyTo", Object.class, Element.DataType.class, int.class);
        allocationHiddenCopyToMethod.setAccessible(true);
    } catch (NoSuchMethodException e) {
        throw new RuntimeException("Could not find allocationHiddenCopyToMethod");
    }

    return allocationHiddenCopyToMethod;
}

3) 执行复制:

// Gets reflected method
Method copyToWithoutValidationMethod = getCopyToWithoutValidationMethod();

// Tries to copy contents
try {
    copyToWithoutValidationMethod.invoke(allocationGrayPointOrdered, destinationArray, 
                                                Element.DataType.UNSIGNED_8, destinationArray.length);
} catch (IllegalAccessException e) {
    throw new RuntimeException(e);
} catch (InvocationTargetException e) {
    throw new RuntimeException(e);
}

4) 一旦数组被源数据填充,就可以将其内容映射到人类可读的结构。

// Defines the destination array
ScriptField_Point.Item mappedItems[][] = new ScriptField_Point.Item[sizeX][sizeY];

// Wraps array contents
ByteBuffer byteBuffer = ByteBuffer.wrap(destinationArray);
// Sets byte order to be Android-like
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);

// Iterates on every column and row
for (int x = 0; x < sizeX; x++) {
    for (int y = 0; y < sizeY; y++) {

        // Allocates a new item
        ScriptField_Point.Item currentItem = new ScriptField_Point.Item();

        // Calculate the offset in the source array
        int currentOffset = (x + y * sizeX) * ScriptField_Point.Item.sizeof;

        // Gets data from the byte array
        currentItem.x = byteBuffer.getInt(currentOffset);
        currentItem.y = byteBuffer.getInt(currentOffset + 4);

        mappedItems[x][y] = currentItem;
    }
}

完整解释请参考book

【讨论】:

  • 嗯,但您指定了如何使用反射层创建分配。我的问题是如何在内核运行(和修改)后在 java 中读取结构
  • 我添加了过程:)
猜你喜欢
  • 2013-10-25
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 2020-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多