如何在Metal片段着色器中实现/使用原子计数器?

时间:2017-11-10 00:39:37

标签: metal atomicinteger

我想在Metal应用程序中实现A-Buffer算法,以实现与顺序无关的透明度。该技术的描述提到使用原子计数器。我从来没有使用过这些,甚至没有听过。我刚刚阅读了金属着色语言规范中的原子变量,但我无法弄清楚如何实际实现或使用它。

有没有人在Metal中有这些经验?你能指点我一个如何设置和使用简单整数计数器的例子吗?基本上每个渲染过程我都需要能够从片段着色器中增加一个整数,从零开始。这用于索引A-Buffer。

谢谢!

1 个答案:

答案 0 :(得分:4)

嗯,您的问题缺乏足够的细节,不仅仅提供一般概述。您可以考虑添加一个不完整的着色器函数,使用伪代码,您不确定如何实现某些内容。

无论如何,原子计数器是atomic_uint类型的变量(如果需要符号,则为atomic_int)。为了有用,需要在特定地址空间中共享变量。您的示例听起来需要device地址空间。因此,您需要一个由缓冲区支持的device变量。你会将其声明为:

fragment FragmentOut my_fragment_func(device atomic_uint &counter [[buffer(0)]], ...)
{
    ...
}

您还可以为参数使用结构类型,并将结构的字段设为您的atomic_uint变量。

要原子地将原子变量递增1并获得先前值,您可以这样做:

    uint value = atomic_fetch_add_explicit(&counter, 1, memory_order_relaxed);

原子变量的初始值取自执行draw或dispatch命令之前的缓冲区内容。它没有在规范中记录,但原子类型的大小和位解释似乎与相应的非原子类型相匹配。也就是说,您可以将uint(a.k.a。unsigned intuint32_t)写入缓冲区以初始化atomic_uint