我正在学习如何使用Renderscript,我在the docs中找到了这个部分:
在大多数方面,这与标准C功能相同。该 第一个值得注意的功能是应用于属性((内核)) 功能原型。
它们显示了一个内核函数的示例代码:
uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {
uchar4 out = in;
out.r = 255 - in.r;
out.g = 255 - in.g;
out.b = 255 - in.b;
return out;
}
似乎有些样本显示内核函数的参数可能不同,而不仅仅是上面显示的参数。
示例:
uchar4 __attribute__((kernel)) grayscale(uchar4 v_in) {
float4 f4 = rsUnpackColor8888(v_in);
float3 mono = dot(f4.rgb, gMonoMult);
return rsPackColorTo8888(mono);
}
事实上,Java上生成的函数对于所有这些函数仍然是相同的:
void forEach_FUNCTIONNAME(Allocation ain, Allocation aout)
其中FUNCTIONNAME是RS上函数的名称。
所以我假设并非所有可能的函数都可以作为内核函数,并且所有函数都需要遵循一些规则(除了" 属性(内核)"部分,需要添加)。
但我无法找到这些规则。
我发现的只有文档:
内核可能有输入分配,输出分配或两者。 内核可能没有多个输入或一个输出分配。如果 需要多个输入或输出,这些对象应该是 绑定到rs_allocation脚本全局变量并从内核或 通过rsGetElementAt_type()或rsSetElementAt_type()调用invokable函数。 内核可以使用。访问当前执行的坐标 x,y和z参数。这些参数是可选的,但是类型 坐标参数必须是uint32_t。
除了编写的内容之外,创建内核函数的规则有哪些?
允许使用哪些其他参数?我的意思是,我可以通过哪些其他参数?只是那些2"模板"我可以使用的函数,还是可以使用其他具有其他参数集的内核函数?
是否有有效的内核函数列表?一个显示允许哪些参数集?
我可以自定义这些内核函数,以获得更多参数吗?例如,如果我有一个模糊功能(我知道我们有一个内置的功能),我可以设置半径和模糊算法。
基本上所有这些问题都是相同的
答案 0 :(得分:1)
真的没有那么多规则。你必须有输入和/或输出,因为内核在那里存在的范围内执行(即你有一个2-D Allocation,x = 200,y = 400 - 它将在输入/输出的每个单元格上执行)。我们确实支持无分配启动,但它仅在最新的Android版本中提供,因此在大多数设备上都不可用。我们也支持Android M的多输入,但早期的目标API不会用它构建(除非您使用兼容性库)。
参数通常是基本类型(char,int,unsigned int,long,float,double,...)或向量类型(例如float4,int2,...)。您也可以使用结构,前提是它们的定义中不包含指针。除非使用遗留内核API,否则不能使用指针类型,但即使这样,您也只能使用指向非指针数据的单个指针。 https://android.googlesource.com/platform/cts/+/master/tests/tests/renderscript/src/android/renderscript/cts/kernel_all.rs有很多简单的内核,我们用它来进行琐碎的测试。它显示了如何组合大多数类型。
您可以选择包含rs_kernel_context参数(可以让您查找有关启动大小的信息)。您还可以选择传递x,y和/或z(每个都使用uint32_t类型)以获取当前执行发生的实际索引。每次x / y / z坐标对于单次启动都是唯一的,让您知道正在操作的单元格。
对于您的问题4,您无法按照您想要的方式使用半径。它必须是一个全局变量作为输入,因为我们唯一的内核输入传统上随着输入/输出分配的单元格而变化。您可以查看https://android.googlesource.com/platform/cts/+/master/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs,了解有关模糊的示例。
答案 1 :(得分:1)
当我开始学习RS时,我正在努力的一些关键点。基本上,上面的黄色文本包括所有RS智慧,但是以“过于紧凑”的方式理解。为了回答您的问题1和2,您必须区分两种类型的分配。我称之为“正式”分配的第一种分配方式。在内核表达式
中 uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {
这是(类型为uchar4的输入分配,即8位无符号整数)和输出分配输出也是uchar4 - 这是您可以在内核表达式左侧看到的类型。输出将通过“return”返回,与Java函数相同。您至少需要一个正式分配(即一个输入或一个输出或两者都有)。
我称之为“side Allocation”的其他类型的分配。这是您通过脚本全局变量处理的,这些也可以是输入或输出分配。如果将它们用作输入,则将通过copyTo()从Java端传递输入。如果如果将它们用作输出,则将通过copyFrom()将输出提供给Java端。
现在,重点在于,虽然您需要至少一次正式分配,但正式和侧面分配之间没有质的差别,您唯一需要注意的是您至少使用一次正式分配。 / p>
内核中的所有分配(无论是“正式”还是“侧”)在宽度和高度方面具有相同的尺寸。
问题3由1和2隐含地回答。
问题4:是的。在Gauss示例中,如果要传递模糊半径(例如1-100)或模糊算法(例如类型1,2和3),您只需为每个模型使用一个全局变量,这样它们就可以在内核中应用。在这里我不会谈到上面意义上的“分配”,因为它们总是与内核跨越的网格具有相同的维度(通常是x宽度乘以y高度)。不过你还需要通过script_setxxx(yyy)传递这些参数。
希望这有点帮助。