1
\$\begingroup\$

If I want to bind an instance matrix to a vertex shader, how do I go about it?

For example, here is a super-simple VS input:

struct VS_IN {
    float4 Position : POSITION;
    row_major float4x4 WorldMat : INSTANCE_TRANSFORM;
};

How would the corresponding bindings look when creating the ID3D11InputLayout?

I figured it would be something akin to:

D3D11_INPUT_ELEMENT_DESC[] bindings = ...;
bindings[0] = { 
    "POSITION", // SemanticName
    0U, // SemanticIndex
    DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT, // Format
    0U, // InputSlot
    0U, // AlignedByteOffset
    D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_VERTEX_DATA, // InputSlotClass
    0U // InstanceDataStepRate
};
bindings[1] = { 
    "INSTANCE_TRANSFORM", // SemanticName
    0U, // SemanticIndex
    DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT, // Format
    1U, // InputSlot
    0U, // AlignedByteOffset
    D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_INSTANCE_DATA, // InputSlotClass
    1U // InstanceDataStepRate
};
bindings[2] = { 
    "INSTANCE_TRANSFORM", // SemanticName
    0U, // SemanticIndex
    DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT, // Format
    2U, // InputSlot
    0U, // AlignedByteOffset
    D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_INSTANCE_DATA, // InputSlotClass
    1U // InstanceDataStepRate
};
bindings[3] = { 
    "INSTANCE_TRANSFORM", // SemanticName
    0U, // SemanticIndex
    DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT, // Format
    3U, // InputSlot
    0U, // AlignedByteOffset
    D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_INSTANCE_DATA, // InputSlotClass
    1U // InstanceDataStepRate
};
bindings[4] = { 
    "INSTANCE_TRANSFORM", // SemanticName
    0U, // SemanticIndex
    DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT, // Format
    4U, // InputSlot
    0U, // AlignedByteOffset
    D3D11_INPUT_CLASSIFICATION::D3D11_INPUT_PER_INSTANCE_DATA, // InputSlotClass
    1U // InstanceDataStepRate
};

In the example above, I'm increasing the InputSlot value with each 'row' of the instance matrix, because I would expect that each row of the matrix would take up the next 128-bit input register.

However, in other examples I've seen on the internet, people seem to increase the SemanticIndex with each row instead. I thought that might because they declare the input as four float4 fields instead of a matrix, but then I looked at this question, and that doesn't seem to be the case.

Anyway, to cut to the point, if I want to use VS_IN in the format I've provided, what is the correct way to lay out the input elements?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

If you use same semantic for SemanticName, then you need to increase number for SemanticIndex.

I also see that you are increasing InputSlot. This may be correct or not depending on how your data is layed out. If you really have 4 vertex streams (vertex buffers) then it's fine, but I assume that your instance transform is stored in one vertex buffer. Then you need to set same stream number to InputSlot in every instance binding.

assume that:

stream_number = 4;

You'll also need to set this stream:

//  most probably offset_in_vertices will be 0 in your case
// vert_buf - contains your instrancing data
IASetVertexBuffers(stream_number, 1, &vert_buf, &stride, &offset_in_vertices);

Also while AlignedByteOffset is optional i suggest at least use D3D11_APPEND_ALIGNED_ELEMENT to specify that data go sequentially one after another.

so, setup code will look like this:

bindings[0] = { 
    // nothing changed
};
bindings[1] = { 
    "INSTANCE_TRANSFORM", // SemanticName
    0U, // SemanticIndex
    stream_number, // InputSlot
    0, // AlignedByteOffset: zero because start of a matrix
    // ...
};
bindings[2] = { 
   "INSTANCE_TRANSFORM", 
    1U, // SemanticIndex
    stream_number, // InputSlot
    D3D11_APPEND_ALIGNED_ELEMENT, // or 16 (4 float32)    AlignedByteOffset
    // ...
};
bindings[3] = { 
    "INSTANCE_TRANSFORM", 
    2U, // SemanticIndex
    stream_number, // InputSlot
    D3D11_APPEND_ALIGNED_ELEMENT, //or 32, AlignedByteOffset +4 float32
    // ...
};
bindings[4] = { 
    "INSTANCE_TRANSFORM", // SemanticName
    3U, // SemanticIndex
    stream_number, // InputSlot
    D3D11_APPEND_ALIGNED_ELEMENT, // or 48 AlignedByteOffset +4 float32
    // ...
};

Then your vertex shader input structure will look like this:

struct VS_IN
{
    float4 Pos          : POSITION;
    float4 r0           : INSTANCE_TRANSFORM0;
    float4 r1           : INSTANCE_TRANSFORM1;
    float4 r2           : INSTANCE_TRANSFORM2;
    float4 r3           : INSTANCE_TRANSFORM3;
};

Or like this:

struct VS_IN
{
    float4 Pos                  : POSITION;
    row_major float4x4 inst_mat : INSTANCE_TRANSFORM;
};
\$\endgroup\$
3
  • \$\begingroup\$ Thanks. But is there no way to use an input row_major float4x4 INSTANCE_TRANSFORM;? \$\endgroup\$ Commented Jan 29, 2015 at 23:51
  • \$\begingroup\$ Yes there is. I've edited my answer to address your question. Have not tried it but it should work. Also do not forget about AlignedByteOffset, you should set correct value. E.g. for binding[2] it would be 16 (4 float32) for binding[1] = 32 and so on \$\endgroup\$
    – alariq
    Commented Jan 30, 2015 at 0:42
  • \$\begingroup\$ See the InstancingFX11 sample on MSDN Code Gallery \$\endgroup\$ Commented Jan 30, 2015 at 5:47

You must log in to answer this question.

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