I've learnt it over time, reading bits and pieces here and there, talking to fellow coders, etc.

This is my Delphi conversion of a render state manager that was originally found on a GameDev.Net forum. What it does is compare the block of states that you want to change with the states that it knows are already set, and only changes the states necessary. Note it does not work with a pure device, because you cannot query a pure device for the current state.

[pascal]unit DonkRenderStateManager;

interface

{
RenderStateManager.h - John Dexter - 21/6/2005

This class implements functionality to do 2 things:
1)Maintain the D3D render & texture stage states in a reliable way
2)Reduce the number of D3D Renderstate and TextureStagestate changes
}

uses
Direct3D9, Windows;

const
NUM_TEXTURE_STAGES = 8;
MAX_RENDER_STATE_STACK_DEPTH = 16;
MAX_RENDER_STATE_STACK_SIZE = 256;
MAX_TEXTURE_STAGE_STATE_STACK_DEPTH = 16;
MAX_TEXTURE_STAGE_STATE_STACK_SIZE = 256;

type
PDKRenderState = ^TDKRenderState;
TDKRenderState = record
State: TD3DRenderStateType;
Value: DWord;
end;

PDKTextureStageState = ^TDKTextureStageState;
TDKTextureStageState = record
Stage: DWord;
State: TD3DTextureStageStateType;
Value: DWord;
end;

PDKStackIndex = ^TDKStackIndex;
TDKStackIndex = record
Start: Cardinal;
Count: Cardinal;
end;

TDKRenderStateManager = class
private
FDevice: IDirect3DDevice9; // The D3D Device to set the states on
FRenderStates: array [TD3DRenderStateType] of DWord; // The current set of D3D render states which are required
FTextureStageStates: array [0..NUM_TEXTURE_STAGES - 1, TD3DTextureStageStateType] of DWord; // The current set of D3D texture stage states which are required for each stage

FRenderStateStackDepth: Cardinal;
FRenderStateStackIndexes: array [0..MAX_RENDER_STATE_STACK_DEPTH - 1] of TDKStackIndex;
FRenderStateStack: array [0..MAX_RENDER_STATE_STACK_SIZE - 1] of TDKRenderState;

FTextureStageStateStackDepth: Cardinal;
FTextureStageStateStackIndexes: array [0..MAX_TEXTURE_STAGE_STATE_STACK_DEPTH - 1] of TDKStackIndex;
FTextureStageStateStack: array [0..MAX_TEXTURE_STAGE_STATE_STACK_SIZE - 1] of TDKTextureStageState;

FNumRenderStateCalls: Cardinal;
FNumRenderRedundantStateCalls: Cardinal;
FNumTextureStageStateCalls: Cardinal;
FNumTextureStageRedundantStateCalls: Cardinal;
FNumConsecutiveRenderPushes: Cardinal;
FNumConsecutiveTextureStagePushes: Cardinal;
public
constructor Create(ADevice: IDirect3DDevice9);
{ pass in a set of states and their desired values. The current values for these
set of states are recorded, and the new values applied }
procedure PushRenderStateBlock(Block: PDKRenderState; Count: Cardinal);
{ gets the last set of states set, and restores the previous values }
procedure PopRenderStateBlock;
{ pass in a set of stage states and their desired values. The current values for these
set of states are recorded, and the new values applied }
procedure PushTextureStageStateBlock(Block: PDKTextureStageState; Count: Cardinal);
{ gets the last set of states set, and restores the previous values }
procedure PopTextureStageStateBlock;
procedure BeginScene;
procedure EndScene;
end;

implementation

{ TDKRenderStateManager }

constructor TDKRenderStateManager.Create(ADevice: IDirect3DDevice9);
var
RST: TD3DRenderStateType;
TST: TD3DTextureStageStateType;
Stage: Integer;
begin
FDevice := ADevice;

for RST := Low(TD3DRenderStateType) to High(TD3DRenderStateType) do
FDevice.GetRenderState(RST, FRenderStates[RST]);

for TST := Low(TD3DTextureStageStateType) to High(TD3DTextureStageStateType) do
for Stage := 0 to NUM_TEXTURE_STAGES - 1 do
FDevice.GetTextureStageState(Stage, TST, FTextureStageStates[Stage, TST]);

FRenderStateStackDepth := 0;
FTextureStageStateStackDepth := 0;
end;

{ pass in a set of states and their desired values. The current values for these
set of states are recorded, and the new values applied }
procedure TDKRenderStateManager.PushRenderStateBlock(Block: PDKRenderState; Count: Cardinal);
var
Index: Cardinal;
StackIndex: PDKStackIndex;
RS: PDKRenderState;
begin
Assert(FRenderStateStackDepth < MAX_RENDER_STATE_STACK_DEPTH - 1);
Index := 0;
if FRenderStateStackDepth > 0 then
begin
StackIndex := @FRenderStateStackIndexes[FRenderStateStackDepth - 1];
Index := StackIndex^.Start + StackIndex^.Count;
end;
Inc(FRenderStateStackDepth);
StackIndex := @FRenderStateStackIndexes[FRenderStateStackDepth - 1];
StackIndex^.Start := Index;
StackIndex^.Count := 0;

