我想在Metal应用程序中实现A-Buffer算法,以实现与顺序无关的透明度。该技术的描述提到使用原子计数器。我从来没有使用过这些,甚至没有听过。我刚刚阅读了金属着色语言规范中的原子变量,但我无法弄清楚如何实际实现或使用它。
有没有人在Metal中有这些经验?你能指点我一个如何设置和使用简单整数计数器的例子吗?基本上每个渲染过程我都需要能够从片段着色器中增加一个整数,从零开始。这用于索引A-Buffer。
谢谢!
答案 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 int
或uint32_t
)写入缓冲区以初始化atomic_uint
。