2

I am trying to get a hold of how memoryBarrier() works in OpenGL 4.4 I tried the following once with a texture image and once with Shader Storage Buffer Object (SSBO). The basic idea is to create an array of flags for however many objects that need to be rendered in my scene and then perform a simple test in the geometry shader.

  1. For each primitive in GS, if at least one vertex passes the test, it sets the corresponding flag in the array at the location specified by this primitive's object ID (Object IDs are passed to GS as vertex attributes).

  2. I then perform a memoryBarrier() to make sure all threads have written their values.

  3. Next, I have all primitives read from the flags array and only emit a vertex if the flag is set.

Here is some code from my shaders to explain:

// Vertex Shader: 
#version 440
uniform mat4 model_view;
uniform mat4 projection;
layout(location = 0) in vec3 in_pos;
layout(location = 1) in vec3 in_color; 
layout(location = 2) in int lineID;

out VS_GS_INTERFACE
{ 
   vec4 position; 
   vec4 color;
   int lineID;
 } vs_out;

void main(void) {
   vec4 pos = vec4(in_pos, 1.0);
   vs_out.position = pos;
   vs_out.color = vec4(in_colo, 1.0);
   vs_out.lineID = lineID;

   gl_Position = projection * model_view * pos;
 }

and here is a simple Geometry shader in which I use only a simple test based on lineID ( I realize this test doesn't need a shared data structure but this is just to test program behavior)

 #version 440 
 layout (lines) in; 
 layout (line_strip, max_vertices = 2) out;
 layout (std430, binding = 0) buffer BO {
       int IDs[]; 
   }; 
 in VS_GS_INTERFACE
  {
   vec4 position;
   vec4 color;
   int lineID;
   } gs_in[];

 out vec4 f_color;

 void main()
 {
  if(gs_in[0].lineID < 500) 
      { 
        IDs[gs_in[0].lineID] = 1;
       }
  else
       {
         IDs[gs_in[0].lineID] = -1;
       }
  memoryBarrier();

  // read back the flag value
  int flag = IDs[gs_in[0].lineID];
   if ( flag > 0) 
    {
     int n;
     for( n = 0; n < gl_in.length(), n++) 
       {
         f_color = gs_in[n].color;
         gl_Position = gl_in[n].gl_Position;
         emitVertex();
        }
      }
 }

No matter what value I put instead of 500, this code always renders only 2 objects. If I change the condition for rendering in the GS to if( flag > = 0) it seems to me that all objects are rendered which means the -1 is never written by the time these IDs are read back by the shader. Can someone please explain why the writes are not coherently visible to all shader invocations despite the memoryBarrier() and what would be the most efficient work around to get this to work?

Thanks.

MaYa
  • 180
  • 7
  • You already answered your own question, the variable (SSB) is not `coherent`. The only variables that are implicitly `coherent` are atomic counters; SSBs, while they can be used to provide the storage for an atomic counter, are not. So add `coherent` to your `buffer` declaration. – Andon M. Coleman Jun 16 '14 at 23:39
  • Thanks for your comment. I added coherent and volatile to the buffer declaration but I am still getting the same behavior – MaYa Jun 17 '14 at 04:07
  • I am actually a little confused as to why your `gs_in` is not being referenced by an array index to be honest now that I take a much closer look at your shader. Your input primitive type is `lines`, so you actually have potentially two `lineIDs`. Now, hopefully they would be the same line ID otherwise it does not make a lot of sense, but you need to index your array to access either one of them. If you assume that both vertices have the same line id, then you can just write: `gs_in [0].lineID`... but otherwise, this actually should not even compile. – Andon M. Coleman Jun 17 '14 at 04:13
  • Sorry about that. I am referencing the zeroths element as you pointed out in my code I just had this mistake in my question. I edited my question to reflect that. – MaYa Jun 17 '14 at 04:19
  • I added a loop after the 'memoryBarrier()' call ' uint flag; do{ flag = IDs[gs_in[0].lineID]; } while (flag == 0);' and then added a second memoryBarrier() after .. it is now looping indefinitely so I am going to do another selection criteria based on position and see if any writes take place – MaYa Jun 17 '14 at 04:29

0 Answers0