Fastest way to pass vertices?

Started by
11 comments, last by Omaha 18 years, 10 months ago
Hi, Probably a simple question for you gurus: I have a fairly large amount of meshes, each with there own vertices, normals, texcoords (and some also have tangents/biNormals) Each group is made out of GL_TRIANGLE and has a polycount varying from 12 to 26. Now my question it, what's the fastest way in this case to pass all this data? As far as I know, there are 4 possilbities: - glMultiDrawArrayEXT - glMultiDrawElementsEXT - glDrawArrays - glDrawElements - directly (for i=0 to count do ... glVertex3f etc.) Could somebody order this list on speed and memory usage? Thanks! By the way, I'm currently using glDrawElements, would I gain much speed (>10 frames) by using a faster method for let's say 5000 triangles? Or is it barely noticable on nowadays hardware? Greetings, Rick
Advertisement
Quote:Original post by spek
By the way, I'm currently using glDrawElements, would I gain much speed (>10 frames) by using a faster method for let's say 5000 triangles?


Yeah, if you were drawing much larger batches of polygons, you'd do much better performance-wise.

Anyway, the multidraw calls will probably perform best. But what you should look at doing is combining multiple meshes into a single VBO, if possible. Then you can render the whole thing at once, ordynamically concatenate indices into a dynamic index buffer if you need to change what's being rendered every frame. This is probably optimal for a static environment. If the stuff is moving around, then you should still group them into a single VBO, but you'll probably have to use MultiDraw*. (Actually, another alternative is doing the vertex transformations on the CPU into a stream vertex buffer and feeding pretransformed coordinates into the system. I don't know if this will be faster, as it's probably situation dependent.)
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Thanks for a quick reply! Unfortunately, I can't put all thse small groups into one large vertex as the matrix might differ for every group. It isn't a static scene so that's why. All these groups are used for physics, volumetric shadows etc.

Anyway, I guess I should use glMultiDrawArrayEXT/glMultiDrawElementsEXT, or wouldn't it work for my small arrays? Anyway each little bit of performance is nice, but I should also watch my memory. glMultiDrawElementsEXT is using indices and this takes less memory right? Does it also takes less memory than the glDrawElements?

Thanks
You can still put them all in the same buffer, you simply can't draw them all at once. You don't have to draw an entire buffer in any call, so you can draw lots of things with different matrices without having to change vertex buffer (which can be expensive).
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Yeah as long as the actual vertices aren't changing each frame (pre-transform), you can dump them into a static vertex array. Even better, you can put them in a vertex buffer object with the "static" flag which will dump them into video memory. I don't think you can get much faster than the latter :)

I'd even guess that dynamic vertex/index buffers are going to be faster than just setting pointers from RAM. Either way even with VBOs you use the same functions for setting your array pointers and rendering (well, *almost* the same... see the ARB_vertex_buffer_object extension), you just bind your VBO first.
Interresting... The vertices themselves can't be changed. The matrices and materials per group can differ, and some groups are using tangents/binormals, others don't. But I could group on that. But then there's yet another problem, the groups can get multipassed, depending on how many lights are shining on them. Some of the groups will get rendered once, others 3 for example. I never uses glDrawMultiArraysEXT, but if I understand it right, it gets its data from the videocard RAM instead of ordinary RAM right? In that case, I'm not 100% sure if I should use it, its also stuffed with textures and stuff.

Anyway, would it be possible to give a small example how to upload into memory and render with multiple matrices and materials? By the way, is the same thing possible with glDrawElements/glDrawArrays(in case I want to spare the videocard RAM)?

Thanks again!!
u forgot glDrawRangeElements which in theory gives better performance than glDrawElements
Quote:Original post by spek
As far as I know, there are 4 possilbities:
- glMultiDrawArrayEXT
- glMultiDrawElementsEXT
- glDrawArrays
- glDrawElements
- directly (for i=0 to count do ... glVertex3f etc.)

There's also good ol' display lists, as long as your geometry doesn't change. If you compile all the mess together (or into few lists containing logical groups) depending on implementation the compiled display list may actually do its own optimizations and draw it all in more efficient manner. I think some people reported VBOs and display list tend to come about even speed-wise on modern cards.
not long ago i did alot of tests comparing a few different methods of drawing static terrain and a static plane(just a heightmap with no y value basically) ..i only ever tested on my 9800pro

the results where as follows

Display list with GL_TRIANGLE_STRIP was fastest
Second was using glDrawElements and placing both the indice array and vertex array into Video Memory (GL_ARB_vertex_buffer_object extension) again using GL_TRIANGLE_STRIP. using GL_TRIANGLES was always slower than triangle strips in my tests.

I realise this doesn't really help you because i was rendering 1 large group of polygons where you are rendering small groups of polygons.

It isn't really too hard to set up a demo app to test the results of all the different methods, so i would suggest you try that and see for yourself which way works fastest with what you are doing

Even with the constraints you've listed, there's no reason you can't use VBOs. You'll save having to send all that data to the video card every frame. It's not like you have to use everything that's in the data store with every render call, so as long as everything is there, you can enable/disable it as needed and use the pointer calls to grab the right data.

Also, the Multi versions of DrawArrays and DrawElements are really just there for convenience. They don't really have any performance advantages over multiple glDrawArrays or glDrawElements calls (or as zedzeek mentioned, glDrawRangeElements).

This topic is closed to new replies.

Advertisement