Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1924 lines
65 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #define DISABLE_PROTECTED_THINGS
  9. #include "togl/rendermechanism.h"
  10. #include "TransitionTable.h"
  11. #include "recording.h"
  12. #include "shaderapidx8.h"
  13. #include "shaderapi/ishaderutil.h"
  14. #include "tier1/convar.h"
  15. #include "materialsystem/imaterialsystemhardwareconfig.h"
  16. #include "vertexshaderdx8.h"
  17. #include "tier0/vprof.h"
  18. #include "shaderdevicedx8.h"
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. enum
  22. {
  23. TEXTURE_STAGE_BIT_COUNT = 4,
  24. TEXTURE_STAGE_MAX_STAGE = 1 << TEXTURE_STAGE_BIT_COUNT,
  25. TEXTURE_STAGE_MASK = TEXTURE_STAGE_MAX_STAGE - 1,
  26. TEXTURE_OP_BIT_COUNT = 7 - TEXTURE_STAGE_BIT_COUNT,
  27. TEXTURE_OP_SHIFT = TEXTURE_STAGE_BIT_COUNT,
  28. TEXTURE_OP_MASK = ((1 << TEXTURE_OP_BIT_COUNT) - 1) << TEXTURE_OP_SHIFT,
  29. };
  30. //-----------------------------------------------------------------------------
  31. // Texture op compressing/uncompressing
  32. //-----------------------------------------------------------------------------
  33. inline unsigned char TextureOp( TextureStateFunc_t func, int stage )
  34. {
  35. // This fails if we've added too many texture stages states to fit in a byte.
  36. COMPILE_TIME_ASSERT( TEXTURE_STATE_COUNT < (1 << TEXTURE_OP_BIT_COUNT) );
  37. Assert( stage < TEXTURE_STAGE_MAX_STAGE );
  38. return ((func << TEXTURE_OP_SHIFT) & TEXTURE_OP_MASK) | (stage & TEXTURE_STAGE_MASK);
  39. }
  40. inline void GetTextureOp( unsigned char nBits, TextureStateFunc_t *pFunc, int *pStage )
  41. {
  42. *pStage = (nBits & TEXTURE_STAGE_MASK);
  43. *pFunc = (TextureStateFunc_t)((nBits & TEXTURE_OP_MASK) >> TEXTURE_OP_SHIFT);
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Stats
  47. //-----------------------------------------------------------------------------
  48. static int s_pRenderTransitions[RENDER_STATE_COUNT];
  49. static int s_pTextureTransitions[TEXTURE_STATE_COUNT][TEXTURE_STAGE_MAX_STAGE];
  50. //-----------------------------------------------------------------------------
  51. // Singleton
  52. //-----------------------------------------------------------------------------
  53. CTransitionTable *g_pTransitionTable = NULL;
  54. #ifdef DEBUG_BOARD_STATE
  55. inline ShadowState_t& BoardState()
  56. {
  57. return g_pTransitionTable->BoardState();
  58. }
  59. #endif
  60. inline CTransitionTable::CurrentState_t& CurrentState()
  61. {
  62. return g_pTransitionTable->CurrentState();
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Less functions
  66. //-----------------------------------------------------------------------------
  67. bool CTransitionTable::ShadowStateDictLessFunc::Less( const CTransitionTable::ShadowStateDictEntry_t &src1, const CTransitionTable::ShadowStateDictEntry_t &src2, void *pCtx )
  68. {
  69. return src1.m_nChecksum < src2.m_nChecksum;
  70. }
  71. bool CTransitionTable::SnapshotDictLessFunc::Less( const CTransitionTable::SnapshotDictEntry_t &src1, const CTransitionTable::SnapshotDictEntry_t &src2, void *pCtx )
  72. {
  73. return src1.m_nChecksum < src2.m_nChecksum;
  74. }
  75. bool CTransitionTable::UniqueSnapshotLessFunc::Less( const CTransitionTable::TransitionList_t &src1, const CTransitionTable::TransitionList_t &src2, void *pCtx )
  76. {
  77. return src1.m_NumOperations > src2.m_NumOperations;
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Constructor, destructor
  81. //-----------------------------------------------------------------------------
  82. CTransitionTable::CTransitionTable() : m_DefaultStateSnapshot(-1),
  83. m_CurrentShadowId(-1), m_CurrentSnapshotId(-1), m_TransitionOps( 0, 8192 ), m_ShadowStateList( 0, 256 ),
  84. m_TransitionTable( 0, 256 ), m_SnapshotList( 0, 256 ),
  85. m_ShadowStateDict(0, 256 ),
  86. m_SnapshotDict( 0, 256 ),
  87. m_UniqueTransitions( 0, 4096 )
  88. {
  89. Assert( !g_pTransitionTable );
  90. g_pTransitionTable = this;
  91. #ifdef DEBUG_BOARD_STATE
  92. memset( &m_BoardState, 0, sizeof( m_BoardState ) );
  93. memset( &m_BoardShaderState, 0, sizeof( m_BoardShaderState ) );
  94. #endif
  95. }
  96. CTransitionTable::~CTransitionTable()
  97. {
  98. Assert( g_pTransitionTable == this );
  99. g_pTransitionTable = NULL;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Initialization, shutdown
  103. //-----------------------------------------------------------------------------
  104. bool CTransitionTable::Init( )
  105. {
  106. return true;
  107. }
  108. void CTransitionTable::Shutdown( )
  109. {
  110. Reset();
  111. }
  112. //-----------------------------------------------------------------------------
  113. // Creates a shadow, adding an entry into the shadow list and transition table
  114. //-----------------------------------------------------------------------------
  115. StateSnapshot_t CTransitionTable::CreateStateSnapshot( ShadowStateId_t shadowStateId, const ShadowShaderState_t& currentShaderState )
  116. {
  117. StateSnapshot_t snapshotId = m_SnapshotList.AddToTail();
  118. // Copy our snapshot into the list
  119. SnapshotShaderState_t &shaderState = m_SnapshotList[snapshotId];
  120. shaderState.m_ShadowStateId = shadowStateId;
  121. memcpy( &shaderState.m_ShaderState, &currentShaderState, sizeof(ShadowShaderState_t) );
  122. memset( shaderState.m_ShaderState.m_nReserved, 0, sizeof( shaderState.m_ShaderState.m_nReserved ) );
  123. shaderState.m_nReserved = 0; // needed to get a good CRC
  124. shaderState.m_nReserved2 = 0;
  125. // Insert entry into the lookup table
  126. SnapshotDictEntry_t insert;
  127. CRC32_Init( &insert.m_nChecksum );
  128. CRC32_ProcessBuffer( &insert.m_nChecksum, &shaderState, sizeof(SnapshotShaderState_t) );
  129. CRC32_Final( &insert.m_nChecksum );
  130. insert.m_nSnapshot = snapshotId;
  131. m_SnapshotDict.Insert( insert );
  132. return snapshotId;
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Creates a shadow, adding an entry into the shadow list and transition table
  136. //-----------------------------------------------------------------------------
  137. CTransitionTable::ShadowStateId_t CTransitionTable::CreateShadowState( const ShadowState_t &currentState )
  138. {
  139. int newShaderState = m_ShadowStateList.AddToTail();
  140. // Copy our snapshot into the list
  141. memcpy( &m_ShadowStateList[newShaderState], &currentState, sizeof(ShadowState_t) );
  142. // all existing states must transition to the new state
  143. int i;
  144. for ( i = 0; i < newShaderState; ++i )
  145. {
  146. // Add a new transition to all existing states
  147. int newElem = m_TransitionTable[i].AddToTail();
  148. m_TransitionTable[i][newElem].m_FirstOperation = INVALID_TRANSITION_OP;
  149. m_TransitionTable[i][newElem].m_NumOperations = 0;
  150. }
  151. // Add a new vector for this transition
  152. int newTransitionElem = m_TransitionTable.AddToTail();
  153. m_TransitionTable[newTransitionElem].EnsureCapacity( 32 );
  154. Assert( newShaderState == newTransitionElem );
  155. for ( i = 0; i <= newShaderState; ++i )
  156. {
  157. // Add a new transition from all existing states
  158. int newElem = m_TransitionTable[newShaderState].AddToTail();
  159. m_TransitionTable[newShaderState][newElem].m_FirstOperation = INVALID_TRANSITION_OP;
  160. m_TransitionTable[newShaderState][newElem].m_NumOperations = 0;
  161. }
  162. // Insert entry into the lookup table
  163. ShadowStateDictEntry_t insert;
  164. CRC32_Init( &insert.m_nChecksum );
  165. CRC32_ProcessBuffer( &insert.m_nChecksum, &m_ShadowStateList[newShaderState], sizeof(ShadowState_t) );
  166. CRC32_Final( &insert.m_nChecksum );
  167. insert.m_nShadowStateId = newShaderState;
  168. m_ShadowStateDict.Insert( insert );
  169. return newShaderState;
  170. }
  171. //-----------------------------------------------------------------------------
  172. // Finds a snapshot, if it exists. Or creates a new one if it doesn't.
  173. //-----------------------------------------------------------------------------
  174. CTransitionTable::ShadowStateId_t CTransitionTable::FindShadowState( const ShadowState_t& currentState ) const
  175. {
  176. ShadowStateDictEntry_t find;
  177. CRC32_Init( &find.m_nChecksum );
  178. CRC32_ProcessBuffer( &find.m_nChecksum, &currentState, sizeof(ShadowState_t) );
  179. CRC32_Final( &find.m_nChecksum );
  180. int nDictCount = m_ShadowStateDict.Count();
  181. int i = m_ShadowStateDict.FindLessOrEqual( find );
  182. if ( i < 0 )
  183. return (ShadowStateId_t)-1;
  184. for ( ; i < nDictCount; ++i )
  185. {
  186. const ShadowStateDictEntry_t &entry = m_ShadowStateDict[i];
  187. // Didn't find a match
  188. if ( entry.m_nChecksum > find.m_nChecksum )
  189. break;
  190. if ( entry.m_nChecksum != find.m_nChecksum )
  191. continue;
  192. ShadowStateId_t nShadowState = entry.m_nShadowStateId;
  193. if (!memcmp(&m_ShadowStateList[nShadowState], &currentState, sizeof(ShadowState_t) ))
  194. return nShadowState;
  195. }
  196. // Need to create a new one
  197. return (ShadowStateId_t)-1;
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Finds a snapshot, if it exists. Or creates a new one if it doesn't.
  201. //-----------------------------------------------------------------------------
  202. StateSnapshot_t CTransitionTable::FindStateSnapshot( ShadowStateId_t id, const ShadowShaderState_t& currentState ) const
  203. {
  204. SnapshotShaderState_t temp;
  205. temp.m_ShaderState = currentState;
  206. temp.m_ShadowStateId = id;
  207. memset( temp.m_ShaderState.m_nReserved, 0, sizeof( temp.m_ShaderState.m_nReserved ) );
  208. temp.m_nReserved = 0; // needed to get a good CRC
  209. temp.m_nReserved2 = 0;
  210. SnapshotDictEntry_t find;
  211. CRC32_Init( &find.m_nChecksum );
  212. CRC32_ProcessBuffer( &find.m_nChecksum, &temp, sizeof(temp) );
  213. CRC32_Final( &find.m_nChecksum );
  214. int nDictCount = m_SnapshotDict.Count();
  215. int i = m_SnapshotDict.FindLessOrEqual( find );
  216. if ( i < 0 )
  217. return (StateSnapshot_t)-1;
  218. for ( ; i < nDictCount; ++i )
  219. {
  220. // Didn't find a match
  221. if ( m_SnapshotDict[i].m_nChecksum > find.m_nChecksum )
  222. break;
  223. if ( m_SnapshotDict[i].m_nChecksum != find.m_nChecksum )
  224. continue;
  225. StateSnapshot_t nShapshot = m_SnapshotDict[i].m_nSnapshot;
  226. if ( (id == m_SnapshotList[nShapshot].m_ShadowStateId) &&
  227. !memcmp(&m_SnapshotList[nShapshot].m_ShaderState, &currentState, sizeof(ShadowShaderState_t)) )
  228. {
  229. return nShapshot;
  230. }
  231. }
  232. // Need to create a new one
  233. return (StateSnapshot_t)-1;
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Used to clear the transition table when we know it's become invalid.
  237. //-----------------------------------------------------------------------------
  238. void CTransitionTable::Reset()
  239. {
  240. m_ShadowStateList.RemoveAll();
  241. m_SnapshotList.RemoveAll();
  242. m_TransitionTable.RemoveAll();
  243. m_TransitionOps.RemoveAll();
  244. m_ShadowStateDict.RemoveAll();
  245. m_SnapshotDict.RemoveAll();
  246. m_UniqueTransitions.RemoveAll();
  247. m_CurrentShadowId = -1;
  248. m_CurrentSnapshotId = -1;
  249. m_DefaultStateSnapshot = -1;
  250. }
  251. //-----------------------------------------------------------------------------
  252. // Sets the texture stage state
  253. //-----------------------------------------------------------------------------
  254. #ifdef _WIN32
  255. #pragma warning( disable : 4189 )
  256. #endif
  257. static inline void SetTextureStageState( int stage, D3DTEXTURESTAGESTATETYPE state, DWORD val )
  258. {
  259. #if !defined( _X360 )
  260. Assert( !g_pShaderDeviceDx8->IsDeactivated() );
  261. Dx9Device()->SetTextureStageState( stage, state, val );
  262. #endif
  263. }
  264. //Moved to a #define so every instance of this skips unsupported render states at compile time
  265. #define SetSamplerState( _stage, _state, _val ) \
  266. { \
  267. if ( (_state != D3DSAMP_NOTSUPPORTED) ) \
  268. { \
  269. Assert( !g_pShaderDeviceDx8->IsDeactivated() ); \
  270. Dx9Device()->SetSamplerState( _stage, _state, _val ); \
  271. } \
  272. }
  273. //Moved to a #define so every instance of this skips unsupported render states at compile time
  274. #define SetRenderState( _state, _val ) \
  275. { \
  276. if ( _state != D3DRS_NOTSUPPORTED ) \
  277. { \
  278. Assert( !g_pShaderDeviceDx8->IsDeactivated() ); \
  279. Dx9Device()->SetRenderState( _state, _val ); \
  280. } \
  281. }
  282. #ifdef DX_TO_GL_ABSTRACTION
  283. #define SetRenderStateConstMacro( state, val ) { if ( state != D3DRS_NOTSUPPORTED ) Dx9Device()->SetRenderStateConstInline( state, val ); }
  284. #else
  285. #define SetRenderStateConstMacro( state, val ) SetRenderState( state, val )
  286. #endif
  287. #ifdef _WIN32
  288. #pragma warning( default : 4189 )
  289. #endif
  290. //-----------------------------------------------------------------------------
  291. // Methods that actually apply the state
  292. //-----------------------------------------------------------------------------
  293. #ifdef DEBUG_BOARD_STATE
  294. static bool g_SpewTransitions = false;
  295. #define UPDATE_BOARD_RENDER_STATE( _d3dState, _state ) \
  296. { \
  297. BoardState().m_ ## _state = shaderState.m_ ## _state; \
  298. if (g_SpewTransitions) \
  299. { \
  300. char buf[128]; \
  301. sprintf( buf, "Apply %s : %d\n", #_d3dState, shaderState.m_ ## _state ); \
  302. Plat_DebugString(buf); \
  303. } \
  304. }
  305. #define UPDATE_BOARD_TEXTURE_STAGE_STATE( _d3dState, _state, _stage ) \
  306. { \
  307. BoardState().m_TextureStage[_stage].m_ ## _state = shaderState.m_TextureStage[_stage].m_ ## _state; \
  308. if (g_SpewTransitions) \
  309. { \
  310. char buf[128]; \
  311. sprintf( buf, "Apply Tex %s (%d): %d\n", #_d3dState, _stage, shaderState.m_TextureStage[_stage].m_ ## _state ); \
  312. Plat_DebugString(buf); \
  313. } \
  314. }
  315. #define UPDATE_BOARD_SAMPLER_STATE( _d3dState, _state, _stage ) \
  316. { \
  317. BoardState().m_SamplerState[_stage].m_ ## _state = shaderState.m_SamplerState[_stage].m_ ## _state; \
  318. if (g_SpewTransitions) \
  319. { \
  320. char buf[128]; \
  321. sprintf( buf, "Apply SamplerSate %s (%d): %d\n", #_d3dState, stage, shaderState.m_SamplerState[_stage].m_ ## _state ); \
  322. Plat_DebugString(buf); \
  323. } \
  324. }
  325. #else
  326. #define UPDATE_BOARD_RENDER_STATE( _d3dState, _state ) {}
  327. #define UPDATE_BOARD_TEXTURE_STAGE_STATE( _d3dState, _state, _stage ) {}
  328. #define UPDATE_BOARD_SAMPLER_STATE( _d3dState, _state, _stage ) {}
  329. #endif
  330. #define APPLY_RENDER_STATE_FUNC( _d3dState, _state ) \
  331. void Apply ## _state( const ShadowState_t& shaderState, int arg ) \
  332. { \
  333. SetRenderState( _d3dState, shaderState.m_ ## _state ); \
  334. UPDATE_BOARD_RENDER_STATE( _d3dState, _state ); \
  335. }
  336. #define APPLY_TEXTURE_STAGE_STATE_FUNC( _d3dState, _state ) \
  337. void Apply ## _state( const ShadowState_t& shaderState, int stage ) \
  338. { \
  339. SetTextureStageState( stage, _d3dState, shaderState.m_TextureStage[stage].m_ ## _state ); \
  340. UPDATE_BOARD_TEXTURE_STAGE_STATE( _d3dState, _state, stage ); \
  341. }
  342. #define APPLY_SAMPLER_STATE_FUNC( _d3dState, _state ) \
  343. void Apply ## _state( const ShadowState_t& shaderState, int stage ) \
  344. { \
  345. SetSamplerState( stage, _d3dState, shaderState.m_SamplerState[stage].m_ ## _state ); \
  346. UPDATE_BOARD_SAMPLER_STATE( _d3dState, _state, stage ); \
  347. }
  348. // Special overridden sampler state to turn on Fetch4 on ATI hardware (and 360?)
  349. void ApplyFetch4Enable( const ShadowState_t& shaderState, int stage )
  350. {
  351. if ( ShaderAPI()->SupportsFetch4() )
  352. {
  353. SetSamplerState( stage, ATISAMP_FETCH4, shaderState.m_SamplerState[stage].m_Fetch4Enable ? ATI_FETCH4_ENABLE : ATI_FETCH4_DISABLE );
  354. }
  355. UPDATE_BOARD_SAMPLER_STATE( ATISAMP_FETCH4, Fetch4Enable, stage );
  356. }
  357. #ifdef DX_TO_GL_ABSTRACTION
  358. void ApplyShadowFilterEnable( const ShadowState_t& shaderState, int stage )
  359. {
  360. SetSamplerState( stage, D3DSAMP_SHADOWFILTER, shaderState.m_SamplerState[stage].m_ShadowFilterEnable );
  361. UPDATE_BOARD_SAMPLER_STATE( D3DSAMP_SHADOWFILTER, ShadowFilterEnable, stage );
  362. }
  363. #endif
  364. //APPLY_RENDER_STATE_FUNC( D3DRS_ZWRITEENABLE, ZWriteEnable )
  365. //APPLY_RENDER_STATE_FUNC( D3DRS_COLORWRITEENABLE, ColorWriteEnable )
  366. APPLY_RENDER_STATE_FUNC( D3DRS_FILLMODE, FillMode )
  367. APPLY_RENDER_STATE_FUNC( D3DRS_LIGHTING, Lighting )
  368. APPLY_RENDER_STATE_FUNC( D3DRS_SPECULARENABLE, SpecularEnable )
  369. APPLY_RENDER_STATE_FUNC( D3DRS_DIFFUSEMATERIALSOURCE, DiffuseMaterialSource )
  370. APPLY_TEXTURE_STAGE_STATE_FUNC( D3DTSS_TEXCOORDINDEX, TexCoordIndex )
  371. void ApplyZWriteEnable( const ShadowState_t& shaderState, int arg )
  372. {
  373. SetRenderStateConstMacro( D3DRS_ZWRITEENABLE, shaderState.m_ZWriteEnable );
  374. #if defined( _X360 )
  375. //SetRenderStateConstMacro( D3DRS_HIZWRITEENABLE, shaderState.m_ZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  376. #endif
  377. UPDATE_BOARD_RENDER_STATE( D3DRS_ZWRITEENABLE, ZWriteEnable );
  378. }
  379. void ApplyColorWriteEnable( const ShadowState_t& shaderState, int arg )
  380. {
  381. SetRenderState( D3DRS_COLORWRITEENABLE, shaderState.m_ColorWriteEnable );
  382. g_pTransitionTable->CurrentState().m_ColorWriteEnable = shaderState.m_ColorWriteEnable;
  383. UPDATE_BOARD_RENDER_STATE( D3DRS_COLORWRITEENABLE, ColorWriteEnable );
  384. }
  385. void ApplySRGBReadEnable( const ShadowState_t& shaderState, int stage )
  386. {
  387. # if ( !defined( _X360 ) )
  388. {
  389. SetSamplerState( stage, D3DSAMP_SRGBTEXTURE, shaderState.m_SamplerState[stage].m_SRGBReadEnable );
  390. }
  391. # else
  392. {
  393. ShaderAPI()->ApplySRGBReadState( stage, shaderState.m_SamplerState[stage].m_SRGBReadEnable );
  394. }
  395. # endif
  396. UPDATE_BOARD_SAMPLER_STATE( D3DSAMP_SRGBTEXTURE, SRGBReadEnable, stage );
  397. }
  398. void ApplySRGBWriteEnable( const ShadowState_t& shadowState, int stageUnused )
  399. {
  400. g_pTransitionTable->ApplySRGBWriteEnable( shadowState );
  401. }
  402. void CTransitionTable::ApplySRGBWriteEnable( const ShadowState_t& shaderState )
  403. {
  404. // ApplySRGBWriteEnable set to true means that the shader is writing linear values.
  405. if ( CurrentState().m_bLinearColorSpaceFrameBufferEnable )
  406. {
  407. // The shader had better be writing linear values since we can't convert to gamma here.
  408. // Can't leave this assert here since there are cases where the shader is doing the right thing.
  409. // This is good to test occasionally to make sure that the shaders are doing the right thing.
  410. // Assert( shaderState.m_SRGBWriteEnable );
  411. // render target is linear
  412. SetRenderStateConstMacro( D3DRS_SRGBWRITEENABLE, 0 );
  413. ShaderAPI()->EnabledSRGBWrite( false );
  414. // fog isn't fixed-function with linear frame buffers, so don't bother with that here.
  415. }
  416. else
  417. {
  418. // render target is gamma
  419. // SRGBWrite enable can affect the space in which fog color is defined
  420. if ( HardwareConfig()->NeedsShaderSRGBConversion() )
  421. {
  422. if ( HardwareConfig()->SupportsPixelShaders_2_b() ) //in 2b supported devices, we never actually enable SRGB writes, but instead handle the conversion in the pixel shader. But we want all other code to be unaware.
  423. {
  424. SetRenderStateConstMacro( D3DRS_SRGBWRITEENABLE, 0 );
  425. }
  426. else
  427. {
  428. SetRenderStateConstMacro( D3DRS_SRGBWRITEENABLE, shaderState.m_SRGBWriteEnable );
  429. }
  430. }
  431. else
  432. {
  433. SetRenderStateConstMacro( D3DRS_SRGBWRITEENABLE, shaderState.m_SRGBWriteEnable );
  434. }
  435. ShaderAPI()->EnabledSRGBWrite( shaderState.m_SRGBWriteEnable );
  436. if ( HardwareConfig()->SpecifiesFogColorInLinearSpace() )
  437. {
  438. ShaderAPI()->ApplyFogMode( shaderState.m_FogMode, shaderState.m_SRGBWriteEnable, shaderState.m_bDisableFogGammaCorrection );
  439. }
  440. }
  441. #ifdef _DEBUG
  442. BoardState().m_SRGBWriteEnable = shaderState.m_SRGBWriteEnable;
  443. if (g_SpewTransitions)
  444. {
  445. char buf[128];
  446. sprintf( buf, "Apply %s : %d\n", "D3DRS_SRGBWRITEENABLE", shaderState.m_SRGBWriteEnable );
  447. Plat_DebugString(buf);
  448. }
  449. #endif
  450. }
  451. void ApplyDisableFogGammaCorrection( const ShadowState_t& shadowState, int stageUnused )
  452. {
  453. ShaderAPI()->ApplyFogMode( shadowState.m_FogMode, shadowState.m_SRGBWriteEnable, shadowState.m_bDisableFogGammaCorrection );
  454. #ifdef DEBUG_BOARD_STATE
  455. g_pTransitionTable->BoardState().m_bDisableFogGammaCorrection = shadowState.m_bDisableFogGammaCorrection;
  456. #endif
  457. }
  458. void ApplyDepthTest( const ShadowState_t& state, int stage )
  459. {
  460. g_pTransitionTable->ApplyDepthTest( state );
  461. }
  462. void CTransitionTable::SetZEnable( D3DZBUFFERTYPE nEnable )
  463. {
  464. if (m_CurrentState.m_ZEnable != nEnable )
  465. {
  466. SetRenderStateConstMacro( D3DRS_ZENABLE, nEnable );
  467. #if defined( _X360 )
  468. //SetRenderState( D3DRS_HIZENABLE, nEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  469. #endif
  470. m_CurrentState.m_ZEnable = nEnable;
  471. }
  472. }
  473. void CTransitionTable::SetZFunc( D3DCMPFUNC nCmpFunc )
  474. {
  475. if (m_CurrentState.m_ZFunc != nCmpFunc )
  476. {
  477. SetRenderStateConstMacro( D3DRS_ZFUNC, nCmpFunc );
  478. m_CurrentState.m_ZFunc = nCmpFunc;
  479. }
  480. }
  481. void CTransitionTable::ApplyDepthTest( const ShadowState_t& state )
  482. {
  483. SetZEnable( state.m_ZEnable );
  484. if (state.m_ZEnable != D3DZB_FALSE)
  485. {
  486. SetZFunc( state.m_ZFunc );
  487. }
  488. if (m_CurrentState.m_ZBias != state.m_ZBias)
  489. {
  490. ShaderAPI()->ApplyZBias( state );
  491. m_CurrentState.m_ZBias = (PolygonOffsetMode_t) state.m_ZBias; // Cast two bits from m_ZBias
  492. }
  493. #ifdef DEBUG_BOARD_STATE
  494. // This isn't quite true, but it's necessary for other error checking to work
  495. BoardState().m_ZEnable = state.m_ZEnable;
  496. BoardState().m_ZFunc = state.m_ZFunc;
  497. BoardState().m_ZBias = state.m_ZBias;
  498. #endif
  499. }
  500. void ApplyAlphaTest( const ShadowState_t& state, int stage )
  501. {
  502. g_pTransitionTable->ApplyAlphaTest( state );
  503. }
  504. void CTransitionTable::ApplyAlphaTest( const ShadowState_t& state )
  505. {
  506. if (m_CurrentState.m_AlphaTestEnable != state.m_AlphaTestEnable)
  507. {
  508. SetRenderStateConstMacro( D3DRS_ALPHATESTENABLE, state.m_AlphaTestEnable );
  509. m_CurrentState.m_AlphaTestEnable = state.m_AlphaTestEnable;
  510. }
  511. if (state.m_AlphaTestEnable)
  512. {
  513. // Set the blend state here...
  514. if (m_CurrentState.m_AlphaFunc != state.m_AlphaFunc)
  515. {
  516. SetRenderStateConstMacro( D3DRS_ALPHAFUNC, state.m_AlphaFunc );
  517. m_CurrentState.m_AlphaFunc = state.m_AlphaFunc;
  518. }
  519. if (m_CurrentState.m_AlphaRef != state.m_AlphaRef)
  520. {
  521. SetRenderStateConstMacro( D3DRS_ALPHAREF, state.m_AlphaRef );
  522. m_CurrentState.m_AlphaRef = state.m_AlphaRef;
  523. }
  524. }
  525. #ifdef DEBUG_BOARD_STATE
  526. // This isn't quite true, but it's necessary for other error checking to work
  527. BoardState().m_AlphaTestEnable = state.m_AlphaTestEnable;
  528. BoardState().m_AlphaFunc = state.m_AlphaFunc;
  529. BoardState().m_AlphaRef = state.m_AlphaRef;
  530. #endif
  531. }
  532. void ApplyAlphaBlend( const ShadowState_t& state, int stage )
  533. {
  534. g_pTransitionTable->ApplyAlphaBlend( state );
  535. }
  536. void CTransitionTable::ApplyAlphaBlend( const ShadowState_t& state )
  537. {
  538. if (m_CurrentState.m_AlphaBlendEnable != state.m_AlphaBlendEnable)
  539. {
  540. SetRenderStateConstMacro( D3DRS_ALPHABLENDENABLE, state.m_AlphaBlendEnable );
  541. m_CurrentState.m_AlphaBlendEnable = state.m_AlphaBlendEnable;
  542. }
  543. if (state.m_AlphaBlendEnable)
  544. {
  545. // Set the blend state here...
  546. if (m_CurrentState.m_SrcBlend != state.m_SrcBlend)
  547. {
  548. SetRenderStateConstMacro( D3DRS_SRCBLEND, state.m_SrcBlend );
  549. m_CurrentState.m_SrcBlend = state.m_SrcBlend;
  550. }
  551. if (m_CurrentState.m_DestBlend != state.m_DestBlend)
  552. {
  553. SetRenderStateConstMacro( D3DRS_DESTBLEND, state.m_DestBlend );
  554. m_CurrentState.m_DestBlend = state.m_DestBlend;
  555. }
  556. if (m_CurrentState.m_BlendOp != state.m_BlendOp )
  557. {
  558. SetRenderStateConstMacro( D3DRS_BLENDOP, state.m_BlendOp );
  559. m_CurrentState.m_BlendOp = state.m_BlendOp;
  560. }
  561. }
  562. #ifdef DEBUG_BOARD_STATE
  563. // This isn't quite true, but it's necessary for other error checking to work
  564. BoardState().m_AlphaBlendEnable = state.m_AlphaBlendEnable;
  565. BoardState().m_SrcBlend = state.m_SrcBlend;
  566. BoardState().m_DestBlend = state.m_DestBlend;
  567. BoardState().m_BlendOp = state.m_BlendOp;
  568. #endif
  569. }
  570. void ApplySeparateAlphaBlend( const ShadowState_t& state, int stage )
  571. {
  572. g_pTransitionTable->ApplySeparateAlphaBlend( state );
  573. }
  574. void CTransitionTable::ApplySeparateAlphaBlend( const ShadowState_t& state )
  575. {
  576. if (m_CurrentState.m_SeparateAlphaBlendEnable != state.m_SeparateAlphaBlendEnable)
  577. {
  578. SetRenderStateConstMacro( D3DRS_SEPARATEALPHABLENDENABLE, state.m_SeparateAlphaBlendEnable );
  579. m_CurrentState.m_SeparateAlphaBlendEnable = state.m_SeparateAlphaBlendEnable;
  580. }
  581. if (state.m_SeparateAlphaBlendEnable)
  582. {
  583. // Set the blend state here...
  584. if (m_CurrentState.m_SrcBlendAlpha != state.m_SrcBlendAlpha)
  585. {
  586. SetRenderStateConstMacro( D3DRS_SRCBLENDALPHA, state.m_SrcBlendAlpha );
  587. m_CurrentState.m_SrcBlendAlpha = state.m_SrcBlendAlpha;
  588. }
  589. if (m_CurrentState.m_DestBlendAlpha != state.m_DestBlendAlpha)
  590. {
  591. SetRenderStateConstMacro( D3DRS_DESTBLENDALPHA, state.m_DestBlendAlpha );
  592. m_CurrentState.m_DestBlendAlpha = state.m_DestBlendAlpha;
  593. }
  594. if (m_CurrentState.m_BlendOpAlpha != state.m_BlendOpAlpha )
  595. {
  596. SetRenderStateConstMacro( D3DRS_BLENDOPALPHA, state.m_BlendOpAlpha );
  597. m_CurrentState.m_BlendOpAlpha = state.m_BlendOpAlpha;
  598. }
  599. }
  600. #ifdef DEBUG_BOARD_STATE
  601. // This isn't quite true, but it's necessary for other error checking to work
  602. BoardState().m_SeparateAlphaBlendEnable = state.m_SeparateAlphaBlendEnable;
  603. BoardState().m_SrcBlendAlpha = state.m_SrcBlendAlpha;
  604. BoardState().m_DestBlendAlpha = state.m_DestBlendAlpha;
  605. BoardState().m_BlendOpAlpha = state.m_BlendOpAlpha;
  606. #endif
  607. }
  608. //-----------------------------------------------------------------------------
  609. // Applies alpha texture op
  610. //-----------------------------------------------------------------------------
  611. void ApplyColorTextureStage( const ShadowState_t& state, int stage )
  612. {
  613. g_pTransitionTable->ApplyColorTextureStage( state, stage );
  614. }
  615. void ApplyAlphaTextureStage( const ShadowState_t& state, int stage )
  616. {
  617. g_pTransitionTable->ApplyAlphaTextureStage( state, stage );
  618. }
  619. void CTransitionTable::ApplyColorTextureStage( const ShadowState_t& state, int stage )
  620. {
  621. D3DTEXTUREOP op = state.m_TextureStage[stage].m_ColorOp;
  622. int arg1 = state.m_TextureStage[stage].m_ColorArg1;
  623. int arg2 = state.m_TextureStage[stage].m_ColorArg2;
  624. if (m_CurrentState.m_TextureStage[stage].m_ColorOp != op)
  625. {
  626. SetTextureStageState( stage, D3DTSS_COLOROP, op );
  627. m_CurrentState.m_TextureStage[stage].m_ColorOp = op;
  628. }
  629. if (op != D3DTOP_DISABLE)
  630. {
  631. if (m_CurrentState.m_TextureStage[stage].m_ColorArg1 != arg1)
  632. {
  633. SetTextureStageState( stage, D3DTSS_COLORARG1, arg1 );
  634. m_CurrentState.m_TextureStage[stage].m_ColorArg1 = arg1;
  635. }
  636. if (m_CurrentState.m_TextureStage[stage].m_ColorArg2 != arg2)
  637. {
  638. SetTextureStageState( stage, D3DTSS_COLORARG2, arg2 );
  639. m_CurrentState.m_TextureStage[stage].m_ColorArg2 = arg2;
  640. }
  641. }
  642. #ifdef DEBUG_BOARD_STATE
  643. // This isn't quite true, but it's necessary for other error checking to work
  644. BoardState().m_TextureStage[stage].m_ColorOp = op;
  645. BoardState().m_TextureStage[stage].m_ColorArg1 = arg1;
  646. BoardState().m_TextureStage[stage].m_ColorArg2 = arg2;
  647. #endif
  648. }
  649. void CTransitionTable::ApplyAlphaTextureStage( const ShadowState_t& state, int stage )
  650. {
  651. D3DTEXTUREOP op = state.m_TextureStage[stage].m_AlphaOp;
  652. int arg1 = state.m_TextureStage[stage].m_AlphaArg1;
  653. int arg2 = state.m_TextureStage[stage].m_AlphaArg2;
  654. if (m_CurrentState.m_TextureStage[stage].m_AlphaOp != op)
  655. {
  656. SetTextureStageState( stage, D3DTSS_ALPHAOP, op );
  657. m_CurrentState.m_TextureStage[stage].m_AlphaOp = op;
  658. }
  659. if (op != D3DTOP_DISABLE)
  660. {
  661. if (m_CurrentState.m_TextureStage[stage].m_AlphaArg1 != arg1)
  662. {
  663. SetTextureStageState( stage, D3DTSS_ALPHAARG1, arg1 );
  664. m_CurrentState.m_TextureStage[stage].m_AlphaArg1 = arg1;
  665. }
  666. if (m_CurrentState.m_TextureStage[stage].m_AlphaArg2 != arg2)
  667. {
  668. SetTextureStageState( stage, D3DTSS_ALPHAARG2, arg2 );
  669. m_CurrentState.m_TextureStage[stage].m_AlphaArg2 = arg2;
  670. }
  671. }
  672. #ifdef DEBUG_BOARD_STATE
  673. // This isn't quite true, but it's necessary for other error checking to work
  674. BoardState().m_TextureStage[stage].m_AlphaOp = op;
  675. BoardState().m_TextureStage[stage].m_AlphaArg1 = arg1;
  676. BoardState().m_TextureStage[stage].m_AlphaArg2 = arg2;
  677. #endif
  678. }
  679. void ApplyActivateFixedFunction( const ShadowState_t& state, int stage )
  680. {
  681. int nStageCount = HardwareConfig()->GetTextureStageCount();
  682. for ( int i = 0; i < nStageCount; ++i )
  683. {
  684. g_pTransitionTable->ApplyColorTextureStage( state, i );
  685. g_pTransitionTable->ApplyAlphaTextureStage( state, i );
  686. }
  687. }
  688. //-----------------------------------------------------------------------------
  689. // Enables textures
  690. //-----------------------------------------------------------------------------
  691. void ApplyTextureEnable( const ShadowState_t& state, int stage )
  692. {
  693. // This may well enable/disable textures that are already enabled/disabled
  694. // but the ShaderAPI will handle that
  695. int i;
  696. int nSamplerCount = HardwareConfig()->GetSamplerCount();
  697. for ( i = 0; i < nSamplerCount; ++i )
  698. {
  699. ShaderAPI()->ApplyTextureEnable( state, i );
  700. #ifdef DEBUG_BOARD_STATE
  701. BoardState().m_SamplerState[i].m_TextureEnable = state.m_SamplerState[i].m_TextureEnable;
  702. #endif
  703. }
  704. // Needed to prevent mat_dxlevel assertions
  705. #ifdef DEBUG_BOARD_STATE
  706. for ( i = nSamplerCount; i < MAX_SAMPLERS; ++i )
  707. {
  708. BoardState().m_SamplerState[i].m_TextureEnable = false;
  709. }
  710. #endif
  711. }
  712. //-----------------------------------------------------------------------------
  713. // All transitions below this point depend on dynamic render state
  714. // FIXME: Eliminate these virtual calls?
  715. //-----------------------------------------------------------------------------
  716. void ApplyCullEnable( const ShadowState_t& state, int arg )
  717. {
  718. ShaderAPI()->ApplyCullEnable( state.m_CullEnable );
  719. #ifdef DEBUG_BOARD_STATE
  720. BoardState().m_CullEnable = state.m_CullEnable;
  721. #endif
  722. }
  723. //-----------------------------------------------------------------------------
  724. void ApplyAlphaToCoverage( const ShadowState_t& state, int arg )
  725. {
  726. ShaderAPI()->ApplyAlphaToCoverage( state.m_EnableAlphaToCoverage );
  727. #ifdef DEBUG_BOARD_STATE
  728. BoardState().m_EnableAlphaToCoverage = state.m_EnableAlphaToCoverage;
  729. #endif
  730. }
  731. //-----------------------------------------------------------------------------
  732. void ApplyVertexBlendEnable( const ShadowState_t& state, int stage )
  733. {
  734. ShaderAPI()->SetVertexBlendState( state.m_VertexBlendEnable ? -1 : 0 );
  735. #ifdef DEBUG_BOARD_STATE
  736. BoardState().m_VertexBlendEnable = state.m_VertexBlendEnable;
  737. #endif
  738. }
  739. //-----------------------------------------------------------------------------
  740. // Outputs the fog mode string
  741. //-----------------------------------------------------------------------------
  742. #ifdef RECORDING
  743. const char *ShaderFogModeToString( ShaderFogMode_t fogMode )
  744. {
  745. switch( fogMode )
  746. {
  747. case SHADER_FOGMODE_DISABLED:
  748. return "SHADER_FOGMODE_DISABLED";
  749. case SHADER_FOGMODE_OO_OVERBRIGHT:
  750. return "SHADER_FOGMODE_OO_OVERBRIGHT";
  751. case SHADER_FOGMODE_BLACK:
  752. return "SHADER_FOGMODE_BLACK";
  753. case SHADER_FOGMODE_GREY:
  754. return "SHADER_FOGMODE_GREY";
  755. case SHADER_FOGMODE_FOGCOLOR:
  756. return "SHADER_FOGMODE_FOGCOLOR";
  757. case SHADER_FOGMODE_WHITE:
  758. return "SHADER_FOGMODE_WHITE";
  759. case SHADER_FOGMODE_NUMFOGMODES:
  760. return "SHADER_FOGMODE_NUMFOGMODES";
  761. default:
  762. return "ERROR";
  763. }
  764. }
  765. #endif
  766. // Uses GetConfig().overbright and GetSceneFogMode, so
  767. // will have to fix up the state manually when those change.
  768. void ApplyFogMode( const ShadowState_t& state, int arg )
  769. {
  770. #ifdef RECORDING
  771. char buf[1024];
  772. sprintf( buf, "ApplyFogMode( %s )", ShaderFogModeToString( state.m_FogMode ) );
  773. RECORD_DEBUG_STRING( buf );
  774. #endif
  775. ShaderAPI()->ApplyFogMode( state.m_FogMode, state.m_SRGBWriteEnable, state.m_bDisableFogGammaCorrection );
  776. #ifdef DEBUG_BOARD_STATE
  777. BoardState().m_FogMode = state.m_FogMode;
  778. #endif
  779. }
  780. //-----------------------------------------------------------------------------
  781. // Function tables mapping enum to function
  782. //-----------------------------------------------------------------------------
  783. ApplyStateFunc_t s_pRenderFunctionTable[] =
  784. {
  785. ApplyDepthTest,
  786. ApplyZWriteEnable,
  787. ApplyColorWriteEnable,
  788. ApplyAlphaTest,
  789. ApplyFillMode,
  790. ApplyLighting,
  791. ApplySpecularEnable,
  792. ApplySRGBWriteEnable,
  793. ApplyAlphaBlend,
  794. ApplySeparateAlphaBlend,
  795. ApplyCullEnable,
  796. ApplyVertexBlendEnable,
  797. ApplyFogMode,
  798. ApplyActivateFixedFunction,
  799. ApplyTextureEnable, // Enables textures on *all* stages
  800. ApplyDiffuseMaterialSource,
  801. ApplyDisableFogGammaCorrection,
  802. ApplyAlphaToCoverage,
  803. };
  804. ApplyStateFunc_t s_pTextureFunctionTable[] =
  805. {
  806. ApplyTexCoordIndex,
  807. ApplySRGBReadEnable,
  808. ApplyFetch4Enable,
  809. #ifdef DX_TO_GL_ABSTRACTION
  810. ApplyShadowFilterEnable,
  811. #endif
  812. // Fixed function states
  813. ApplyColorTextureStage,
  814. ApplyAlphaTextureStage,
  815. };
  816. //-----------------------------------------------------------------------------
  817. // Creates an entry in the state transition table
  818. //-----------------------------------------------------------------------------
  819. inline void CTransitionTable::AddTransition( RenderStateFunc_t func )
  820. {
  821. int nElem = m_TransitionOps.AddToTail();
  822. TransitionOp_t &op = m_TransitionOps[nElem];
  823. op.m_nInfo.m_bIsTextureCode = false;
  824. op.m_nInfo.m_nOpCode = func;
  825. // Stats
  826. // ++s_pRenderTransitions[ func ];
  827. }
  828. inline void CTransitionTable::AddTextureTransition( TextureStateFunc_t func, int stage )
  829. {
  830. int nElem = m_TransitionOps.AddToTail();
  831. TransitionOp_t &op = m_TransitionOps[nElem];
  832. op.m_nInfo.m_bIsTextureCode = true;
  833. op.m_nInfo.m_nOpCode = TextureOp( func, stage );
  834. // Stats
  835. // ++s_pTextureTransitions[ func ][stage];
  836. }
  837. #define ADD_RENDER_STATE_TRANSITION( _state ) \
  838. if (bForce || (toState.m_ ## _state != fromState.m_ ## _state)) \
  839. { \
  840. AddTransition( RENDER_STATE_ ## _state ); \
  841. ++numOps; \
  842. }
  843. #define ADD_TEXTURE_STAGE_STATE_TRANSITION( _stage, _state )\
  844. if (bForce || (toState.m_TextureStage[_stage].m_ ## _state != fromState.m_TextureStage[_stage].m_ ## _state)) \
  845. { \
  846. Assert( _stage < MAX_TEXTURE_STAGES ); \
  847. AddTextureTransition( TEXTURE_STATE_ ## _state, _stage ); \
  848. ++numOps; \
  849. }
  850. #define ADD_SAMPLER_STATE_TRANSITION( _stage, _state )\
  851. if (bForce || (toState.m_SamplerState[_stage].m_ ## _state != fromState.m_SamplerState[_stage].m_ ## _state)) \
  852. { \
  853. Assert( _stage < MAX_SAMPLERS ); \
  854. AddTextureTransition( TEXTURE_STATE_ ## _state, _stage ); \
  855. ++numOps; \
  856. }
  857. int CTransitionTable::CreateNormalTransitions( const ShadowState_t& fromState, const ShadowState_t& toState, bool bForce )
  858. {
  859. int numOps = 0;
  860. // Special case for alpha blending to eliminate extra transitions
  861. bool blendEnableDifferent = (toState.m_AlphaBlendEnable != fromState.m_AlphaBlendEnable);
  862. bool srcBlendDifferent = toState.m_AlphaBlendEnable && (toState.m_SrcBlend != fromState.m_SrcBlend);
  863. bool destBlendDifferent = toState.m_AlphaBlendEnable && (toState.m_DestBlend != fromState.m_DestBlend);
  864. bool blendOpDifferent = toState.m_AlphaBlendEnable && ( toState.m_BlendOp != fromState.m_BlendOp );
  865. if (bForce || blendOpDifferent || blendEnableDifferent || srcBlendDifferent || destBlendDifferent)
  866. {
  867. AddTransition( RENDER_STATE_AlphaBlend );
  868. ++numOps;
  869. }
  870. // Shouldn't have m_SeparateAlphaBlendEnable set unless m_AlphaBlendEnable is also set.
  871. Assert ( toState.m_AlphaBlendEnable || !toState.m_SeparateAlphaBlendEnable );
  872. bool blendSeparateAlphaEnableDifferent = (toState.m_SeparateAlphaBlendEnable != fromState.m_SeparateAlphaBlendEnable);
  873. bool srcBlendAlphaDifferent = toState.m_SeparateAlphaBlendEnable && (toState.m_SrcBlendAlpha != fromState.m_SrcBlendAlpha);
  874. bool destBlendAlphaDifferent = toState.m_SeparateAlphaBlendEnable && (toState.m_DestBlendAlpha != fromState.m_DestBlendAlpha);
  875. bool blendOpAlphaDifferent = toState.m_SeparateAlphaBlendEnable && ( toState.m_BlendOpAlpha != fromState.m_BlendOpAlpha );
  876. if (bForce || blendOpAlphaDifferent || blendSeparateAlphaEnableDifferent || srcBlendAlphaDifferent || destBlendAlphaDifferent)
  877. {
  878. AddTransition( RENDER_STATE_SeparateAlphaBlend );
  879. ++numOps;
  880. }
  881. bool bAlphaTestEnableDifferent = (toState.m_AlphaTestEnable != fromState.m_AlphaTestEnable);
  882. bool bAlphaFuncDifferent = toState.m_AlphaTestEnable && (toState.m_AlphaFunc != fromState.m_AlphaFunc);
  883. bool bAlphaRefDifferent = toState.m_AlphaTestEnable && (toState.m_AlphaRef != fromState.m_AlphaRef);
  884. if (bForce || bAlphaTestEnableDifferent || bAlphaFuncDifferent || bAlphaRefDifferent)
  885. {
  886. AddTransition( RENDER_STATE_AlphaTest );
  887. ++numOps;
  888. }
  889. bool bDepthTestEnableDifferent = (toState.m_ZEnable != fromState.m_ZEnable);
  890. bool bDepthFuncDifferent = (toState.m_ZEnable != D3DZB_FALSE) && (toState.m_ZFunc != fromState.m_ZFunc);
  891. bool bDepthBiasDifferent = (toState.m_ZBias != fromState.m_ZBias);
  892. if (bForce || bDepthTestEnableDifferent || bDepthFuncDifferent || bDepthBiasDifferent)
  893. {
  894. AddTransition( RENDER_STATE_DepthTest );
  895. ++numOps;
  896. }
  897. if ( bForce || (toState.m_UsingFixedFunction && !fromState.m_UsingFixedFunction) )
  898. {
  899. AddTransition( RENDER_STATE_ActivateFixedFunction );
  900. ++numOps;
  901. }
  902. if ( bForce || (toState.m_bDisableFogGammaCorrection != fromState.m_bDisableFogGammaCorrection) )
  903. {
  904. AddTransition( RENDER_STATE_DisableFogGammaCorrection );
  905. ++numOps;
  906. }
  907. int nStageCount = HardwareConfig()->GetTextureStageCount();
  908. int i;
  909. for ( i = 0; i < nStageCount; ++i )
  910. {
  911. // Special case for texture stage ops to eliminate extra transitions
  912. // NOTE: If we're forcing transitions, then ActivateFixedFunction above will take care of all these transitions
  913. if ( !bForce && toState.m_UsingFixedFunction && fromState.m_UsingFixedFunction )
  914. {
  915. const TextureStageShadowState_t& fromTexture = fromState.m_TextureStage[i];
  916. const TextureStageShadowState_t& toTexture = toState.m_TextureStage[i];
  917. bool fromEnabled = (fromTexture.m_ColorOp != D3DTOP_DISABLE);
  918. bool toEnabled = (toTexture.m_ColorOp != D3DTOP_DISABLE);
  919. if ( fromEnabled || toEnabled )
  920. {
  921. bool opDifferent = (toTexture.m_ColorOp != fromTexture.m_ColorOp);
  922. bool arg1Different = (toTexture.m_ColorArg1 != fromTexture.m_ColorArg1);
  923. bool arg2Different = (toTexture.m_ColorArg2 != fromTexture.m_ColorArg2);
  924. if (opDifferent || arg1Different || arg2Different )
  925. {
  926. AddTextureTransition( TEXTURE_STATE_ColorTextureStage, i );
  927. ++numOps;
  928. }
  929. }
  930. fromEnabled = (fromTexture.m_AlphaOp != D3DTOP_DISABLE);
  931. toEnabled = (toTexture.m_AlphaOp != D3DTOP_DISABLE);
  932. if ( fromEnabled || toEnabled )
  933. {
  934. bool opDifferent = (toTexture.m_AlphaOp != fromTexture.m_AlphaOp);
  935. bool arg1Different = (toTexture.m_AlphaArg1 != fromTexture.m_AlphaArg1);
  936. bool arg2Different = (toTexture.m_AlphaArg2 != fromTexture.m_AlphaArg2);
  937. if (opDifferent || arg1Different || arg2Different )
  938. {
  939. AddTextureTransition( TEXTURE_STATE_AlphaTextureStage, i );
  940. ++numOps;
  941. }
  942. }
  943. }
  944. ADD_TEXTURE_STAGE_STATE_TRANSITION( i, TexCoordIndex );
  945. }
  946. int nSamplerCount = HardwareConfig()->GetSamplerCount();
  947. for ( int i = 0; i < nSamplerCount; ++i )
  948. {
  949. ADD_SAMPLER_STATE_TRANSITION( i, SRGBReadEnable );
  950. ADD_SAMPLER_STATE_TRANSITION( i, Fetch4Enable );
  951. #ifdef DX_TO_GL_ABSTRACTION
  952. ADD_SAMPLER_STATE_TRANSITION( i, ShadowFilterEnable );
  953. #endif
  954. }
  955. return numOps;
  956. }
  957. void CTransitionTable::CreateTransitionTableEntry( int to, int from )
  958. {
  959. // You added or removed a state to the enums but not to the function table lists!
  960. COMPILE_TIME_ASSERT( sizeof(s_pRenderFunctionTable) == sizeof(ApplyStateFunc_t) * RENDER_STATE_COUNT );
  961. COMPILE_TIME_ASSERT( sizeof(s_pTextureFunctionTable) == sizeof(ApplyStateFunc_t) * TEXTURE_STATE_COUNT );
  962. // If from < 0, that means add *all* transitions into it.
  963. unsigned int firstElem = m_TransitionOps.Count();
  964. unsigned short numOps = 0;
  965. const ShadowState_t& toState = m_ShadowStateList[to];
  966. const ShadowState_t& fromState = (from >= 0) ? m_ShadowStateList[from] : m_ShadowStateList[to];
  967. bool bForce = (from < 0);
  968. ADD_RENDER_STATE_TRANSITION( ZWriteEnable )
  969. ADD_RENDER_STATE_TRANSITION( ColorWriteEnable )
  970. ADD_RENDER_STATE_TRANSITION( FillMode )
  971. ADD_RENDER_STATE_TRANSITION( Lighting )
  972. ADD_RENDER_STATE_TRANSITION( SpecularEnable )
  973. ADD_RENDER_STATE_TRANSITION( SRGBWriteEnable )
  974. ADD_RENDER_STATE_TRANSITION( DiffuseMaterialSource )
  975. // Some code for the non-trivial transitions
  976. numOps += CreateNormalTransitions( fromState, toState, bForce );
  977. // NOTE: From here on down are transitions that depend on dynamic state
  978. // and which can therefore not appear in the state block
  979. ADD_RENDER_STATE_TRANSITION( CullEnable )
  980. ADD_RENDER_STATE_TRANSITION( EnableAlphaToCoverage )
  981. ADD_RENDER_STATE_TRANSITION( VertexBlendEnable )
  982. // NOTE! : Have to do the extra check for changes in m_UsingFixedFunction
  983. // since d3d fog state is different if you are using fixed function vs.
  984. // using a vsh/psh.
  985. // This code is derived from: ADD_RENDER_STATE_TRANSITION( FogMode )
  986. // If ADD_RENDER_STATE_TRANSITION ever changes, this needs to be updated!
  987. // This is another reason to try to have very little fixed function in the dx8/dx9 path.
  988. if( bForce || (toState.m_FogMode != fromState.m_FogMode ) ||
  989. ( toState.m_UsingFixedFunction != fromState.m_UsingFixedFunction ) )
  990. {
  991. AddTransition( RENDER_STATE_FogMode );
  992. ++numOps;
  993. }
  994. bool bDifferentTexturesEnabled = false;
  995. int nSamplerCount = HardwareConfig()->GetSamplerCount();
  996. for ( int i = 0; i < nSamplerCount; ++i )
  997. {
  998. if ( toState.m_SamplerState[i].m_TextureEnable != fromState.m_SamplerState[i].m_TextureEnable )
  999. {
  1000. bDifferentTexturesEnabled = true;
  1001. break;
  1002. }
  1003. }
  1004. if ( bForce || bDifferentTexturesEnabled )
  1005. {
  1006. AddTransition( RENDER_STATE_TextureEnable );
  1007. ++numOps;
  1008. }
  1009. // Look for identical transition lists, and use those instead...
  1010. TransitionList_t& transition = (from >= 0) ?
  1011. m_TransitionTable[to][from] : m_DefaultTransition;
  1012. Assert( numOps <= 255 );
  1013. transition.m_NumOperations = numOps;
  1014. // This condition can happen, and is valid. It occurs when we snapshot
  1015. // state but do not generate a transition function for that state
  1016. if (numOps == 0)
  1017. {
  1018. transition.m_FirstOperation = INVALID_TRANSITION_OP;
  1019. return;
  1020. }
  1021. // An optimization to try to early out of the identical transition check
  1022. // taking advantage of the fact that the matrix is usually diagonal.
  1023. unsigned int nFirstTest = INVALID_TRANSITION_OP;
  1024. if (from >= 0)
  1025. {
  1026. TransitionList_t &diagonalList = m_TransitionTable[from][to];
  1027. if ( diagonalList.m_NumOperations == numOps )
  1028. {
  1029. nFirstTest = diagonalList.m_FirstOperation;
  1030. }
  1031. }
  1032. unsigned int identicalListFirstElem = FindIdenticalTransitionList( firstElem, numOps, nFirstTest );
  1033. if (identicalListFirstElem == INVALID_TRANSITION_OP)
  1034. {
  1035. transition.m_FirstOperation = firstElem;
  1036. m_UniqueTransitions.Insert( transition );
  1037. Assert( (int)firstElem + (int)numOps < 16777215 );
  1038. if( (int)firstElem + (int)numOps >= 16777215 )
  1039. {
  1040. Warning("**** WARNING: Transition table overflow. Grab Brian\n");
  1041. }
  1042. }
  1043. else
  1044. {
  1045. // Remove the transitions ops we made; use the duplicate copy
  1046. transition.m_FirstOperation = identicalListFirstElem;
  1047. m_TransitionOps.RemoveMultiple( firstElem, numOps );
  1048. }
  1049. }
  1050. //-----------------------------------------------------------------------------
  1051. // Tests a snapshot to see if it can be used
  1052. //-----------------------------------------------------------------------------
  1053. #define PERFORM_RENDER_STATE_TRANSITION( _state, _func ) \
  1054. ::Apply ## _func( _state, 0 );
  1055. #define PERFORM_TEXTURE_STAGE_STATE_TRANSITION( _state, _stage, _func ) \
  1056. ::Apply ## _func( _state, _stage );
  1057. #define PERFORM_SAMPLER_STATE_TRANSITION( _state, _stage, _func ) \
  1058. ::Apply ## _func( _state, _stage );
  1059. bool CTransitionTable::TestShadowState( const ShadowState_t& state, const ShadowShaderState_t &shaderState )
  1060. {
  1061. PERFORM_RENDER_STATE_TRANSITION( state, DepthTest )
  1062. PERFORM_RENDER_STATE_TRANSITION( state, ZWriteEnable )
  1063. PERFORM_RENDER_STATE_TRANSITION( state, ColorWriteEnable )
  1064. PERFORM_RENDER_STATE_TRANSITION( state, AlphaTest )
  1065. PERFORM_RENDER_STATE_TRANSITION( state, FillMode )
  1066. PERFORM_RENDER_STATE_TRANSITION( state, Lighting )
  1067. PERFORM_RENDER_STATE_TRANSITION( state, SpecularEnable )
  1068. PERFORM_RENDER_STATE_TRANSITION( state, SRGBWriteEnable )
  1069. PERFORM_RENDER_STATE_TRANSITION( state, AlphaBlend )
  1070. PERFORM_RENDER_STATE_TRANSITION( state, SeparateAlphaBlend )
  1071. PERFORM_RENDER_STATE_TRANSITION( state, CullEnable )
  1072. PERFORM_RENDER_STATE_TRANSITION( state, AlphaToCoverage )
  1073. PERFORM_RENDER_STATE_TRANSITION( state, VertexBlendEnable )
  1074. PERFORM_RENDER_STATE_TRANSITION( state, FogMode )
  1075. PERFORM_RENDER_STATE_TRANSITION( state, ActivateFixedFunction )
  1076. PERFORM_RENDER_STATE_TRANSITION( state, TextureEnable )
  1077. PERFORM_RENDER_STATE_TRANSITION( state, DiffuseMaterialSource )
  1078. int i;
  1079. int nStageCount = HardwareConfig()->GetTextureStageCount();
  1080. for ( i = 0; i < nStageCount; ++i )
  1081. {
  1082. PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, ColorTextureStage );
  1083. PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, AlphaTextureStage );
  1084. PERFORM_TEXTURE_STAGE_STATE_TRANSITION( state, i, TexCoordIndex );
  1085. }
  1086. int nSamplerCount = HardwareConfig()->GetSamplerCount();
  1087. for ( i = 0; i < nSamplerCount; ++i )
  1088. {
  1089. PERFORM_SAMPLER_STATE_TRANSITION( state, i, SRGBReadEnable );
  1090. PERFORM_SAMPLER_STATE_TRANSITION( state, i, Fetch4Enable );
  1091. #ifdef DX_TO_GL_ABSTRACTION
  1092. PERFORM_SAMPLER_STATE_TRANSITION( state, i, ShadowFilterEnable );
  1093. #endif
  1094. }
  1095. // Just make sure we've got a good snapshot
  1096. RECORD_COMMAND( DX8_VALIDATE_DEVICE, 0 );
  1097. #if !defined( _X360 )
  1098. DWORD numPasses;
  1099. HRESULT hr = Dx9Device()->ValidateDevice( &numPasses );
  1100. bool ok = !FAILED(hr);
  1101. #else
  1102. bool ok = true;
  1103. #endif
  1104. // Now set the board state to match the default state
  1105. ApplyTransition( m_DefaultTransition, m_DefaultStateSnapshot );
  1106. ShaderManager()->SetVertexShader( shaderState.m_VertexShader );
  1107. ShaderManager()->SetPixelShader( shaderState.m_PixelShader );
  1108. return ok;
  1109. }
  1110. //-----------------------------------------------------------------------------
  1111. // Finds identical transition lists and shares them
  1112. //-----------------------------------------------------------------------------
  1113. unsigned int CTransitionTable::FindIdenticalTransitionList( unsigned int firstElem,
  1114. unsigned short numOps, unsigned int nFirstTest ) const
  1115. {
  1116. VPROF("CTransitionTable::FindIdenticalTransitionList");
  1117. // As it turns out, this works most of the time
  1118. if ( nFirstTest != INVALID_TRANSITION_OP )
  1119. {
  1120. const TransitionOp_t *pCurrOp = &m_TransitionOps[firstElem];
  1121. const TransitionOp_t *pTestOp = &m_TransitionOps[nFirstTest];
  1122. if ( !memcmp( pCurrOp, pTestOp, numOps * sizeof(TransitionOp_t) ) )
  1123. return nFirstTest;
  1124. }
  1125. // Look for a common list
  1126. const TransitionOp_t &op = m_TransitionOps[firstElem];
  1127. int nCount = m_UniqueTransitions.Count();
  1128. for ( int i = 0; i < nCount; ++i )
  1129. {
  1130. const TransitionList_t &list = m_UniqueTransitions[i];
  1131. // We can early out here because we've sorted the unique transitions
  1132. // descending by count
  1133. if ( list.m_NumOperations < numOps )
  1134. return INVALID_TRANSITION_OP;
  1135. // If we don't find a match in the first
  1136. int nPotentialMatch;
  1137. int nLastTest = list.m_FirstOperation + list.m_NumOperations - numOps;
  1138. for ( nPotentialMatch = list.m_FirstOperation; nPotentialMatch <= nLastTest; ++nPotentialMatch )
  1139. {
  1140. // Find the first match
  1141. const TransitionOp_t &testOp = m_TransitionOps[nPotentialMatch];
  1142. if ( testOp.m_nBits == op.m_nBits )
  1143. break;
  1144. }
  1145. // No matches found, continue
  1146. if ( nPotentialMatch > nLastTest )
  1147. continue;
  1148. // Ok, found a match of the first op, lets see if they all match
  1149. if ( numOps == 1 )
  1150. return nPotentialMatch;
  1151. const TransitionOp_t *pCurrOp = &m_TransitionOps[firstElem + 1];
  1152. const TransitionOp_t *pTestOp = &m_TransitionOps[nPotentialMatch + 1];
  1153. if ( !memcmp( pCurrOp, pTestOp, (numOps - 1) * sizeof(TransitionOp_t) ) )
  1154. return nPotentialMatch;
  1155. }
  1156. return INVALID_TRANSITION_OP;
  1157. }
  1158. //-----------------------------------------------------------------------------
  1159. // Create startup snapshot
  1160. //-----------------------------------------------------------------------------
  1161. void CTransitionTable::TakeDefaultStateSnapshot( )
  1162. {
  1163. if (m_DefaultStateSnapshot == -1)
  1164. {
  1165. m_DefaultStateSnapshot = TakeSnapshot();
  1166. // This will create a transition which sets *all* shadowed state
  1167. CreateTransitionTableEntry( m_DefaultStateSnapshot, -1 );
  1168. }
  1169. }
  1170. //-----------------------------------------------------------------------------
  1171. // Applies the transition list
  1172. //-----------------------------------------------------------------------------
  1173. void CTransitionTable::ApplyTransitionList( int snapshot, int nFirstOp, int nOpCount )
  1174. {
  1175. VPROF("CTransitionTable::ApplyTransitionList");
  1176. // Don't bother if there's nothing to do
  1177. if (nOpCount > 0)
  1178. {
  1179. // Trying to avoid function overhead here
  1180. ShadowState_t& shadowState = m_ShadowStateList[snapshot];
  1181. TransitionOp_t* pTransitionOp = &m_TransitionOps[nFirstOp];
  1182. for (int i = 0; i < nOpCount; ++i )
  1183. {
  1184. // invoke the transition method
  1185. if ( pTransitionOp->m_nInfo.m_bIsTextureCode )
  1186. {
  1187. TextureStateFunc_t code;
  1188. int nStage;
  1189. GetTextureOp( pTransitionOp->m_nInfo.m_nOpCode, &code, &nStage );
  1190. (*s_pTextureFunctionTable[code])( shadowState, nStage );
  1191. }
  1192. else
  1193. {
  1194. (*s_pRenderFunctionTable[pTransitionOp->m_nInfo.m_nOpCode])( shadowState, 0 );
  1195. }
  1196. ++pTransitionOp;
  1197. }
  1198. }
  1199. }
  1200. //-----------------------------------------------------------------------------
  1201. // Apply startup snapshot
  1202. //-----------------------------------------------------------------------------
  1203. #ifdef _WIN32
  1204. #pragma warning( disable : 4189 )
  1205. #endif
  1206. void CTransitionTable::ApplyTransition( TransitionList_t& list, int snapshot )
  1207. {
  1208. VPROF("CTransitionTable::ApplyTransition");
  1209. if ( g_pShaderDeviceDx8->IsDeactivated() )
  1210. return;
  1211. // Transition lists when using state blocks have 2 parts: the first
  1212. // is the stateblock part, which is states that are not related to
  1213. // dynamic state at all; followed by states that *are* affected by dynamic state
  1214. int nFirstOp = list.m_FirstOperation;
  1215. int nOpCount = list.m_NumOperations;
  1216. ApplyTransitionList( snapshot, nFirstOp, nOpCount );
  1217. // Semi-hacky code to override what the transitions are doing
  1218. PerformShadowStateOverrides();
  1219. // Set the current snapshot id
  1220. m_CurrentShadowId = snapshot;
  1221. #ifdef DEBUG_BOARD_STATE
  1222. // Copy over the board states that aren't explicitly in the transition table
  1223. // so the assertion works...
  1224. int i;
  1225. int nSamplerCount = HardwareConfig()->GetSamplerCount();
  1226. for ( i = nSamplerCount; i < MAX_SAMPLERS; ++i )
  1227. {
  1228. m_BoardState.m_SamplerState[i].m_TextureEnable =
  1229. CurrentShadowState()->m_SamplerState[i].m_TextureEnable;
  1230. }
  1231. int nTextureStageCount = HardwareConfig()->GetTextureStageCount();
  1232. for ( i = nTextureStageCount; i < MAX_TEXTURE_STAGES; ++i )
  1233. {
  1234. memcpy( &m_BoardState.m_TextureStage[i], &CurrentShadowState()->m_TextureStage[i], sizeof(TextureStageShadowState_t) );
  1235. }
  1236. m_BoardState.m_UsingFixedFunction = CurrentShadowState()->m_UsingFixedFunction;
  1237. // State blocks bypass the code that sets the board state
  1238. #ifdef _DEBUG
  1239. // NOTE: A memcmp here isn't enough since we don't set alpha args in cases where the op is nothing.
  1240. // Assert( !memcmp( &m_BoardState, &CurrentShadowState(), sizeof(m_BoardState) ) );
  1241. const ShadowState_t &testState1 = *CurrentShadowState();
  1242. ShadowState_t testState2 = m_BoardState;
  1243. if ( testState1.m_ZEnable == D3DZB_FALSE )
  1244. {
  1245. testState2.m_ZBias = testState1.m_ZBias;
  1246. testState2.m_ZFunc = testState1.m_ZFunc;
  1247. }
  1248. if ( !testState1.m_AlphaTestEnable )
  1249. {
  1250. testState2.m_AlphaRef = testState1.m_AlphaRef;
  1251. testState2.m_AlphaFunc = testState1.m_AlphaFunc;
  1252. }
  1253. for( i = 0; i < nTextureStageCount; i++ )
  1254. {
  1255. if ( !testState1.m_UsingFixedFunction )
  1256. {
  1257. testState2.m_TextureStage[i].m_ColorOp = testState1.m_TextureStage[i].m_ColorOp;
  1258. testState2.m_TextureStage[i].m_ColorArg1 = testState1.m_TextureStage[i].m_ColorArg1;
  1259. testState2.m_TextureStage[i].m_ColorArg2 = testState1.m_TextureStage[i].m_ColorArg2;
  1260. testState2.m_TextureStage[i].m_AlphaOp = testState1.m_TextureStage[i].m_AlphaOp;
  1261. testState2.m_TextureStage[i].m_AlphaArg1 = testState1.m_TextureStage[i].m_AlphaArg1;
  1262. testState2.m_TextureStage[i].m_AlphaArg2 = testState1.m_TextureStage[i].m_AlphaArg2;
  1263. }
  1264. else
  1265. {
  1266. if ( testState1.m_TextureStage[i].m_ColorOp == D3DTOP_DISABLE )
  1267. {
  1268. testState2.m_TextureStage[i].m_ColorArg1 = testState1.m_TextureStage[i].m_ColorArg1;
  1269. testState2.m_TextureStage[i].m_ColorArg2 = testState1.m_TextureStage[i].m_ColorArg2;
  1270. }
  1271. if ( testState1.m_TextureStage[i].m_AlphaOp == D3DTOP_DISABLE )
  1272. {
  1273. testState2.m_TextureStage[i].m_AlphaArg1 = testState1.m_TextureStage[i].m_AlphaArg1;
  1274. testState2.m_TextureStage[i].m_AlphaArg2 = testState1.m_TextureStage[i].m_AlphaArg2;
  1275. }
  1276. }
  1277. }
  1278. Assert( !memcmp( &testState1, &testState2, sizeof( testState1 ) ) );
  1279. #endif
  1280. #endif
  1281. }
  1282. #ifdef _WIN32
  1283. #pragma warning( default : 4189 )
  1284. #endif
  1285. //-----------------------------------------------------------------------------
  1286. // Takes a snapshot, hooks it into the material
  1287. //-----------------------------------------------------------------------------
  1288. StateSnapshot_t CTransitionTable::TakeSnapshot( )
  1289. {
  1290. // Do any final computation of the shadow state
  1291. ShaderShadow()->ComputeAggregateShadowState();
  1292. // Get the current snapshot
  1293. const ShadowState_t& currentState = ShaderShadow()->GetShadowState();
  1294. // Create a new snapshot
  1295. ShadowStateId_t shadowStateId = FindShadowState( currentState );
  1296. if (shadowStateId == -1)
  1297. {
  1298. // Create entry in state transition table
  1299. shadowStateId = CreateShadowState( currentState );
  1300. // Now create new transition entries
  1301. for (int to = 0; to < shadowStateId; ++to)
  1302. {
  1303. CreateTransitionTableEntry( to, shadowStateId );
  1304. }
  1305. for (int from = 0; from < shadowStateId; ++from)
  1306. {
  1307. CreateTransitionTableEntry( shadowStateId, from );
  1308. }
  1309. }
  1310. const ShadowShaderState_t& currentShaderState = ShaderShadow()->GetShadowShaderState();
  1311. StateSnapshot_t snapshotId = FindStateSnapshot( shadowStateId, currentShaderState );
  1312. if (snapshotId == -1)
  1313. {
  1314. // Create entry in state transition table
  1315. snapshotId = CreateStateSnapshot( shadowStateId, currentShaderState );
  1316. }
  1317. return snapshotId;
  1318. }
  1319. //-----------------------------------------------------------------------------
  1320. // Apply shader state (stuff that doesn't lie in the transition table)
  1321. //-----------------------------------------------------------------------------
  1322. void CTransitionTable::ApplyShaderState( const ShadowState_t &shadowState, const ShadowShaderState_t &shaderState )
  1323. {
  1324. VPROF("CTransitionTable::ApplyShaderState");
  1325. // Don't bother testing against the current state because there
  1326. // could well be dynamic state modifiers affecting this too....
  1327. if ( !shadowState.m_UsingFixedFunction )
  1328. {
  1329. // FIXME: Improve early-binding of vertex shader index
  1330. ShaderManager()->SetVertexShader( shaderState.m_VertexShader );
  1331. ShaderManager()->SetPixelShader( shaderState.m_PixelShader );
  1332. #ifdef DEBUG_BOARD_STATE
  1333. BoardShaderState().m_VertexShader = shaderState.m_VertexShader;
  1334. BoardShaderState().m_PixelShader = shaderState.m_PixelShader;
  1335. BoardShaderState().m_nStaticVshIndex = shaderState.m_nStaticVshIndex;
  1336. BoardShaderState().m_nStaticPshIndex = shaderState.m_nStaticPshIndex;
  1337. #endif
  1338. }
  1339. else
  1340. {
  1341. ShaderManager()->SetVertexShader( INVALID_SHADER );
  1342. ShaderManager()->SetPixelShader( INVALID_SHADER );
  1343. #if defined( _X360 )
  1344. // no fixed function support
  1345. Assert( 0 );
  1346. #endif
  1347. #ifdef DEBUG_BOARD_STATE
  1348. BoardShaderState().m_VertexShader = INVALID_SHADER;
  1349. BoardShaderState().m_PixelShader = INVALID_SHADER;
  1350. BoardShaderState().m_nStaticVshIndex = 0;
  1351. BoardShaderState().m_nStaticPshIndex = 0;
  1352. #endif
  1353. }
  1354. }
  1355. //-----------------------------------------------------------------------------
  1356. // Makes the board state match the snapshot
  1357. //-----------------------------------------------------------------------------
  1358. void CTransitionTable::UseSnapshot( StateSnapshot_t snapshotId )
  1359. {
  1360. VPROF("CTransitionTable::UseSnapshot");
  1361. ShadowStateId_t id = m_SnapshotList[snapshotId].m_ShadowStateId;
  1362. if (m_CurrentSnapshotId != snapshotId)
  1363. {
  1364. // First apply things that are in the transition table
  1365. if ( m_CurrentShadowId != id )
  1366. {
  1367. TransitionList_t& transition = m_TransitionTable[id][m_CurrentShadowId];
  1368. ApplyTransition( transition, id );
  1369. }
  1370. // NOTE: There is an opportunity here to set non-dynamic state that we don't
  1371. // store in the transition list if we ever need it.
  1372. m_CurrentSnapshotId = snapshotId;
  1373. }
  1374. // NOTE: This occurs regardless of whether the snapshot changed because it depends
  1375. // on dynamic state (namely, the dynamic vertex + pixel shader index)
  1376. // Followed by things that are not
  1377. ApplyShaderState( m_ShadowStateList[id], m_SnapshotList[snapshotId].m_ShaderState );
  1378. #ifdef _DEBUG
  1379. // NOTE: We can't ship with this active because mod makers may well violate this rule
  1380. // We don't want no stinking fixed-function on hardware that has vertex and pixel shaders. .
  1381. // This could cause a serious perf hit.
  1382. if( HardwareConfig()->SupportsVertexAndPixelShaders() )
  1383. {
  1384. // Assert( !CurrentShadowState().m_UsingFixedFunction );
  1385. }
  1386. #endif
  1387. }
  1388. //-----------------------------------------------------------------------------
  1389. // Cause the board to match the default state snapshot
  1390. //-----------------------------------------------------------------------------
  1391. void CTransitionTable::UseDefaultState( )
  1392. {
  1393. VPROF("CTransitionTable::UseDefaultState");
  1394. // Need to blat these out because they are tested during transitions
  1395. m_CurrentState.m_AlphaBlendEnable = false;
  1396. m_CurrentState.m_SrcBlend = D3DBLEND_ONE;
  1397. m_CurrentState.m_DestBlend = D3DBLEND_ZERO;
  1398. m_CurrentState.m_BlendOp = D3DBLENDOP_ADD;
  1399. SetRenderStateConstMacro( D3DRS_ALPHABLENDENABLE, m_CurrentState.m_AlphaBlendEnable );
  1400. SetRenderStateConstMacro( D3DRS_SRCBLEND, m_CurrentState.m_SrcBlend );
  1401. SetRenderStateConstMacro( D3DRS_DESTBLEND, m_CurrentState.m_DestBlend );
  1402. SetRenderStateConstMacro( D3DRS_BLENDOP, m_CurrentState.m_BlendOp );
  1403. m_CurrentState.m_SeparateAlphaBlendEnable = false;
  1404. m_CurrentState.m_SrcBlendAlpha = D3DBLEND_ONE;
  1405. m_CurrentState.m_DestBlendAlpha = D3DBLEND_ZERO;
  1406. m_CurrentState.m_BlendOpAlpha = D3DBLENDOP_ADD;
  1407. SetRenderStateConstMacro( D3DRS_SEPARATEALPHABLENDENABLE, m_CurrentState.m_SeparateAlphaBlendEnable );
  1408. SetRenderStateConstMacro( D3DRS_SRCBLENDALPHA, m_CurrentState.m_SrcBlendAlpha );
  1409. SetRenderStateConstMacro( D3DRS_DESTBLENDALPHA, m_CurrentState.m_DestBlendAlpha );
  1410. SetRenderStateConstMacro( D3DRS_BLENDOPALPHA, m_CurrentState.m_BlendOpAlpha );
  1411. m_CurrentState.m_ZEnable = D3DZB_TRUE;
  1412. m_CurrentState.m_ZFunc = D3DCMP_LESSEQUAL;
  1413. m_CurrentState.m_ZBias = SHADER_POLYOFFSET_DISABLE;
  1414. SetRenderStateConstMacro( D3DRS_ZENABLE, m_CurrentState.m_ZEnable );
  1415. #if defined( _X360 )
  1416. //SetRenderStateConstMacro( D3DRS_HIZENABLE, m_CurrentState.m_ZEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  1417. #endif
  1418. SetRenderStateConstMacro( D3DRS_ZFUNC, m_CurrentState.m_ZFunc );
  1419. m_CurrentState.m_AlphaTestEnable = false;
  1420. m_CurrentState.m_AlphaFunc = D3DCMP_GREATEREQUAL;
  1421. m_CurrentState.m_AlphaRef = 0;
  1422. SetRenderStateConstMacro( D3DRS_ALPHATESTENABLE, m_CurrentState.m_AlphaTestEnable );
  1423. SetRenderStateConstMacro( D3DRS_ALPHAFUNC, m_CurrentState.m_AlphaFunc );
  1424. SetRenderStateConstMacro( D3DRS_ALPHAREF, m_CurrentState.m_AlphaRef );
  1425. int nTextureStages = ShaderAPI()->GetActualTextureStageCount();
  1426. for ( int i = 0; i < nTextureStages; ++i)
  1427. {
  1428. TextureStage(i).m_ColorOp = D3DTOP_DISABLE;
  1429. TextureStage(i).m_ColorArg1 = D3DTA_TEXTURE;
  1430. TextureStage(i).m_ColorArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT;
  1431. TextureStage(i).m_AlphaOp = D3DTOP_DISABLE;
  1432. TextureStage(i).m_AlphaArg1 = D3DTA_TEXTURE;
  1433. TextureStage(i).m_AlphaArg2 = (i == 0) ? D3DTA_DIFFUSE : D3DTA_CURRENT;
  1434. SetTextureStageState( i, D3DTSS_COLOROP, TextureStage(i).m_ColorOp );
  1435. SetTextureStageState( i, D3DTSS_COLORARG1, TextureStage(i).m_ColorArg1 );
  1436. SetTextureStageState( i, D3DTSS_COLORARG2, TextureStage(i).m_ColorArg2 );
  1437. SetTextureStageState( i, D3DTSS_ALPHAOP, TextureStage(i).m_AlphaOp );
  1438. SetTextureStageState( i, D3DTSS_ALPHAARG1, TextureStage(i).m_AlphaArg1 );
  1439. SetTextureStageState( i, D3DTSS_ALPHAARG2, TextureStage(i).m_AlphaArg2 );
  1440. }
  1441. int nSamplerCount = ShaderAPI()->GetActualSamplerCount();
  1442. for ( int i = 0; i < nSamplerCount; ++i)
  1443. {
  1444. SetSamplerState( i, D3DSAMP_SRGBTEXTURE, SamplerState(i).m_SRGBReadEnable );
  1445. // Set default Fetch4 state on parts which support it
  1446. if ( ShaderAPI()->SupportsFetch4() )
  1447. {
  1448. SetSamplerState( i, ATISAMP_FETCH4, SamplerState(i).m_Fetch4Enable ? ATI_FETCH4_ENABLE : ATI_FETCH4_DISABLE );
  1449. }
  1450. #ifdef DX_TO_GL_ABSTRACTION
  1451. SetSamplerState( i, D3DSAMP_SHADOWFILTER, SamplerState(i).m_ShadowFilterEnable );
  1452. #endif
  1453. }
  1454. // Disable z overrides...
  1455. m_CurrentState.m_bOverrideDepthEnable = false;
  1456. m_CurrentState.m_bOverrideAlphaWriteEnable = false;
  1457. m_CurrentState.m_bOverrideColorWriteEnable = false;
  1458. m_CurrentState.m_ForceDepthFuncEquals = false;
  1459. m_CurrentState.m_bLinearColorSpaceFrameBufferEnable = false;
  1460. ApplyTransition( m_DefaultTransition, m_DefaultStateSnapshot );
  1461. ShaderManager()->SetVertexShader( INVALID_SHADER );
  1462. ShaderManager()->SetPixelShader( INVALID_SHADER );
  1463. m_CurrentSnapshotId = -1;
  1464. }
  1465. //-----------------------------------------------------------------------------
  1466. // Snapshotted state overrides
  1467. //-----------------------------------------------------------------------------
  1468. void CTransitionTable::ForceDepthFuncEquals( bool bEnable )
  1469. {
  1470. if( bEnable != m_CurrentState.m_ForceDepthFuncEquals )
  1471. {
  1472. // Do this so that we can call this from within the rendering code
  1473. // See OverrideDepthEnable + PerformShadowStateOverrides for a version
  1474. // that isn't expected to be called from within rendering code
  1475. if( !ShaderAPI()->IsRenderingMesh() )
  1476. {
  1477. ShaderAPI()->FlushBufferedPrimitives();
  1478. }
  1479. m_CurrentState.m_ForceDepthFuncEquals = bEnable;
  1480. if( bEnable )
  1481. {
  1482. SetZFunc( D3DCMP_EQUAL );
  1483. }
  1484. else
  1485. {
  1486. if ( CurrentShadowState() )
  1487. {
  1488. SetZFunc( CurrentShadowState()->m_ZFunc );
  1489. }
  1490. }
  1491. }
  1492. }
  1493. void CTransitionTable::OverrideDepthEnable( bool bEnable, bool bDepthEnable )
  1494. {
  1495. if ( bEnable != m_CurrentState.m_bOverrideDepthEnable )
  1496. {
  1497. ShaderAPI()->FlushBufferedPrimitives();
  1498. m_CurrentState.m_bOverrideDepthEnable = bEnable;
  1499. m_CurrentState.m_OverrideZWriteEnable = bDepthEnable ? D3DZB_TRUE : D3DZB_FALSE;
  1500. if ( m_CurrentState.m_bOverrideDepthEnable )
  1501. {
  1502. SetZEnable( D3DZB_TRUE );
  1503. SetRenderStateConstMacro( D3DRS_ZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable );
  1504. #if defined( _X360 )
  1505. //SetRenderStateConstMacro( D3DRS_HIZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  1506. #endif
  1507. }
  1508. else
  1509. {
  1510. if ( CurrentShadowState() )
  1511. {
  1512. SetZEnable( CurrentShadowState()->m_ZEnable );
  1513. SetRenderStateConstMacro( D3DRS_ZWRITEENABLE, CurrentShadowState()->m_ZWriteEnable );
  1514. #if defined( _X360 )
  1515. //SetRenderStateConstMacro( D3DRS_HIZWRITEENABLE, CurrentShadowState()->m_ZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  1516. #endif
  1517. }
  1518. }
  1519. }
  1520. }
  1521. void CTransitionTable::OverrideAlphaWriteEnable( bool bOverrideEnable, bool bAlphaWriteEnable )
  1522. {
  1523. if ( bOverrideEnable != m_CurrentState.m_bOverrideAlphaWriteEnable )
  1524. {
  1525. ShaderAPI()->FlushBufferedPrimitives();
  1526. m_CurrentState.m_bOverrideAlphaWriteEnable = bOverrideEnable;
  1527. m_CurrentState.m_bOverriddenAlphaWriteValue = bAlphaWriteEnable;
  1528. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable;
  1529. if ( m_CurrentState.m_bOverrideAlphaWriteEnable )
  1530. {
  1531. if( m_CurrentState.m_bOverriddenAlphaWriteValue )
  1532. {
  1533. dwSetValue |= D3DCOLORWRITEENABLE_ALPHA;
  1534. }
  1535. else
  1536. {
  1537. dwSetValue &= ~D3DCOLORWRITEENABLE_ALPHA;
  1538. }
  1539. }
  1540. else
  1541. {
  1542. if ( CurrentShadowState() )
  1543. {
  1544. //probably being paranoid, but only copy the alpha flag from the shadow state
  1545. dwSetValue &= ~D3DCOLORWRITEENABLE_ALPHA;
  1546. dwSetValue |= CurrentShadowState()->m_ColorWriteEnable & D3DCOLORWRITEENABLE_ALPHA;
  1547. }
  1548. }
  1549. if( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1550. {
  1551. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1552. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1553. }
  1554. }
  1555. }
  1556. void CTransitionTable::OverrideColorWriteEnable( bool bOverrideEnable, bool bColorWriteEnable )
  1557. {
  1558. if ( bOverrideEnable != m_CurrentState.m_bOverrideColorWriteEnable )
  1559. {
  1560. ShaderAPI()->FlushBufferedPrimitives();
  1561. m_CurrentState.m_bOverrideColorWriteEnable = bOverrideEnable;
  1562. m_CurrentState.m_bOverriddenColorWriteValue = bColorWriteEnable;
  1563. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable;
  1564. if ( m_CurrentState.m_bOverrideColorWriteEnable )
  1565. {
  1566. if( m_CurrentState.m_bOverriddenColorWriteValue )
  1567. {
  1568. dwSetValue |= (D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1569. }
  1570. else
  1571. {
  1572. dwSetValue &= ~(D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1573. }
  1574. }
  1575. else
  1576. {
  1577. if ( CurrentShadowState() )
  1578. {
  1579. //probably being paranoid, but only copy the alpha flag from the shadow state
  1580. dwSetValue &= ~(D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1581. dwSetValue |= CurrentShadowState()->m_ColorWriteEnable & (D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1582. }
  1583. }
  1584. if( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1585. {
  1586. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1587. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1588. }
  1589. }
  1590. }
  1591. void CTransitionTable::EnableLinearColorSpaceFrameBuffer( bool bEnable )
  1592. {
  1593. if ( m_CurrentState.m_bLinearColorSpaceFrameBufferEnable != bEnable && CurrentShadowState() )
  1594. {
  1595. ShaderAPI()->FlushBufferedPrimitives();
  1596. m_CurrentState.m_bLinearColorSpaceFrameBufferEnable = bEnable;
  1597. ApplySRGBWriteEnable( *CurrentShadowState() );
  1598. }
  1599. }
  1600. //-----------------------------------------------------------------------------
  1601. // Perform state block overrides
  1602. //-----------------------------------------------------------------------------
  1603. void CTransitionTable::PerformShadowStateOverrides( )
  1604. {
  1605. VPROF("CTransitionTable::PerformShadowStateOverrides");
  1606. // Deal with funky overrides here, because the state blocks can't...
  1607. if ( m_CurrentState.m_ForceDepthFuncEquals )
  1608. {
  1609. SetZFunc( D3DCMP_EQUAL );
  1610. }
  1611. if ( m_CurrentState.m_bOverrideDepthEnable )
  1612. {
  1613. SetZEnable( D3DZB_TRUE );
  1614. SetRenderStateConstMacro( D3DRS_ZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable );
  1615. #if defined( _X360 )
  1616. //SetRenderStateConstMacro( D3DRS_HIZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  1617. #endif
  1618. }
  1619. if ( m_CurrentState.m_bOverrideAlphaWriteEnable )
  1620. {
  1621. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable & ~D3DCOLORWRITEENABLE_ALPHA;
  1622. dwSetValue |= m_CurrentState.m_bOverriddenAlphaWriteValue ? D3DCOLORWRITEENABLE_ALPHA : 0;
  1623. if ( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1624. {
  1625. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1626. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1627. }
  1628. }
  1629. if ( m_CurrentState.m_bOverrideColorWriteEnable )
  1630. {
  1631. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable & ~(D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1632. dwSetValue |= m_CurrentState.m_bOverriddenColorWriteValue ? (D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE) : 0;
  1633. if ( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1634. {
  1635. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1636. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1637. }
  1638. }
  1639. }