📄 transitiontable.cpp
字号:
ADD_RENDER_STATE_TRANSITION( AlphaFunc )
ADD_RENDER_STATE_TRANSITION( AlphaRef )
ADD_RENDER_STATE_TRANSITION( FillMode )
ADD_RENDER_STATE_TRANSITION( Lighting )
ADD_RENDER_STATE_TRANSITION( SpecularEnable )
ADD_RENDER_STATE_TRANSITION( SRGBWriteEnable )
// Some code for the non-trivial transitions
if (m_bUsingStateBlocks)
{
numOps += CreateStateBlockTransitions( fromState, toState, bForce );
}
else
{
numOps += CreateNormalTransitions( fromState, toState, bForce );
}
int nOpsBeforeDynamicState = numOps;
// NOTE: From here on down are transitions that depend on dynamic state
// and which can therefore not appear in the state block
ADD_RENDER_STATE_TRANSITION( ZBias )
ADD_RENDER_STATE_TRANSITION( CullEnable )
ADD_RENDER_STATE_TRANSITION( VertexBlendEnable )
ADD_RENDER_STATE_TRANSITION( VertexShaderOverbright )
int nStageCount = HardwareConfig()->GetNumTextureStages();
for ( int i = 0; i < nStageCount; ++i )
{
ADD_TEXTURE_STAGE_STATE_TRANSITION( i, TextureEnable );
}
// Look for identical transition lists, and use those instead...
TransitionList_t& transition = (from >= 0) ?
m_TransitionTable[to][from] : m_DefaultTransition;
Assert( numOps <= 255 );
transition.m_NumOperations = numOps;
transition.m_nOpCountInStateBlock = nOpsBeforeDynamicState;
transition.m_pStateBlock = NULL;
// This condition can happen, and is valid. It occurs when we snapshot
// state but do not generate a transition function for that state
if (numOps == 0)
{
transition.m_FirstOperation = INVALID_TRANSITION_OP;
return;
}
unsigned short identicalListFirstElem = FindIdenticalTransitionList( firstElem, numOps );
if (identicalListFirstElem == INVALID_TRANSITION_OP)
{
transition.m_FirstOperation = firstElem;
Assert( (int)firstElem + (int)numOps < 65535 );
if( (int)firstElem + (int)numOps >= 65535 )
{
Warning("**** WARNING: Transition table overflow. Grab Brian\n");
}
}
else
{
// Remove the transitions ops we made; use the duplicate copy
transition.m_FirstOperation = identicalListFirstElem;
m_TransitionOps.RemoveMultiple( firstElem, numOps );
}
if ( m_bUsingStateBlocks && transition.m_nOpCountInStateBlock != 0 )
{
// Find a transition list that matches *exactly* to share its state block
IDirect3DStateBlock9 *pStateBlock = (from >= 0) ? FindIdenticalStateBlock( &transition, to ) : NULL;
if (pStateBlock)
{
transition.m_pStateBlock = pStateBlock;
transition.m_pStateBlock->AddRef();
}
else
{
transition.m_pStateBlock = CreateStateBlock( transition, to );
}
}
}
//-----------------------------------------------------------------------------
// Tests a snapshot to see if it can be used
//-----------------------------------------------------------------------------
#define PERFORM_RENDER_STATE_TRANSITION( _state, _func ) \
::Apply ## _func( _state, 0 );
#define PERFORM_TEXTURE_STAGE_STATE_TRANSITION( _state, _stage, _func ) \
::Apply ## _func( _state, _stage );
bool CTransitionTable::TestShadowState( const ShadowState_t& state, const ShadowShaderState_t &shaderState )
{
PERFORM_RENDER_STATE_TRANSITION( state, ZFunc )
PERFORM_RENDER_STATE_TRANSITION( state, ZWriteEnable )
PERFORM_RENDER_STATE_TRANSITION( state, ZEnable )
PERFORM_RENDER_STATE_TRANSITION( state, ZBias )
PERFORM_RENDER_STATE_TRANSITION( state, ColorWriteEnable )
PERFORM_RENDER_STATE_TRANSITION( state, AlphaBlend )
PERFORM_RENDER_STATE_TRANSITION( state, AlphaTestEnable )
PERFORM_RENDER_STATE_TRANSITION( state, AlphaFunc )
PERFORM_RENDER_STATE_TRANSITION( state, AlphaRef )
PERFORM_RENDER_STATE_TRANSITION( state, FillMode )
PERFORM_RENDER_STATE_TRANSITION( state, CullEnable )
PERFORM_RENDER_STATE_TRANSITION( state, Lighting )
PERFORM_RENDER_STATE_TRANSITION( state, SpecularEnable )
PERFORM_RENDER_STATE_TRANSITION( state, SRGBWriteEnable )
PERFORM_RENDER_STATE_TRANSITION( state, VertexBlendEnable )
PERFORM_RENDER_STATE_TRANSITION( state, VertexShaderOverbright )
int i;
int nStageCount = HardwareConfig()->GetNumTextureStages();
for ( i = 0; i < nStageCount; ++i )
{
PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, ColorTextureStage );
PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, AlphaTextureStage );
PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, TexCoordIndex );
PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, TextureEnable );
}
// Just make sure we've got a good snapshot
RECORD_COMMAND( DX8_VALIDATE_DEVICE, 0 );
DWORD numPasses;
HRESULT hr = D3DDevice()->ValidateDevice( &numPasses );
bool ok = !FAILED(hr);
// Now set the board state to match the default state
ApplyTransition( m_DefaultTransition, m_DefaultStateSnapshot );
ShaderManager()->SetVertexShader( shaderState.m_VertexShader, shaderState.m_nStaticVshIndex );
ShaderManager()->SetPixelShader( shaderState.m_PixelShader, shaderState.m_nStaticPshIndex );
return ok;
}
//-----------------------------------------------------------------------------
// Finds identical transition lists and shares them
//-----------------------------------------------------------------------------
unsigned short CTransitionTable::FindIdenticalTransitionList( unsigned short firstElem,
unsigned short numOps ) const
{
// Look for a common list
const TransitionOp_t &op = m_TransitionOps[firstElem];
int maxTest = firstElem - numOps;
for (int i = 0; i < maxTest; )
{
// Fast out...
if ( (m_TransitionOps[i].m_Op != op.m_Op) ||
(m_TransitionOps[i].m_Argument != op.m_Argument) )
{
++i;
continue;
}
unsigned short potentialMatch = (unsigned short )i;
int matchCount = 1;
++i;
while( matchCount < numOps )
{
if ( (m_TransitionOps[i].m_Op != m_TransitionOps[firstElem+matchCount].m_Op) ||
(m_TransitionOps[i].m_Argument != m_TransitionOps[firstElem+matchCount].m_Argument) )
{
break;
}
++i;
++matchCount;
}
if (matchCount == numOps)
return potentialMatch;
}
return INVALID_TRANSITION_OP;
}
//-----------------------------------------------------------------------------
// Create startup snapshot
//-----------------------------------------------------------------------------
void CTransitionTable::TakeDefaultStateSnapshot( )
{
if (m_DefaultStateSnapshot == -1)
{
m_DefaultStateSnapshot = TakeSnapshot();
// This will create a transition which sets *all* shadowed state
CreateTransitionTableEntry( m_DefaultStateSnapshot, -1 );
}
}
//-----------------------------------------------------------------------------
// Applies the transition list
//-----------------------------------------------------------------------------
void CTransitionTable::ApplyTransitionList( int snapshot, int nFirstOp, int nOpCount )
{
// Don't bother if there's nothing to do
if (nOpCount > 0)
{
// Trying to avoid function overhead here
ShadowState_t& shadowState = m_ShadowStateList[snapshot];
TransitionOp_t* pTransitionOp = &m_TransitionOps[nFirstOp];
for (int i = 0; i < nOpCount; ++i )
{
// invoke the transition method
(*pTransitionOp->m_Op)(shadowState, pTransitionOp->m_Argument);
++pTransitionOp;
MaterialSystemStats()->IncrementCountedStat( MATERIAL_SYSTEM_STATS_SHADOW_STATE, 1 );
}
}
}
//-----------------------------------------------------------------------------
// Apply startup snapshot
//-----------------------------------------------------------------------------
#pragma warning( disable : 4189 )
void CTransitionTable::ApplyTransition( TransitionList_t& list, int snapshot )
{
if ( ShaderAPI()->IsDeactivated() )
return;
// Transition lists when using state blocks have 2 parts: the first
// is the stateblock part, which is states that are not related to
// dynamic state at all; followed by states that *are* affected by dynamic state
int nFirstOp = list.m_FirstOperation;
int nOpCount = list.m_NumOperations;
if ( m_bUsingStateBlocks )
{
if ( list.m_pStateBlock )
{
HRESULT hr = list.m_pStateBlock->Apply();
Assert( !FAILED(hr) );
}
nFirstOp += list.m_nOpCountInStateBlock;
nOpCount -= list.m_nOpCountInStateBlock;
}
ApplyTransitionList( snapshot, nFirstOp, nOpCount );
// Semi-hacky code to override what the transitions are doing
PerformShadowStateOverrides();
// Set the current snapshot id
m_CurrentShadowId = snapshot;
#ifdef DEBUG_BOARD_STATE
// Copy over the board states that aren't explicitly in the transition table
// so the assertion works...
int nStageCount = HardwareConfig()->GetNumTextureStages();
for (int i = 0; i < nStageCount; ++i)
{
m_BoardState.m_TextureStage[i].m_GenerateSphericalCoords =
CurrentShadowState().m_TextureStage[i].m_GenerateSphericalCoords;
}
m_BoardState.m_AmbientCubeOnStage0 = CurrentShadowState().m_AmbientCubeOnStage0;
m_BoardState.m_ModulateConstantColor = CurrentShadowState().m_ModulateConstantColor;
m_BoardState.m_VertexUsage = CurrentShadowState().m_VertexUsage;
m_BoardState.m_UsingFixedFunction = CurrentShadowState().m_UsingFixedFunction;
// State blocks bypass the code that sets the board state
if ( !m_bUsingStateBlocks )
{
Assert( !memcmp( &m_BoardState, &CurrentShadowState(), sizeof(m_BoardState) ) );
}
#endif
}
#pragma warning( default : 4189 )
//-----------------------------------------------------------------------------
// Takes a snapshot, hooks it into the material
//-----------------------------------------------------------------------------
StateSnapshot_t CTransitionTable::TakeSnapshot( )
{
// Do any final computation of the shadow state
ShaderShadow()->ComputeAggregateShadowState();
// Get the current snapshot
const ShadowState_t& currentState = ShaderShadow()->GetShadowState();
// Create a new snapshot
ShadowStateId_t shadowStateId = FindShadowState( currentState );
if (shadowStateId == -1)
{
// Create entry in state transition table
shadowStateId = CreateShadowState();
// Copy our snapshot into the list
memcpy( &m_ShadowStateList[shadowStateId], ¤tState, sizeof(ShadowState_t) );
// Now create new transition entries
for (int to = 0; to < shadowStateId; ++to)
{
CreateTransitionTableEntry( to, shadowStateId );
}
for (int from = 0; from < shadowStateId; ++from)
{
CreateTransitionTableEntry( shadowStateId, from );
}
}
const ShadowShaderState_t& currentShaderState = ShaderShadow()->GetShadowShaderState();
StateSnapshot_t snapshotId = FindStateSnapshot( shadowStateId, currentShaderState );
if (snapshotId == -1)
{
// Create entry in state transition table
snapshotId = CreateStateSnapshot();
// Copy our snapshot into the list
m_SnapshotList[snapshotId].m_ShadowStateId = shadowStateId;
memcpy( &m_SnapshotList[snapshotId].m_ShaderState, ¤tShaderState, sizeof(ShadowShaderState_t) );
}
return snapshotId;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -