locked
Instancing and buffer size issues... Or input layout issues... Or something...

    Question

  • DrawIndexedInstanced: Vertex Buffer at the input vertex slot 1 is not big enough for what the Draw*() call expects to traverse.

    This is the error message that I'm getting through the output.

    Here's my input layout.

    D3D11_INPUT_ELEMENT_DESC layout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "TANGENT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 44, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    	{ "TEXCOORD", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 }
        };

    Here's the HLSL vertex shader code.

    struct VertexInputType
    {
        float4 pos : POSITION0;
        float3 normal : NORMAL;
        float4 tangent : TANGENT0;
        float4 color : COLOR0;
        float2 uv : TEXCOORD;
        float3 instancePos : TEXCOORD1;
    };

    Here's the struct, that goes on the buffer.

    struct InstanceData
    	{
    		XMFLOAT3 transforms;
    	};

    Here's the buffer creation part

    InstanceData* instances = new InstanceData[4];
    	instances[0].transforms = XMFLOAT3(-10.5f, -1.5f, 5.0f);
    	instances[1].transforms = XMFLOAT3(-10.5f, 1.5f, 5.0f);
    	instances[2].transforms = XMFLOAT3(10.5f, -1.5f, 5.0f);
    	instances[3].transforms = XMFLOAT3(10.5f, 1.5f, 5.0f);
    	instances = new InstanceData[4];
    
    	CD3D11_BUFFER_DESC instanceDataBufferDesc;
    	instanceDataBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    	instanceDataBufferDesc.ByteWidth = sizeof(InstanceData)* 4;
    	instanceDataBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    	instanceDataBufferDesc.CPUAccessFlags = 0;
    	instanceDataBufferDesc.MiscFlags = 0;
    	instanceDataBufferDesc.StructureByteStride = 0;
    
    	D3D11_SUBRESOURCE_DATA instanceData;
    	instanceData.pSysMem = instances;
    	instanceData.SysMemPitch = 0;
    	instanceData.SysMemSlicePitch = 0;
    	//(1000 * sizeof(InstanceData), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DEFAULT, 0);
    
    	DX::ThrowIfFailed(m_d3dDevice->CreateBuffer(&instanceDataBufferDesc, &instanceData, &m_instanceDataBuffer));

    Finally, I'll show the vertex assignment part, along with the draw code.

    UINT stride = sizeof(Vertex);
    			UINT offset = 0;
    			context->IASetVertexBuffers(0, 1, &mesh.m_vertexBuffers[submesh.VertexBufferIndex], &stride, &offset);
    			context->IASetVertexBuffers(1, 1, &instanceBuffer, &instanceStride, &instanceOffset);
    			context->IASetIndexBuffer(mesh.m_indexBuffers[submesh.IndexBufferIndex], DXGI_FORMAT_R16_UINT, 0);
    
    			// Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
    			context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    
    			context->VSSetConstantBuffers(0, 1, &m_matrixBuffer);
    			context->VSSetConstantBuffers(1, 1, &m_materialBuffer);
    			context->PSSetConstantBuffers(1, 1, &m_materialBuffer);
    			context->VSSetConstantBuffers(2, 1, &m_cameraBuffer);
    
    			context->DrawIndexedInstanced(submesh.PrimCount * 3, instanceCount, submesh.StartIndex, 0, 0);

    Too my eye, I don't see anything wrong. But, yet I'm getting this error code. Also, the other instances seem like they don't draw. I did some graphics diagnostics and found that the other instances are indeed drawing, but at the exact same location. Resulting in them failing the depth test. They draw at the same location because instancePos, in the VertexInputType ,is set to all zeros. It's as if the input assembler isn't get the instance position variable. Any help?


    • Edited by DualOpAmp Thursday, November 28, 2013 3:38 PM
    Thursday, November 28, 2013 3:37 PM

All replies

  • Hi DualOpAmp,

    Welcome here!

    From above I couldn't find any issue as well. But it seems that there is no enough buffer of  input vertex slot 1 for Draw*() call.

    Could you give me a more clear meaning about " They draw at the same location because instancePos"?

    Regards!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, November 29, 2013 10:59 AM
    Moderator
  • What I mean is that the it would look like there's only one "entity" drawing. These entities would normally move across the screen, because they're being spawned. Seeing only one, I started a graphics diagnostics and took a screenshot. Upon investigating a pixel, I found (through the pixel history) that there are other instances being drawn. The pixel history says vertex 2 out of 100, instance 2; vertex 2 out of 100, instance 3; vertex 2 out of 100, instance 4, etc. Curious still, I stepped through the vertex shader of one of these instances and found that the variable "instancePos" is set to all zeros. InstancePos is the float3 I use to adjust the position of an instance, you can see it in the VertexInputType.

    Thanks.

    Friday, November 29, 2013 1:06 PM
  • In the buffer creation part, you have:

    InstanceData* instances = new InstanceData[4];
    	instances[0].transforms = XMFLOAT3(-10.5f, -1.5f, 5.0f);
    	instances[1].transforms = XMFLOAT3(-10.5f, 1.5f, 5.0f);
    	instances[2].transforms = XMFLOAT3(10.5f, -1.5f, 5.0f);
    	instances[3].transforms = XMFLOAT3(10.5f, 1.5f, 5.0f);
    	instances = new InstanceData[4]; // <-- This is the bug. Remove this line.
    

    The last line is the problem. Also, in general you really shouldn't use naked new statements like that. Use smart pointers such as std::unique_ptr or, if you know the size you need in advance, just use a fixed size array. Otherwise you're likely going to wind up with memory leaks. In the code you posted, you don't have a corresponding "delete[] instances;" call after your call to CreateBuffer. It's possible you just didn't post that, but if you used unique_ptr you wouldn't need one in the first place and you wouldn't have to worry about that memory leaking ever.


    Visual C++ MVP | Website | Blog | @mikebmcl | Windows Store DirectX Game Template

    Friday, December 13, 2013 11:39 PM