Odd issue with gl_InstanceID

Hey there,

I have a problem with hardware geometry instancing. I’m trying to render two instances of an object. So I send the geometry and the indices to a buffer, create VAO and all the stuff, then I render this way :

glDrawElementsInstanced(P_TRIANGLE, 36, UINT, 0, 2);

P_TRIANGLE and UINT are just part of my framework, it’s not a point here. You can see I render 2 instances. Well, here the vertex shader :


#version 150

uniform mat4 projection;
uniform mat4 view;
in vec4 co;

layout (std140) uniform B {
    mat4 model[2];
} instance;

vec4 transf() {
    return projection * view * instance.model[gl_InstanceID] * co; /* actually fails */

#if 0
    if (gl_InstanceID == 0)
        return projection * view * instance.model[0] * co;
    else if (gl_InstanceID == 1)
        return projection * view * instance.model[1] * co;
#endif
}

void main() {
    gl_Position = transf();
}

If I render it, I got a really weird static render (though the matrices represents rotations and translations that change along the time …).

If I comment the return in the transf() function and get the #if/#endif out, all is ok.

Is this a compiler error ? Thanks.

I’m not even sure why the function works at all when using the if/else if statements. The symbol model2 isn’t defined anywhere in the shader (typo perhaps?) and even if you used model[0] or model[1] the compiler is supposed to report an error, because the symbol would still not be defined.

Since you’re using a named instance of the interface block B, the correct name can only be instance.model[i]. model2[i] implies an array type declared at global scope.

Please revise and correct the shader code.

Oh yes sorry, I just mixed some versions of the vertex shader… sorry for that.

I really don’t think the using the instance ID is the issue here. If you can use the ID in an if-statement, it makes absolutely no sense that it would produce different results when used directly.

Just out of curiosity, does anything change when you assign the result directly like this:


gl_Position = projection * view * instance.model[gl_InstanceID] * co;

Nothing changes thokra. I check all things I can check (compilation state, any OpenGL error, buffer correctly sent, correctly bound, binding point, etc …), all is ok.

Another thing :

gl_Position = transf();
gl_Position += gl_InstanceID * 10;

This actually works too. I have my two instances drawn. The fact gl_InstanceID can not be used as an array index is really odd (it must be !).

I have the brand new Macbook Pro 15" 2.2GHz, on Mac OSX Lion 10.7.2. I’m gonna try to compile my sample on another platform, see if the issue is driver-related.

Using it as an index for array lookups is one of proposed use cases. So yes, it has to work.

As for your code, I have absolutely no idead why that works. For the first instance it doesn’t do anything and the second alters the w-component thus changing the NDCs which is supposed to yield a differently projected vertex. So, absolutely no idea. :slight_smile:

Then again, I’ve never used a Mac before and don’t know about conformance and reliability of Apple’s drivers.

Ok new clue. I tried to use simple uniforms (a simple uniform instances[2] in the global uniform bloc and use glUniformMatrix4fv). And here, I can index the instances[2] array with gl_InstanceID, so the problem is within the uniform block.

Once the shaders are compiled and the program linked, I get the index of the uniform block named “B” using glGetUniformBlockIndex. Then I get its size and store it in a variable (even if I don’t use it). Then I reserve enough space for storing my two matrices in a buffer. Next, I link the binding point 0 to the buffer location. I bind the uniform block then. In the end, before any call to glDrawElementsInstanced, I send the two matrices to the buffer.

Any new idea ?

EDIT: Oh ! I found it ! Really weird the 0 and 1 work and gl_InstanceID doesn’t, but here the thing : I only bound the buffer once (just before the render loop). I thought it was just a link done between the buffer location and the binding point one, but apparently, after the first glDrawElementsInstanced, I have to bind again.

Arrays in uniform block can be indexed with gl_InstanceID as well as with any other dynamic index.

Also, binding a uniform buffer to a binding once should have effect on all subsequent draw commands, unless you replace the binding, of course.

So I think this is is gonna be a bug in the Apple drivers, if I understand you correctly.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.