Ryan K
Ryan K

Reputation: 51

glGetUniformIndices not returning correct index

I am trying to learn how to use uniform buffer objects, reading the OpenGL Superbible 5. I have a uniform block in the my shader:

layout(std140) uniform SkeletonBlock  
{  
    vec3 position[64];  
    vec4 orientation[64];  
} Skeleton;

Now my code to grab the index is:

const GLchar* uniformNames[2] =
{
    "SkeletonBlock.position",
    "SkeletonBlock.orientation"
};

GLuint uniformIndex[2];
glGetUniformIndices(shaderProgram, 2, uniformNames, uniformIndex);

For some reason this call is giving me a really high index (4294967295, consistently) and I am not sure why. I feel like I am missing something obvious. OpenGL is reporting one active uniform block, which is correct, out a max allowed of 15. No error flags are active before or after this section of code either. Any suggestions where it could be going wrong?

Upvotes: 4

Views: 2234

Answers (3)

James Bedford
James Bedford

Reputation: 28982

You will probably encounter this if the uniform block variable isn't referenced (i.e. used) in the shader's GLSL source code. The shader source code compiler will remove the variable from the shader altogether as an optimization. Then, when you call glGetUniformIndices, GL_INVALID_INDEX will be returned.

Upvotes: 0

Nicol Bolas
Nicol Bolas

Reputation: 474136

layout(std140) uniform SkeletonBlock  
{  
    vec3 position[64];  
    vec4 orientation[64];  
} Skeleton;

Here is how this definition reads:

  • There is a uniform block named SkeletonBlock.
  • It contains an array of 64 vec3s called position, followed by an array of 64 vec4s called orientation.
  • The name for all of its members is qualified in GLSL by the identifier Skeleton.

Note the last part. In GLSL, and only in GLSL, the position array is identified by Skeleton.position. In C++, the array is identified by either SkeletonBlock.position or SkeletonBlock.position[0]. The point here is that from C++ code you use the block name SkeletonBlock as a prefix, not the instance name Skeleton.

The SkeletonBlock block has an index that can be queried with glGetUniformBlockIndex (note the use of the word "Block" and the lack of plurality on "Index"). The individual uniform members also have indices, but they are indices into the list of uniforms. And these variables must be named correctly. If the uniform block has an instance name, then the uniform block members must be prefixed by the block name, not the instance name.

If you're passing those names to the OpenGL function and not getting valid indices, then you likely have a driver bug.

Upvotes: 2

scpayson
scpayson

Reputation: 192

I believe you want

const GLchar* uniformNames[2] =
{
    "Skeleton.position",
    "Skeleton.orientation"
};

As the semantics of a C-style language (such as GLSL) have it, you are declaring a variable of type uniform SkeletonBlock named Skeleton. Hence, "SkeletonBlock.position" is of the form <typename>.<member>, where you want <variable>.<member>.

The OpenGL docs say that you will get a GL_INVALID_INDEX from glGetUniformIndices() when you give it a bad uniform name. It might be smart to check each of the returned indices against this. I would bet that GL_INVALID_INDEX == -1.

Also, this number 4294967295 is the unsigned interpretation of a 32-bit -1 (twos complement).

Upvotes: 1

Related Questions