Today my question is a about instance mesh performance in DX 11, the way I do my instancing is the standard way I think, its the same way I did it in XNA.
To start with each frame(every 2nd) I build a vertex stream filled with the world matrix for the mesh I want to instance, this second vertex stream is then set to the GPU with the mesh vertex buffer in slot 1, I have it set to InputClassification.PerInstanceData in the vertex element array.
Looks like this:
Public Shared Elements As InputElement() = New InputElement() {New InputElement("POSITION", 0, DXGI.Format.R32G32B32_Float, 0, 0, InputClassification.PerVertexData, 0),
New InputElement("NORMAL", 0, DXGI.Format.R32G32B32_Float, InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0),
New InputElement("BINORMAL", 0, DXGI.Format.R32G32B32_Float, InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0),
New InputElement("TANGENT", 0, DXGI.Format.R32G32B32_Float, InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0),
New InputElement("COLOR", 0, DXGI.Format.R32G32B32_Float, InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0),
New InputElement("TEXCOORD", 0, DXGI.Format.R32G32_Float, InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0),
New InputElement("WORLD", 0, DXGI.Format.R32G32B32A32_Float, 0, 1, InputClassification.PerInstanceData, 1),
New InputElement("WORLD", 1, DXGI.Format.R32G32B32A32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1),
New InputElement("WORLD", 2, DXGI.Format.R32G32B32A32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1),
New InputElement("WORLD", 3, DXGI.Format.R32G32B32A32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1)
}
This setup works fine but I'm still getting a big frame time hit when I draw my trees, my trees are made with SpeedTree and are around 3k-10k triangles, some of them could be up to 5 draw calls per tree and that's why I'm using instance because I figure it has to be faster to instance it than to not, I mean I'm drawing the same thing over and over so isn't that why you use instancing?
For my world I have 8 types of tree and 5 variations of each and some trees have up to 5 meshes, I can only seem to render around 750-1250 instances per frame and keep it running smooth, btw that's total for all the trees not each type, I'm not sure of the tree type count because its random but ill ball park it to 100-150 of each tree type.
I draw the leafs with alpha test so I don't get early-z on the trunks too because I have no way of turning off alpha test for the trunks right now.
I know there are many things that will affect my frame times but as far as I can tell this is whats costing the most right now, with no trees I'm running at 90-110 fps and with trees I drop to 35-55. If I change the tree cull distance then of course I get more frames.
I have a bit of batching going on, first by Mesh name then by blend state.
I use a tile based deferred render, its based on AMD's code, I also have cascaded shadow maps with 3 splits, water reflections and sometimes dynamic cube map faces. So each mesh could end up getting drawn 6 times but I dont update the last shadow cascade every frame, I split the cube rendering over 6 frames and only render stuff that the water can see into the reflection target.
So I guess my question is am I doing instancing correct and I'm just trying to draw to much and need to work on LoD or am I doing it wrong? What do others get from there instancing systems?
Ps. 90-110 fps isn't for an empty world that's what I get for my full world but without the trees