Jump to content

Poll: Best Practice - VBO, VA, or Immediate Rendering


jakj

Recommended Posts

Immediate (glBegin/glEnd):

- Most flexible in ordering, data specification, and memory usage

- Slow as fuck

Vertex Arrays:

- Fewer function calls, leading to greater efficiency

- Greater memory usage

Vertex Buffer Objects:

- Fastest possible, storing data directly on the card

- Can blow apart a card's memory very quickly, dragging down the entire program

The dilemma:

Minecraft is already a hog, and the situation where VBOs would truly be valuable (as in, where performance actually degrades: large complex models) are also where they would be least successful (few people are likely to use giant models, and video-card memory is precious).

For lots of little models, in theory VBOs could help, but considering the fragmented nature of a mod, near-impossible to truly optimize and utilize. Most of the techniques that can be used when making a whole program, break down when having to inject code into an existing program that doesn't even use the same methods.

My thought so far:

I think vertex arrays are probably the best way to go. It's more memory, but it's all system memory, which is slower but more plentiful. Some of my transformations have to be cached anyway, instead of just using render-time matrices, so it may as well be cached in vertex arrays, which (as far as I can tell) can be used like any other array in the mean time.

This mod already requires a video card with shader support, so, at a rough guess...six-ish year old cards? Something like that. And really, people aren't going to be running out of system memory on computers that modern.

Thoughts?

Link to comment
Share on other sites

How much memory do you anticipate using? The latest Steam hardware survey lists about 70% of participants having at least 1GB of VRAM. In the end it's up to those who use your API to optimize their models, unless you want to use real-time edge collapsing.

Disclaimer: I started learning OpenGL a couple weeks ago. I'm by no means an expert. :)

Link to comment
Share on other sites

Well, I did a bit more research today into VBOs, spurred on by the discovery that in GL 3.1+ every single thing is either deprecated or removed except VBOs, attributes, and shaders. So here's my new theory:

Data per vertex: 3 floats for position, 3 floats for normal, 2 floats for texture coordinate, making 32 bytes (which ATI likes, being not as flexible as nVidia). Fast 16-bit indices, limit to 65536 vertices per model. That makes 2 MiB, which is right in the range of 1-4 MiB recommended for VBOs on most mid-range hardware.

So, for a maximum of 8 MiB (and more likely 3-4 MiB) total, I get two VBOs I can keep bound for the duration of Minecraft's running, which should work even if some mod turns on Minecraft's shitty native VBO mechanism. Allocate both VBOs as static data.

Whenever a model is instructed to be rendered, stick it in the VBO, and keep a stack pointer to the next free spot. If the VBO fills up, reallocate the buffer (using the quick method of binding a new buffer-body of null which is either a no-op (if no GL calls are pending) or quick-allocates a new buffer from a pool (since we choose a common size) and the GL calls can continue in the background). This also allows the disabling of synchronization on the buffer, because we're never writing to a byte more than once.

As more and more models become rendered, the VBO gets purged, but overall, that should happen very infrequently, and most of the time the VBO will be sitting partially-full with the most-common models in it.

Another possibility includes a slightly-larger VBO (probably 4 MiB) to make it less- likely that larger models will overflow the VBO. Alternately, models larger than X vertices could be placed into their own VBO, though by that point, performance would probably be degrading to the point that the extra rebinding costs would collapse the framerate. It depends on whether it would be more costly to keep rewriting the VBO (allocated with static hint, remember) or to do several rebinds every frame.

Link to comment
Share on other sites

Is there a reason you limit yourself to 8 MiB? That seems small considering the poly counts for some models I found here.

Unrelated, I've been using this book with the OpenGL Superbible to learn so far. It covers a lot with plenty of references to more in-depth studies. The later parts look like they deal with real world optimization techniques which might be useful to you.

Link to comment
Share on other sites

Well, answering the last part first, there's only so much that can be squeezed in between Minecraft's already-bloated render frames that honestly are as maximally-inefficient as any human being could achieve.

VBOs are recommended by most to sit around the 1-4 MiB range to make sure that they fit in any available space (and don't cause memory fragmentation) and that they are not so large that the driver decides they're too big to fit in VRAM anyway. Don't forget, amongst everything else (meaning VRAM that's needed as scratch space for normal drawing every frame), there're also texture packs, which are the biggest memory-hog around. (I have a 256x texture pack that's already over 200 megs with maximal PNG compression.)

In terms of vertices required, remember that only the simplest models will be using facet normals and disjoint texture coordinates (where such differences are discernable): Complex models with smooth surfaces will have vertex normals and some sort of uniform texturing (such as projective) so that each vertex/texcoord/normal will be specified only once, and then glDrawElements (or whatever) to re-use the vertices (which hopefully will be available in the post-render cache; not sure how much I want to bother with things like vertex sorting).

Assume a closed model (so all facets form a continuous surface): A huge number of vertices will be re-used. One triangle is 3, two are 4, three are 5, and so on. For a complex model, assume the first two are insignificant, and we roughly get number of triangles = number of vertices. So, your 10,000-ish polygon models are barely taking up a fifth of the 2 MiB buffer.

As for the 200k+ polygon models...fuck me. No way in hell would it be of any use to allocate VBOs that large, when it's just going to go to waste most of the time. Trying to resize VBOs on the fly is fiddly, and letting the user specify the number is just asking for stupid bug-reports to come in. Probably the thing to do would be to allocate a tertiary small VBO with the Streaming hint, and then just split the model up into pieces and throw them at the buffer in bite-sized chunks. Maybe try using a mapped buffer and hope the driver connects it straight across the system bus.

(But, let's be honest: I could spend weeks just working on optimization, even sorting vertices, but are we really going to sit here and pretend 200k+ polygon models are feasible in Minecraft?)

Link to comment
Share on other sites

Haha, yeah I wasn't expecting models that large. I was more concerned with having multiple models about as detailed as the Half Life zombie in that link. Sure, it fills about 1% of the buffer, but that leaves only 100 models per buffer object at that level of detail. One mod would (most likely) never even come close to filling that up, but what about all of the mods in a pack like Technic? There are a *lot* of items added in there.

With that said I highly doubt every mod item would get a fancy new model. Won't stop me dreaming about it though.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...