Search code examples
openglgraphics3dglslssbo

Can SSBO be read/write within the same shader?


I wrote a small tessellation program. I can write to a SSBO (checked output using RenderDoc) but reading the data back right away in the same shader (TCS) does not seem to work. If I set the tessellation levels directly, I can see that my code works:

In the main of the Tessellation Control shader:

 gl_TessLevelInner[0] = 1;
 gl_TessLevelOuter[0] = 1;
 gl_TessLevelOuter[1] = 2;
 gl_TessLevelOuter[2] = 4;

But going through the SSBO memory, it does not work. The display is blank like 0 were placed in the gl_TessLevelInner & gl_TessLevelOuter output.

Here is the SSBO in the TCS:

   struct SSBO_Data {
      float Inside;   // Inside Tessellation factor
      float Edges[3]; // Outside Tessellation factor
   };

   layout(std430, binding=2) volatile buffer Tiling {
      SSBO_Data Tiles[];
   };

In the main of the Tessellation Control shader

   Tiles[0].Inside   = 1;
   Tiles[0].Edges[0] = 1;
   Tiles[0].Edges[1] = 2;
   Tiles[0].Edges[2] = 4;

   gl_TessLevelInner[0] = Tiles[0].Inside;
   gl_TessLevelOuter[0] = Tiles[0].Edges[0];
   gl_TessLevelOuter[1] = Tiles[0].Edges[1];
   gl_TessLevelOuter[2] = Tiles[0].Edges[2];

In C++, I use the ShaderBuffer class from nVidia to create an array of a few thousand tiles and transfer data to the SSBO. I confirmed that the correct data is stored in the SSBO using RenderDoc.

  • In the ShaderBuffer class, I tried changing the glBufferData usage to GL_DYNAMIC_DRAW instead of GL_STATIC_DRAW but it did not help.
  • I also set the SSBO to volatile but that did not help.
  • I also inserted a barrier(); between the writing and reading of the SSBO data and it did not help either.

Is it possible to use SSBO for writing and reading back within the same shader?


Solution

  • Writing to any incoherent memory location (SSBO or image load/store)from a single shader instance and then reading from the same location works in the same stage if and only if:

    1. You are reading it in the same instance that did the writing.
    2. Only that instance wrote to the memory being read.

    #2 holds even if all instances are writing the same value. Violating #2 creates a race condition (again, regardless of the value written), which is UB.