2
\$\begingroup\$

I have some vertices in an array from which I create a vertex buffer. Let's say I have vertices:

v1, v2, v3, v4

I use indices:

0, 1, 2, 3

Is there any performance impact if I change the indices to

1, 3, 0, 2

(to have another geometry)? I just wonder whether the directx will iterate through vertices jumping to different addresses in a memory to get vertices (not linearly) or maybe the directx is able to recreate the vertex buffer (before it is sent to the graphics card) to suit the indices like this (it could then iterate it linearly):

v2, v4, v1, v3

(beacuse it is obvious that is is better to iterate through data put linearly in a memory)?

Is the question understandable?

\$\endgroup\$
  • 1
    \$\begingroup\$ Have you tried benchmarking this yourself? That's a good place to start \$\endgroup\$ – Outurnate Jul 15 '13 at 16:28
  • \$\begingroup\$ Well, true, I could test it myself, however it needs some preparations and maybe somebody has already checked it and know the answer. \$\endgroup\$ – tobi Jul 15 '13 at 16:30
5
\$\begingroup\$

The order can impact performance, but not in a simple triangle vertex reordering like you're talking about. The order of the vertices doesn't matter much in terms of access and jumping around; any performance degradation from non-linear vertex access is more than made up for in other ways when using properly ordered indices.

DirectX/OpenGL will not reorder your vertex buffer to match the index buffer. It can't, really; the index buffer could reference the same vertex more than once (that's the primary point of an index buffer). The GPU is also designed to assume you'll have non-linear vertex accesses; that's pretty standard.

You should be aware of the "vertex cache," though you don't at all need to think about it much for most indie/hobby scale projects. Basically there is a small cache of processed vertices that the GPU keeps around. This is important when any vertices are shared, which is very common for 3D models but is rarer in 2D sprite games and most cube/voxel engines (few or no shared vertices, in which case indices may not even be all that useful).

If two triangles use the same index, the GPU wants to avoid running the vertex shader twice for that vertex. However, the cache has limited space. If you use vertex 3, then 0, 1, and 2, then use 3 again, that vertex will be in the vertex cache and the GPU as no need to rerun the vertex shader for it. Hoerver, if you reference vertex 3, then 1000 other vertices, then reference vertex 3 again, the GPU will probably be forced to rerun the vertex shader (the existence and size of this cache is a hardware optimization, not part of any spec).

Therefor, keeping reused vertex indices in your index buffer relatively close together to the extent possible means less time will be spent rerunning vertex shaders. There are libraries for this so you shouldn't need to worry about how to do this and for your game it almost certainly won't make a measurable difference anyway (it starts to matter for very large games with very complex/detailed meshes though).

There is also an effect where it can be faster to process certain vertices (or triangles, more accurately) first dependent on where they are in the mesh. Triangles inside of "inner concave" features (say, an armpit) are more likely to be occluded, so it's more efficient overall to draw the other triangles first so early-Z kicks in (and even with Z-prepass, such ordering means writing to the depth buffer less). Again, there are libraries for this, and it's probably not something you'll need to worry about unless you're making the next CryTek or 3DS Max. For a MineCraft-like engine, I would only recommend building vertices top-down since you'll often be seeing only the surface of the world; maybe there's some ordering optimizations to faces inside caves you can figure out, but it probably won't matter in the slightest.

If you're unsure if you need to worry about an optimization, just test and profile and see if it's a real problem affecting work or platform support. If you're unsure if a change is a pessimization, again, profile and see. Even if it is, use the profile to see if it's one that even matters for your specific game and target hardware (if you lose 2 FPS but were already running at 400, and the change brings some other benefit, why waste time caring about the FPS loss now?).

Short version: no, reordering your indices to better handle triangle strips is not going to affect performance in any meaningful way.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

The purpose of indexing is to make meshes more compact in memory. It does not matter in what order the indices are. If you use indexing, it will always be the same speed with the same amount of indices. It wouldn't make sense (at least while speed is in concern, and it always is) for the graphics driver to look through the indices and determine if they are in order or not.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Could you enlighten me how it is placed in memory then, because I cannot understand why this doesn't matter without additional sorting. The graphics card has memory too, so it would need to iterate through vertices to render them and if they are not sorted it will jump to the different places in memory. \$\endgroup\$ – tobi Jul 15 '13 at 17:35
  • \$\begingroup\$ There are better answers now. You should read them. \$\endgroup\$ – Lasse Jul 15 '13 at 18:18
1
\$\begingroup\$

I'd put the vertex order linear in memory.

If your vertex size is not a clean multiple of 32 bytes or so, then having the order be linear can enable the vertex fetch unit on your GPU to actually pre-fetch some of the next vertex at the same time as the current one. Of course, you'll need to get a nice high vertex count in order to get meaningful figures from any profiling run, but that can prove to be a small but significant performance boost.

The purpose of indexing, by the way, is not just to reduce memory requirements - I guess people have become conditioned to thinking that reducing memory usage is everything. Indexing serves two additional purposes, which will give you much greater performance than reducing memory:

  • It enables your hardware's vertex cache to actually work, so your hardware can determine if it's already shaded a vertex and just pull the result from the cache instead of having to shade it again.
  • It allows for concatenation of multiple primitives which improves draw call batching (by reducing draw call counts) with much less overhead than using degenerate triangles.

For these, whether the vertices are accessed in linear order doesn't matter so much; for the first a more cache-friendly order is what you need, for the second it doesn't actually matter at all.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.