Hello!
In my C++ code I am trying to send a struct A
and a variable B
to the fragment shader as a UBO (inside the descriptor set, or course).
- “
A
” has a bunch of member variables of different size (int, floats, glm::vec3
), which makes a total size of 84 bytes. - “
B
” has a size of 12 bytes (glm::vec3
). Both together make a total of (84 + 12) 96 bytes. Since the “minimum UBO offset alignment” here should be 256 bytes, I reserve that amount of memory for my UBO, copyA
andB
inside and send this UBO buffer to the shader.
In my shader (my GLSL code) I created the struct A
again, and received the data in the following uniform:
layout(set = 0, binding = 1) uniform dataBlock {
A light;
B camPos;
} obj;
However, in the shader, when I try to access “camPos
” (like in obj.camPos.x
) I got wrong values. Then, I thought that this could be due to the alignment of “light
” in the shader. Therefore, using the trial and error method, I finally added some padding bytes at the end of my C++ A
struct (28 bytes more, making a total of 112). This way, in my GLSL code, I can successfully access the correct values at camPos
.
In case it’s relevant, A
has the following members: one int, six floats, and five glm::vec3
. On the other hand, B
is a glm::vec3
. In C++, A and B look like this:
struct A
{
A();
int a;
glm::vec3 b;
glm::vec3 c;
glm::vec3 d;
glm::vec3 e;
glm::vec3 f;
float g;
float h;
float i;
float j;
float k;
};
glm::vec3 x;
However, I don’t understand what exactly is happening here. Why are those 24 additional bytes required for correctly accessing B
(and not 12, for example)? It shouldn’t be required to use the trial and error method to find the correct padding. What is the logic behind this?
PD:
Ok, I could solve my question. I found out how the shader is aligning my struct. The padding it is applying behaves as follows:
struct A
{
A();
int a;
float padding1[3];
glm::vec3 b;
float padding2[1];
glm::vec3 c;
float padding3[1];
glm::vec3 d;
float padding4[1];
glm::vec3 e;
float padding5[1];
glm::vec3 f;
float g;
float h;
float i;
float j;
float k;
};
It took some hours of testing to find this. Now I can see why I couldn’t access easily some of the members since the padding was a bit different than I expected (for example, I didn’t expect the last members not to be padded).
Note that A
size in the shader is 112, which is a multiple of 16 (i.e. 7 = 112 / 16).