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.