Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I want to auto-bind uniform blocks with certain named values to certain binding points when I compile a shader. For example, I have some basic, default fixed binding points that are always used for certain things like:

0 Camera
1 Model
2 Material
3 Lights

At the moment I'm binding manually by finding the index of a named block with glGetUniformBlockIndex, and then binding it with glUniformBlockBinding. What I'd like to do is fetch the set of all block names in my shader program. When I iterate with glGetActiveUniformsiv, I get a list of all uniforms, which excludes block names.

Is there any way to do this without testing and failing each of my above names to see if it's an active block with glGetUniformBlockIndex? There's no glGetActiveUniformBlocksiv, is there...

share|improve this question
    
Is there some reason you can't use ARB_shading_language_420pack and specify them in the shader itself? It's a pretty widely available extension. –  Nicol Bolas Feb 7 '13 at 18:26
    
Didn't actually know this existed. I'll look at it. Thanks :) –  Robinson Feb 8 '13 at 10:52
add comment

1 Answer

up vote 4 down vote accepted

This is pretty easy; just the program introspection API to fetch the indices. First, ask how many uniform blocks there are:

GLint numBlocks;
glGetProgramiv(prog, GL_ACTIVE_UNIFORM_BLOCKS, &numBlocks);​

All of your uniform block indices are on the half-open range [0, numBlocks). So iterate through them and get their names.

std::vector<std::string> nameList;
nameList.reserve(numBlocks);
for(int blockIx = 0; blockIx < numBlocks; ++blockIx)
{
    GLint nameLen;
    glGetActiveUniformBlockiv​(prog, blockIx, GL_UNIFORM_BLOCK_NAME_LENGTH, &nameLen);

    std::vector<GLchar> name; //Yes, not std::string. There's a reason for that.
    name.resize(nameLen);
    glGetActiveUniformBlockName​(prog, blockIx, nameLen, NULL, &name[0]);

    nameList.push_back(std::string());
    nameList.back().assign(name.begin(), name.end() - 1); //Remove the null terminator.
}

BTW, if you're doing this because you think it's faster, stop. First, performance is irrelevant since this is one-time setup code. Second, you're doing this for maybe 4-8 blocks at most. It's not going to affect actual performance in any way. So really, there's no reason to not just get the indices by name if that's what you're ultimately doing. The introspection API is for when you don't know what is there.

share|improve this answer
    
I wasn't do it so it was faster Nicol, just because I thought it was more "correct" to enumerate them, rather than trying each one and failing if it wasn't there. Anyway, thanks very much for this. –  Robinson Feb 8 '13 at 10:47
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.