WineD3D State management - going live(TM)

Stefan Dösinger stefandoesinger at gmx.at
Thu Oct 19 15:17:32 CDT 2006


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?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: state.c
Type: text/x-csrc
Size: 28636 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20061019/8a73739e/state-0001.c


More information about the wine-devel mailing list