1
\$\begingroup\$

I've heard something about instancing and understood it's useful for drawing the same object many times with slight changes. It's faster because you call the draw function once per frame and update the buffer (in this case the instance buffer) once per frame too while with constant buffers, for example, if you need a world matrix you have to update your constant buffer once per object.

But if I have only one object, would instancing be faster (or at least as fast as) using a constant buffer? With instancing, you have to call only an update buffer function (for the vertex-instance buffer) while with CB you need two calls: one for the vertex buffer and one for the constant buffer.

Another question about instancing:

Since I have to update the instance buffer once per frame, I need to create it with DYNAMIC_USAGE and with a byte width representing the maximum number of objects I can draw with one call. For example, if I want to pass a matrix, I need insBufferdesc.bwitdh= sizeof(matrixtype)*maxNumObjs. Is this right? Given that maxNumObjs is 20 and I want to render only 10 objs, I've should just update the first 10 matrices of the buffer and call drawInstanced(..., 10). Will I get some error if I don't use all of the buffer?

\$\endgroup\$
1
\$\begingroup\$

First question: You are wrong where you state that with instancing you have to update one buffer while with constatnt buffers two buffers. There is no vertex-instance buffer but a vertex buffer and an instance buffer (which is also created with the D3D11_BIND_VERTEX_BUFFER flag). So either way you have to update the vertex buffer and instance (or constant) buffer - If they need to be updated.

You second question is correct, you have to create a buffer with maximum size which could be used and only write the visible objects to the beginning of the buffer. Then call draw with the appropriate number of vertices for example: drawinstanced(...,10*object.vertices.count());

\$\endgroup\$
  • \$\begingroup\$ ok ,i know that buffer doesnt exist but you update the two buffers with a single call so i think it's faster. you use IAsetvertexbuffer(or somethiong similar) passing the two buffers(instancing and vertices) instead of (IAsetvertexbuffer once and once vs/pssetconstantbuffer). anyway dont i lose performance instancing a single object, do i?? \$\endgroup\$ – Liuka May 17 '14 at 16:59
  • \$\begingroup\$ What you say is not updating a buffer but setting it as the active buffer which is different, and it still sets two buffers, but only by one IASetVertexBuffers call which is probably not noticable. For instancing a single object please refer to this question which has some great answers: gamedev.stackexchange.com/questions/74464/… \$\endgroup\$ – János Turánszki May 17 '14 at 17:02
0
\$\begingroup\$

You don't need a second vertex buffer (passing 2 vertex buffers) It's more easy to use one vertex buffer en still call the DrawIndexedInstanced(triangleIndicesCount, instanceCount, 0, 0, 0). Your vertex shader will be called for all instances, but you need to add another symantic to your vertex_in struct.

struct VertexIn
{
    float3 PosL : POSITION;
    float3 Normal : NORMAL;
    float2 Tex : TEXCOORD;
    unsigned int InstanceId : SV_InstanceID;   // <-- this one will be filled with the instance index.
};

For the instances (world matrix, colors, etc), you can use a StructuredBuffer or a ConstantBuffer. Structured buffers can be larger than 64k, Constant buffers are faster (but need to be aligned on 128bit).

Using a constant/structured buffer over a second vertex buffer is way more maintainable, because you don't need to specify the combined InputLayout for both the vertex and the instance etc. The Vertex format for single draw/multi instanced draw is the same.


Another optimize you could think of (instead of directly choosing hardware instancing) is combining meshes into a single geometry. For example, instead of rendering 10k blades of grass, you could combine multiple blades in one geometry and rendering them through eachother, which will look as all blades are moving separately.

Rendering one mesh with many vertices VS rendering multiple times the same meshes, the one mesh is way more parallel. The one mesh vertices are calculated completely parallel. Hardware instancing doesn't render the geometries parallel(the are rendered in serial, so the vertices aren't calculated parallel across multiple instances), but it only eliminates the DrawIndexed() call and updating multiple matrices instead of a single one for each draw.

\$\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.