[Solved] BlockIndex-Issues with Uniform Buffer Object

Started by Source_of_Truth, April 15, 2020, 15:18:40

Previous topic - Next topic

Source_of_Truth

Hello people of the LWJGL-forum, I got a question.

My shader programs, consisting of the usual vertex and fragment parts, employ uniform buffer objects. Now, the pipeline I established for handling UBOs has proven very successful thus far, but now I have hit a weird conundrum that I cannot explain.
In this exact, scenario, there are two UBOs, one in the vertex-shader:

(...)
layout (std140) uniform Matrices {
	mat4 viewMatrix;
	mat4 projectionMatrix;
	vec3 camPosition;
};
(...)


and one in the fragment-shader:
(...)
layout (std140) uniform SpecialData{
	float arrA[16];
	float arrB[24];
};
(...)


As usual with OpenGL-Problems, if you got a bug then you either get garbage or nothing. In my case, it was nothing. Expecting my data to be at fault, I wrote tests that verified that the data I was giving to the card was correct. Yes, I have decided to go with std140 layout and, yes, I am aware of the waste-of-space that comes with that, especially with float-arrays that I am employing here. To my knowledge, that should be irrelevant to the problem I am facing.

This is the relevant code that produces the mapping between the blocks and their binding points after the shader programm has been linked and validated.
int uniformBlockLocation = glGetUniformBlockIndex(programId, uniformBlockName);
if (uniformBlockLocation == GL_INVALID_VALUE || uniformBlockLocation == GL_INVALID_OPERATION)
   throw new ShaderError("Shader program '" + programDescription.programName + "' is in an illegal state!");
if (uniformBlockLocation != -1) {
   (...) // associate 'uniformBlockName' with 'uniformBlockLocation'
} else {
    //driver eliminated this variable, it was not needed/used
    System.err.println("Warning: Uniform Block '" + uniformBlockName + "' in Shader Program '" + programDescription.programName + "' was eliminated by the driver!");
}


For reference, I later employ this association-data to link a uniform block with a binding point like this
if(/* association exists */) {
   //associate shader's uniform block to a specific binding point (at which a buffer resides):
   var index = /*get computed 'uniformBlockLocation' earlier */
   glUniformBlockBinding(id, index, block.bindingPoint);
} else {
   System.err.println("Uniform Block '" + uniformBlockName + "' does not exist within this shader-program.");
}
if( /* association exists */ ) {
   glUniformBlockBinding(id, getAssociationFor(uniformBlockName) /* returns previously stored result from 'glGetUniformBlockIndex' */, block.bindingPoint);
} else {
   System.err.println("Uniform Block '" + uniformBlockName + "' does not exist within this shader-program.");
}


while the buffer itself was also associated with the binding point:

var bufferHandle = glGenBuffers();
glBindBuffer(GL_UNIFORM_BUFFER, bufferHandle);
glBufferData(GL_UNIFORM_BUFFER, data, GL_STATIC_DRAW); //send data
glBindBuffer(GL_UNIFORM_BUFFER, 0); //is this wrong?
(...)
glBindBufferBase(GL_UNIFORM_BUFFER, block.bindingPoint, bufferHandle );


Now, since stuff has stopped working once I started using two UBOs and the data looks good, I thought the most likely issue is how I bind them. Perhaps I simply mixed up some stuff but it worked by accident thus far (classical case of 0 is the default)?

I am on an OpenGL 4.4 by the way:

        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);



Rephrasing this into questions:

1.) am I understanding the relationship between the buffer's handle, the binding point and the uniform block index correctly?
2.) must certain things be bound (e.g.) the buffer while calling any binding-point related functions?



KaiHH

The uniform block index you get with glGetUniformBlockIndex() is _NOT_ the binding location you use to bind to the shader.
You must query the bind location via glUniformBlockBinding() taking the index as one of the parameters.
Read: https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object

Source_of_Truth

Hm, no, that is a misunderstanding. I do bind this, but somewhere else. I updated the original post, so my question remains?

Source_of_Truth

Okay, as expected there is no binding issue :(. It seems the data send over is problematic, see this thread.

Thanks to all who read this and thought about what it could be...