State management in D3D... is currently kind of a mess.
Stefan D. posted a message about this some time ago, but I can't find it right now...

- some states are applied immediately (via Set* calls)
- some are applied at draw time (like shaders, textures, transforms, ...)
- some are recorded into a stateblock structure, and applied when the app says apply().
- the GL code is all over the place, tightly coupled to the d3d code.

===============================
There's a number of projects going on at the moment, from what I understand:

- Roderick is working on making wined3d -> wgl
- Stefan D. has expressed concern about multithreaded d3d (where the D3D device state is shared, but not necessarily the GL one - or can GL contexts be shared between multiple threads?) - I'm trying to get FBOs to work, where the FBO needs to be bound once both the render and stencil target have been assigned (that's 2 calls from the app in any order) - i.e I need those states to be applied in a delayed fashion, before draw - Henri Verbeet wants multiple render target support added to that (meaning the FBO needs to be bound once *all* render targets are assigned in addition to the depth/stencil one).
================================
All of the above have a common theme - better state management is needed, with more encapsulation, and better separation between D3D and GL. So, let's come up with a plan, and try to implement it. How about we redesign the stateblock object like this:

- remove deltas. I.E. if a SetLightEnable() command is sent, fetch the light, enable it, then save the light back - store only state, and no deltas. This should make the recording stateblock (updateStateBlock) the same as the initial device stateblock, which stores states

- provide a uniform internal interface for accessing states inside the stateblock - like:
     SetState(stateblock, ID_XYZ, (void*) state_data);
     GetState(stateblock, ID_XYZ, (void**) state_data);
     CaptureState(stateblock, ID_XYZ);
     ApplyState(stateblock, ID_XYZ);

ID_XYZ could be an individual state, or a "trigger" keyword, which will refer to a whole group of states.
Those would be private functions in addition to the standard interface.

- provide a fn pointer table inside the stateblock [ which can be directed to OGL or WGL or AGL ], which, for each ID_XYZ, maps a get and set function using the same interface

- move all device.c GL code into those functions

- now all device.c Get* and Set* requests will do is:
      - error checking
      - recording into updateStateBlock
- or writing to stateBlock (which may be applied later, at our discretion).

- apply() would just loop through all the IDs and call the corresponding function pointer if the states are marked dirty (we'll keep the 'dirty' field)

- capture() would do the same in the get* direction.

- new object can be instantiated per device, or per device per thread to address multithreading.
 It could have an associated glContext, and can be locked as necessary.

- it would use ideas from the d3d9 test framework for stateblock, except of course more competently written, and cleaner :)






Reply via email to