Monday, October 30, 2017

GLSL: Can I combine MRT, ssbo and imageAtomic operations in the same shader (pass)?

Leave a Comment

A 2-pass rendering system in OpenGL is using an MRT shader that is bound to 2 framebuffer textures tex1 and tex2. The goal of the mrt pass is to compute the overdraw in the scene and render it out in a gather pass. I use the framebuffer textures to pass on the result.

It also has a working ssbo buffer that is quite large (and using a fixed screen resolution) and takes ages to link, but I can use it to do atomicAdds. What I am trying to accomplish is to replace this with imageAtomicAdd operations on a uiimage2D, just like with the mrt passes.

The problem is that the result of imageAtomicAdd is always zero, where I expect it to go up just like atomicAdd does at that point..

#version 440 core  layout(early_fragment_tests) in;  // this works fine layout (location = 0) out vec4 tex1; layout (location = 1) out vec4 tex2;  // this works fine layout(std430, binding = 3) buffer ssbo_data {         uint v[1024*768]; };  // this does not work at all. uniform volatile layout(r32ui) uimage2D imgCounter;  out vec4 frag_colour;  void main ()  {            ivec2 coords = ivec2(gl_FragCoord.xy);     uint addValue = 1u;      uint countOverdraw1 = atomicAdd(v[coords.x + coords.y * 1024], 1u);     uint countOverdraw2 = imageAtomicAdd(imgCounter, ivec2(0,0), 1u);       memoryBarrier();      // supports 256 levels of overdraw..     float overdrawDepth = 256.0;     vec3 c1 = vec3(float(countOverdraw1+1)/overdrawDepth ,0,1);     vec3 c2 = vec3(float(countOverdraw2+1)/overdrawDepth ,0,1);      tex1 = vec4(c1,1);       tex2 = vec4(c2,1);       frag_colour = vec4(1,1,1,1); } 

From the khronos website on image atomic operations I gather that..

Atomic operations to any texel that is outside of the boundaries of the bound image will return 0 and do nothing.

.. but the coordinate ivec2(0,0) would be well within the bounds of the texture size (1024 x 768).

Maybe the texture is not set up correctly? This is how I construct the uiimage2D (pieced together from the pipeline flow):

EDIT: I update the code as per suggestion by the answer from Nicol Bolas: texture parameters are set instead of sampler parameters

char data[1024*768*4]; glGenTextures(1, &m_Handle);  m_Target = GL_TEXTURE_2D;  glActiveTexture(GL_TEXTURE0+6); glBindTexture(m_Target,m_Handle);  // updated : a sampler object was bound to the texture, but is now removed  glTexParameteri(m_Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  // updated glTexParameteri(m_Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  // updated glTexParameteri(m_Target, GL_TEXTURE_WRAP_R, GL_REPEAT);       // updated glTexParameteri(m_Target, GL_TEXTURE_WRAP_S, GL_REPEAT);       // updated glTexParameteri(m_Target, GL_TEXTURE_WRAP_T, GL_REPEAT);       // updated glTexImage2D(m_Target, 0, R32UI, 1024, 768, 0, GL_RED_INTEGER, GL_UNSIGNED_INT,  data);      

If I run it through gDEBugger GL, I see that "Texture data is not available at this time" and while the 'Texture 4' parameters of the texture are filled in and correct, none of the 'Texture Parameters' and 'Level 0 parameters' are shown (N/A). Trapping the debugger at that point throws a whole number of problems that do not appear outside of gDEBugger. Here are the first few:

GL_INVALID_OPERATION error generated. The required buffer is missing. GL_INVALID_ENUM error generated. <pname> requires feature(s) disabled in the current profile.  GL_INVALID_OPERATION error generated. <index> exceeds the maximum number of supported texture units.  GL_INVALID_ENUM error generated. or require feature(s) disabled in the current profile.   GL_INVALID_OPERATION error generated. Can't mix integer and non-integer data ... 

I'm explicitly forcing GL 4.4 or GL4.4 'core' profile so I'm a bit puzzled what may be the problem with the required buffer that is missing. Could it be that it is mistakingly seeing the imgCounter as part of the MRT setup for the framebuffer?

1 Answers

Answers 1

That texture is incomplete.

See, when you bind a texture for use with image load/store operations, you don't bind a sampler along with it. So all of those glSamplerParameter calls are meaningless to the texture's completeness status.

The texture is incomplete because the filtering parameters are GL_LINEAR, but the texture is an unsigned integer format. When creating integer format textures, you should always set the texture's parameters to valid values.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment