Reputation: 3942
I'm sending data to uniform block in OpenGL, following a book GLSL by David Wolff.
layout(std140) uniform BlobSettings {
vec4 InnerColor;
vec4 OuterColor;
float RadiusInner;
float RadiusOuter;
};
Client code:
GLuint blockIndex = glGetUniformBlockIndex(programHandle, "BlobSettings");
// Allocate space for the buffer
GLint blockSize;
glGetActiveUniformBlockiv(programHandle, blockIndex,
GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
GLubyte* blockBuffer = (GLubyte *) malloc(blockSize);
// Query for the offsets of each block variable
const GLchar *names[] = { "BlobSettings.InnerColor", "BlobSettings.OuterColor",
"BlobSettings.RadiusInner", "BlobSettings.RadiusOuter" };
GLuint indices[4];
glGetUniformIndices(programHandle, 4, names, indices);
GLint offset[4];
glGetActiveUniformsiv(programHandle, 4, indices, GL_UNIFORM_OFFSET, offset);
// Store data within the buffer at the appropriate offsets
GLfloat outerColor[] = {0.0f, 0.0f, 0.0f, 0.0f};
GLfloat innerColor[] = {1.0f, 1.0f, 0.75f, 1.0f};
GLfloat innerRadius = 0.25f, outerRadius = 0.45f;
memcpy(blockBuffer + offset[0], innerColor, 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[1], outerColor, 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[2], &innerRadius, sizeof(GLfloat));
memcpy(blockBuffer + offset[3], &outerRadius, sizeof(GLfloat));
The program has segmentation fault when doing memcpy. When I set a breakpoint there, I found that glGetActiveUniformsiv return offset and indices wrong. For example:
offset[]
0: 530332809
1: 2686632
2: 1971058176
3:0
While I'm expecting them to be 0, 4,8, 12 etc or something close to that. How do I fix this error?
Upvotes: 0
Views: 1264
Reputation: 43369
I have to wonder why you are using this offset mechanism when std140
is being used in the first place?
I think your book is failing to mention that std140
has very specific alignment rules that mean you can figure out the offset of all of these members without querying them. This is an important concept that if skipped is not going to help you at all.
Following std140
rules, you have a properly aligned data structure already.
layout(std140) uniform BlobSettings {
vec4 InnerColor; // 4N begins at 0
vec4 OuterColor; // 4N begins at 4 (divisible by 4 -- YES)
float RadiusInner; // 1N begins at 8 (divisible by 1 -- YES)
float RadiusOuter; // 1N begins at 9 (divisible by 1 -- YES)
};
The offsets for this data structure will be
0 (InnerColor),
16 (OuterColor), // 4x sizeof GLfloat (vec4)
32 (RadiusInner), // 8x sizeof GLfloat (vec4, vec4)
36 (RadiusOuter) // 8x sizeof GLfloat + sizeof GLfloat (vec4, vec4, float)
There is one thing you need to keep in mind here though, if you were to declare an array of this structure following std140
rules, then you would need to add an additional 8-bytes to the end of the structure for proper alignment. Otherwise vec4 InnerColor
would begin on the wrong boundary after the first element in the array (see rule 10 in the document linked below).
This is all discussed more formally in 7.6.2.2 Standard Uniform Block Layout of the OpenGL 4.5 specification.
Upvotes: 3