1

Let's say I create two vertex buffers, for two different meshes.

     (I'm assuming creating separate buffers for separate meshes is how it's usually done)

Now, let's say I want to draw one of the meshes using an index buffer. Looking at the book Practical Rendering and Computation with Direct3D 11 it doesnt seem like the creation of an index buffer in any way references a vertex buffer, so how does the index buffer know (during input assembly) what vertex buffer to act on?

I've done some googling without answers, which leads me to assume there's something obvious about it that I'm missing.

Elias Finoli
  • 121
  • 9

2 Answers2

2

You are right, index buffers do not reference specific vertex buffers. During DrawIndexed active index buffer is used to supply indices into active vertex buffers (the ones you set using SetIndexBuffer/SetVertexBuffers).

w1ck3dg0ph3r
  • 1,011
  • 6
  • 5
  • Alright I wasnt aware of that. So tell me, was my assumption correct in that you have separate buffers for separate meshes? I understand having a single one can be useful for certain meshes such as static props in a scene and such but in general is it good/bad practice? Are there any limitations as to how many one can/should use? – Elias Finoli Feb 14 '17 at 17:57
  • 1
    You can organize your VBs/IBs in many different ways. The key issue is you have to be able to submit each 'mesh subset' as a distinct draw because material settings need to change between draws. You can even use one VB and one IB for whole levels (within [hardware limitations](https://blogs.msdn.microsoft.com/chuckw/2012/06/20/direct3d-feature-levels/)). If you are new to DirectX, you should just do what's simple. BTW, take a look at the [DirectX Tool Kit](https://github.com/Microsoft/DirectXTK/wiki/Getting-Started). – Chuck Walbourn Feb 14 '17 at 18:50
  • 1
    @EliasFinoli Best practice (from the point of performance) is reducing number of DI calls, i.e. batching - grouping meshes that share vertex layout, some textures and some shaders together by concatenating their VB/IB and rendering them in one call. There is no generic best batching strategy, it depends on your scene, target hardware capabilities etc. Some of the techniques are mentioned [here](https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch28.html). – w1ck3dg0ph3r Feb 14 '17 at 19:08
  • @w1ck3dg0ph3r Thank you both, it's all much clearer now. So far we've only drawn a single rectangle on screen in our course and it never made sense to me how it all would work for complex scenes. – Elias Finoli Feb 15 '17 at 03:52
1

Indeed, Index Buffers and Vertex Buffers are completely independent.

Index buffer will know about VertexBuffer at draw time (eg: when both as bound to the pipeline)

You can think of Index Buffer as a "Lookup Table", where you keep a list or elements indices to draw.

That also means you can attach two completely "logically unrelated" buffers to the pipeline and draw it, nothing will prevent you from doing that, but you will of course have some strange visual results.

Decoupling both has many advantages, here are a few examples:

  • You can reuse an index buffer (for example, two displaced grids with identical resolution can share the same index buffer). That can be a decent memory gain.
  • You can draw your Vertex buffer on it's own and do some processing per vertex (draw a point list for sprites for example, or apply skinning/displacement into a Stream Output buffer , then draw the resulting vertex buffer using DrawIndexed)
  • Both Vertex/Index buffers can also be bound as ByteAddressBuffer, so you can also process your geometry in Compute Shader, and build another optimized index buffer, with culled triangles for example, then process the Indexed Draw with the optimized buffer. Applying those culls in with indices instead of vertices is often faster than vertex, as you will move much less memory.
  • This is a niche case, but sometimes I have to draw a mesh as a set of triangles, but then draw as a set of lines (some form of wireframe). If as example, you take a single Box, you will not want to draw the diagonals as lines, so I have a shared Vertexbuffer with box vertices, then one IndexBuffer dedicated to draw triangle list, and another to draw line list. In case of large models, this can also be an effective memory gain.
mrvux
  • 8,523
  • 1
  • 27
  • 61