OpenGL 4.5 - Shader storage: write in vertex shader, read in fragment shader

976 Views Asked by At

Both my fragment and vertex shaders contain the following two guys:

struct Light {
  mat4 view;
  mat4 proj;
  vec4 fragPos;
};

layout (std430, binding = 0) buffer Lights {
  Light lights[];
};

My problem is that that last field, fragPos, is computed by the vertex shader like this, but the fragment shader does not see the changes made by the vertex shader in fragPos (or any changes at all):

aLight.fragPos = bias * aLight.proj * aLight.view * vec4(vs_frag_pos, 1.0);

... where aLight is lights[i] in a loop. As you can imagine I'm computing the position of the vertex in the coordinate systems of each light present to be used in shadow mapping. Any idea what's wrong here? Am I doing a fundamentally wrong thing?

Here is how I initialize my storage:

struct LightData {
  glm::mat4 view;
  glm::mat4 proj;
  glm::vec4 fragPos;
};

glGenBuffers(1, &BBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, BBO);

glNamedBufferStorage(BBO, lights.size() * sizeof(LightData), NULL, GL_DYNAMIC_STORAGE_BIT);

// lights is a vector of a wrapper class for LightData.
for (unsigned int i = 0; i < lights.size(); i++) {
  glNamedBufferSubData(BBO, i * sizeof(LightData), sizeof(LightData), &(lights[i]->data));
}

It may be worth noting that if I move fragPos to a fixed-size array out variable in the vertex shader out fragPos[2], leave the results there and then add the fragment shader counterpart in fragPos[2] and use that for the rest of my stuff then things are OK. So what I want to know more about here is why my fragment shader does not see the numbers crunched down by the vertex shader.

1

There are 1 best solutions below

6
On

I will not be very accurate, but I will try to explain you why your fragment shader does not see what your vertex shader write :

When your vertex shader write some informations inside your buffer, the value you write are not mandatory to be wrote inside video memory, but can be stored in a kind of cache. The same idea occur when your fragment shader will read your buffer, it may read value in a cache (that is not the same as the vertex shader).

To avoid this problem, you must do two things, first, you have to declare your buffer as coherent (inside the glsl) : layout(std430) coherent buffer ...

Once you have that, after your writes, you must issue a barrier (globally, it says : be careful, I write value inside the buffer, values that you will read may be invalid, please, take the new values I wrote).

How to do such a thing ? Using the function memoryBarrierBuffer after your writes. https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/memoryBarrierBuffer.xhtml

BTW : don't forget to divide by w after your projection.