0
\$\begingroup\$

So here is the premise:

I have 2 vertex buffers buffers whose data and corresponding definition is as follows:

Vertex 1: This one contains the per instance data

// Somewhere defined in the header
std::vector<XMMATRIX> instancedMeshTransformMatrixArray;

...// Following code is in a function called loading data

// We will compute and setup the buffer with the information of the indexed mesh here
static float angle = 0.0f;
//angle += 90.0f * deltaTime;
XMVECTOR rotationAxis = XMVectorSet(0, 1, 1, 0);

g_WorldMatrix = XMMatrixIdentity();
XMMATRIX scale = XMMatrixScaling(1.0f, 1.0f, 1.0f);
XMMATRIX rotate = XMMatrixRotationAxis(rotationAxis, XMConvertToRadians(angle));
XMMATRIX translate = XMMatrixTranslation(0.8, 0.0f, 0.0f);
g_WorldMatrix *= translate  * rotate * scale;

// We will also fill/process the matrix buffer here that will be used to index into to rendered indexed mesh
instancedMeshTransformMatrixArray.push_back(g_WorldMatrix);

// create and initialize the instanced data buffer 
D3D11_BUFFER_DESC vertexInstancedBufferDesc = {};
vertexInstancedBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexInstancedBufferDesc.ByteWidth = sizeof(XMMATRIX) * instancedMeshTransformMatrixArray.size();
vertexInstancedBufferDesc.CPUAccessFlags = 0;
vertexInstancedBufferDesc.Usage = D3D11_USAGE_DEFAULT;

D3D11_SUBRESOURCE_DATA resourceData = {};
//ZeroMemory(&resourceData, sizeof(D3D11_SUBRESOURCE_DATA));

resourceData.pSysMem = &instancedMeshTransformMatrixArray[0];

HRESULT hr = g_d3dDevice->CreateBuffer(&vertexInstancedBufferDesc, &resourceData, &g_d3dIndexedVertexBuffer);
if (FAILED(hr))
{
    return false;
}

Vertex 2: This contains the per model data

// Somewhere in the header
// Vertex data for a colored cube.
struct VertexPosColor
{
    XMFLOAT3 Position;
    XMFLOAT3 Color;
};

