Am Donnerstag 19 Oktober 2006 12:08 schrieb Stefan Dösinger:
Hi, I considererd that it would be finally time to get started with the state management rewrite :-) Just a mail with the final plan, if anyone has comments.
Well, I started with the thing, and I want to show the first results so others can better see where we are headed :-)
I named the file state.c, no idea why. At the moment it only contains a state management table which is basically empty. The state management table contains a representative for each state(e.g. ALPHAFUNC is the representative for ALPHAFUNC and ALPHAREF, because both states affect the same gl state. Most states are their own representative for now, this will change when the stuff is implemented. Those will be used to group render states depending on each other
For each state there is a pointer to a function for applying the state. At the moment those pointers are NULL, but later this file will contain static functions for applying a specific state, referenced by the table. So a state can be applied by calling
States[STATE_RENDER(RenderState)]->func(IWineD3DStateBlockImpl *);
STATE_RENDER is defined as #define STATE_RENDER(a) (a)
for sampler states, ..., I will add a #define STATE_SAMPLER(b, a) STATE_RENDER(WINEHIGHEST_RENDER_STATE + WINEHIGHEST_SAMPLER_STATE * b + a) and so on. Simmilar, if needed a STATE_IS_SAMPLER, but I don't think we'll need that.
For the function that applies all the states in drawprim I was thinking about 2 ways: Using a pointer to the apply function in the table, or inline functions, aka
LIST_FOR_EACH(dirty_states_list) { switch(current_state_number) { case STATE_RENDER(D3DRS_LIGHTING) call_some_inline_function; break; } }
This would have avoided a full call+ret for each state that is applied, but this switch block would grow terribly long, ~500 entries with all states in one list, or the equivalent number in seperate switch blocks. I think a call is faster than checking against 500 constants, and it allows us to apply a single state with ease.
A for(i = 0; i < HIGHEST_STATE_ENTRY; i++) { if(States[i]->func) States[i]->func(Stateblock); } will allow us to record a full stateblock into an opengl display list :-)
Concernes: The state table will get pretty big, with some gaps. I want to allow finding a state by just going into the array with the state number without having to search for the state(yes, binary search is easilly possible, but still). We can stuff the gaps with other states if we really, really want to, and code for searching might take more memory than the gaps in the list.
The list can get hard to maintain, one missing entry and all pointers go wrong... But we have to write it only once, d3d10 is unlikely to add more stuff as the fixed function pipeline was kicked.
Grouping the states: Should work nice basically, but once concern about the vertex type, lighting, fog, vertex shaders: Fog and Lighting depends on the vertex type, and fog depends on wether a vertex shader is used. So D3DRS_LIGHTING, D3DRS_FOGSTART, D3DRS_FOGEND, D3DRS_FOGENABLE, D3DRS_FOGTABLEMODE, D3DRS_FOGVERTEXMODE, The vertex type, the bound vertex shader will be linked together. Pretty huge block... Any suggestions about breaking it up nicely?
More?