引用here:
此函数返回时,使用其他着色器调用对同一地址进行的任何以后的一致性存储器访问,将对使用调用之前执行的一致性变量执行的任何存储器存储的结果可见。
好吧,说我想在片段着色器中这样做:
void main() {
ivec2 fc = ivec2(gl_FragCoord.xy);
vec4 f = imageLoad(image, fc);
f *= 2;
imageStore(image, fc, f);
}
我相信这不需要在imageLoad和imageStore之间使用memoryBarrier()。然后执行以下操作:
out vec4 OUT;
void main() {
ivec2 fc = ivec2(gl_FragCoord.xy);
imageStore(image, fc, vec4(5));
vec4 f = imageLoad(image, fc);
OUT = f * 2;
}
我正确理解GLSL的memoryBarrier吗?
答案 0 :(得分:2)
您在此处发布的方案依赖于未声明和未知的信息,您可能会假设渲染过程的性质,而您并未假设它们无关紧要。即使他们做得很多,我们也会在这里看到。
所以,让我们从那里开始。如果我们假设您正在发出渲染调用,以使两个片段永远不会具有相同的gl_FragCoord
值(因此,两个着色器调用都不会尝试写入相同的位置) ,则这两种情况都是定义明确的,不需要记忆障碍。对真的;根据GLSL规范:
在一个着色器调用中,该调用的可见性和写入顺序是明确定义的。
请参见,着色器内memoryBarrier
函数和coherent
限定符与读取由单独着色器调用编写的值有关。读取您的调用写入的值不是问题。因此,无论哪种情况,您都不需要在这里coherent
。
因此需要初始假设。因为,如果这种假设消失了,如果片段之间有任何重叠,以致两次调用将尝试写入同一位置,则两种情况都是 undefined 。 memoryBarrier
不会更改。为什么?
因为来自同一阶段的两个调用之间没有顺序。 GLSL不保证同一阶段中的任何两个调用何时执行。它们可能同时执行,或者尽管它们顺序混乱,也可能执行来自较早基元的片段,而不是较早基元中的某个片段。
memoryBarrier
和类似功能仅在shader invocations have some kind of order dependency between them的情况下重要。这可能是发出barrier
调用的计算或镶嵌控制着色器,也可能是写入数据的顶点着色器,该数据是与该顶点关联的图元的片段着色器读取的,或者是其他情况下,调用。
同一渲染命令(或该母题的不同渲染命令)中的两个片段着色器执行之间没有任何排序。因此,障碍将无济于事。
您不希望多个片段着色器调用尝试写入同一内存。除非它们在不同的渲染命令中,并且它们之间有适当的glMemoryBarrier
调用,否则不会。