Reputation: 33395
I am reading about std140 and std430 layouts in GLSL.
Consider, in C++:
struct Foo
{
glm::vec4 alpha;
float beta;
float gamma;
glm::vec4 delta;
float epsilon;
};
In GLSL:
uniform (layout=std140) MyUniformBlock
{
vec4 alpha;
float beta;
float gamma;
vec4 delta;
float epsilon;
};
If I'm reading the documentation correctly, the offsets in MyUniformBlock
will be 0, 16, 32, 48, 64, bytes: all multiples of sizeof(vec4)==16
. Right?
However, in C/C++, it is permitted for gamma
to have an offset of 20 bytes, right?
So under what conditions will the C/C++ struct and the GLSL interface block have the same layout?
If I use layout=packed
and give the struct __attribute__ ((packed))
or equivalent, is that guaranteed to match?
Also, consider
Foo array [N];
If C/C++ permits sizeof(Foo)
to be not a multiple of sizeof(vec4)
because there is no padding after the last element, does that cause problems if I try to send the whole of array
to the buffer with glBufferData
?
Upvotes: 2
Views: 794
Reputation: 473407
If I'm reading the documentation correctly, the offsets in MyUniformBlock will be 0, 16, 32, 48, 64, bytes: all multiples of sizeof(vec4)==16. Right?
No. A naked float
in std140
has a base alignment of 4 bytes and takes up 4 bytes. Your structure's offsets are:
uniform (layout=std140) MyUniformBlock
{
vec4 alpha; //offset 0, size 16, min-alignment 16
float beta; //offset 16, size 4, min-alignment 4
float gamma; //offset 20, size 4, min-alignment 4
vec4 delta; //offset 32, size 16, min-alignment 16
float epsilon; //offset 48, size 4, min-alignment 4
};
If I use
layout=packed
and give the struct__attribute__ ((packed))
or equivalent, is that guaranteed to match?
packed
layout gives you fewer guarantees than std140
. In fact, it gives you basically nothing. You can't even assume that all the members you specify in the block will contribute to the layout, because compilers are allowed to optimize away the storage for any variable that you don't use. You can't assume anything with packed
; you must always query the layout explicitly.
Broadly speaking, std140
will match most compilers' natural C and C++ layout, so long as:
vec3
. Note that this applies to matrices that have 3 columns/rows (depending on your matrix orientation).You alignas
/_Alignas
your vector members properly. vec2
objects must be 8-byte aligned, and vec4
must be 16-byte aligned. Note that this applies to matrix types that have 2 or 4 columns/rows too.
C's _Alignas
feature only applies to variable declarations, so you can't apply it to the type. You have to put it on each variable as you use it.
std140
, you never make arrays of anything that isn't a vec4
or equivalent.std140
, struct members of a block should be aligned to 16-bytes.If you don't follow these rules, then your C or C++ structure layout will have to be different from the GLSL equivalent in order to match up properly. For example, a float array[5]
in GLSL would have to be a vec4 array[5]
in C or C++.
Upvotes: 2