I noticed that there's IASetVertexBuffers() to set multiple vertex buffers at once but there's only IASetIndexBuffer() to set one index buffer. So I assume that I can simultaneously only have one index buffer set but I can have multiple vertex buffers set at the same time.

  1. Is that correct?
  2. How do I use index buffer with multiple vertex buffers? I.e. what indices do I provide to use more than one vertex buffer and how do I know what buffer conrete indices refer to?

Or is this used only in the case when instead of interleaved vertex data: (Pos, Normal, Pos, Normal, Pos, Normal) I provide the data in multiple buffers: (Pos, Pos, Pos) (Normal, Normal, Normal) and conrete indices refer to the same vertices in each buffer?


3 Answers 3


Multiple vertex buffers would be used when your data is non-interleaved. If your data was interleaved then you'd put it all in one vertex buffer. (You can also have vertex data partially interleaved and partially not. For instance, all the positions could be in one buffer, and all the other attributes - normals, UVs, etc. - interleaved in another buffer.)

Regardless of the vertex layout, there's only one index buffer bound at a time, and the same index is used for all vertex buffers. If the number 47 is found in the index buffer then the GPU will load the 47th element of the first vertex buffer, the 47th element of the second vertex buffer, etc. The data from all bound vertex buffers will be available as inputs to the vertex shader.

  • \$\begingroup\$ My friend had actually already given me that answer before but I haven't had time to post it. :P \$\endgroup\$
    – NPS
    Commented Aug 25, 2013 at 21:08

This question comes up a lot in relation to the .obj model format, and the answer is that yes: you can only have a single index buffer, but it works with both interleaved and non-interleaved data.

For the non-interleaved case I'm assuming that you're thinking of a case where the data is fully de-duplicated (again, like .obj). What's important to realise here is that this kind of case may be optimized for storage, but it's not optimized for rendering.

The solution is to re-introduce duplicate vertex attributes so that the single index buffer is capable of handling all streams. Roundabout this time many people say "surely that's less efficient because it uses more memory?" The answer to that one is "no".

Saving memory is not the be-all and end-all of performance. Using an index buffer gives other advantages too, and both of these are more important for performance than saving memory:

  • Your hardware's vertex cache will now work, meaning that recently transformed vertices will not need to be re-transformed if they're shared, and:
  • An entire model can be drawn in a single draw call rather than having to split it into multiple draw calls.

It may be the case that future hardware will allow for multiple index buffers, or an extra level of index indirection, but there's no sign of that on the horizon. The current approaches work more than well enough, and a little extra memory usage is a fair tradeoff for a lot of extra performance.

  • 1
    \$\begingroup\$ I have no bloody idea what "de-duplicated" means. I also have no idea what you meant by "re-introduce duplicate vertex attributes". You also didn't say if non-interleaved data is THE ONLY case when I can use multiple vertex buffers or not. If not then I still don't know how to use them. \$\endgroup\$
    – NPS
    Commented Aug 24, 2013 at 21:40

Look at my answer on a similar question on stack overflow here for interleaving and duplicate vertex attribute from an obj file.

Also, the way to use non interleaved vertex attributes ( but with matching indices ) is by tweaking the input layout.

The InputSlot attribute of D3D11_INPUT_ELEMENT_DESC provide to CreateInputLayout is what you are seeking for.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .