当 AppendStructuredBuffer 在计算着色器中溢出时会发生什么?
What happens when an AppendStructuredBuffer overflows in a compute shader?
我有一个 Unity 项目,我在其中通过计算着色器中的 Append(triangle)
写入 AppendStructuredBuffer<Triangle>
。
在这种情况下,我知道可能存在的三角形数量的理论限制,因此显然正确的方法是相应地调整缓冲区的大小。不过,作为 hack,我正在尝试分配更小的缓冲区,以便系统的其他部分可以更有效地处理它们(特别是回读 CPU)。可以想象在其他情况下可能不知道或错误地假设了特定限制。
显然,这是有潜在危险的。我确信有更强大的方法可以用于我当前的系统(或更一般地)而不牺牲性能,但我不是(特别是)就此寻求建议。
我想知道的是,当程序调用 Append()
超出此类缓冲区的容量时,预期的行为是什么。我想它是未定义的,并且可能会破坏 VRAM 的其他区域,在某种程度上取决于 GPU 驱动程序/DirectX 版本等。它可能是更正式指定的,但我一直无法找到它.
当然,即使行为是指定的,故意冒险似乎有些鲁莽。不过,我想知道:
- 是否可以在内核函数的上下文中检测到此类缓冲区已满(考虑到高度线程化的特性,这可能是不切实际的)。
- 如果可能的话,这对性能有何影响。
- 溢出的后果是什么(在这种情况下我特别期待它,但错误发生了)。
- 对于不同的硬件供应商、API 等,上述所有内容可能会有何不同。
也许是'safe'到这样的程度,多余的数据会毫无代价地简单地丢失到虚无中。在任何情况下,系统都可以 - 例如 - 定期检查缓冲区的完整性并做任何可能需要的额外家务......留下这样一个系统调整中的任何错误可能有多严重的问题。
在许多情况下,至少在 DirectX 中,越界访问被定义为返回 0。我仍然不完全确定写入,但认为有理由相信它们在当前实现中通常应该是安全的。
5.3.10.2 Using Unordered Count and Append Buffers
...
The counter behind imm_atomic_alloc and imm_atomic_consume has no
overflow or underflow clamping, and there is no feedback given to the
shader as to whether overflow/underflow happened (wrapping of the
counter). The only thing the counter really accomplishes is a way of
generating unique addresses that is conveniently bundled with the UAV.
There is no clamping of the count, so it wraps on overflow.
在这些情况下,我认为我将 'wrapping' 解释为缓冲区的长度并没有错。
因此,据我了解,答案是在 Append()
时内部计数器将换行,随后的调用将最终覆盖之前的数据。碰巧的是,我目前正在渲染我的缓冲区而不引用这样的计数器(因为我在 'triangles' 上进行了另一次传递以将它们变成用于渲染的顶点,我目前在 non-AppendBuffer 上进行)。我应该尝试将带有计数的缓冲区传递给该绘制调用,这应该允许我验证我的大部分模型是否在我溢出时突然消失。
无论如何,从不破坏系统其他部分的角度来看,该操作似乎应该是安全的,但引用计数器可能是检测问题的错误方法。
我有一个 Unity 项目,我在其中通过计算着色器中的 Append(triangle)
写入 AppendStructuredBuffer<Triangle>
。
在这种情况下,我知道可能存在的三角形数量的理论限制,因此显然正确的方法是相应地调整缓冲区的大小。不过,作为 hack,我正在尝试分配更小的缓冲区,以便系统的其他部分可以更有效地处理它们(特别是回读 CPU)。可以想象在其他情况下可能不知道或错误地假设了特定限制。
显然,这是有潜在危险的。我确信有更强大的方法可以用于我当前的系统(或更一般地)而不牺牲性能,但我不是(特别是)就此寻求建议。
我想知道的是,当程序调用 Append()
超出此类缓冲区的容量时,预期的行为是什么。我想它是未定义的,并且可能会破坏 VRAM 的其他区域,在某种程度上取决于 GPU 驱动程序/DirectX 版本等。它可能是更正式指定的,但我一直无法找到它.
当然,即使行为是指定的,故意冒险似乎有些鲁莽。不过,我想知道:
- 是否可以在内核函数的上下文中检测到此类缓冲区已满(考虑到高度线程化的特性,这可能是不切实际的)。
- 如果可能的话,这对性能有何影响。
- 溢出的后果是什么(在这种情况下我特别期待它,但错误发生了)。
- 对于不同的硬件供应商、API 等,上述所有内容可能会有何不同。
也许是'safe'到这样的程度,多余的数据会毫无代价地简单地丢失到虚无中。在任何情况下,系统都可以 - 例如 - 定期检查缓冲区的完整性并做任何可能需要的额外家务......留下这样一个系统调整中的任何错误可能有多严重的问题。
在许多情况下,至少在 DirectX 中,越界访问被定义为返回 0。我仍然不完全确定写入,但认为有理由相信它们在当前实现中通常应该是安全的。
5.3.10.2 Using Unordered Count and Append Buffers
... The counter behind imm_atomic_alloc and imm_atomic_consume has no overflow or underflow clamping, and there is no feedback given to the shader as to whether overflow/underflow happened (wrapping of the counter). The only thing the counter really accomplishes is a way of generating unique addresses that is conveniently bundled with the UAV.
There is no clamping of the count, so it wraps on overflow.
在这些情况下,我认为我将 'wrapping' 解释为缓冲区的长度并没有错。
因此,据我了解,答案是在 Append()
时内部计数器将换行,随后的调用将最终覆盖之前的数据。碰巧的是,我目前正在渲染我的缓冲区而不引用这样的计数器(因为我在 'triangles' 上进行了另一次传递以将它们变成用于渲染的顶点,我目前在 non-AppendBuffer 上进行)。我应该尝试将带有计数的缓冲区传递给该绘制调用,这应该允许我验证我的大部分模型是否在我溢出时突然消失。
无论如何,从不破坏系统其他部分的角度来看,该操作似乎应该是安全的,但引用计数器可能是检测问题的错误方法。