Modifying uniform variable arrays inside a UBO.


When I have an array of uniform variables like:

uniform vec3 positions[20];

I can modify all of them at once by querying the location of positions[0] and doing something like

glUniform3fv(positionsArrayUnif, 20, positionsArray);

Now, I can kind of do the same thing with uniform buffer objects.

layout(std140) uniform UniformBlock
    vec3 positions[20];

Now let’s say I’ve successfully made the association between that block and an a uniform buffer object via a uniform buffer binding point. How would I change that entire array in the UBO efficiently? I could try something like this:

glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(array_of_vec3s), array_of_vec3s);

(glm is a library that imitates GLSL types for C++, at least that’s what I think it does.)
But this seems rather unsafe. Maybe it’s OK if I use the “std140” layout for the uniform block, but would there be any way to do this if I used the “packed” layout? Sorry if I’m being incorrect or ambiguous. I don’t know if it’s just me, but OpenGL’s structure and terminology is very confusing.

Edit: Specifically, I mean, if I use the “packed” layout, would it be possible to efficiently change the entire array, without having to query the location of each element?

Edit 2: I may have solved my problem, but I guess I’ll leave this up here for other people’s reference and if anyone else has other considerations, as I don’t feel completely sure if I can really trust this specification to work across all implementations.

From the OpenGL wiki:

Uniform arrays in a buffer are stored sequentially. But they are not guaranteed to be tightly packed. Therefore, for any array uniforms in a block, you must query a stride value with GL_UNIFORM_ARRAY_STRIDE. This stride is the byte distance from the beginning of one element to the beginning of the next.

Edit 3: Anyways, according to the 3.2 core specification, if you use “std140”, array_of_vec3s should have a vec4 of memory for each element, so it’s like 3 floats of data and a sizeof(float) of padding per element.

If you don’t trust the specification beeing implemented the same way, you can’t program OpenGL at all…
std140 has a well defined data layout that is exactly defined in the spec (you might have to read it more than once but the definition is complete) so you can upload everything in your UBO without querying individual offsets.
As for other layouts uploading everything at once is possible but you need to query the layout at runtime.

I suppose, but I heard that some parts of the spec are “iffy”. I can’t really think of any examples though…

The specification is well defined. Just look it up. The only “iffy” parts are how it is implemented. If you want to be safe (ie: you’re not testing on various different hardware), I would avoid vec3s entirely. The padding and alignment requirements could be implemented wrong. If you want an array of vectors, just explicitly pad them out to vec4s.