6

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

有没有人在金属方面有这些经验?你能给我举个例子来说明如何设置和使用一个简单的整数计数器吗?基本上每个渲染通道我都需要能够从片段着色器中增加一个整数,从零开始。这用于对 A-Buffer 进行索引。

谢谢!

4

1 回答 1

11

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

无论如何,原子计数器是类型的变量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);

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

于 2017-11-10T04:53:35.963 回答