我有几个需要按一定顺序执行的计算着色器,它们的输出取决于以前的输入。理想情况下,我永远不需要在客户端复制缓冲区并在GPU上完成所有工作。

考虑到我有两个编译并链接为program_oneprogram_two的计算着色器。假设我还有一个GL_SHADER_STORAGE_BUFFER,其中包含由program_one写入并由program_two读取的数据。我可以简单地执行以下操作吗?

glUseProgram(program_one);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer);
glDispatchCompute(16, 16, 1);

glUseProgram(program_two);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer);
glDispatchCompute(16, 16, 1);


是否可以保证第一个计算着色器的所有调用都将在第二个计算着色器的任何调用之前完成(以避免读取之间的数据竞争)并写buffer)?如果没有,如何同步它们?

#1 楼

不,这不能保证,因为OpenGL规范允许两个Compute Shader同时运行,甚至可以以不同的顺序运行。

您需要在第二个glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)之前调用glDispatchCompute,以确保对program_one写入的可见性。 br />

从OpenGL.org Wiki上有关内存模型的文章:阶段之间的调用可以按任意顺序执行。这包括由不同的渲染命令启动的调用。来自不同渲染操作的两个顶点着色器可能不太可能同时运行,但这也是可能的,因此OpenGL无法提供保证。


来自Opengl.org Wiki有关着色器存储缓冲区的文章:


SSBO读写使用不连贯的内存访问,因此它们需要适当的屏障,就像图像加载存储操作一样。