Indexed vs Non-indexed primitives

Started by
10 comments, last by 21st Century Moose 11 years, 3 months ago

Hello,

I am trying to choose the right way for me. I am rewriting some parts of my engine and now i stand before this question.

I will use these indexed/nonindexed primitives only for imported models ( characters or objects ), not for terrains, particles.

Let's say the advantages and disadvantages.

Advantages of indexed primitives:

  • Primitive can take less memory
  • They are rendered faster ( because of first point ? )

Disadvantages of indexed primitives:

  • More complex models needs normals/bitangents/tangents/uvs/colours per vertex
  • We have to bind two buffers, vertex and index
  • cache miss, if indexes not ordered propertly

and nonindexed are opposite of these.

Is indexed primitives really faster to render for medium complex objects ( even, 50% of vertices needs different normals/tangents/.... so they are reperating actually ). Perhaps it's easy to answer, i would like to hear opinions from more experienced users.

Thank you very much.

DirectX 11, C++

Advertisement
I am trying to choose the right way for me. I am rewriting some parts of my engine and now i stand before this question.

I will use these indexed/nonindexed primitives only for imported models ( characters or objects ), not for terrains, particles.

The right way would depends on your particular usage and scenario. Advantages and disadvantages also change accordingly, as I mention in following quotes...

Let's say the advantages and disadvantages.

Advantages of indexed primitives:

  • Primitive can take less memory

They take less memory if you have enough shared vertices; otherwise the index buffer will be larger than the amount by which you can reduce the vertex buffer(s).

  • They are rendered faster ( because of first point ? )

Not necessarily. It probably will if you have enough shared vertices with a cache-friedly layout. Otherwise, you may be in for a performance hit.

Disadvantages of indexed primitives:

  • More complex models needs normals/bitangents/tangents/uvs/colours per vertex

You need exactly one attribute per vertex no matter what, so this is neither an advantage nor a disadvantage but a fundamental requirement for vertex arrays of any kind.

  • We have to bind two buffers, vertex and index

Not very big of a deal, but yeah, one more buffer to handle.

  • cache miss, if indexes not ordered propertly

That is correct, but not an inherent disadvantage of the index buffer itself, but rather a problem with an incorrect usage of them. You could say, though, that it adds extra complexity to ensure that it doesn't happen.

and nonindexed are opposite of these.

Not really. It doesn't have the added complexity of ensuring cache-friendly indexing, but the points in general are not the opposite. For example, the points with less memory and faster rendering is about using the correct type (non-indexed vs indexed) for a particular model, and not something that is true in general.

Is indexed primitives really faster to render for medium complex objects ( even, 50% of vertices needs different normals/tangents/.... so they are reperating actually ). Perhaps it's easy to answer, i would like to hear opinions from more experienced users.

If vertices needs different normals and such, they need to be duplicated no matter what. You cannot have same vertex with different attributes even with non-indexed buffers.

In general, advantages and disadvantages depends. It adds some complexity to ensure a cache-friendly indexing and it can result in faster rendering in comparison to non-indexed buffers. But it can also be worse. You need to profile and see if the there is actually an observable difference, and if it is worth the extra complexity.

The other advantage of indexed primitives that often seems ignored - probably because it's not as directly measurable as e.g. memory usage - is that they let you join multiple primitive types together. Say you have a model that may be composed of multiple strips, or a mixture of strips and fans - using indexed primitives allows you to take the entire model in one draw call, whereas with non-indexed you would have multiple calls. That can be a big win and can be a fair tradeoff of memory usage versus batching potential.

(Sure, you could do the same with primitive restart, but indexing gives you it on GL_VERSIONs that don't have primitive restart available, and also allows for mixing of different primitive types, which primitive restart doesn't.)

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

[quote name='wh1sp3rik' timestamp='1358426328' post='5022498']
I am trying to choose the right way for me.
[/quote]

it depends on what you need, obviously. I needed speed (the 10,000 blades of grass challenge). testing revealed indexed to be the way to go.

determine your selection criteria (speed, memory, etc). write some test routines. the numbers don't lie.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

In the general case for artist-authored meshes you'd use in a game, indexing is going to be a win. It will allow you to share verts from multiple triangles which not only saves you memory, but can also save you vertex shader executions.

Thank you very much for your answers.

I will stay with indexed primitives and i will try find a way, how to improve it :)

DirectX 11, C++


Let's say the advantages and disadvantages.

Advantages of indexed primitives:

  • Primitive can take less memory


They take less memory if you have enough shared vertices; otherwise the index buffer will be larger than the amount by which you can reduce the vertex buffer(s).



Great post!

I admit I'm pretty behind the times here. Having said that, what domains are you finding shared vertices to be limited?
Whoops, sorry for the double post!

Let's say the advantages and disadvantages.

Advantages of indexed primitives:

  • Primitive can take less memory

They take less memory if you have enough shared vertices; otherwise the index buffer will be larger than the amount by which you can reduce the vertex buffer(s).


Great post!

I admit I'm pretty behind the times here. Having said that, what domains are you finding shared vertices to be limited?

Hard corners and edges don't have shared vertices. The cube is the typical and ultimate example; it has eight corners but needs 24 vertices because all corners and edges are hard, and there are no shared vertices at all. Basically, any time you have two vertices that share position but not some other attribute such as normal.

Smooth corners and edges, for example a sphere (with the possible exception for special places such as its poles), can share vertices since all attributes are typically continuous over the surface. Hard corners and edges introduce discontinuities that break the shared vertices.


Let's say the advantages and disadvantages.

Advantages of indexed primitives:

  • Primitive can take less memory

They take less memory if you have enough shared vertices; otherwise the index buffer will be larger than the amount by which you can reduce the vertex buffer(s).


Great post!

I admit I'm pretty behind the times here. Having said that, what domains are you finding shared vertices to be limited?

Hard corners and edges don't have shared vertices. The cube is the typical and ultimate example; it has eight corners but needs 24 vertices because all corners and edges are hard, and there are no shared vertices at all. Basically, any time you have two vertices that share position but not some other attribute such as normal.

Smooth corners and edges, for example a sphere (with the possible exception for special places such as its poles), can share vertices since all attributes are typically continuous over the surface. Hard corners and edges introduce discontinuities that break the shared vertices.

But even in this case, the indexed version is smaller. Assume that you have really small vertices (16 bytes each). You're still talking about 24 vertices plus 36 (2 byte) indices for the indexed version: 456 bytes total. For the non-indexed version, you're looking at 36 verts, for a total of 576 bytes. As the vertices get larger (to a more realistic size), the numbers just get worse. In the absolute best case for non-indexed, you could render the cube as 6 separate tri-strips of four vertices each, so you only need the 24 vertices... but you still need enough other meta-data to remember that it's actually 6 strips of length 4. Plus, you're now issuing 6 draw calls for one cube.

Basically... it's almost always better to use indices these days. The vertex caching wins inside the GPU, the simplification in tools, the reduced memory footprint in nearly every case, ... it's pretty clear cut.

This topic is closed to new replies.

Advertisement