I'm having difficulty understanding how glBindBufferRange offset / alignment works in the Nvidia example project gl_commandlist_basic. I've read that the offset needs to be a multiple of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT which is 256 and/or that offset and alignment is very important with glBindBuffer range.. I have an example UBO that works with mat4/vec4 and a non-working example with mat4/mat3/vec4. The UBO doesn't add up to be a multiple of 256 in either case. I'm try to send vec4(0.f, 1.f, 0.f, 1.f).
If mat4 = 64 bytes, mat3 = 36 bytes, vec4 = 16 bytes then the working example has 64+16=80 bytes, which isn't a multiple of 256. The non-working example has 64+36+16 = 116 bytes.
NV uses an inline called uboAligned which is defined as
inline size_t uboAligned(size_t size) { return ((size + 255) / 256) * 256; }
Removing this from the working/non made no difference either way.
I assume I need to add some "padding" to the UBO in the form of a float/vec2/vec3/vec4, etc. How do I determine the correct amount of padding I need if I want to use the mat4/mat3/vec4 UBO?
/* APPLICATION */
typedef struct
{
glm::mat4 MM;
// glm::mat3 NM;
glm::vec4 Cs;
} myData0;
Gluint objectUBO;
glCreateBuffers(1, &objectUBO);
glNamedBufferData(objectUBO, uboAligned(sizeof(abjObjectData) * 2), 0, GL_STATIC_DRAW); //
for (unsigned int i = 0; i < allObj.size(); ++i)
{
myData0 myDataTemp;
myDataTemp.Cs = glm::vec4(0.f, 1.f, 0.f, 1.f);
glNamedBufferSubData(objectUBO, sizeof(abjObjectData) * i, sizeof(abjObjectData), &objDataInit);
}
//hot loop
for (unsigned int i = 0; i < allObj.size(); ++i)
{
glBindBufferRange(GL_UNIFORM_BUFFER, 1, objectUBO, uboAligned(sizeof(abjObjectData)) * i, sizeof(abjObjectData));
//draw
}
/* HW */
out vec4 Ci;
struct ObjectData
{
mat4 MM;
// mat3 NM;
vec4 Cs;
};
layout (std140, binding = 1) uniform objectBuffer { ObjectData object; };
void main()
{
Ci = object.Cs;
}