VAO state simplified

2017-01-28 Permalink

There is a common confusion of what state VAOs hold. Some of the non-DSA functions used to setup the VAO modify the global state instead, further complicating the matter.

OpenGL specification contains detailed tables documenting what state VAOs are made of. However, I find them not as comprehensible. Instead I prefer to present the state in a way akin to a C structure:

struct VertexArrayObject
	// VertexArrayElementBuffer
	uint element_buffer;

	struct Binding {
		// VertexArrayVertexBuffers
		uint buffer;
		intptr offset;
		sizei stride;

		// VertexArrayBindingDivisor
		uint divisor;
	} bindings[];

	struct Attrib {
		// VertexArrayAttribBinding
		uint binding; // This is an index into bindings[]

		// EnableVertexArrayAttrib
		bool enabled;

		// VertexArrayAttrib*Format
		int size;
		enum type;
		boolean normalized;
		boolean integer;
		boolean long;
		uint relativeoffset;
	} attribs[];

The functions in the comments are the DSA functions that should be used to setup the corresponding state. If you use the older non-DSA functions, you should remember that glBind­Buffer(GL_­VERTEX_­ARRAY) does not modify the VAO state, it’s glVertex­Attrib­Pointer which sets the VAO binding to the current GL_­VERTEX_­ARRAY value.

Note also that the VAO is a container object. Thus it prolongs the lifetime of the buffer objects that it points to. Therefore you can delete the buffers the moment you bind them to the VAO.[1]


  1. If the VAO is currently bound then unbind the VAO first. Otherwise glDeleteBuffers unbinds the buffer from the VAO. It’s not an issue if you use DSA to setup your VAOs.

Share on