Broadly speaking, what you want to avoid are having lots of vertex formats. Indeed, if you pretend that buffers can’t be attached to VAOs at all, that vertex buffer bindings are actually context state, it’d be best for everyone.
So, step 1: use the separate attribute format API for manipulating VAOs. You create a VAO when you have a distinct vertex format to use (aka: the state set by
Sort your models by vertex format. So for a particular vertex format, you’ll have many models. Try to combine different models into the same buffer object where possible, but if you need to change buffer objects, you can do so via
This is not about how much memory a VAO represents; it’s about how much changing vertex formats costs during rendering. Some hardware doesn’t actually have vertex fetching hardware, so a vertex format is really a piece of vertex shader code that gets grafted to your shader right before rendering. If you keep the VAO (and program) the same as much as possible, then the system won’t have to stitch together new vertex format shader code.
Changing vertex buffer bindings is cheap; changing vertex formats is expensive.