Counter Strike : Global Offensive Source Code
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.

1317 lines
48 KiB

  1. //===== Copyright 1996-2005, 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. #include "shaderapi_global.h"
  20. #include "materialsystem/materialsystem_config.h"
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. enum
  24. {
  25. TEXTURE_STAGE_BIT_COUNT = 4,
  26. TEXTURE_STAGE_MAX_STAGE = 1 << TEXTURE_STAGE_BIT_COUNT,
  27. TEXTURE_STAGE_MASK = TEXTURE_STAGE_MAX_STAGE - 1,
  28. TEXTURE_OP_BIT_COUNT = 7 - TEXTURE_STAGE_BIT_COUNT,
  29. TEXTURE_OP_SHIFT = TEXTURE_STAGE_BIT_COUNT,
  30. TEXTURE_OP_MASK = ((1 << TEXTURE_OP_BIT_COUNT) - 1) << TEXTURE_OP_SHIFT,
  31. };
  32. //-----------------------------------------------------------------------------
  33. // Singleton
  34. //-----------------------------------------------------------------------------
  35. CTransitionTable *g_pTransitionTable = NULL;
  36. #ifdef DEBUG_BOARD_STATE
  37. inline ShadowState_t& BoardState()
  38. {
  39. return g_pTransitionTable->BoardState();
  40. }
  41. #endif
  42. inline CTransitionTable::CurrentState_t& CurrentState()
  43. {
  44. return g_pTransitionTable->CurrentState();
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Less functions
  48. //-----------------------------------------------------------------------------
  49. bool CTransitionTable::ShadowStateDictLessFunc::Less( const CTransitionTable::ShadowStateDictEntry_t &src1, const CTransitionTable::ShadowStateDictEntry_t &src2, void *pCtx )
  50. {
  51. return src1.m_nChecksum < src2.m_nChecksum;
  52. }
  53. bool CTransitionTable::SnapshotDictLessFunc::Less( const CTransitionTable::SnapshotDictEntry_t &src1, const CTransitionTable::SnapshotDictEntry_t &src2, void *pCtx )
  54. {
  55. return src1.m_nChecksum < src2.m_nChecksum;
  56. }
  57. bool CTransitionTable::UniqueSnapshotLessFunc::Less( const CTransitionTable::TransitionList_t &src1, const CTransitionTable::TransitionList_t &src2, void *pCtx )
  58. {
  59. return src1.m_NumOperations > src2.m_NumOperations;
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Constructor, destructor
  63. //-----------------------------------------------------------------------------
  64. CTransitionTable::CTransitionTable() : m_DefaultStateSnapshot(-1),
  65. m_CurrentShadowId(-1), m_CurrentSnapshotId(-1), m_TransitionOps( 0, 8192 ), m_ShadowStateList( 0, 256 ),
  66. m_TransitionTable( 0, 256 ), m_SnapshotList( 0, 256 ),
  67. m_ShadowStateDict(0, 256 ),
  68. m_SnapshotDict( 0, 256 ),
  69. m_UniqueTransitions( 0, 4096 ),
  70. m_bShadowDepthBiasValuesDirty( false )
  71. {
  72. Assert( !g_pTransitionTable );
  73. g_pTransitionTable = this;
  74. #ifdef DEBUG_BOARD_STATE
  75. memset( &m_BoardState, 0, sizeof( m_BoardState ) );
  76. memset( &m_BoardShaderState, 0, sizeof( m_BoardShaderState ) );
  77. #endif
  78. }
  79. CTransitionTable::~CTransitionTable()
  80. {
  81. Assert( g_pTransitionTable == this );
  82. g_pTransitionTable = NULL;
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Initialization, shutdown
  86. //-----------------------------------------------------------------------------
  87. bool CTransitionTable::Init( )
  88. {
  89. return true;
  90. }
  91. void CTransitionTable::Shutdown( )
  92. {
  93. Reset();
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Creates a shadow, adding an entry into the shadow list and transition table
  97. //-----------------------------------------------------------------------------
  98. StateSnapshot_t CTransitionTable::CreateStateSnapshot( ShadowStateId_t shadowStateId, const ShadowShaderState_t& currentShaderState )
  99. {
  100. StateSnapshot_t snapshotId = m_SnapshotList.AddToTail();
  101. // Copy our snapshot into the list
  102. SnapshotShaderState_t &shaderState = m_SnapshotList[snapshotId];
  103. shaderState.m_ShadowStateId = shadowStateId;
  104. memcpy( &shaderState.m_ShaderState, &currentShaderState, sizeof(ShadowShaderState_t) );
  105. shaderState.m_nReserved = 0; // needed to get a good CRC
  106. shaderState.m_nReserved2 = 0;
  107. // Insert entry into the lookup table
  108. SnapshotDictEntry_t insert;
  109. CRC32_Init( &insert.m_nChecksum );
  110. CRC32_ProcessBuffer( &insert.m_nChecksum, &shaderState, sizeof(SnapshotShaderState_t) );
  111. CRC32_Final( &insert.m_nChecksum );
  112. insert.m_nSnapshot = snapshotId;
  113. m_SnapshotDict.Insert( insert );
  114. return snapshotId;
  115. }
  116. //-----------------------------------------------------------------------------
  117. // Creates a shadow, adding an entry into the shadow list and transition table
  118. //-----------------------------------------------------------------------------
  119. CTransitionTable::ShadowStateId_t CTransitionTable::CreateShadowState( const ShadowState_t &currentState )
  120. {
  121. int newShaderState = m_ShadowStateList.AddToTail();
  122. // Copy our snapshot into the list
  123. memcpy( &m_ShadowStateList[newShaderState], &currentState, sizeof(ShadowState_t) );
  124. // all existing states must transition to the new state
  125. int i;
  126. for ( i = 0; i < newShaderState; ++i )
  127. {
  128. // Add a new transition to all existing states
  129. int newElem = m_TransitionTable[i].AddToTail();
  130. m_TransitionTable[i][newElem].m_FirstOperation = INVALID_TRANSITION_OP;
  131. m_TransitionTable[i][newElem].m_NumOperations = 0;
  132. }
  133. // Add a new vector for this transition
  134. int newTransitionElem = m_TransitionTable.AddToTail();
  135. m_TransitionTable[newTransitionElem].EnsureCapacity( 32 );
  136. Assert( newShaderState == newTransitionElem );
  137. for ( i = 0; i <= newShaderState; ++i )
  138. {
  139. // Add a new transition from all existing states
  140. int newElem = m_TransitionTable[newShaderState].AddToTail();
  141. m_TransitionTable[newShaderState][newElem].m_FirstOperation = INVALID_TRANSITION_OP;
  142. m_TransitionTable[newShaderState][newElem].m_NumOperations = 0;
  143. }
  144. // Insert entry into the lookup table
  145. ShadowStateDictEntry_t insert;
  146. CRC32_Init( &insert.m_nChecksum );
  147. CRC32_ProcessBuffer( &insert.m_nChecksum, &m_ShadowStateList[newShaderState], sizeof(ShadowState_t) );
  148. CRC32_Final( &insert.m_nChecksum );
  149. insert.m_nShadowStateId = newShaderState;
  150. m_ShadowStateDict.Insert( insert );
  151. return newShaderState;
  152. }
  153. //-----------------------------------------------------------------------------
  154. // Finds a snapshot, if it exists. Or creates a new one if it doesn't.
  155. //-----------------------------------------------------------------------------
  156. CTransitionTable::ShadowStateId_t CTransitionTable::FindShadowState( const ShadowState_t& currentState ) const
  157. {
  158. ShadowStateDictEntry_t find;
  159. CRC32_Init( &find.m_nChecksum );
  160. CRC32_ProcessBuffer( &find.m_nChecksum, &currentState, sizeof(ShadowState_t) );
  161. CRC32_Final( &find.m_nChecksum );
  162. int nDictCount = m_ShadowStateDict.Count();
  163. int i = m_ShadowStateDict.FindLessOrEqual( find );
  164. if ( i < 0 )
  165. return (ShadowStateId_t)-1;
  166. for ( ; i < nDictCount; ++i )
  167. {
  168. const ShadowStateDictEntry_t &entry = m_ShadowStateDict[i];
  169. // Didn't find a match
  170. if ( entry.m_nChecksum > find.m_nChecksum )
  171. break;
  172. if ( entry.m_nChecksum != find.m_nChecksum )
  173. continue;
  174. ShadowStateId_t nShadowState = entry.m_nShadowStateId;
  175. if (!memcmp(&m_ShadowStateList[nShadowState], &currentState, sizeof(ShadowState_t) ))
  176. return nShadowState;
  177. }
  178. // Need to create a new one
  179. return (ShadowStateId_t)-1;
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Finds a snapshot, if it exists. Or creates a new one if it doesn't.
  183. //-----------------------------------------------------------------------------
  184. StateSnapshot_t CTransitionTable::FindStateSnapshot( ShadowStateId_t id, const ShadowShaderState_t& currentState ) const
  185. {
  186. SnapshotShaderState_t temp;
  187. temp.m_ShaderState = currentState;
  188. temp.m_ShadowStateId = id;
  189. temp.m_nReserved = 0; // needed to get a good CRC
  190. temp.m_nReserved2 = 0;
  191. SnapshotDictEntry_t find;
  192. CRC32_Init( &find.m_nChecksum );
  193. CRC32_ProcessBuffer( &find.m_nChecksum, &temp, sizeof(temp) );
  194. CRC32_Final( &find.m_nChecksum );
  195. int nDictCount = m_SnapshotDict.Count();
  196. int i = m_SnapshotDict.FindLessOrEqual( find );
  197. if ( i < 0 )
  198. return (StateSnapshot_t)-1;
  199. for ( ; i < nDictCount; ++i )
  200. {
  201. // Didn't find a match
  202. if ( m_SnapshotDict[i].m_nChecksum > find.m_nChecksum )
  203. break;
  204. if ( m_SnapshotDict[i].m_nChecksum != find.m_nChecksum )
  205. continue;
  206. StateSnapshot_t nShapshot = m_SnapshotDict[i].m_nSnapshot;
  207. if ( (id == m_SnapshotList[nShapshot].m_ShadowStateId) &&
  208. !memcmp(&m_SnapshotList[nShapshot].m_ShaderState, &currentState, sizeof(ShadowShaderState_t)) )
  209. {
  210. return nShapshot;
  211. }
  212. }
  213. // Need to create a new one
  214. return (StateSnapshot_t)-1;
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Used to clear the transition table when we know it's become invalid.
  218. //-----------------------------------------------------------------------------
  219. void CTransitionTable::Reset()
  220. {
  221. m_ShadowStateList.RemoveAll();
  222. m_SnapshotList.RemoveAll();
  223. m_TransitionTable.RemoveAll();
  224. m_TransitionOps.RemoveAll();
  225. m_ShadowStateDict.RemoveAll();
  226. m_SnapshotDict.RemoveAll();
  227. m_UniqueTransitions.RemoveAll();
  228. m_CurrentShadowId = -1;
  229. m_CurrentSnapshotId = -1;
  230. m_DefaultStateSnapshot = -1;
  231. }
  232. //-----------------------------------------------------------------------------
  233. // Sets the texture stage state
  234. //-----------------------------------------------------------------------------
  235. #ifdef _WIN32
  236. #pragma warning( disable : 4189 )
  237. #endif
  238. static inline void SetTextureStageState( int stage, D3DTEXTURESTAGESTATETYPE state, DWORD val )
  239. {
  240. #if !defined( _X360 )
  241. Assert( !g_pShaderDeviceDx8->IsDeactivated() );
  242. Dx9Device()->SetTextureStageState( stage, state, val );
  243. #endif
  244. }
  245. //Moved to a #define so every instance of this skips unsupported render states at compile time
  246. #define SetSamplerState( _stage, _state, _val ) \
  247. { \
  248. if ( (_state != D3DSAMP_NOTSUPPORTED) ) \
  249. { \
  250. Assert( !g_pShaderDeviceDx8->IsDeactivated() ); \
  251. Dx9Device()->SetSamplerState( _stage, _state, _val ); \
  252. } \
  253. }
  254. //Moved to a #define so every instance of this skips unsupported render states at compile time
  255. #define SetRenderState( _state, _val ) \
  256. { \
  257. if ( _state != D3DRS_NOTSUPPORTED ) \
  258. { \
  259. Assert( !g_pShaderDeviceDx8->IsDeactivated() ); \
  260. Dx9Device()->SetRenderState( _state, _val ); \
  261. } \
  262. }
  263. #ifdef DX_TO_GL_ABSTRACTION
  264. #define SetRenderStateConstMacro( state, val ) { if ( state != D3DRS_NOTSUPPORTED ) Dx9Device()->SetRenderStateConstInline( state, val ); }
  265. #else
  266. #define SetRenderStateConstMacro( state, val ) SetRenderState( state, val )
  267. #endif
  268. #ifdef _WIN32
  269. #pragma warning( default : 4189 )
  270. #endif
  271. //-----------------------------------------------------------------------------
  272. // Methods that actually apply the state
  273. //-----------------------------------------------------------------------------
  274. #ifdef DEBUG_BOARD_STATE
  275. static bool g_SpewTransitions = false;
  276. #define UPDATE_BOARD_RENDER_STATE( _d3dState, _state ) \
  277. { \
  278. BoardState().m_ ## _state = shaderState.m_ ## _state; \
  279. if (g_SpewTransitions) \
  280. { \
  281. char buf[128]; \
  282. sprintf( buf, "Apply %s : %d\n", #_d3dState, shaderState.m_ ## _state ); \
  283. Plat_DebugString(buf); \
  284. } \
  285. }
  286. #define UPDATE_BOARD_RENDER_STATE_ALPHATEST_AND_MISC( _d3dState, _state ) \
  287. { \
  288. BoardState().m_AlphaTestAndMiscState.m_ ## _state = shaderState.m_AlphaTestAndMiscState.m_ ## _state; \
  289. if (g_SpewTransitions) \
  290. { \
  291. char buf[128]; \
  292. sprintf( buf, "Apply %s : %d\n", #_d3dState, shaderState.m_AlphaTestAndMiscState.m_ ## _state ); \
  293. Plat_DebugString(buf); \
  294. } \
  295. }
  296. #define UPDATE_BOARD_TEXTURE_STAGE_STATE( _d3dState, _state, _stage ) \
  297. { \
  298. BoardState().m_TextureStage[_stage].m_ ## _state = shaderState.m_TextureStage[_stage].m_ ## _state; \
  299. if (g_SpewTransitions) \
  300. { \
  301. char buf[128]; \
  302. sprintf( buf, "Apply Tex %s (%d): %d\n", #_d3dState, _stage, shaderState.m_TextureStage[_stage].m_ ## _state ); \
  303. Plat_DebugString(buf); \
  304. } \
  305. }
  306. #define UPDATE_BOARD_SAMPLER_STATE( _d3dState, _state, _stage ) \
  307. { \
  308. BoardState().m_n ## _state = BoardState().m_n ## _state & ~( 1 << _stage ) | ( shaderState.m_n ## _state & ( 1 << _stage ) ); \
  309. if (g_SpewTransitions) \
  310. { \
  311. char buf[128]; \
  312. sprintf( buf, "Apply SamplerSate %s (%d): %d\n", #_d3dState, stage, 0 != (shaderState.m_n ## _state & ( 1 << _stage ) ) ); \
  313. Plat_DebugString(buf); \
  314. } \
  315. }
  316. #else
  317. #define UPDATE_BOARD_RENDER_STATE( _d3dState, _state ) {}
  318. #define UPDATE_BOARD_RENDER_STATE_ALPHATEST_AND_MISC( _d3dState, _state ) {}
  319. #define UPDATE_BOARD_TEXTURE_STAGE_STATE( _d3dState, _state, _stage ) {}
  320. #define UPDATE_BOARD_SAMPLER_STATE( _d3dState, _state, _stage ) {}
  321. #endif
  322. #define APPLY_RENDER_STATE_FUNC( _d3dState, _state ) \
  323. void Apply ## _state( const ShadowState_t& shaderState, int arg ) \
  324. { \
  325. SetRenderState( _d3dState, shaderState.m_ ## _state ); \
  326. UPDATE_BOARD_RENDER_STATE( _d3dState, _state ); \
  327. }
  328. #define APPLY_RENDER_STATE_FUNC_ALPHATEST_AND_MISC( _d3dState, _state ) \
  329. void Apply ## _state( const ShadowState_t& shaderState, int arg ) \
  330. { \
  331. SetRenderState( _d3dState, shaderState.m_AlphaTestAndMiscState.m_ ## _state ); \
  332. UPDATE_BOARD_RENDER_STATE_ALPHATEST_AND_MISC( _d3dState, _state ); \
  333. }
  334. #define APPLY_TEXTURE_STAGE_STATE_FUNC( _d3dState, _state ) \
  335. void Apply ## _state( const ShadowState_t& shaderState, int stage ) \
  336. { \
  337. SetTextureStageState( stage, _d3dState, shaderState.m_TextureStage[stage].m_ ## _state ); \
  338. UPDATE_BOARD_TEXTURE_STAGE_STATE( _d3dState, _state, stage ); \
  339. }
  340. #define APPLY_SAMPLER_STATE_FUNC( _d3dState, _state ) \
  341. void Apply ## _state( const ShadowState_t& shaderState, int stage ) \
  342. { \
  343. SetSamplerState( stage, _d3dState, shaderState.m_SamplerState[stage].m_ ## _state ); \
  344. UPDATE_BOARD_SAMPLER_STATE( _d3dState, _state, stage ); \
  345. }
  346. // Special overridden sampler state to turn on Fetch4 on ATI hardware (and 360?)
  347. void ApplyFetch4Enable( const ShadowState_t& shaderState, int stage )
  348. {
  349. if ( HardwareConfig()->SupportsFetch4() )
  350. {
  351. SetSamplerState( stage, ATISAMP_FETCH4, shaderState.m_nFetch4Enable & ( 1 << stage ) ? ATI_FETCH4_ENABLE : ATI_FETCH4_DISABLE );
  352. }
  353. UPDATE_BOARD_SAMPLER_STATE( ATISAMP_FETCH4, Fetch4Enable, stage );
  354. }
  355. #ifdef DX_TO_GL_ABSTRACTION
  356. void ApplyShadowFilterEnable( const ShadowState_t& shaderState, int stage )
  357. {
  358. SetSamplerState( stage, D3DSAMP_SHADOWFILTER, shaderState.m_nShadowFilterEnable & ( 1 << stage ) );
  359. UPDATE_BOARD_SAMPLER_STATE( D3DSAMP_SHADOWFILTER, ShadowFilterEnable, stage );
  360. }
  361. #endif
  362. //APPLY_RENDER_STATE_FUNC( D3DRS_ZWRITEENABLE, ZWriteEnable )
  363. //APPLY_RENDER_STATE_FUNC( D3DRS_COLORWRITEENABLE, ColorWriteEnable )
  364. APPLY_RENDER_STATE_FUNC_ALPHATEST_AND_MISC( D3DRS_FILLMODE, FillMode )
  365. void ApplyZWriteEnable( const ShadowState_t& shaderState, int arg )
  366. {
  367. SetRenderState( D3DRS_ZWRITEENABLE, shaderState.m_DepthTestState.m_ZWriteEnable );
  368. #if defined( _X360 )
  369. //SetRenderState( D3DRS_HIZWRITEENABLE, shaderState.m_ZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  370. #endif
  371. #ifdef DEBUG_BOARD_STATE
  372. BoardState().m_DepthTestState.m_ZWriteEnable = shaderState.m_DepthTestState.m_ZWriteEnable;
  373. #endif
  374. }
  375. void ApplyColorWriteEnable( const ShadowState_t& shaderState, int arg )
  376. {
  377. SetRenderState( D3DRS_COLORWRITEENABLE, shaderState.m_DepthTestState.m_ColorWriteEnable );
  378. g_pTransitionTable->CurrentState().m_ColorWriteEnable = shaderState.m_DepthTestState.m_ColorWriteEnable;
  379. #ifdef DEBUG_BOARD_STATE
  380. BoardState().m_DepthTestState.m_ColorWriteEnable = shaderState.m_DepthTestState.m_ColorWriteEnable;
  381. #endif
  382. }
  383. void ApplySRGBWriteEnable( const ShadowState_t& shadowState, int stageUnused )
  384. {
  385. g_pTransitionTable->ApplySRGBWriteEnable( shadowState );
  386. }
  387. void CTransitionTable::ApplySRGBWriteEnable( const ShadowState_t& shaderState )
  388. {
  389. // ApplySRGBWriteEnable set to true means that the shader is writing linear values.
  390. if ( CurrentState().m_bLinearColorSpaceFrameBufferEnable )
  391. {
  392. // The shader had better be writing linear values since we can't convert to gamma here.
  393. // Can't leave this assert here since there are cases where the shader is doing the right thing.
  394. // This is good to test occasionally to make sure that the shaders are doing the right thing.
  395. // Assert( shaderState.m_SRGBWriteEnable );
  396. // render target is linear
  397. SetRenderState( D3DRS_SRGBWRITEENABLE, 0 );
  398. ShaderAPI()->EnabledSRGBWrite( false );
  399. // fog isn't fixed-function with linear frame buffers, so don't bother with that here.
  400. }
  401. else
  402. {
  403. // render target is gamma
  404. // SRGBWrite enable can affect the space in which fog color is defined
  405. if ( HardwareConfig()->NeedsShaderSRGBConversion() )
  406. {
  407. if ( HardwareConfig()->GetDXSupportLevel() >= 92 ) //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.
  408. {
  409. SetRenderState( D3DRS_SRGBWRITEENABLE, 0 );
  410. }
  411. else
  412. {
  413. SetRenderState( D3DRS_SRGBWRITEENABLE, shaderState.m_FogAndMiscState.m_SRGBWriteEnable );
  414. }
  415. }
  416. else
  417. {
  418. SetRenderState( D3DRS_SRGBWRITEENABLE, shaderState.m_FogAndMiscState.m_SRGBWriteEnable );
  419. }
  420. ShaderAPI()->EnabledSRGBWrite( shaderState.m_FogAndMiscState.m_SRGBWriteEnable );
  421. if ( HardwareConfig()->SpecifiesFogColorInLinearSpace() )
  422. {
  423. ShaderAPI()->ApplyFogMode( shaderState.m_FogAndMiscState.FogMode(), shaderState.m_FogAndMiscState.m_bVertexFogEnable, shaderState.m_FogAndMiscState.m_SRGBWriteEnable, shaderState.m_FogAndMiscState.m_bDisableFogGammaCorrection );
  424. }
  425. }
  426. #ifdef _DEBUG
  427. BoardState().m_FogAndMiscState.m_SRGBWriteEnable = shaderState.m_FogAndMiscState.m_SRGBWriteEnable;
  428. if (g_SpewTransitions)
  429. {
  430. char buf[128];
  431. sprintf( buf, "Apply %s : %d\n", "D3DRS_SRGBWRITEENABLE", shaderState.m_FogAndMiscState.m_SRGBWriteEnable );
  432. Plat_DebugString(buf);
  433. }
  434. #endif
  435. }
  436. void ApplyDisableFogGammaCorrection( const ShadowState_t& shadowState, int stageUnused )
  437. {
  438. ShaderAPI()->ApplyFogMode( shadowState.m_FogAndMiscState.FogMode(), shadowState.m_FogAndMiscState.m_bVertexFogEnable, shadowState.m_FogAndMiscState.m_SRGBWriteEnable, shadowState.m_FogAndMiscState.m_bDisableFogGammaCorrection );
  439. #ifdef DEBUG_BOARD_STATE
  440. g_pTransitionTable->BoardState().m_FogAndMiscState.m_bDisableFogGammaCorrection = shadowState.m_FogAndMiscState.m_bDisableFogGammaCorrection;
  441. #endif
  442. }
  443. void ApplyDepthTest( const ShadowState_t& state, int stage )
  444. {
  445. g_pTransitionTable->ApplyDepthTest( state );
  446. }
  447. void CTransitionTable::SetZEnable( D3DZBUFFERTYPE nEnable )
  448. {
  449. SetRenderState( D3DRS_ZENABLE, nEnable );
  450. #if defined( _X360 )
  451. //SetRenderState( D3DRS_HIZENABLE, nEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  452. #endif
  453. }
  454. void CTransitionTable::SetZFunc( D3DCMPFUNC nCmpFunc )
  455. {
  456. SetRenderState( D3DRS_ZFUNC, nCmpFunc );
  457. }
  458. void CTransitionTable::ApplyDepthTest( const ShadowState_t& state )
  459. {
  460. if ( m_CurrentState.m_nDepthTestStateAsInt != state.m_nDepthTestStateAsInt )
  461. {
  462. SetZEnable( ( D3DZBUFFERTYPE ) state.m_DepthTestState.m_ZEnable );
  463. if (state.m_DepthTestState.m_ZEnable != D3DZB_FALSE)
  464. {
  465. SetZFunc( ( D3DCMPFUNC ) state.m_DepthTestState.m_ZFunc );
  466. }
  467. if ( ( state.m_DepthTestState.m_ZBias == SHADER_POLYOFFSET_SHADOW_BIAS ) && m_bShadowDepthBiasValuesDirty )
  468. {
  469. ShaderAPI()->ApplyZBias( state.m_DepthTestState );
  470. }
  471. #ifdef DEBUG_BOARD_STATE
  472. // This isn't quite true, but it's necessary for other error checking to work
  473. BoardState().m_DepthTestState = state.m_DepthTestState;
  474. #endif
  475. m_CurrentState.m_nDepthTestStateAsInt = state.m_nDepthTestStateAsInt;
  476. }
  477. }
  478. void ApplyAlphaTest( const ShadowState_t& state, int stage )
  479. {
  480. g_pTransitionTable->ApplyAlphaTest( state );
  481. }
  482. void CTransitionTable::ApplyAlphaTest( const ShadowState_t& state )
  483. {
  484. SetRenderState( D3DRS_ALPHATESTENABLE, state.m_AlphaTestAndMiscState.m_AlphaTestEnable );
  485. // Set the blend state here...
  486. SetRenderState( D3DRS_ALPHAFUNC, state.m_AlphaTestAndMiscState.m_AlphaFunc );
  487. SetRenderState( D3DRS_ALPHAREF, state.m_AlphaTestAndMiscState.m_AlphaRef );
  488. #ifdef DEBUG_BOARD_STATE
  489. // This isn't quite true, but it's necessary for other error checking to work
  490. BoardState().m_AlphaTestAndMiscState = state.m_AlphaTestAndMiscState;
  491. #endif
  492. }
  493. void ApplyAlphaBlend( const ShadowState_t& state, int stage )
  494. {
  495. g_pTransitionTable->ApplyAlphaBlend( state );
  496. }
  497. void CTransitionTable::ApplyAlphaBlend( const ShadowState_t& state )
  498. {
  499. if (m_CurrentState.m_AlphaBlendState.m_AlphaBlendEnable != state.m_AlphaBlendState.m_AlphaBlendEnable)
  500. {
  501. SetRenderState( D3DRS_ALPHABLENDENABLE, state.m_AlphaBlendState.m_AlphaBlendEnable );
  502. m_CurrentState.m_AlphaBlendState.m_AlphaBlendEnable = state.m_AlphaBlendState.m_AlphaBlendEnable;
  503. }
  504. if (state.m_AlphaBlendState.m_AlphaBlendEnable)
  505. {
  506. // Set the blend state here...
  507. if (m_CurrentState.m_AlphaBlendState.m_SrcBlend != state.m_AlphaBlendState.m_SrcBlend)
  508. {
  509. SetRenderState( D3DRS_SRCBLEND, state.m_AlphaBlendState.m_SrcBlend );
  510. m_CurrentState.m_AlphaBlendState.m_SrcBlend = state.m_AlphaBlendState.m_SrcBlend;
  511. }
  512. if (m_CurrentState.m_AlphaBlendState.m_DestBlend != state.m_AlphaBlendState.m_DestBlend)
  513. {
  514. SetRenderState( D3DRS_DESTBLEND, state.m_AlphaBlendState.m_DestBlend );
  515. m_CurrentState.m_AlphaBlendState.m_DestBlend = state.m_AlphaBlendState.m_DestBlend;
  516. }
  517. if (m_CurrentState.m_AlphaBlendState.m_BlendOp != state.m_AlphaBlendState.m_BlendOp )
  518. {
  519. SetRenderState( D3DRS_BLENDOP, state.m_AlphaBlendState.m_BlendOp );
  520. m_CurrentState.m_AlphaBlendState.m_BlendOp = state.m_AlphaBlendState.m_BlendOp;
  521. }
  522. }
  523. #ifdef DEBUG_BOARD_STATE
  524. // This isn't quite true, but it's necessary for other error checking to work
  525. BoardState().m_AlphaBlendState.m_AlphaBlendEnable = state.m_AlphaBlendState.m_AlphaBlendEnable;
  526. BoardState().m_AlphaBlendState.m_AlphaBlendEnabledForceOpaque = state.m_AlphaBlendState.m_AlphaBlendEnabledForceOpaque;
  527. BoardState().m_AlphaBlendState.m_SrcBlend = state.m_AlphaBlendState.m_SrcBlend;
  528. BoardState().m_AlphaBlendState.m_DestBlend = state.m_AlphaBlendState.m_DestBlend;
  529. BoardState().m_AlphaBlendState.m_BlendOp = state.m_AlphaBlendState.m_BlendOp;
  530. #endif
  531. }
  532. void ApplySeparateAlphaBlend( const ShadowState_t& state, int stage )
  533. {
  534. g_pTransitionTable->ApplySeparateAlphaBlend( state );
  535. }
  536. void CTransitionTable::ApplySeparateAlphaBlend( const ShadowState_t& state )
  537. {
  538. if (m_CurrentState.m_AlphaBlendState.m_SeparateAlphaBlendEnable != state.m_AlphaBlendState.m_SeparateAlphaBlendEnable)
  539. {
  540. SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE, state.m_AlphaBlendState.m_SeparateAlphaBlendEnable );
  541. m_CurrentState.m_AlphaBlendState.m_SeparateAlphaBlendEnable = state.m_AlphaBlendState.m_SeparateAlphaBlendEnable;
  542. }
  543. if (state.m_AlphaBlendState.m_SeparateAlphaBlendEnable)
  544. {
  545. // Set the blend state here...
  546. if (m_CurrentState.m_AlphaBlendState.m_SrcBlendAlpha != state.m_AlphaBlendState.m_SrcBlendAlpha)
  547. {
  548. SetRenderState( D3DRS_SRCBLENDALPHA, state.m_AlphaBlendState.m_SrcBlendAlpha );
  549. m_CurrentState.m_AlphaBlendState.m_SrcBlendAlpha = state.m_AlphaBlendState.m_SrcBlendAlpha;
  550. }
  551. if (m_CurrentState.m_AlphaBlendState.m_DestBlendAlpha != state.m_AlphaBlendState.m_DestBlendAlpha)
  552. {
  553. SetRenderState( D3DRS_DESTBLENDALPHA, state.m_AlphaBlendState.m_DestBlendAlpha );
  554. m_CurrentState.m_AlphaBlendState.m_DestBlendAlpha = state.m_AlphaBlendState.m_DestBlendAlpha;
  555. }
  556. if (m_CurrentState.m_AlphaBlendState.m_BlendOpAlpha != state.m_AlphaBlendState.m_BlendOpAlpha )
  557. {
  558. SetRenderState( D3DRS_BLENDOPALPHA, state.m_AlphaBlendState.m_BlendOpAlpha );
  559. m_CurrentState.m_AlphaBlendState.m_BlendOpAlpha = state.m_AlphaBlendState.m_BlendOpAlpha;
  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_AlphaBlendState.m_SeparateAlphaBlendEnable = state.m_AlphaBlendState.m_SeparateAlphaBlendEnable;
  565. BoardState().m_AlphaBlendState.m_SrcBlendAlpha = state.m_AlphaBlendState.m_SrcBlendAlpha;
  566. BoardState().m_AlphaBlendState.m_DestBlendAlpha = state.m_AlphaBlendState.m_DestBlendAlpha;
  567. BoardState().m_AlphaBlendState.m_BlendOpAlpha = state.m_AlphaBlendState.m_BlendOpAlpha;
  568. #endif
  569. }
  570. //-----------------------------------------------------------------------------
  571. // Enables textures
  572. //-----------------------------------------------------------------------------
  573. void ApplyTextureEnable( const ShadowState_t& state, int stage )
  574. {
  575. }
  576. //-----------------------------------------------------------------------------
  577. // All transitions below this point depend on dynamic render state
  578. // FIXME: Eliminate these virtual calls?
  579. //-----------------------------------------------------------------------------
  580. void ApplyCullEnable( const ShadowState_t& state, int arg )
  581. {
  582. ShaderAPI()->ApplyCullEnable( state.m_AlphaTestAndMiscState.m_CullEnable );
  583. #ifdef DEBUG_BOARD_STATE
  584. BoardState().m_AlphaTestAndMiscState.m_CullEnable = state.m_AlphaTestAndMiscState.m_CullEnable;
  585. #endif
  586. }
  587. //-----------------------------------------------------------------------------
  588. void ApplyAlphaToCoverage( const ShadowState_t& state, int arg )
  589. {
  590. ShaderAPI()->ApplyAlphaToCoverage( state.m_AlphaTestAndMiscState.m_EnableAlphaToCoverage );
  591. #ifdef DEBUG_BOARD_STATE
  592. BoardState().m_AlphaTestAndMiscState.m_EnableAlphaToCoverage = state.m_AlphaTestAndMiscState.m_EnableAlphaToCoverage;
  593. #endif
  594. }
  595. //-----------------------------------------------------------------------------
  596. // Outputs the fog mode string
  597. //-----------------------------------------------------------------------------
  598. #ifdef RECORDING
  599. const char *ShaderFogModeToString( ShaderFogMode_t fogMode )
  600. {
  601. switch( fogMode )
  602. {
  603. case SHADER_FOGMODE_DISABLED:
  604. return "SHADER_FOGMODE_DISABLED";
  605. case SHADER_FOGMODE_OO_OVERBRIGHT:
  606. return "SHADER_FOGMODE_OO_OVERBRIGHT";
  607. case SHADER_FOGMODE_BLACK:
  608. return "SHADER_FOGMODE_BLACK";
  609. case SHADER_FOGMODE_GREY:
  610. return "SHADER_FOGMODE_GREY";
  611. case SHADER_FOGMODE_FOGCOLOR:
  612. return "SHADER_FOGMODE_FOGCOLOR";
  613. case SHADER_FOGMODE_WHITE:
  614. return "SHADER_FOGMODE_WHITE";
  615. case SHADER_FOGMODE_NUMFOGMODES:
  616. return "SHADER_FOGMODE_NUMFOGMODES";
  617. default:
  618. return "ERROR";
  619. }
  620. }
  621. #endif
  622. // Uses GetConfig().overbright and GetSceneFogMode, so
  623. // will have to fix up the state manually when those change.
  624. void ApplyFogMode( const ShadowState_t& state, int arg )
  625. {
  626. #ifdef RECORDING
  627. char buf[1024];
  628. sprintf( buf, "ApplyFogMode( %s )", ShaderFogModeToString( state.m_FogMode ) );
  629. RECORD_DEBUG_STRING( buf );
  630. #endif
  631. ShaderAPI()->ApplyFogMode( state.m_FogAndMiscState.FogMode(), state.m_FogAndMiscState.m_bVertexFogEnable, state.m_FogAndMiscState.m_SRGBWriteEnable, state.m_FogAndMiscState.m_bDisableFogGammaCorrection );
  632. #ifdef DEBUG_BOARD_STATE
  633. BoardState().m_FogAndMiscState.m_FogMode = state.m_FogAndMiscState.m_FogMode;
  634. BoardState().m_FogAndMiscState.m_bVertexFogEnable = state.m_FogAndMiscState.m_bVertexFogEnable;
  635. #endif
  636. }
  637. //-----------------------------------------------------------------------------
  638. // Finds identical transition lists and shares them
  639. //-----------------------------------------------------------------------------
  640. unsigned int CTransitionTable::FindIdenticalTransitionList( unsigned int firstElem,
  641. unsigned short numOps, unsigned int nFirstTest ) const
  642. {
  643. VPROF("CTransitionTable::FindIdenticalTransitionList");
  644. // As it turns out, this works most of the time
  645. if ( nFirstTest != INVALID_TRANSITION_OP )
  646. {
  647. const TransitionOp_t *pCurrOp = &m_TransitionOps[firstElem];
  648. const TransitionOp_t *pTestOp = &m_TransitionOps[nFirstTest];
  649. if ( !memcmp( pCurrOp, pTestOp, numOps * sizeof(TransitionOp_t) ) )
  650. return nFirstTest;
  651. }
  652. // Look for a common list
  653. const TransitionOp_t &op = m_TransitionOps[firstElem];
  654. int nCount = m_UniqueTransitions.Count();
  655. for ( int i = 0; i < nCount; ++i )
  656. {
  657. const TransitionList_t &list = m_UniqueTransitions[i];
  658. // We can early out here because we've sorted the unique transitions
  659. // descending by count
  660. if ( list.m_NumOperations < numOps )
  661. return INVALID_TRANSITION_OP;
  662. // If we don't find a match in the first
  663. int nPotentialMatch;
  664. int nLastTest = list.m_FirstOperation + list.m_NumOperations - numOps;
  665. for ( nPotentialMatch = list.m_FirstOperation; nPotentialMatch <= nLastTest; ++nPotentialMatch )
  666. {
  667. // Find the first match
  668. const TransitionOp_t &testOp = m_TransitionOps[nPotentialMatch];
  669. if ( testOp.m_nBits == op.m_nBits )
  670. break;
  671. }
  672. // No matches found, continue
  673. if ( nPotentialMatch > nLastTest )
  674. continue;
  675. // Ok, found a match of the first op, lets see if they all match
  676. if ( numOps == 1 )
  677. return nPotentialMatch;
  678. const TransitionOp_t *pCurrOp = &m_TransitionOps[firstElem + 1];
  679. const TransitionOp_t *pTestOp = &m_TransitionOps[nPotentialMatch + 1];
  680. if ( !memcmp( pCurrOp, pTestOp, (numOps - 1) * sizeof(TransitionOp_t) ) )
  681. return nPotentialMatch;
  682. }
  683. return INVALID_TRANSITION_OP;
  684. }
  685. //-----------------------------------------------------------------------------
  686. // Create startup snapshot
  687. //-----------------------------------------------------------------------------
  688. void CTransitionTable::TakeDefaultStateSnapshot( )
  689. {
  690. if (m_DefaultStateSnapshot == -1)
  691. {
  692. m_DefaultStateSnapshot = TakeSnapshot();
  693. // This will create a transition which sets *all* shadowed state
  694. //CreateTransitionTableEntry( m_DefaultStateSnapshot, -1 );
  695. }
  696. }
  697. //-----------------------------------------------------------------------------
  698. // Takes a snapshot, hooks it into the material
  699. //-----------------------------------------------------------------------------
  700. StateSnapshot_t CTransitionTable::TakeSnapshot( )
  701. {
  702. // Do any final computation of the shadow state
  703. ShaderShadow()->ComputeAggregateShadowState();
  704. // Get the current snapshot
  705. const ShadowState_t& currentState = ShaderShadow()->GetShadowState();
  706. // Create a new snapshot
  707. ShadowStateId_t shadowStateId = FindShadowState( currentState );
  708. if (shadowStateId == -1)
  709. {
  710. // Create entry in state transition table
  711. shadowStateId = CreateShadowState( currentState );
  712. }
  713. const ShadowShaderState_t& currentShaderState = ShaderShadow()->GetShadowShaderState();
  714. StateSnapshot_t snapshotId = FindStateSnapshot( shadowStateId, currentShaderState );
  715. if (snapshotId == -1)
  716. {
  717. // Create entry in state transition table
  718. snapshotId = CreateStateSnapshot( shadowStateId, currentShaderState );
  719. }
  720. return snapshotId;
  721. }
  722. //-----------------------------------------------------------------------------
  723. // Apply shader state (stuff that doesn't lie in the transition table)
  724. //-----------------------------------------------------------------------------
  725. void CTransitionTable::ApplyShaderState( const ShadowState_t &shadowState, const ShadowShaderState_t &shaderState )
  726. {
  727. VPROF("CTransitionTable::ApplyShaderState");
  728. // FIXME: Improve early-binding of vertex shader index
  729. ShaderManager()->SetVertexShader( shaderState.m_VertexShader );
  730. ShaderManager()->SetPixelShader( shaderState.m_PixelShader );
  731. #ifdef DEBUG_BOARD_STATE
  732. BoardShaderState().m_VertexShader = shaderState.m_VertexShader;
  733. BoardShaderState().m_PixelShader = shaderState.m_PixelShader;
  734. BoardShaderState().m_nStaticVshIndex = shaderState.m_nStaticVshIndex;
  735. BoardShaderState().m_nStaticPshIndex = shaderState.m_nStaticPshIndex;
  736. #endif
  737. }
  738. void CTransitionTable::SetBoardStateFromShadowState( ShadowState_t const &shadowState )
  739. {
  740. if ( m_CurrentState.m_nDepthTestStateAsInt != shadowState.m_nDepthTestStateAsInt )
  741. {
  742. SetRenderState( D3DRS_ZWRITEENABLE, shadowState.m_DepthTestState.m_ZWriteEnable );
  743. SetRenderState( D3DRS_ZENABLE, shadowState.m_DepthTestState.m_ZEnable );
  744. if (shadowState.m_DepthTestState.m_ZEnable != D3DZB_FALSE)
  745. {
  746. SetRenderState( D3DRS_ZFUNC, shadowState.m_DepthTestState.m_ZFunc );
  747. }
  748. if ( ( m_CurrentState.m_DepthTestState.m_ZBias != shadowState.m_DepthTestState.m_ZBias ) ||
  749. ( ( shadowState.m_DepthTestState.m_ZBias == SHADER_POLYOFFSET_SHADOW_BIAS ) ) && m_bShadowDepthBiasValuesDirty )
  750. {
  751. ShaderAPI()->ApplyZBias( shadowState.m_DepthTestState );
  752. }
  753. SetRenderState( D3DRS_COLORWRITEENABLE, shadowState.m_DepthTestState.m_ColorWriteEnable );
  754. m_CurrentState.m_nDepthTestStateAsInt = shadowState.m_nDepthTestStateAsInt;
  755. #ifdef DEBUG_BOARD_STATE
  756. BoardState().m_DepthTestState = shadowState.m_DepthTestState;
  757. #endif
  758. }
  759. if ( m_CurrentState.m_nAlphaTestAndMiscStateAsInt != shadowState.m_nAlphaTestAndMiscStateAsInt )
  760. {
  761. SetRenderState( D3DRS_ALPHATESTENABLE, shadowState.m_AlphaTestAndMiscState.m_AlphaTestEnable );
  762. SetRenderState( D3DRS_ALPHAFUNC, shadowState.m_AlphaTestAndMiscState.m_AlphaFunc );
  763. SetRenderState( D3DRS_ALPHAREF, shadowState.m_AlphaTestAndMiscState.m_AlphaRef );
  764. ShaderAPI()->ApplyAlphaToCoverage( shadowState.m_AlphaTestAndMiscState.m_EnableAlphaToCoverage );
  765. ShaderAPI()->ApplyCullEnable( shadowState.m_AlphaTestAndMiscState.m_CullEnable );
  766. SetRenderState( D3DRS_FILLMODE, shadowState.m_AlphaTestAndMiscState.m_FillMode );
  767. m_CurrentState.m_nAlphaTestAndMiscStateAsInt = shadowState.m_nAlphaTestAndMiscStateAsInt;
  768. #ifdef DEBUG_BOARD_STATE
  769. BoardState().m_AlphaTestAndMiscState = shadowState.m_AlphaTestAndMiscState;
  770. #endif
  771. }
  772. if ( m_CurrentState.m_nFogAndMiscStateAsInt != shadowState.m_nFogAndMiscStateAsInt )
  773. {
  774. bool bSetting = shadowState.m_FogAndMiscState.m_SRGBWriteEnable;
  775. if ( m_CurrentState.m_FogAndMiscState.m_SRGBWriteEnable != bSetting )
  776. {
  777. // ApplySRGBWriteEnable set to true means that the shader is writing linear values.
  778. if ( ( CurrentState().m_bLinearColorSpaceFrameBufferEnable ) ||
  779. (
  780. HardwareConfig()->NeedsShaderSRGBConversion() &&
  781. ( HardwareConfig()->GetDXSupportLevel() >= 92 ) ) ) //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.
  782. {
  783. // The shader had better be writing linear values since we can't convert to gamma here.
  784. // Can't leave this assert here since there are cases where the shader is doing the right thing.
  785. // This is good to test occasionally to make sure that the shaders are doing the right thing.
  786. // Assert( shaderState.m_SRGBWriteEnable );
  787. // render target is linear
  788. bSetting = false;
  789. // fog isn't fixed-function with linear frame buffers, so don't bother with that here.
  790. }
  791. ShaderAPI()->SetSRGBWrite( bSetting );
  792. }
  793. ShaderAPI()->ApplyFogMode( shadowState.m_FogAndMiscState.FogMode(), shadowState.m_FogAndMiscState.m_bVertexFogEnable, bSetting, shadowState.m_FogAndMiscState.m_bDisableFogGammaCorrection );
  794. m_CurrentState.m_nFogAndMiscStateAsInt = shadowState.m_nFogAndMiscStateAsInt;
  795. #ifdef _DEBUG
  796. BoardState().m_FogAndMiscState.m_SRGBWriteEnable = shadowState.m_FogAndMiscState.m_SRGBWriteEnable;
  797. if (g_SpewTransitions)
  798. {
  799. char buf[128];
  800. sprintf( buf, "Apply %s : %d\n", "D3DRS_SRGBWRITEENABLE", shadowState.m_FogAndMiscState.m_SRGBWriteEnable );
  801. Plat_DebugString(buf);
  802. }
  803. #endif
  804. }
  805. if ( m_CurrentState.m_nAlphaBlendStateAsInt != shadowState.m_nAlphaBlendStateAsInt )
  806. {
  807. SetRenderState( D3DRS_ALPHABLENDENABLE, shadowState.m_AlphaBlendState.m_AlphaBlendEnable );
  808. if (shadowState.m_AlphaBlendState.m_AlphaBlendEnable)
  809. {
  810. // Set the blend state here...
  811. SetRenderState( D3DRS_SRCBLEND, shadowState.m_AlphaBlendState.m_SrcBlend );
  812. SetRenderState( D3DRS_DESTBLEND, shadowState.m_AlphaBlendState.m_DestBlend );
  813. SetRenderState( D3DRS_BLENDOP, shadowState.m_AlphaBlendState.m_BlendOp );
  814. }
  815. SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE, shadowState.m_AlphaBlendState.m_SeparateAlphaBlendEnable );
  816. if (shadowState.m_AlphaBlendState.m_SeparateAlphaBlendEnable)
  817. {
  818. // Set the blend state here...
  819. SetRenderState( D3DRS_SRCBLENDALPHA, shadowState.m_AlphaBlendState.m_SrcBlendAlpha );
  820. SetRenderState( D3DRS_DESTBLENDALPHA, shadowState.m_AlphaBlendState.m_DestBlendAlpha );
  821. SetRenderState( D3DRS_BLENDOPALPHA, shadowState.m_AlphaBlendState.m_BlendOpAlpha );
  822. }
  823. m_CurrentState.m_nAlphaBlendStateAsInt = shadowState.m_nAlphaBlendStateAsInt;
  824. #ifdef DEBUG_BOARD_STATE
  825. // This isn't quite true, but it's necessary for other error checking to work
  826. BoardState().m_nAlphaBlendStateAsInt = shadowState.m_nAlphaBlendStateAsInt;
  827. #endif
  828. }
  829. if ( m_CurrentState.m_ForceDepthFuncEquals ||
  830. m_CurrentState.m_bOverrideDepthEnable ||
  831. m_CurrentState.m_bOverrideAlphaWriteEnable ||
  832. m_CurrentState.m_bOverrideColorWriteEnable )
  833. {
  834. PerformShadowStateOverrides();
  835. }
  836. }
  837. //-----------------------------------------------------------------------------
  838. // Makes the board state match the snapshot
  839. //-----------------------------------------------------------------------------
  840. void CTransitionTable::UseSnapshot( StateSnapshot_t snapshotId, bool bApplyShaderState /*= true*/ )
  841. {
  842. VPROF("CTransitionTable::UseSnapshot");
  843. ShadowStateId_t id = m_SnapshotList[snapshotId].m_ShadowStateId;
  844. if (m_CurrentSnapshotId != snapshotId)
  845. {
  846. // apply the shadow state
  847. if ( m_CurrentShadowId != id )
  848. {
  849. SetBoardStateFromShadowState( m_ShadowStateList[id] );
  850. m_CurrentShadowId = id;
  851. }
  852. m_CurrentSnapshotId = snapshotId;
  853. }
  854. // NOTE: This occurs regardless of whether the snapshot changed because it depends
  855. // on dynamic state (namely, the dynamic vertex + pixel shader index)
  856. // Followed by things that are not
  857. if ( bApplyShaderState )
  858. {
  859. ApplyShaderState( m_ShadowStateList[id], m_SnapshotList[snapshotId].m_ShaderState );
  860. }
  861. }
  862. //-----------------------------------------------------------------------------
  863. // Cause the board to match the default state snapshot
  864. //-----------------------------------------------------------------------------
  865. void CTransitionTable::UseDefaultState( )
  866. {
  867. VPROF("CTransitionTable::UseDefaultState");
  868. // Need to blat these out because they are tested during transitions
  869. m_CurrentState.m_AlphaBlendState.m_AlphaBlendEnable = false;
  870. m_CurrentState.m_AlphaBlendState.m_SrcBlend = D3DBLEND_ONE;
  871. m_CurrentState.m_AlphaBlendState.m_DestBlend = D3DBLEND_ZERO;
  872. m_CurrentState.m_AlphaBlendState.m_BlendOp = D3DBLENDOP_ADD;
  873. SetRenderState( D3DRS_ALPHABLENDENABLE, m_CurrentState.m_AlphaBlendState.m_AlphaBlendEnable );
  874. SetRenderState( D3DRS_SRCBLEND, m_CurrentState.m_AlphaBlendState.m_SrcBlend );
  875. SetRenderState( D3DRS_DESTBLEND, m_CurrentState.m_AlphaBlendState.m_DestBlend );
  876. SetRenderState( D3DRS_BLENDOP, m_CurrentState.m_AlphaBlendState.m_BlendOp );
  877. m_CurrentState.m_AlphaBlendState.m_SeparateAlphaBlendEnable = false;
  878. m_CurrentState.m_AlphaBlendState.m_SrcBlendAlpha = D3DBLEND_ONE;
  879. m_CurrentState.m_AlphaBlendState.m_DestBlendAlpha = D3DBLEND_ZERO;
  880. m_CurrentState.m_AlphaBlendState.m_BlendOpAlpha = D3DBLENDOP_ADD;
  881. SetRenderState( D3DRS_SEPARATEALPHABLENDENABLE, m_CurrentState.m_AlphaBlendState.m_SeparateAlphaBlendEnable );
  882. SetRenderState( D3DRS_SRCBLENDALPHA, m_CurrentState.m_AlphaBlendState.m_SrcBlendAlpha );
  883. SetRenderState( D3DRS_DESTBLENDALPHA, m_CurrentState.m_AlphaBlendState.m_DestBlendAlpha );
  884. SetRenderState( D3DRS_BLENDOPALPHA, m_CurrentState.m_AlphaBlendState.m_BlendOpAlpha );
  885. m_CurrentState.m_nDepthTestStateAsInt = 0;
  886. m_CurrentState.m_DepthTestState.m_ZEnable = D3DZB_TRUE;
  887. m_CurrentState.m_DepthTestState.m_ZFunc = (ShaderUtil()->GetConfig().bReverseDepth ^ ReverseDepthOnX360()) ? D3DCMP_GREATEREQUAL : D3DCMP_LESSEQUAL;
  888. m_CurrentState.m_DepthTestState.m_ZBias = SHADER_POLYOFFSET_DISABLE;
  889. SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
  890. SetRenderState( D3DRS_ZFUNC, m_CurrentState.m_DepthTestState.m_ZFunc );
  891. m_CurrentState.m_nAlphaTestAndMiscStateAsInt = 0;
  892. m_CurrentState.m_AlphaTestAndMiscState.m_AlphaFunc = D3DCMP_GREATEREQUAL;
  893. m_CurrentState.m_AlphaTestAndMiscState.m_AlphaRef = 0;
  894. m_CurrentState.m_AlphaTestAndMiscState.m_FillMode = D3DFILL_SOLID;
  895. m_CurrentState.m_AlphaTestAndMiscState.m_AlphaTestEnable = false;
  896. m_CurrentState.m_AlphaTestAndMiscState.m_EnableAlphaToCoverage = false;
  897. m_CurrentState.m_AlphaTestAndMiscState.m_CullEnable = true;
  898. SetRenderState( D3DRS_ALPHATESTENABLE, m_CurrentState.m_AlphaTestAndMiscState.m_AlphaTestEnable );
  899. SetRenderState( D3DRS_ALPHAFUNC, m_CurrentState.m_AlphaTestAndMiscState.m_AlphaFunc );
  900. SetRenderState( D3DRS_ALPHAREF, m_CurrentState.m_AlphaTestAndMiscState.m_AlphaRef );
  901. ShaderAPI()->ApplyAlphaToCoverage( m_CurrentState.m_AlphaTestAndMiscState.m_EnableAlphaToCoverage );
  902. ShaderAPI()->ApplyCullEnable( m_CurrentState.m_AlphaTestAndMiscState.m_CullEnable );
  903. SetRenderState( D3DRS_FILLMODE, m_CurrentState.m_AlphaTestAndMiscState.m_FillMode );
  904. m_CurrentState.m_FogAndMiscState.m_SRGBWriteEnable = 0;
  905. if ( D3DRS_SRGBWRITEENABLE != D3DRS_NOTSUPPORTED )
  906. {
  907. SetRenderState( D3DRS_SRGBWRITEENABLE, 0 );
  908. }
  909. int nSamplerCount = ShaderAPI()->GetActualSamplerCount();
  910. for ( int i = 0; i < nSamplerCount; ++i)
  911. {
  912. SetSamplerState( i, D3DSAMP_SRGBTEXTURE, SamplerState(i).m_SRGBReadEnable );
  913. #if 0
  914. // Set default Fetch4 state on parts which support it
  915. if ( HardwareConfig()->SupportsFetch4() )
  916. {
  917. SetSamplerState( i, ATISAMP_FETCH4, SamplerState(i).m_Fetch4Enable ? ATI_FETCH4_ENABLE : ATI_FETCH4_DISABLE );
  918. }
  919. #endif
  920. #ifdef DX_TO_GL_ABSTRACTION
  921. SetSamplerState( i, D3DSAMP_SHADOWFILTER, SamplerState(i).m_ShadowFilterEnable );
  922. #endif
  923. }
  924. // Disable z overrides...
  925. m_CurrentState.m_bOverrideDepthEnable = false;
  926. m_CurrentState.m_bOverrideAlphaWriteEnable = false;
  927. m_CurrentState.m_bOverrideColorWriteEnable = false;
  928. m_CurrentState.m_ForceDepthFuncEquals = false;
  929. m_CurrentState.m_bLinearColorSpaceFrameBufferEnable = false;
  930. ShaderManager()->SetVertexShader( INVALID_SHADER );
  931. ShaderManager()->SetPixelShader( INVALID_SHADER );
  932. m_CurrentSnapshotId = -1;
  933. m_CurrentShadowId = -1;
  934. }
  935. //-----------------------------------------------------------------------------
  936. // Snapshotted state overrides
  937. //-----------------------------------------------------------------------------
  938. void CTransitionTable::ForceDepthFuncEquals( bool bEnable )
  939. {
  940. if( bEnable != m_CurrentState.m_ForceDepthFuncEquals )
  941. {
  942. m_CurrentState.m_ForceDepthFuncEquals = bEnable;
  943. if( bEnable )
  944. {
  945. SetZFunc( D3DCMP_EQUAL );
  946. }
  947. else
  948. {
  949. if ( CurrentShadowState() )
  950. {
  951. SetZFunc( ( D3DCMPFUNC ) CurrentShadowState()->m_DepthTestState.m_ZFunc );
  952. }
  953. }
  954. }
  955. }
  956. void CTransitionTable::OverrideDepthEnable( bool bEnable, bool bDepthWriteEnable, bool bDepthTestEnable )
  957. {
  958. if ( bEnable != m_CurrentState.m_bOverrideDepthEnable ||
  959. ( bEnable && ( bDepthWriteEnable != m_CurrentState.m_OverrideZWriteEnable || bDepthTestEnable != m_CurrentState.m_OverrideZTestEnable ) ) )
  960. {
  961. m_CurrentState.m_bOverrideDepthEnable = bEnable;
  962. m_CurrentState.m_OverrideZWriteEnable = bDepthWriteEnable;
  963. m_CurrentState.m_OverrideZTestEnable = bDepthTestEnable;
  964. if ( m_CurrentState.m_bOverrideDepthEnable )
  965. {
  966. SetZEnable( D3DZB_TRUE );
  967. SetRenderState( D3DRS_ZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable ? TRUE : FALSE );
  968. if ( !m_CurrentState.m_OverrideZTestEnable )
  969. {
  970. SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );
  971. }
  972. #if defined( _X360 )
  973. //SetRenderState( D3DRS_HIZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  974. #endif
  975. }
  976. else
  977. {
  978. if ( CurrentShadowState() )
  979. {
  980. SetZEnable( (D3DZBUFFERTYPE ) CurrentShadowState()->m_DepthTestState.m_ZEnable );
  981. SetRenderState( D3DRS_ZWRITEENABLE, CurrentShadowState()->m_DepthTestState.m_ZWriteEnable );
  982. SetRenderState( D3DRS_ZFUNC, CurrentShadowState()->m_DepthTestState.m_ZFunc );
  983. #if defined( _X360 )
  984. //SetRenderState( D3DRS_HIZWRITEENABLE, CurrentShadowState()->m_ZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  985. #endif
  986. }
  987. }
  988. }
  989. }
  990. void CTransitionTable::OverrideAlphaWriteEnable( bool bOverrideEnable, bool bAlphaWriteEnable )
  991. {
  992. if ( bOverrideEnable != m_CurrentState.m_bOverrideAlphaWriteEnable )
  993. {
  994. m_CurrentState.m_bOverrideAlphaWriteEnable = bOverrideEnable;
  995. m_CurrentState.m_bOverriddenAlphaWriteValue = bAlphaWriteEnable;
  996. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable;
  997. if ( m_CurrentState.m_bOverrideAlphaWriteEnable )
  998. {
  999. if( m_CurrentState.m_bOverriddenAlphaWriteValue )
  1000. {
  1001. dwSetValue |= D3DCOLORWRITEENABLE_ALPHA;
  1002. }
  1003. else
  1004. {
  1005. dwSetValue &= ~D3DCOLORWRITEENABLE_ALPHA;
  1006. }
  1007. }
  1008. else
  1009. {
  1010. if ( CurrentShadowState() )
  1011. {
  1012. //probably being paranoid, but only copy the alpha flag from the shadow state
  1013. dwSetValue &= ~D3DCOLORWRITEENABLE_ALPHA;
  1014. dwSetValue |= CurrentShadowState()->m_DepthTestState.m_ColorWriteEnable & D3DCOLORWRITEENABLE_ALPHA;
  1015. }
  1016. }
  1017. if( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1018. {
  1019. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1020. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1021. }
  1022. }
  1023. }
  1024. void CTransitionTable::OverrideColorWriteEnable( bool bOverrideEnable, bool bColorWriteEnable )
  1025. {
  1026. if ( bOverrideEnable != m_CurrentState.m_bOverrideColorWriteEnable )
  1027. {
  1028. m_CurrentState.m_bOverrideColorWriteEnable = bOverrideEnable;
  1029. m_CurrentState.m_bOverriddenColorWriteValue = bColorWriteEnable;
  1030. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable;
  1031. if ( m_CurrentState.m_bOverrideColorWriteEnable )
  1032. {
  1033. if( m_CurrentState.m_bOverriddenColorWriteValue )
  1034. {
  1035. dwSetValue |= (D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1036. }
  1037. else
  1038. {
  1039. dwSetValue &= ~(D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1040. }
  1041. }
  1042. else
  1043. {
  1044. if ( CurrentShadowState() )
  1045. {
  1046. //probably being paranoid, but only copy the alpha flag from the shadow state
  1047. dwSetValue &= ~(D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1048. dwSetValue |= CurrentShadowState()->m_DepthTestState.m_ColorWriteEnable & (D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1049. }
  1050. }
  1051. if( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1052. {
  1053. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1054. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1055. }
  1056. }
  1057. }
  1058. void CTransitionTable::EnableLinearColorSpaceFrameBuffer( bool bEnable )
  1059. {
  1060. if ( m_CurrentState.m_bLinearColorSpaceFrameBufferEnable != bEnable && CurrentShadowState() )
  1061. {
  1062. m_CurrentState.m_bLinearColorSpaceFrameBufferEnable = bEnable;
  1063. ApplySRGBWriteEnable( *CurrentShadowState() );
  1064. }
  1065. }
  1066. //-----------------------------------------------------------------------------
  1067. // Perform state block overrides
  1068. //-----------------------------------------------------------------------------
  1069. void CTransitionTable::PerformShadowStateOverrides( )
  1070. {
  1071. VPROF("CTransitionTable::PerformShadowStateOverrides");
  1072. // Deal with funky overrides here, because the state blocks can't...
  1073. if ( m_CurrentState.m_ForceDepthFuncEquals )
  1074. {
  1075. SetZFunc( D3DCMP_EQUAL );
  1076. }
  1077. if ( m_CurrentState.m_bOverrideDepthEnable )
  1078. {
  1079. SetZEnable( D3DZB_TRUE );
  1080. SetRenderState( D3DRS_ZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable ? TRUE : FALSE );
  1081. if ( !m_CurrentState.m_OverrideZTestEnable )
  1082. {
  1083. SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );
  1084. }
  1085. #if defined( _X360 )
  1086. //SetRenderState( D3DRS_HIZWRITEENABLE, m_CurrentState.m_OverrideZWriteEnable ? D3DHIZ_AUTOMATIC : D3DHIZ_DISABLE );
  1087. #endif
  1088. }
  1089. if ( m_CurrentState.m_bOverrideAlphaWriteEnable )
  1090. {
  1091. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable & ~D3DCOLORWRITEENABLE_ALPHA;
  1092. dwSetValue |= m_CurrentState.m_bOverriddenAlphaWriteValue ? D3DCOLORWRITEENABLE_ALPHA : 0;
  1093. if ( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1094. {
  1095. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1096. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1097. }
  1098. }
  1099. if ( m_CurrentState.m_bOverrideColorWriteEnable )
  1100. {
  1101. DWORD dwSetValue = m_CurrentState.m_ColorWriteEnable & ~(D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
  1102. dwSetValue |= m_CurrentState.m_bOverriddenColorWriteValue ? (D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE) : 0;
  1103. if ( dwSetValue != m_CurrentState.m_ColorWriteEnable )
  1104. {
  1105. m_CurrentState.m_ColorWriteEnable = dwSetValue;
  1106. SetRenderState( D3DRS_COLORWRITEENABLE, m_CurrentState.m_ColorWriteEnable );
  1107. }
  1108. }
  1109. }