Single VBO memory management and state change optimization techniques

No. No single change or combination of changes, whatever they are, will “guarantee high performance” in general, without any qualification of hardware, software, drivers, or technique.

Possibly you refer to the one mentioned here?:

originally posted in this NVIDIA presentation here?:

These aren’t really the only choices, or even the best choices.

It seems you may be unaware of interleaved vertex attributes, or that buffer objects themselves are typeless. For instance, you can store all of your vertex attributes and index lists, for multiple batches, in the same GPU buffer object, with no problems at all.

Sounds like you want to read this wiki page, if you haven’t already, and ask follow-up questions:

That’s for handling efficient streaming of dynamic content to the GPU. For static content, you don’t really need this.

True. But you really don’t want to go that route anyway.

Motivational blog post (that actually strongly related to your question):

But seriously, for dynamically uploaded content, just read that Buffer Object Streaming wiki page and ask questions.

You just haven’t tripped over it yet. There are chapters in books about some of this.

Two basic issues:

  1. How to manage buffer object memory for vertex attributes and indices
  2. How to issue draw calls sourcing from those buffer objects most efficiently.

From a performance standpoint, the cost of #2 is actually a driver for #1. **

Re #2, I can’t tell you how your GPU+driver performs, but you can run tests to determine cost per draw call in various scenarios. I can tell you that on NVIDIA GPUs, command lists and NVIDIA bindless are about the fastest ways to issue batches (draw calls) referring to VBO data. Behind that, it’s VAOs backed by VBO data and client arrays (depending on batch size). And often slowest, plain old unaccelerated VBOs. The larger your batches (draw calls), the fewer your draw calls, and the less the cost per draw call matters. But bottom-line is, you care about minimizing total draw call cost and overhead, especially if you have a ton of tiny batches.

Re #1, for static content, just pre-upload that on startup to whatever buffer objects you want. To the extent that you’ll batch draws for multiple objects together in shared draw calls, obviously you’d want to combine those in the same buffer object or objects (they talk about this way back in that 2014 presentation, for instance). For dynamically-uploaded content, see that Buffer Object Streaming page for a primer. In either case, you make those buffer objects as quickly accessible to draw calls as possible, to keep your cost per draw low. Minimizing draw calls by batching more content together can help reduce this overhead, to a point. But at some point you start trading culling efficiency.

** (There’s also the issue of how to dynamically generate this content on the GPU when needed, but we’ll assume you’re not doing that for now.)