如何在金属片段着色器中 implement/use 原子计数器?

How to implement/use atomic counter in Metal fragment shader?

我想在我的 Metal 应用程序中实现顺序无关透明的 A-Buffer 算法。该技术的描述提到使用原子计数器。我从未使用过其中之一,甚至从未听说过它们。我刚刚在 Metal Shading Language Specification 中阅读了有关原子变量的内容,但我无法弄清楚如何实际实现或使用它。

有人在 Metal 中使用过这些吗?你能给我举一个如何设置和使用简单整数计数器的例子吗?基本上每个渲染通道我都需要能够从片段着色器中增加一个整数,从零开始。这用于索引到 A 缓冲区。

谢谢!

好吧,您的问题缺乏足够的细节,无法提供比一般概述更多的内容。您可能会考虑添加一个不完整的着色器函数,在您不确定如何实现某些东西的地方使用伪代码。

无论如何,原子计数器是 atomic_uint 类型的变量(如果需要符号,则为 atomic_int 类型)。为了有用,变量需要在特定地址 space 之间共享。您的示例听起来需要 device 地址 space。因此,您需要一个由缓冲区支持的 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);

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