Managing State

Started by
2 comments, last by Hodgman 9 years, 2 months ago

I am noticing that a lot of errors are cropping up in my directX application because I am setting values (depth/stencil state, raster state, etc.) when doing rendering operations and then forgetting to unset those values. In d3d9, it appears that issues similar to this could be managed using state blocks. I'm wonder: what is the best way to implement the same functionality in d3d11? Are there any existing implementations in use that people find to work well?

J.W.
Advertisement

I wrap up every API in a stateless abstraction. e.g. at the lowest level, every renderable object is made up of (or dynamically creates per frame) DrawItems similar to below.

The renderer then just knows how to consume these DrawItems, which fully define the underlying API state, so it's impossible to accidentally forget to unset some previous state.

enum DrawType { Linear, Indexed, Indirect; }
struct Resources { vertex/instance/texture/cbuffer pointers };
struct DrawItem { u8 raster; u8 depthStencil; u8 blend; u8 primitive; u8 drawType; u16 shader; u16 inputLayout; Resources* bind; u32 vertexCount; u32 vbOffset; u32 ibOffset; };
typedef vector<DrawItem*> DrawList;

Although not being as explicit as possible, the following approach may make a transition from the existing implementation easier:

Based on what Hodgman has written above, but for cases where not the entire state vector is put into each DrawItem, a reasonable default setting can be defined (perhaps dependent on the active graphic pipeline stage). Any explicitly set state overrides its default equivalent, of course. From the low level renderer's point of view, each draw call then has an entire set of state.

In practice, at the beginning of the draw call processing, the default set of states is copied onto a local set of states. The state as available by DrawItem is then written "piecewise" onto the local set. Then the local set is compared with the state set that represents the current GPU state, and any difference cause a call to the render context as well as adapting the latter set accordingly.

In practice, at the beginning of the draw call processing, the default set of states is copied onto a local set of states. The state as available by DrawItem is then written "piecewise" onto the local set. Then the local set is compared with the state set that represents the current GPU state, and any difference cause a call to the render context as well as adapting the latter set accordingly.

I actually do this kind of "layering" earlier, and the result is a "compiled" DrawItem structure biggrin.png
Often I have multiple state vectors being overlaid, such as defaults on the bottom, shaders-specific defaults on top of that, then material states, then per-object states, then per-pass overrides.

This topic is closed to new replies.

Advertisement