# Storing and rendering Mesh Data in stl container

I'm trying to refresh my DirectX11 knowledge, and ran into a problem while trying to render multiple meshes instanced.

What I want to do is give my ObjectManager class the name of an .obj file and it then parses the vertex/index data out of that file. If I try to load the same .obj more than once, it should instead add an instance at the desired position in the scene. To do so I have a Vector storing all the Data for the objects. (see code below)

My problem is a massive performance drop when iterating though the vector of mesh info instead of just rendering the first object in the vector (for test purposes). Now, this sounds obvious of course, what I'm struggling to understand is, that this performance drop happens even when the vector only contains 1 element. So simply adding the for loop seems to cause this , even without rendering more or even effectively iterating through a bunch of items. (it drops from 2000+ fps to around 300, plus a very regular lag while moving. This is so substantial with so little change that I must assume something funny is going on).

So my assumption is either:

1. Vector is not a good way to store the mesh data and render all of it every frame. Is a vector not the common, or at least a feasible way, of storing this kind of data?
2. I might be doing something wrong while creating/updating the buffers for every object.

ObjectManager should hold all the objects i spawn in the scene, and in it's render function it will render all objects I have registered with it. To reduce draw calls I want to instance multiple calls of the same object, so my idea was to have a struct like this:

struct MeshDataBundle { std::string name; //used as ID to not spawn multiple struct with same Model std::shared_ptr<Model> model; std::vector<Instance> instances; //Instance = struct with just XMFLOAT3 for position };

My ObjectManager class now has a std::vector of this struct. In the render function, it should iterate though the vector and render the Model in it with the instance information in the included instances vector.

The render function looks like this:

//D3D class, passed as paramter, has the Device, DeviceContext etc.
public void ObjectManager::render(D3D& d3d)
{
//called only the first time
if (!initialized)
{
initBuffers(d3d);
}

//run through all models
for (auto val : modelData)
{
//update the subresources and buffers
DirectX::XMMATRIX tempWorld;
//cbPerObject is a struct with only a XMMATRIX world world-matrix
m_cbPerObject.world = DirectX::XMMatrixTranspose(tempWorld);

//Update Buffers with vertices and instance information. Using CComPtr's, thus the "..Buffer.p".
//Dynamic buffers bc updated multiple times per frame
D3D11_MAPPED_SUBRESOURCE mappedResource = { 0 };
d3d.DevCon->Map(cbPerObjectBuffer.p, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy(mappedResource.pData, &m_cbPerObject, sizeof(cbPerObject));
d3d.DevCon->Unmap(cbPerObjectBuffer.p, 0);

D3D11_MAPPED_SUBRESOURCE mappedResourceInst = { 0 };
d3d.DevCon->Map(cbInstanceBuffer.p, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResourceInst);
memcpy(mappedResourceInst.pData, &val.instances[0], sizeof(Instance)*val.instances.size());
d3d.DevCon->Unmap(cbInstanceBuffer.p, 0);

d3d.DevCon.p->VSSetConstantBuffers(0, 1, &cbPerObjectBuffer.p);

//model class has its own vertex and index buffer, which we get and use
CComPtr<ID3D11Buffer> bufferPointers[2] = { val.model->getVertexBuffer(), cbInstanceBuffer.p };

UINT32 strides[2] = { sizeof(Vertex), sizeof(Instance) };
UINT32 offsets[2] = { 0, 0 };

d3d.DevCon.p->IASetVertexBuffers(0, 2, &bufferPointers[0].p, strides, offsets);

d3d.DevCon.p->IASetIndexBuffer(val.model->getIndexBuffer(), DXGI_FORMAT_R32_UINT, 0);
d3d.DevCon.p->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

d3d.DevCon.p->DrawIndexedInstanced(val.model->getIndexCount(), val.instances.size(), 0, 0, 0);

}
};


MISC:

Things I suppose might also be of relevance:

1.Creating the buffers in the ObjectManager (the class containing the above)

D3D11_BUFFER_DESC cbbd;
ZeroMemory(&cbbd, sizeof(D3D11_BUFFER_DESC));

cbbd.Usage = D3D11_USAGE_DYNAMIC;
cbbd.ByteWidth = sizeof(cbPerObject);
cbbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbbd.MiscFlags = 0;

hr = d3d.Device.p->CreateBuffer(&cbbd, NULL, &cbPerObjectBuffer);

D3D11_BUFFER_DESC cbbd2;
ZeroMemory(&cbbd2, sizeof(D3D11_BUFFER_DESC));

cbbd2.Usage = D3D11_USAGE_DYNAMIC;
cbbd2.ByteWidth = sizeof(Instance)*maxInstanceBufferSize;//largest possibly needed buffer for instances
cbbd2.BindFlags = D3D11_BIND_VERTEX_BUFFER;
cbbd2.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbbd2.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA instanceData;
instanceData.pSysMem = &modelData[largestIndex].instances[0];
instanceData.SysMemPitch = 0;
instanceData.SysMemSlicePitch = 0;

hr = d3d.Device.p->CreateBuffer(&cbbd2, &instanceData, &cbInstanceBuffer);


2.The Model class has it's own vertex and index buffers. These are used in the above rendering function via getter functions. The Buffers of every Model are created like this:

vertexCount = v.size();
indexCount = i.size();

//VERTEX BUFFER
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(Vertex) * vertexCount;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;

vertexData.pSysMem = &v[0];
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;

result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &vertexBuffer);

// INDEX BUFFER
// Set up the description of the static index buffer.
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(UINT32) * indexCount;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;

// Give the subresource structure a pointer to the index data.
indexData.pSysMem = &i[0];
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;

result = device->CreateBuffer(&indexBufferDesc, &indexData, &indexBuffer);


So, sorry for the very long post, but hopefully all info needed is in there.

• Measure time in milliseconds/frame, not frames/second. Your loop copies the elements when iterating, consider auto& val. Jan 25 '16 at 3:00
• good point about measuring, I will change that. And you were absolutely correct, auto& resolved the massive performance drop, thanks. I guess I can't upvote or accept it as long as it's only a comment, but the auto& was the issue. Jan 25 '16 at 8:46

The primary thing that stands out is that your loop copy initializes the auto val loop variable with the elements as you iterate.
Even though your type is reasonably small, there's a bunch of overhead in doing so and it's likely that you would gain some by going for auto& val.