c++openglglslopengl-4

glGetProgramResourceIndex returning wrong indices


I'm using a generic mathod to bind buffers (uniform buffers, shader storage buffers, ...) to my shader programs, based on glGetProgramResourceIndex() function and buffer's name, but sometimes I'm getting strange results from the glGetProgramResourceIndex() function.

I have this common code for all my vertex shaders:


...

// uniforms
layout (std140, binding = 0) uniform CameraData
{
    uniform mat4 ViewMatrix;
    uniform mat4 ProjectionMatrix;
    uniform vec3 WCameraPosition;
};
layout (std140, binding = 1) uniform TransformData
{
    uniform mat4 ModelMatrix;
    uniform mat4 NormalMatrix;
};

...

where these two uniform buffers are explicitly linked to binding points 0 and 1. There are other uniform buffer block, but all are different in name and binding point. However, I'm getting the error on these two uniform blocks, so I think that listing all the other uniform blocks is not useful.

I use the generic method to bind them (and all the other buffers), which is done just before the draw call, as follows:


// Get shader program
...

glUseProgram(program);

// binding of textures and uniform data
...

for (auto& buffer : rc.AdditionalBufferData)
{
    GLuint bufferIndex = glGetProgramResourceIndex(program, buffer.ResourceProgramInterface, buffer.Name.data());
    glBindBufferBase(bufferGL.Target, bufferIndex, buffer.ID);
}

// draw
...

(The buffer object contains infos about the buffer, such as the name, program interface (GL_UNIFORM_BLOCK, GL_SHADER_STORAGE_BLOCK, ...), buffer object id, ...)

For some shader programs it works fine, but sometimes I'm getting wrong visual results. During the debugging process, I noticed that for the shader programs giving wrong results the glGetProgramResourceIndex() function returns inverted indices for CameraData and TransformData uniform buffers, 1 and 0 instead of 0 and 1. The RenderDoc capture shows the same behavior:

RenderDoc capture screenshot

it is possible to see the inverted sizes of the buffers.

If I force the indices of the two buffers CameraData and TransformData to be 0 and 1 respectively (instead of 1 and 0), the issues are fixed and the visual results are correct.

I didn't find anything similar on the web, so I tried to change binding points, names and other minor stuff, but had no luck. To me, it seems a low level bug. Has anyone ever had something similar happen?

I'm using opengl core 4.5.


Solution

  • The problem is that you're treating resource indices as binding indices. They are not the same thing.

    Resource indices are arbitrary numbers whose sole purpose is acting as a numerical identifier for a resource in a shader. These indices cannot be set from a shader, and they should only be used in other program resource APIs.

    If you want to get the buffer binding index for a uniform buffer by name, you need to query the GL_BUFFER_BINDING property through glGetProgramResourceiv. You pass the program, buffer.ResourceProgramInterface, and resource index to this function.