I have bound the shader storage buffer
to the shader storage block
like so
GLuint index = glGetProgramResourceIndex(myprogram, GL_SHADER_STORAGE_BLOCK, name);
glShaderStorageBlockBinding(myprogram, index, mybindingpoint);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mybuffer)
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, mybindingpoint, mybuffer, 0, 48);
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 48, &mydata);
mydata
points to a std::vector
containing 4 glm::vec3
objects.
Because I bound 48 bytes
as the buffer range I expect lights[]
to hold 48/(4*3) = 4 vec3s
.
layout(std430) buffer light {
vec3 lights[];
};
The element at index 1
in my std::vector
holds the data x=1.0, y=1.0, z=1.0
.
But viewing the output by doing
gl_FragColor = vec4(lights[1], 1.0);
I see yellow (x=1.0, y=1.0, z=0.0
) pixels. This is not what I loaded into the buffer.
Can somebody tell me what I am doing wrong?
I just changend the shader storage block to
layout(std430) buffer light {
float lights[];
};
and output
gl_FragColor = vec4(lights[3],lights[4],lights[5],1.0);
and it works (white pixels).
If somebody can explain this, that would still be great.
It's because people don't take this simple advice: never use a vec3
in a UBO/SSBO.
The base alignment of a vec3
is 16 bytes. Always. Therefore, when it is arrayed, the array stride (the number of bytes from one element to the next) is always 16. Exactly the same as a vec4
.
Yes, std430
layout is different from std140
. But it's not that different. Specifically, it only prevents the base alignment and stride of array elements (and base alignment of structs) from being rounded up to that of a vec4
. But since the base alignment of vec3
is always equal to that of a vec4
, it changes nothing about them. It only affects scalars and vec2
's.