Opengl GLSL:对着色器存储缓冲区的写入是否被稍后的discard语句丢弃(或撤消)?

Opengl GLSL:对着色器存储缓冲区的写入是否被稍后的discard语句丢弃(或撤消)?,opengl,glsl,shader,fragment-shader,Opengl,Glsl,Shader,Fragment Shader,我有一个片段着色器(GLSL 4.5),它应该将非透明像素写入帧缓冲区(通过写入声明的输出变量),并将透明像素写入着色器存储缓冲区,以便以后合成。为了做到这一点,我计划将透明像素写入着色器存储缓冲区,然后调用discard以防止写入帧缓冲区 现在我偶然发现(我的): discard命令还将阻止任何图像存储和原子操作以及着色器存储缓冲区对象写入(在discard之前发出的)工作 我很惊讶地看到这一点,因为如果你认为不同的着色器调用能够通过编写和读取着色器存储缓冲区来交换信息,因此在达到丢弃语句之前

我有一个片段着色器(GLSL 4.5),它应该将非透明像素写入帧缓冲区(通过写入声明的输出变量),并将透明像素写入着色器存储缓冲区,以便以后合成。为了做到这一点,我计划将透明像素写入着色器存储缓冲区,然后调用
discard
以防止写入帧缓冲区

现在我偶然发现(我的):

discard命令还将阻止任何图像存储和原子操作以及着色器存储缓冲区对象写入(在discard之前发出的)工作

我很惊讶地看到这一点,因为如果你认为不同的着色器调用能够通过编写和读取着色器存储缓冲区来交换信息,因此在达到丢弃语句之前,基于这样的WRET就可以有不同的行为。 我查看了,但是我找不到任何支持Wiki声明的内容


另外:如果这是真的,那么以后对共享存储缓冲区的写入是否没有被丢弃?

规范是明确的。见:

[…]此关键字导致丢弃片段,并且不会更新任何缓冲区之前对其他缓冲区(如着色器存储缓冲区)的任何写入都不受影响。[……]

因此,可以写入SSBO并在写入后放弃写入帧缓冲区,因为之前对SSBO的写入不受影响


进一步看

[…]当着色器正在运行时,它正在更新外部可见的缓冲区,如果说这些更新在以后的
放弃后不知何故不再存在,则是行不通的[…]


“然后调用discard以防止写入帧缓冲区。”您真的不应该这样做。如果你认为不同的着色器调用能够通过编写和读取着色器存储缓冲器来交换信息,在这种情况下,在这样的WiRTEE之前,即使在达到“废弃语句”之前,它们也可以有不同的行为。在片段着色器中,无法同步此类活动,以确保在渲染命令中的写入之后发生读取。因此,您将调用UB。@Nicolas:一次着色器调用可以调用atomicAdd来增加全局计数器,然后调用discard。这将是其他着色器调用可见的副作用。如果我没有弄错的话,这不是UB。“只需使用写掩码来关闭帧缓冲区写入”:我查看了链接的wiki页面,我认为写掩码不会解决我的问题,因为是否写入帧缓冲区是由片段着色器调用决定的(这里基于透明度)。如果我正确理解写入掩码,则必须在进行绘制调用之前设置它们,并将阻止对特定像素的所有写入。应该注意的是,高亮显示的句子直到GLSL 4.60修订版3(缺少该句子的最后一个修订版)之后才存在。所以这是最近的变化,而不是“变化”一节中提到的变化。也没有证据表明这句话是延期的一部分。我没有记录GLSL ES的修订,但ES 3.10(第一个带有SSBO的ES)有这样一句话。这可能就是它进入桌面GL的方式,因为新GLSL规范的源文件似乎已经将ES和桌面合并到了同一个源文件中。由于所有这些,我甚至不知道如何在Wiki上纠正这一点。我应该说这是特定于版本的行为,还是说它总是以这种方式工作?我想了解更多。