RS := Block;
//build a list of the current values for each state which is to change
while Count > 0 do
begin
if RS^.Value <> FRenderStates[RS^.State] then
begin
Assert(Index < MAX_RENDER_STATE_STACK_SIZE - 1);
FRenderStateStack[Index].State := RS^.State;
FRenderStateStack[Index].Value := FRenderStates[RS^.State];
Inc(Index);
StackIndex^.Count := Index - StackIndex^.Start;
//set and record the new value for this state
FRenderStates[RS^.State] := RS^.Value;
FDevice.SetRenderState(RS^.State, RS^.Value);
end
else
begin
Inc(FNumRenderRedundantStateCalls);
end;
Dec(Count);
Inc(FNumRenderStateCalls);
Inc(RS);
end;

Inc(FNumConsecutiveRenderPushes);
if FNumConsecutiveRenderPushes > 1 then
begin
// sprintf(Logger::buffer,"RenderStateManager:ushRenderStateBlock : %d consecutive pushes",m_NumConsecutiveRenderPushes);
// Logger::OutputLine();
end;
end;

{ gets the last set of states set, and restores the previous values }
procedure TDKRenderStateManager.PopRenderStateBlock;
var
Index: Cardinal;
Start, Count: Cardinal;
RS: PDKRenderState;
begin
if FRenderStateStackDepth > 0 then
begin
Dec(FRenderStateStackDepth);
Start := FRenderStateStackIndexes[FRenderStateStackDepth].Start;
Count := FRenderStateStackIndexes[FRenderStateStackDepth].Count;
for Index := Start to Start + Count - 1 do
begin
RS := @FRenderStateStack[Index];
FRenderStates[RS^.State] := RS^.Value;
FDevice.SetRenderState(RS^.State, RS^.Value);
end;
FNumConsecutiveRenderPushes := 0;
end;
end;

{ pass in a set of stage states and their desired values. The current values for these
set of states are recorded, and the new values applied }
procedure TDKRenderStateManager.PushTextureStageStateBlock(B lock: PDKTextureStageState; Count: Cardinal);
var
Index: Cardinal;
StackIndex: PDKStackIndex;
TSS: PDKTextureStageState;
begin
Assert(FTextureStageStateStackDepth < MAX_TEXTURE_STAGE_STATE_STACK_DEPTH - 1);
Index := 0;
if FTextureStageStateStackDepth > 0 then
begin
StackIndex := @FTextureStageStateStackIndexes[FTextureStageStateStackDepth - 1];
Index := StackIndex^.Start + StackIndex^.Count;
end;
Inc(FTextureStageStateStackDepth);
StackIndex := @FTextureStageStateStackIndexes[FTextureStageStateStackDepth - 1];
StackIndex^.Start := Index;
StackIndex^.Count := 0;

TSS := Block;
//build a list of the current values for each state which is to change
while Count > 0 do
begin
if TSS^.Value <> FTextureStageStates[TSS^.Stage, TSS^.State] then
begin
Assert(Index < MAX_TEXTURE_STAGE_STATE_STACK_SIZE - 1);
FTextureStageStateStack[Index].Stage := TSS^.Stage;
FTextureStageStateStack[Index].State := TSS^.State;
FTextureStageStateStack[Index].Value := FTextureStageStates[TSS^.Stage, TSS^.State];
Inc(Index);
StackIndex^.Count := Index - StackIndex^.Start;
//set and record the new value for this state
FTextureStageStates[TSS^.Stage, TSS^.State] := TSS^.Value;
FDevice.SetTextureStageState(TSS^.Stage, TSS^.State, TSS^.Value);
end
else
begin
Inc(FNumTextureStageRedundantStateCalls);
end;
Dec(Count);
Inc(FNumTextureStageStateCalls);
Inc(TSS);
end;

Inc(FNumConsecutiveTextureStagePushes);
if FNumConsecutiveTextureStagePushes > 1 then
begin
// sprintf(Logger::buffer,"RenderStateManager:ushTextureStageStateBlock : %d consecutive pushes", m_NumConsecutiveTextureStagePushes);
// Logger::OutputLine();
end;
end;

{ gets the last set of states set, and restores the previous values }
procedure TDKRenderStateManager.PopTextureStageStateBlock;
var
Index: Cardinal;
Start, Count: Cardinal;
TSS: PDKTextureStageState;
begin
if FTextureStageStateStackDepth > 0 then
begin
Dec(FTextureStageStateStackDepth);
Start := FTextureStageStateStackIndexes[FTextureStageStateStackDepth].Start;
Count := FTextureStageStateStackIndexes[FTextureStageStateStackDepth].Count;
for Index := Start to Start + Count - 1 do
begin
TSS := @FTextureStageStateStack[Index];
FTextureStageStates[TSS^.Stage, TSS^.State] := TSS^.Value;
FDevice.SetTextureStageState(TSS^.Stage, TSS^.State, TSS^.Value);
end;
FNumConsecutiveTextureStagePushes := 0;
end;
end;

procedure TDKRenderStateManager.BeginScene;
begin
FNumRenderStateCalls := 0;
FNumRenderRedundantStateCalls := 0;
FNumTextureStageStateCalls := 0;
FNumTextureStageRedundantStateCalls := 0;
FNumConsecutiveRenderPushes := 0;
FNumConsecutiveTextureStagePushes := 0;
end;

procedure TDKRenderStateManager.EndScene;
begin
// sprintf(Logger::buffer,"RenderStateManager::EndSce ne : Render %u/%u, TextureStage %u/%u",
// m_NumRenderRedundantStateCalls,m_NumRenderStateCal ls,m_NumTextureStageRedundantStateCalls,m_NumTextu reStageStateCalls);
// Logger::OutputLine();
end;

end.[/pascal]

Edit: The pascal tags do not recognize the original Pascal style comments.