WineD3D State management - going live(TM)

Stefan Dösinger stefandoesinger at gmx.at
Sun Oct 22 15:37:48 CDT 2006


Am Sonntag 22 Oktober 2006 10:31 schrieb Ivan Gyurdiev:

I thought that my first reply was a bit off-topic, I think I should describe 
my idea with the table a bit better :-)

Each entry in the state table has 2 fields. They do not strictly depend on 
each other:

struct StateEntry
{
    DWORD           representative;
    APPLYSTATEFUNC  func;
};

The representative is a way to group states which depend on each other. For 
example WINED3DRS_ALPHATESTENABLED, WINED3DRS_ALPHAREF and 
WINED3DRS_COLORKEYENABLE go into the same gl state, so they are grouped. The 
reason for that is in the dirty list. SetRenderState pushes an element to the 
list
instead of device->addDirtyState(This, State); /* Later per context */
it will do this:
device->addDirtyState(This, States[State]->representative)

This way the code applying the states has to be called only once.

The entry func contains a pointer to the function handling setting the state. 
This is still a bunch of code, not a magic instruction how to call gl 
directly. To apply a state to gl

States[State]->func(State, stateblock);

is called. Basically this is equal to the current SetRenderState code:

switch(state)
{
    case WINED3DRS_LIGHTING:
        <do something>
        break;
    case WINED3DRS_SOMETHINGELSE:
        <...>
}

While I think that in that case inline functions containing the <do something> 
block look nicer than the current SetRenderState.

I think you agree that the state grouping is a bit inflexible. For example, 
the vertex declaration affects the fog settings. This way it would be 
consequent to group them. However, as other things depend on the vertex decl 
this will get a way to big group. The bigger the groups are the more likely 
it is that one of the states is changed, so this will eat performance.

While the vertex decl can change the fog, the fog settings will never affect 
the vertex declaration, so we have a sort of one-way dependency(compared to 
the alpha example). To overcome this we can still use some code in the 
function. For example state_fog(state, stateblock) can read the vertex 
declaration to decide what to do. In the same way it is perfectly fine for 
misc_vdecl(state, stateblock) to call state_fog() either unconditionally or 
when it thinks that fog needs to be verified. By doing that dirtifying the 
fog does not require all vertex data pointers to be updated, while the fog is 
still updated when the vertex decl is changed but the fog settings aren't.

One might argue that calling a foreign state function and reading a foreign 
state is not a nice design. Ok - But a switch statement(or bunch of 
if-blocks) wouldn't be better off. If you look at the current code, the fog 
things are scattered all over SetRenderState and drawprim.

Then there are other sorts of states, like sampler states and texture stage 
states. Texture stage states can go into the global state list just fine. One 
issue is that different stages depend on each other, due to D3DOP_DISABLE. To 
handle that properly we need to track the highest enabled texture stage and 
the lowest disabled texture stage per context, and some code in drawprim 
which cares for the stages in between(will be 0 in general, so just an if 
check).

Sampler states and bound textures are more difficult, as they are per-texture 
settings in gl and per device settings in d3d. There is no point in putting 
them into the main state list, instead there should be a dirty list per 
supported sampler. This list will contain the bound texture and the sampler 
states, and use a simmilar dirtification mechanism as the rest of the states. 
There is a one-way dependency too: A change of the texture may require a 
reapplication of the sampler states, but a change of a sampler state will not 
require a change of the texture.

A simmilar list will group sampler states together, and the function binding 
the texture will check the sampler states last used with the texture against 
the states in the stateblock, and if they are different call the sampler 
state specific functions to reapply them. The only way around this would be a 
per-texture dirty sampler state list which will make SetSamplerState way too 
expensive...

I hope that explained the whole plan a bit better than my last mail :-)

Stefan
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20061022/71b4cb60/attachment.pgp


More information about the wine-devel mailing list