这个问题是这个主题的延续: How to bind thousands of buffers properly
这个问题与粒子模拟主题有关。 假设我需要一个包含以下内容的全局结构:
第一个想法是为第一个项目使用3D纹理,为第二个项目使用原子计数器缓冲区,为第三个项目使用SSB。
SSB中的每个条目都是一个粒子加上一个uint,该值指向同一体素中下一个粒子的位置。
这里没什么神奇的。
现在,为了与空间无关(不限于独特的立方体空间),我必须能够将粒子从立方体传递到围绕它的其他人。因为我在一个3D空间,27个立方体(前面)作为物理计算的输入变量,但也有27个立方体(后面)作为输出,因为我可以将一个粒子从一个立方体(前面)写到另一个(后面)覆盖一个空间的不同部分。
这使我需要绑定54个纹理,54个SSB和54个原子计数器。虽然这两个第一次可能不是问题(我的硬件限制大约是90),但ACB绑定限制为8。
假设单个ACB包含每个立方体的粒子数并不容易维护(我没有花很长时间思考,这可能是解决方案,但这不是问题所在。)
背景:
SSB可以包含任何内容。因此,解决方案是将三个结构(标题矩阵,计数器和链表)连接在一个SSB中,该SSB将成为我的立方体超级结构。
我需要在每次传递之前知道SSB中有多少粒子可以进行正确的glDispatchCompute()调用。
问题:
绑定SSB只是为了读取包含粒子数量的uint会不好?
如果不是,那么访问计数的两种方法之一是否比另一种更好?为什么?
GLuint value;
//1st method
m_pFunctions->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
m_pFunctions->glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, OFFSET_TO_VALUE, sizeof(GLuint), &value);
m_pFunctions->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
//2nd method
m_pFunctions->glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_buffer, OFFSET_TO_VALUE, sizeof(GLuint));
m_pFunctions->glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), &value);
m_pFunctions->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
如果不是,是否有好方法或者我应该将计数器与SSB分开?
答案 0 :(得分:0)
即使绑定缓冲区并将计数器放入内部理论上是可行的,但通过进一步推动“一切都在SSB”的概念,有一种更简单的方法。
通过在SSB中保留3个连续uint的空间,我们可以将它们的值用作调度参数X,Y和Z.X仍然是粒子的数量,但Y和Z只是硬设置1s。
然后,在将glDispatchCompute()
目标绑定到glDispatchComputeIndirect()
后,调用GL_DISPATCH_INDIRECT_BUFFER
代替coherent
。
但是,通过使用部分SSB作为伪原子计数器,缓冲区必须以类型限定符coherent
为前缀“以强制执行内存访问的一致性”。还应设置memory barriers以实现{{1}}变量之间的可见性。