Jump to content

  • Log In with Google      Sign In   
  • Create Account


JBurnside

Member Since 23 Jan 2006
Offline Last Active Jul 19 2012 08:33 AM

Topics I've Started

DX9 to DX11 convert, getting a warning, Index buffer has not enough space!

13 July 2012 - 12:11 PM

Hello,

I have been converting a rendering system from using DX9 to DX11. At this point, everything I am currently testing is visually working. Unfortunately I am getting a DX API warning, "D3D11: WARNING: ID3D11DeviceContext::DrawIndexed: Index buffer has not enough space! [ EXECUTION WARNING #359: DEVICE_DRAW_INDEX_BUFFER_TOO_SMALL ]"


I have found that getting this warning depends on the meshes I am loading, and what order they are loaded in. If I load meshes, A, B, C in that order I get the issue when I render B or C. Mesh A appears to be the cause as anything loaded after it will cause a call to DrawIndexed to give that warning. From the warning I would think I am somehow requesting to draw using more indices than our present, but this does not appear to be the case. All three meshes use the same index and vertex buffers. If I load mesh A's vertices but not indices the issue remains, but if I load mesh A's indices but not vertices the issue goes away.


I am setting the vertex and index buffers to be used for rendering per shader, then per object calling DrawIndexed using a start vertex and start index. Here are some snippets of the rendering code:


Per shader -

...


UINT stride = sizeof(VERTEX_POSNORMTANTEX);

UINT offset = 0;

ID3D11Buffer *const vertexBufferPtr =

VertexBufferManager::GetReference().GetPosNormTanTexBuffer().GetVertexBuffer();

Renderer::theContextPtr->IASetVertexBuffers(0, 1, &vertexBufferPtr, &stride, &offset);


Renderer::theContextPtr->IASetIndexBuffer(IndexBuffer::GetReference().GetIndices(), DXGI_FORMAT_R32_UINT, 0);

...

Per Object -

// Assuming we are using triangle lists for now

Renderer::theContextPtr->DrawIndexed(mesh.GetPrimitiveCount() * 3, mesh.GetStartIndex(), mesh.GetStartVertex());


I have found a work around but it does not seem like a good way to do things as it requires setting the index buffer per object. The following code will get rid of the issue:


Per Object -

...

Renderer::theContextPtr->IASetIndexBuffer(IndexBuffer::GetReference().GetIndices(), DXGI_FORMAT_R32_UINT, mesh.GetStartIndex() * 4);

...

// Assuming we are using triangle lists for now

Renderer::theContextPtr->DrawIndexed(mesh.GetPrimitiveCount() * 3, 0, mesh.GetStartVertex());

...


Mesh A is some test geometry that I have been using for years with OGL, DX9 and now DX11 projects, so I feel it is unlikely, but not impossible, that there is something wrong with the data. I can recreate the issue with some other meshes that worked with the DX9 version as well. All my vertices and indices are copied into vector containers until I am down loading then I create the index and vertex buffers based on this data.


I have discovered that I can hard code the "mesh.GetPrimitiveCount()" to return 0, so nothing is drawn and I still get the warning.



Here are the snippets of how I create my index buffer:

For each load -

UINT IndexBuffer::AddIndices(UINT startVert, const UINT *_indices, UINT _numIndices)
{

// Test if this buffer has already been finalized

assert(!indexBufferPtr);

size_t ret = indices.size();

// Implement a solution for the Renderer Lab

for(size_t i = 0; i < _numIndices; ++i)

indices.push_back(_indices[i]);// + startVert);

return (UINT)ret;

}
The return is the StartIndexLocation for this particular mesh.

When I am done loading assets -

void IndexBuffer::Finalize()
{

D3D11_BUFFER_DESC ibd;

ibd.Usage = D3D11_USAGE_IMMUTABLE;

ibd.ByteWidth = sizeof(UINT) * (UINT)indices.size();

ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;

ibd.CPUAccessFlags = 0;

ibd.MiscFlags = 0;

ibd.StructureByteStride = 0;


D3D11_SUBRESOURCE_DATA iinitData;

iinitData.pSysMem = &indices[0];

HR(Renderer::theDevicePtr->CreateBuffer(&ibd, &iinitData, &indexBufferPtr));


// Do not need to keep a local copy of indices

testSize = indices.size();

indices.clear();

}

I have a vertex buffer class that works the same way except for being a template to handle different input layouts. An instance of the vertex buffer class is made for each unique vertex layout. In my example mesh A, B and C all use the same vertex buffer.

PARTNERS