At about how many instances would instancing become effective? DirectX dynamic buffers seem to take a little more out of the fps than an immutable one would. So obviously you wouldn't want to make a dynamic buffer for one mesh. What about two or three? I realize there's probably many variables to take into account but just to get a grasp on it?
-
\$\begingroup\$ It's not entirely clear, but are you implying that you wouldn't still keep all your meshes in immutable buffers even with instancing? Because you should. The instancing dynamic buffers complement the immutable ones, not replace them. There's several ways to update dynamic buffers, and the obvious way is not the way you should do it (you want to stream updates to a dynamic buffer acting roughly as a circular queue). \$\endgroup\$– Sean MiddleditchCommented Jan 21, 2015 at 7:49
2 Answers
Your best bet with these kind of questions is to implement it and see on your target/example hardware how it works out.
For Direct3D 11, you can try out the InstancingFX11 sample from MSDN Code Gallery.
First, instancing will save you only CPU cycles.
You can get most of performance when drawing thousands of small meshes (e.g. 100 triangles). So it's useful for sprites, particles, trees in distance etc.
Bigger meshes save you same amount of CPU cycles as small, but overall impact isn't that great, because you won't be drawing thousands of them.
It's good idea to create immutable vertex buffer with instances for static and sleeping objects (not moving). You can use UpdateSubresource to update it occasionally.
For moving objects, it's good to use either dynamic vertex buffer or just constant buffer. One constant buffer can store up to 1024 world matrices. You can put material data into separate constant buffer...or not.
For moving objects, you update your constant buffers anyway. With instancing, you'll do just one big update and one draw call per batch. Overall impact should be positive even for small number of objects. You move same data from CPU to GPU in same way (to CBs) and render same objects, but with lower number of DirectX calls.
Is it worth it?
It depends how much CPU time you spent rendering objects and how many instances of same objects you're rendering.
Lets say you render 5000 objects and it takes 10ms. There are 500 different objects. Theoretical improvement is 9ms (you go from 5000 batches to 500 batches).
But it won't be so good, you still need to move the same amount of data from CPU to GPU. Also, when rendering 5000 objects, you might sort them to reduce render state changes (if you sorted by shaders, there was only 500 SetVertexShader/SetPixelShader calls and 5000 draw calls).
Based on conditions above it's realistic to expect 5 - 8ms improvement for our case.