glGetVertexArrayIndexediv and GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING

Hi,

I am updating my OpenGL classes and I am currently working on the wrapper for the vertex array object. I am trying to use only direct state access functions. Since one can mess up the connection between buffer object and vertex attribute by chosing different binding points I added an assertion which checks if the expected buffer is bound to an attribute. I used


glGetVertexArrayIndexediv(mHandle, attributeIndex, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &bufferHandle);

to get the handle of the buffer that shares the same binding point with the attribute. When I checked the documentation of glGetVertexArrayIndexediv they dont’t mention GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING. It is only available in the non-DSA version of this function (glGetVertexAttrib). However, the code does exactly what I expected it to do. Now there is the question, is GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING just missing in the documentation or is it really not available for glGetVertexArrayIndexediv? In the latter case my code is probably not portable and I have to use the non DSA version to fix it — would not be to bad, because it is only used for debugging, but still a little bit annoying since I have to save and restore the original binding every time.

Since one can mess up the connection between buffer object and vertex attribute by chosing different binding points

Having a different binding point from the attribute array index is not “messing up”; it’s the way things ought to be.

If you have interleaved arrays pulling from the same buffer object, then all of those attributes should use the same buffer binding index. This is the whole point of separating vertex formats from buffer bindings.

The correct way to do what you’re asking would be to iterate through the enabled attribute indices, find their buffer binding indices, and make sure that a buffer is bound to them. Here’s what the code would look like for that:


bool AreAllAttribsLinkedToBuffers(GLuint vao)
{
	std::vector<GLuint> bufferBindings; //List of buffer object bindings.
	
	GLint numAttribs = 0;
	glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numAttribs);
	bufferBindings.reserve(numAttribs);
	
	for(GLint attrib = 0; attrib < numAttribs; ++attrib)
	{
		GLint isEnabled = 0;
		glGetVertexArrayIndexediv(vao, attrib, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &isEnabled);
		if(isEnabled) {
			GLint bufferBindingIx = 0;
			//glGetVertexArrayIndexediv(vao, attrib, GL_VERTEX_ATTRIB_BINDING, &bufferBindingIx);
			bufferBindings.push_back(bufferBindingIx);
		}
	}
	
	//Remove duplicate elements.
	std::sort(bufferBindings.begin(), bufferBindings.end());
	bufferBindings.erase(
		std::unique(bufferBindings.begin(), bufferBindings.end());
		
	for(auto bindingIx : bufferBindings)
	{
		GLint bufferObj = 0;
		//glGetVertexArrayIndexediv(vao, bindingIx, GL_VERTEX_BINDING_BUFFER, &bufferObj);
		if(!bufferObj)
		{
			//Buffer object at `bindingIx` not found.
		}
	}
}

You’ll notice that there’s are two commented out lines in that code. That’s because you’re right: not only is there no DSA mechanism to query the buffer object from a binding index in a VAO, there’s no DSA mechanism to query the binding index for an attribute index.

I’ve filed a bug on the matter; the bug is actually larger than you’ve seen. Obviously that’s not going to fix anything for you in the immediate future. So if you want to have this verification, you’re going to have to bind the VAO. Replace the first commented out line with glGetVertexAttribiv(attrib, GL_VERTEX_ATTRIB_BINDING, &bufferBindingIx). And replace the second line with glGetIntegeri_v(bindingIx, GL_VERTEX_BINDING_BUFFER, &bufferObj);

[QUOTE=Alfonse Reinheart;1293224]Having a different binding point from the attribute array index is not “messing up”; it’s the way things ought to be.

If you have interleaved arrays pulling from the same buffer object, then all of those attributes should use the same buffer binding index. This is the whole point of separating vertex formats from buffer bindings.
[/QUOTE]

Maybe I was not specific enough about what I meant with messing up. I meant something like you have buffer and an attribute and you want to connect them at binding point 1 but for some reason the buffer gets bound to binding point 2 instead. That’s why I added the assertion. I am not questioning the sense of the binding points :wink:

I also did something quiet similar to what you wrote. I just used GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING instead so that one loop is enough. Since I have to bind the vao anyway I can also stick to that. Its a little bit annoying since I don’t want the function to change the global state. Therefore I have to query the currently bound vao, store it, bind the vao I want to check, ckeck everything and than rebind the original vao… Well, seems that I have to live with it for now if it is a bug as you say.

By the way, I checked the documentation for glGetVertexAttribiv and glGetIntegeri_v and there are no entries for GL_VERTEX_ATTRIB_BINDING and GL_VERTEX_BINDING_BUFFER… -.- Now I get really confused… Is this also or bug or are they just missing in the doc this time? Here are the links:

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetVertexAttrib.xhtml
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetVertexArrayIndexed.xhtml

Greetings

EDIT: And thx for filing the bug. I have made a bookmark and am curios what they will respond.

Then file a bug on that in the GL documentation project. The specification has them in the table correctly.

It’s GitHub; if you have an account, you can just subscribe to the issue and receive notifications. And since the move to GitHub, they’ve actually been pretty responsive on spec-bugs.

Yes I have a GitHub account and already subscribed to your issue. I ll create the new issue later in the evening and post the link to it here. Thanks for your help :slight_smile:

I have created the new issue: GL_VERTEX_BINDING_BUFFER and GL_VERTEX_ATTRIB_BINDING missing · Issue #54 · KhronosGroup/OpenGL-Refpages · GitHub

Saw that there are also