【问题标题】:What are the available kernel-functions that you can create on Renderscript?您可以在 Renderscript 上创建哪些可用的内核函数?
【发布时间】:2015-10-05 16:44:48
【问题描述】:

背景

我正在学习如何使用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 上的函数名称。

所以我假设不是每一个可能的函数都可以是核函数,都需要遵循一些规则(除了“attribute(kernel)”部分,需要添加) .

但我找不到这些规则。

文档中只有我找到的东西:

一个内核可能有一个输入分配,一个输出分配,或两者兼有。 一个内核可能不会有超过一个输入或一个输出分配。如果 需要多个输入或输出,这些对象应该是 绑定到 rs_allocation 脚本全局变量并从内核访问或 通过 rsGetElementAt_type() 或 rsSetElementAt_type() 调用的函数。 内核可以使用 x、y 和 z 参数。这些参数是可选的,但类型 坐标参数必须是 uint32_t。

问题

  1. 除了写的,还有什么创建内核函数的规则?

  2. 允许使用哪些其他参数?我的意思是,我可以传递哪些其他参数?我只能使用这两个“模板”的函数,还是可以使用具有其他参数集的其他内核函数?

  3. 是否有有效内核函数的列表?一个显示哪些参数集是允许的?

  4. 我是否可以自定义这些内核函数,以获得更多参数?例如,如果我制作了一个模糊函数(我知道我们有一个内置函数),我可以设置半径和模糊算法。

基本上所有这些问题都差不多

【问题讨论】:

    标签: android renderscript


    【解决方案1】:

    确实没有那么多规则。你必须有一个输入和/或一个输出,因为内核是在存在的范围内执行的(即你有一个 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 以了解具体关于模糊的示例。

    【讨论】:

    • 我不明白。所以我确实只有 2 个内核函数选项,或者没有?它怎么知道我给它的是输入还是输出?如果它只是输入,它可以做什么?也许修改输入?我可以或不能为内核函数添加额外的参数吗?如果我不能,我可以使用哪些功能?如果可以,它如何知道哪些用于位图(或其他分配)的每个像素机制?
    • 您可以使用传统 API(使用指针作为参数),也可以使用 RS_KERNEL 使用值传递。在遗留内核上 const 抛弃“const”并写入输入是错误的。同样对于 RS_KERNEL 版本,您实际上不能写入输入并让它反映该更新。在提出更多问题之前,请先查看一些示例代码,因为我认为如果您了解基于每个像素(即单元)的内核行为在所有计算语言中的工作原理可能会更容易。
    • 但我发现的代码来自示例。我不明白它是如何工作的。它怎么知道每个参数是什么?我还可以使用哪些其他参数来自动填充?
    • 唯一的自动填充参数是 x, y, (在 Android M 中可能还有 z)。其他参数(在任何 x、y、z 之前)在 Java 反射中转换为分配。如果返回类型不是 void,也会发生同样的事情。
    • 怎么知道哪个参数是哪个,并填充呢?按类型和名称?按订单?我可以放一些奇怪的东西,例如 "x, someInput, y" 吗?
    【解决方案2】:

    只是我开始学习 RS 时遇到的一些关键点。基本上,上面的黄色文本包含了所有 RS 智慧,但以“太紧凑”的方式理解。为了回答您的问题 1 和 2,您必须区分两种类型的分配。第一种类型的分配我称之为“正式”分配。在内核表达式中

          uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) {
    

    这是输入分配(类型为 uchar4,即 8 位无符号整数)和输出分配,也是 uchar4 - 这是您可以在内核表达式左侧看到的类型。输出将通过“return”返回,与 Java 函数相同。您至少需要一个正式分配(即一个输入或一个输出或两者)。

    我称之为“边分配”的另一种分配类型。这是您通过脚本全局处理的内容,这些也可以是输入或输出分配。如果您将它们用作输入,您将通过 copyTo() 从 Java 端传递输入。如果您将它们用作输出,您将通过 copyFrom() 将输出获取到 Java 端。

    现在,重点是,尽管您至少需要一次正式分配,但正式分配和侧面分配之间没有质的区别,您唯一需要注意的是您至少使用了一次正式分配。

    内核中的所有分配(无论是“正式”还是“侧面”)在宽度和高度方面都具有相同的尺寸。

    问题 3 由 1 和 2 隐式回答。

    1. 仅正式的输入分配,
    2. 只有正式的输出分配,
    3. 正式的输入和正式的输出分配
    4. 1.-3。每个都可以有任意数量的额外“边”分配。

    问题 4:是的。在您的高斯示例中,如果您想传递模糊半径(例如 1-100)或模糊算法(例如类型 1,2 和 3),您只需为每一个使用一个全局变量,这样它们就可以在内核中应用。在这里,我不会在上述意义上谈论“分配”,因为它们总是与内核跨越的网格具有相同的维度(通常是 x 宽度乘以 y 高度)。尽管如此,您仍然需要通过 script_setxxx(yyy) 传递这些参数。

    希望这会有所帮助。

    【讨论】:

    • 我的问题是关于内核函数的。除了我使用的以外,我可以使用其他形式吗?什么可以用,什么不能用?
    • 上述第一个和第二个内核之间的唯一区别是第一个内核中的附加参数 uint32_t x, uint32_t y。然而,这些是可选的和隐含的,即如果您需要在内核传递期间访问 x 和 y 坐标,您将添加这些。一个典型的应用程序是 Gaussfilter,您需要访问每个像素的相邻像素以建立一些平均值(通过 rsGetElementAt_type() 访问相邻像素)。两次都需要 forEach_FUNCTIONNAME(Allocation ain, Allocation aout),因为这里有一个 In- AND Out-Allocation。
    • 所以你说我发现的是可选的?还有哪些是可选的,它如何判断每个参数应该是什么?按类型和名称?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2018-02-27
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多