VertexPosColor g_Vertices[8] =
{
    { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT3(0.0f, 0.0f, 0.0f) }, // 0
    { XMFLOAT3(-0.5f,  0.5f, -0.5f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, // 1
    { XMFLOAT3(0.5f,  0.5f, -0.5f), XMFLOAT3(1.0f, 1.0f, 0.0f) }, // 2
    { XMFLOAT3(0.5f, -0.5f, -0.5f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, // 3
    { XMFLOAT3(-0.5f, -0.5f,  0.5f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, // 4
    { XMFLOAT3(-0.5f,  0.5f,  0.5f), XMFLOAT3(0.0f, 1.0f, 1.0f) }, // 5
    { XMFLOAT3(0.5f,  0.5f,  0.5f), XMFLOAT3(1.0f, 1.0f, 1.0f) }, // 6
    { XMFLOAT3(0.5f, -0.5f,  0.5f), XMFLOAT3(1.0f, 0.0f, 1.0f) }  // 7
};

...//Following code is in a function called loading data
   //It is followed by the loading of data for Vertex 1

// Create and initialize the vertex buffer.
D3D11_BUFFER_DESC vertexBufferDesc = {};
//ZeroMemory(&vertexBufferDesc, sizeof(D3D11_BUFFER_DESC));

vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.ByteWidth = sizeof(VertexPosColor) * _countof(g_Vertices);
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;

resourceData.pSysMem = g_Vertices;

hr = g_d3dDevice->CreateBuffer(&vertexBufferDesc, &resourceData, &g_d3dVertexBuffer);
if (FAILED(hr))
    {
    return false;
}

I also load data for the index buffer and constant buffer. I have tested it with the VS Graphics debugger and the data seems to have loaded correctly. However, I can provide how I do that as well if needed.

Following is how is create the Input Desc for the 2 buffers:

// Create the input layout for the vertex shader.
D3D11_INPUT_ELEMENT_DESC vertexLayoutDesc[] = {
// Per vertex data
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(VertexPosColor,Position), D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(VertexPosColor,Color), D3D11_INPUT_PER_VERTEX_DATA, 0 },

// Instanced Data
{ "INSTANCED_MATS", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1},
{ "INSTANCED_MATS", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1},
{ "INSTANCED_MATS", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1},
{ "INSTANCED_MATS", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 64, D3D11_INPUT_PER_INSTANCE_DATA, 1}

};

hr = g_d3dDevice->CreateInputLayout(vertexLayoutDesc, _countof(vertexLayoutDesc), vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_d3dInputLayout);
if (FAILED(hr)) {
    return false;
}

Finally in another function called Draw I attach the data to the IA and call DrawInstanced as follows. :

...
const UINT vertexStride = sizeof(VertexPosColor);
const UINT offset = 0;

const UINT instancedVetexStride = sizeof(XMMATRIX);

g_d3dDeviceContext->IASetVertexBuffers(0, 1, &g_d3dVertexBuffer, &vertexStride, &offset);
g_d3dDeviceContext->IASetVertexBuffers(1, 1, &g_d3dIndexedVertexBuffer, &instancedVetexStride, &offset);
g_d3dDeviceContext->IASetInputLayout(g_d3dInputLayout);
...

// Draw the cube
g_d3dDeviceContext->DrawIndexed(std::size(g_Indicies), 0, 0);
//g_d3dDeviceContext->DrawIndexedInstanced(std::size(g_Indicies), 1, 0, 0, 0);

The following is my vertex shader as is:

//VERTEX SHADER

cbuffer PerApplication : register(b0)
{
    matrix projectionMatrix;
}

cbuffer PerFrame : register(b1)
{
    matrix viewMatrix;
}

cbuffer PerObject : register(b2)
{
    matrix worldMatrix;
}

struct AppData
{
    float3 position : POSITION;
    float3 color: COLOR;
    matrix instancedMatrix : INSTANCED_MATS;
};

struct VertexShaderOutput
{
    float4 color : COLOR;
    float4 position : SV_POSITION;
};

VertexShaderOutput SimpleVertexShader(AppData IN, uint instanceID : SV_InstanceID)
{
    VertexShaderOutput OUT;
    uint p = instanceID;
    matrix mvp = mul(projectionMatrix, mul(viewMatrix, IN.instancedMatrix));// worldMatrix));
    float4 pos = float4(IN.position, 1.0f);
    OUT.position = mul(mvp, pos);
    OUT.color = float4(IN.color, 1.0f);

    return OUT;
}

I am not sure if I am setting the offsets incorrectly or if I am incorrectly attaching the slots for the VB's to the IA. Or is it something to do with my input description for the BV's.

But I get the following D3D11 Warning, which to me is vague as I do not know what offset of 80 it is talking of.

D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: Input vertex slot 1 has stride 64 which is less than the minimum stride logically expected from the current Input Layout (80 bytes). This is OK, as hardware is perfectly capable of reading overlapping data. However the developer probably did not intend to make use of this behavior.  [ EXECUTION WARNING #355: DEVICE_DRAW_VERTEX_BUFFER_STRIDE_TOO_SMALL]
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: Vertex Buffer at the input vertex slot 1 is not big enough for what the Draw*() call expects to traverse. This is OK, as reading off the end of the Buffer is defined to return 0. However the developer probably did not intend to make use of this behavior.  [ EXECUTION WARNING #356: DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL]

I have been stuck here for hours. Any help, hints is greatly appreciated!!

\$\endgroup\$
0
\$\begingroup\$

INSTANCED_MATS", 3, DXGI_FORMAT_R32G32B32A32_FLOAT starts at 48. Not 64.

Your offset is wrong.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This answer would be even better if it included an explanation of how you determined this was the problem/solution, so users can apply similar reasoning to future issues. \$\endgroup\$ – DMGregory Dec 15 '19 at 0:15
  • \$\begingroup\$ That seemed to be the issue, thanks it works now! but I am a bit confused on the usage of the SV_InstanceID as I was expecting to index into the matrix array of data like so: IN.instancedMatrix[instanceID] but the compiler throws an error saying: Error X3017 Cannot implicitly convert from 'const float4' to 'float4x4`. \$\endgroup\$ – Rudraksha Shah Dec 16 '19 at 15:37
  • \$\begingroup\$ Hi. You don't need to use the instance id. Use it like a normal member variable. The matrix is fed in per instance. It's not an array. The other thing you will need to look up is row_major as your matrix maybe in column order, not row order. \$\endgroup\$ – ErnieDingo Dec 16 '19 at 18:51
  • \$\begingroup\$ Just to add to this. You only need to use the instance id if you are accessing a constant buffer. An area of memory. Your vertex input already contains the matrix of the insurance in question. You doubt get direct access to every matrix. \$\endgroup\$ – ErnieDingo Dec 16 '19 at 19:11

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.