I store a 64-bit integer with all the state ID's packed into it, and then XOR two of them to see what needs to change.
e.g.
raster_mask = 0xF;
raster_shift = 42;
u64 SetRaster( u64 packed, int rasterId ) { return (packed&~(raster_mask<<raster_shift)) | (rasterId << raster_shift); }
int GetRaster( u64 packed ) { return (packed>>raster_shift) & raster_mask; }
bool HasRaster( u64 packed ) { return 0!=(packed & (raster_mask<<raster_shift)); }
u64 oldState = ..., newState = ...;
u64 dirty = oldState ^ newState;
oldState = newState;
if( HasRaster(dirty) )
SubmitRaster(device, GetRaster(newState));
Don't use if-statements for state management. The if-statement alone is not free (and the D3D layer is already doing that for you, albeit behind a few more layers of abstraction/overhead). The checks also imply that your higher-level code doesn't know what state is being used and when.
Eh, the overhead of those if statements is some number of nanoseconds per draw on a PC. In my D3D11 engine, a draw call (including state changes for it) takes somewhere on the order of a microsecond (mostly spent inside D3D), so a few nanosecond of extra if statements is pretty negligible :wink:
I'm also not sure if D3D will do the same check internally, or if it just forwards the redundant commands onto the driver anyway.
should be rendered in like groups. e.g., render your meshes, then render your debug line overlays, etc. You never need an if-check then, because your draw code transforms like so:
You can get that grouping automatically by sorting your draw calls before you submit them.
Also, while grouping to reduce state changes is good in general, it's not always the best strategy. e.g. for alpha-blended translucency it's not even a valid solution :) or for forward-rendered opaques without a depth-pre-pass, you often want to do a coarse front to back sort combined with a least-state-changes sort within each coarse depth range.