I need this kind of 'switch', because I don't know what kinds of commands the state-groups contain.
If you had a 'fixed' state-group like below, you wouldn't need any kind of switch/virtual, because you know what kind of commands you're recieving:struct StateGroup
{
Shader* shader;
VertexDeclaration* vd;
VertexBuffer* vb;
IndexBuffer* ib;
int numCb;
CBuffers** cb;
};
I have a queue that's basically a vector of draw/state-array pairs (e.g. [font="Courier New"]struct Item { Draw* d; StateGroup** s; int numStates; }[/font]), which I can submit for drawing (which sends commands to D3D).
I would recommend breaking that up even a bit more.
I keep vertices in their own buffer, as well as normals. Tangents and bi-normals in another buffer, and texture coordinates in a buffer.
The reason is to avoid sending unnecessary data to the card when, for example, lighting is disabled.
When doing any standard multi-pass forward rendering, the first pass is to gather ambient details only, so unless you use hemisphere lighting or similar, you don’t need to submit normals, tangents, and binormals.
Then you will generate shadow maps. Submit only the vertices, omit normals, texture coordinates, etc. This can save you tons of bandwidth, making the generation of shadow maps virtually free.
This also helps with instancing. If an instance of your master model wants to change one part but keep the rest, the instance can generate a replacement for only that attribute. So I could submit a different set of texture coordinates for this one instance, without needing to duplicate the rest of the attributes of the master model.
[In Passing]
Because system states can change at run-time, my system is to perform a binary search for which shader needs to be active and activate it at render-time. I have dirty flags to avoid unnecessary searching, so if the system states are the same as they were last frame, the previous shader is kept.
Then I organize shaders into classes (here I mean classifications, not the C++ class type). One class of shaders for shadow mapping, one for ambient-only lighting, one for lighting, etc. This reduces the bucket sizes for the shared list of shaders and allows the binary search to be negligible (assuming a search is performed at all).
Deciding which shader to use at render-time gives me a lot of flexibility, and I save some RAM by generating only the permutations that are requested.
But I mention this system in passing. Mainly I want to make a strong suggestion to split up the vertex buffers and use streams.
L. Spiro