View Full Version : Size of elements of arrays in shader storage buffer objects

04-19-2013, 02:35 PM
in my compute shader, I have storage buffer object defined like this:

layout (std430, binding = 0) buffer OutputPositionBuffer {
vec3 outPositions[];

For the buffer, memory of size sizeof(float)*3*n is allocated.

Now, when I write to the buffer by

outPositions[i] = vec3(0.f, 0.f, 0.f);

for i = 0...n-1 and plot the resulting points in the buffer, it looks like not all elements of the buffer have been changed to (0,0,0).
Instead, I see some gibberish from other OpenGL operations left in the memory.

However, if I use float instead of vec3 and write 0.f to (then) 3*n elements, it works.
So, somehow OpenGL doesn't use the correct size of vec3 when accessing the array.

What might I be doing wrong?

Thanks in advance. :)

Alfonse Reinheart
04-19-2013, 04:37 PM
Are you doing the proper synchronization work (http://www.opengl.org/wiki/Memory_Model#Incoherent_memory_access) between whatever clears the data and whatever reads it?

04-20-2013, 04:37 AM
Yes, even if I use GL_ALL_BARRIER_BITS, the problem persists.

I think I have narrowed down the error: Actually, I get points spread out along the 3 axes of the coordinate system, which would mean that one of the components of each vector is not set to 0.f.
I think this is what would happen naturally if I used the std140 memory layout, because my drawing would use the wrong offsets. I just tried it, using vec4 instead of vec3 and everything was correctly set to 0.f.
But I'm using the std430 layout, about which I've read that it doesn't do this padding for arrays of vec3s :confused:

04-20-2013, 09:22 AM
Arrays of vec3s have padding on NV driver and I think that it should have even when using std430.

1. If the member is a scalar consuming N basic machine units, the base align-
ment is N .
2. If the member is a two- or four-component vector with components consum-
ing N basic machine units, the base alignment is 2N or 4N , respectively.
3. If the member is a three-component vector with components consuming N
basic machine units, the base alignment is 4N .
4. If the member is an array of scalars or vectors, the base alignment and array
stride are set to match the base alignment of a single array element, according
to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The
array may have padding at the end; the base offset of the member following
the array is rounded up to the next multiple of the base alignment.

Shader storage blocks (see section 7.8) also support the std140 layout qual-
ifier, as well as a std430 qualifier not supported for uniform blocks. When using
the std430 storage layout, shader storage blocks will be laid out in buffer storage
identically to uniform and shader storage blocks using the std140 layout, except
that the base alignment and stride of arrays of scalars and vectors in rule 4 and of
structures in rule 9 are not rounded up a multiple of the base alignment of a vec4.

So, for std430 arrays (in general) are not rounded up to the base alignment of a vec4, but the beginning of point (4) and point (3) still applies.

04-20-2013, 09:37 AM
Hmm, so the last sentence only affects the end of arrays and the case of vec2 because vec3 are already padded because of rule 3? Then I misunderstood the rule.

Is there a way to achieve what I want without writing each float individually?

04-21-2013, 03:05 AM
This should work:

struct Position {
float x, y, z;

layout(std430, binding = 0) buffer OutputPositionBuffer {
Position outPositions[];

04-21-2013, 05:40 AM
Yeah, this looks good. Thanks.