SSBO 作为更大的 UBO?

SSBO as bigger UBO?

我目前正在使用 UBO 在 OpenGL 4.3 中进行渲染,以将我所有的常量数据存储在 GPU 上。 (诸如 material 描述、矩阵等之类的东西)。 它可以工作,但是 UBO 的小尺寸(我的实现为 64kB)迫使我多次切换缓冲区以减慢渲染速度,我正在寻找类似的方法来存储几 MB。

经过一些研究后,我发现 SSBO 确实允许这样做,但也有不需要的 'features':它们可以从着色器中写入,读取速度可能较慢。

是否有比 SSBO 更好的解决方案来为着色器提供大块数据?我觉得我错过了一些东西,为什么要将 UBO 限制在几 kB 而存在能够处理更多数据的更灵活的解决方案?如果着色器存储缓冲区是我正在寻找的,有没有办法确保它们不被着色器修改?

UBO 和 SSBO 从根本上代表两种不同的硬件(通常)1

着色器分组执行,这样每个着色器都以锁步方式执行。每组单独的着色器调用都可以访问一块内存。这种记忆就是 UBO 所代表的。它相对较小(以千字节为单位),但访问速度非常快。执行渲染操作时,来自 UBO 的数据被复制到此着色器本地内存中。

SSBO 代表全局内存。它们基本上是指针。这就是为什么它们通常没有存储限制(最小 GL 要求是 16 Mega 字节,大多数实现返回一个与 GPU 内存大小顺序相同的数字)。

它们的访问速度较慢,但​​这种性能是因为它们存在的位置和访问方式,而不是因为它们可能不是常量。全局内存是全局 GPU 内存而不是本地常量内存。

如果着色器需要访问的数据多于其着色器本地内存所能轻松容纳的数据,则它需要使用全局内存。没有办法解决这个问题,即使您有办法将 SSBO 声明为 "constant".

1:存在没有专用 UBO 存储的硬件(基于 GCN 的 AMD 硬件)。该硬件将 UBO 实现为只读 SSBO,因此所有 UBO 访问都是全局内存访问。这种硬件基本上依赖于拥有大缓存来弥补性能差异,而 UBO 的使用模式往往使这种做法可行。但是仍然有很多硬件有专门的 UBO 存储空间,所以如果您的使用可以满足这些限制,您应该使用它们。