imageStore and gl_FragColor - weird behaviour

Hi everybody.

I’m currently studing CG and I run into some weird OpenGL behaviour when using image_load_store functionalities.

In my test application I render a sphere using a shader that writes its outputs to four different locations:

  • three different image2D (using imageStore);
  • one texture2D that is attached to a color chanel of a framebuffer.
    Here is the result of this setup ( Figure 1 ).

Everything goes fine with this setup, but when I try to NOT WRITE to the texture2D, I get unexpected results ( Figure 2 ).
The unexpeted result is that besides the texture2D not being writen, the imageStore operations appear to have no effect over the three image2D variables.
NOTE: In order to “try to NOT WRITE to the texture2D” I removed the line “gl_FragColor = vec4(1, 1, 1, 1);” from the shader and set “glDrawBuffer(GL_NONE);”.

After several tests I though: What if I masked the the “gl_FragColor = vec4(1, 1, 1, 1);” with a “discard;” command? I tried and it worked ( Figure 3 ).

Follows the Fragment Shader code that resulted from this test.


#version 420 core

layout(rgba8) coherent uniform image2D myImageA;
layout(rgba8) coherent uniform image2D myImageB;
layout(rgba8) coherent uniform image2D myImageC;

in vec4 gl_FragCoord;
out vec4 gl_FragColor;

void main()
{
	// coordinates of this pixel
	ivec2 coord = ivec2(gl_FragCoord.xy);
	
	imageStore(myImageA, coord, vec4(0,1,0,1));
	imageStore(myImageB, coord, vec4(0,0,1,1));
	imageStore(myImageC, coord, vec4(1,0,0,1));

	// used for debug
	discard;
	gl_FragColor = vec4(1, 1, 1, 1);
}

Although the code is providing the result I want, I still don’t know what dark-wizardry is behind all this unexpected (at least for me) behaviour.
I hope someone could shed some light over this subject.

I’m using an AMD 5470 Mobile with Catalyst 11.12.

Thanks in advance.

Speculation on my part: glDrawBuffer suggests that either glDrawBuffer(GL_BACK) for double buffer or glDrawBuffer(GL_FRONT) for single buffer is enabled by default. But when you set glDrawBuffer(GL_NONE) you tell openGL state machine to not do any buffer output operations ie your fragment shader is never run and that includes imageStore ops. Follow up: Reading more of the 4.2 Spec page 304 gives the quote “Specifying NONE as the draw buffer for a fragment color will inhibit that fragment color from being written to any buffer.”

I am assuming with case 3 you had to not use glDrawBuffer(GL_NONE). Hence the fragment shader is executed up to the point where the “discard” call is executed. This is the correct solution – enable the DrawBuffer as normal which runs the fragment shader as expected and just discard fragments as needed – in your case discard none except the gl_FragColor operation.

It seems to me that

will simply disable (as in: NOT perform) any attribution of color to the attached color buffers, but won’t stop the fragment shader to be executed.

A lot more tests later… I think I got it… this is what I THINK.

At first I had the following:

  • I had a color buffer attached to the framebuffer being binded during the shader execution;
  • I was setting glDrawBuffer(GL_NONE);
  • I was NOT setting anything to the gl_FragColor (this was commented from the shader code);
    -> As a result although the glDrawBuffer(GL_NONE), there was a color buffer attached… this could cause the GL to detect that no color was attributed to gl_FragColor and thus override the shader execution. This way I get none of the image2D written.

Now I have the following:

  • I have NO color buffer attached (well… I leave the default which must be none);
  • I set the glDrawBuffer(GL_NONE);
  • I DO NOT set anything to the gl_FragColor (this is commented from the shader code);
    -> This way the shader performs all the writes to the image2D variables.

What do I think to be the wizardry behind this:

I think the GL detects that I have a color buffer attached and since my shader had no color buffer attribution it would simply avoid the shader execution. When I introduced the ‘discard;’ along with the ‘gl_FragColor’ attribution the GL would detect a ‘gl_FragColor’ attribution thus executing the shader (even though it would be discarded). Once I remove the attached color buffer, the GL no longer checks the shader for a ‘gl_FragColor’ attribution and thus executes the shader always.

Ok this seems a bit awkward and confuse… but… what do you think?

Thanks in advance,
Happy new Year (for those who apply) :wink:

Your explanation sounds more plausible than mine.

I would be curious to know if this behaves differently on different hardware ie AMD vs NVIDIA – is it up for interpretation when the fragment shader can be optimized away since the 4.2 Spec quote seems a little vague on further inspection? … but that is beyond this message thread.

Happy New Year

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.