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.

4335 lines
146 KiB

  1. //===== Copyright (c) 1996-2008, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #define DISABLE_PROTECTED_THINGS
  9. #include "locald3dtypes.h"
  10. #include "shaderdevicedx8.h"
  11. #include "shaderapi/ishaderutil.h"
  12. #include "shaderapidx8_global.h"
  13. #include "filesystem.h"
  14. #include "tier0/icommandline.h"
  15. #include "tier2/tier2.h"
  16. #include "shadershadowdx8.h"
  17. #include "colorformatdx8.h"
  18. #include "materialsystem/IShader.h"
  19. #include "shaderapidx8.h"
  20. #include "shaderapidx8_global.h"
  21. #include "imeshdx8.h"
  22. #include "materialsystem/materialsystem_config.h"
  23. #include "vertexshaderdx8.h"
  24. #include "recording.h"
  25. #include "vstdlib/ikeyvaluessystem.h"
  26. #include "winutils.h"
  27. #include "tier0/vprof_telemetry.h"
  28. #include "tier0/miniprofiler.h"
  29. #if defined ( DX_TO_GL_ABSTRACTION )
  30. // Placed here so inlines placed in dxabstract.h can access gGL
  31. COpenGLEntryPoints *gGL = NULL;
  32. #endif
  33. #define D3D_BATCH_PERF_ANALYSIS 0
  34. #if D3D_BATCH_PERF_ANALYSIS
  35. #if defined( DX_TO_GL_ABSTRACTION )
  36. #error Cannot enable D3D_BATCH_PERF_ANALYSIS when using DX_TO_GL_ABSTRACTION, use GL_BATCH_PERF_ANALYSIS instead.
  37. #endif
  38. // Define this if you want all d3d9 interfaces hooked and run through the dx9hook.h shim interfaces. For profiling, etc.
  39. #define DO_DX9_HOOK
  40. #endif
  41. #ifdef DO_DX9_HOOK
  42. #if D3D_BATCH_PERF_ANALYSIS
  43. ConVar d3d_batch_vis( "d3d_batch_vis", "0" );
  44. ConVar d3d_batch_vis_abs_scale( "d3d_batch_vis_abs_scale", ".050" );
  45. ConVar d3d_present_vis_abs_scale( "d3d_batch_vis_abs_scale", ".050" );
  46. ConVar d3d_batch_vis_y_scale( "d3d_batch_vis_y_scale", "0.0" );
  47. uint64 g_nTotalD3DCalls, g_nTotalD3DCycles;
  48. static double s_rdtsc_to_ms;
  49. #endif
  50. #include "dx9hook.h"
  51. #endif
  52. #ifndef _X360
  53. #include "wmi.h"
  54. #endif
  55. #if defined( _X360 )
  56. #include "xbox/xbox_console.h"
  57. #include "xbox/xbox_win32stubs.h"
  58. #include "xbox/xbox_launch.h"
  59. #endif
  60. #ifdef _PS3
  61. #include <sys/tty.h>
  62. #include <sysutil/sysutil_sysparam.h>
  63. #include <ps3gcm/gcmstate.h>
  64. #endif
  65. // NOTE: This has to be the last file included!
  66. #include "tier0/memdbgon.h"
  67. // A logging channel used during engine initialization
  68. DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_EngineInitialization, "EngineInitialization" );
  69. #if defined( _X360 )
  70. #define JUNE_2009_XDK_ISSUES
  71. #endif
  72. //-----------------------------------------------------------------------------
  73. // Globals
  74. //-----------------------------------------------------------------------------
  75. static CShaderDeviceMgrDx8 g_ShaderDeviceMgrDx8;
  76. CShaderDeviceMgrDx8* g_pShaderDeviceMgrDx8 = &g_ShaderDeviceMgrDx8;
  77. #ifndef SHADERAPIDX10
  78. // In the shaderapidx10.dll, we use its version of IShaderDeviceMgr.
  79. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderDeviceMgrDx8, IShaderDeviceMgr,
  80. SHADER_DEVICE_MGR_INTERFACE_VERSION, g_ShaderDeviceMgrDx8 )
  81. #endif
  82. #if defined( _X360 )
  83. IDirect3D9 *m_pD3D;
  84. #endif
  85. // hook into mat_forcedynamic from the engine.
  86. static ConVar mat_forcedynamic( "mat_forcedynamic", "0", FCVAR_CHEAT );
  87. // Turn this on to record frames that are longer than what CERT requires on the 360.
  88. ConVar mat_spew_long_frames( "mat_spew_long_frames", "0", 0, "warn about frames that go over 66ms for CERT purposes." );
  89. #if defined( _PS3 ) || defined( _OSX )
  90. extern ConVar mat_debugalttab;
  91. #else
  92. // this is hooked into the engines convar
  93. ConVar mat_debugalttab( "mat_debugalttab", "0", FCVAR_CHEAT );
  94. #endif
  95. //-----------------------------------------------------------------------------
  96. //
  97. // Device manager
  98. //
  99. //-----------------------------------------------------------------------------
  100. //-----------------------------------------------------------------------------
  101. // constructor, destructor
  102. //-----------------------------------------------------------------------------
  103. CShaderDeviceMgrDx8::CShaderDeviceMgrDx8()
  104. {
  105. m_pD3D = NULL;
  106. m_bAdapterInfoIntialized = false;
  107. #if defined( PIX_INSTRUMENTATION ) && defined ( DX_TO_GL_ABSTRACTION ) && defined( _WIN32 )
  108. m_hD3D9 = NULL;
  109. m_pBeginEvent = NULL;
  110. m_pEndEvent = NULL;
  111. m_pSetMarker = NULL;
  112. m_pSetOptions = NULL;
  113. #endif
  114. }
  115. CShaderDeviceMgrDx8::~CShaderDeviceMgrDx8()
  116. {
  117. }
  118. #ifdef OSX
  119. #include <Carbon/Carbon.h>
  120. #endif
  121. //-----------------------------------------------------------------------------
  122. // Connect, disconnect
  123. //-----------------------------------------------------------------------------
  124. bool CShaderDeviceMgrDx8::Connect( CreateInterfaceFn factory )
  125. {
  126. LOCK_SHADERAPI();
  127. if ( !BaseClass::Connect( factory ) )
  128. return false;
  129. #if defined ( DX_TO_GL_ABSTRACTION )
  130. gGL = ToGLConnectLibraries( factory );
  131. #endif
  132. #if defined( DO_DX9_HOOK )
  133. m_pD3D = Direct3DCreate9Hook(D3D_SDK_VERSION);
  134. #else
  135. m_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
  136. #endif
  137. if ( !m_pD3D )
  138. {
  139. Warning( "Failed to create D3D9!\n" );
  140. return false;
  141. }
  142. #if defined( PIX_INSTRUMENTATION ) && defined ( DX_TO_GL_ABSTRACTION ) && defined( _WIN32 )
  143. // This is a little odd, but AMD PerfStudio hooks D3D9.DLL and intercepts all of the D3DPERF API's (even for OpenGL apps).
  144. // So dynamically load d3d9.dll and get the address of these exported functions.
  145. if ( !m_hD3D9 )
  146. {
  147. m_hD3D9 = LoadLibraryA("d3d9.dll");
  148. }
  149. if ( m_hD3D9 )
  150. {
  151. Plat_DebugString( "PIX_INSTRUMENTATION: Loaded d3d9.dll\n" );
  152. printf( "PIX_INSTRUMENTATION: Loaded d3d9.dll\n" );
  153. m_pBeginEvent = (D3DPERF_BeginEvent_FuncPtr)GetProcAddress( m_hD3D9, "D3DPERF_BeginEvent" );
  154. m_pEndEvent = (D3DPERF_EndEvent_FuncPtr)GetProcAddress( m_hD3D9, "D3DPERF_EndEvent" );
  155. m_pSetMarker = (D3DPERF_SetMarker_FuncPtr)GetProcAddress( m_hD3D9, "D3DPERF_SetOptions" );
  156. m_pSetOptions = (D3DPERF_SetOptions_FuncPtr)GetProcAddress( m_hD3D9, "D3DPERF_SetMarker" );
  157. }
  158. #endif
  159. // FIXME: Want this to be here, but we can't because Steam
  160. // hasn't had it's application ID set up yet.
  161. // InitAdapterInfo();
  162. return true;
  163. }
  164. void CShaderDeviceMgrDx8::Disconnect()
  165. {
  166. LOCK_SHADERAPI();
  167. #if defined( PIX_INSTRUMENTATION ) && defined ( DX_TO_GL_ABSTRACTION ) && defined( _WIN32 )
  168. if ( m_hD3D9 )
  169. {
  170. m_pBeginEvent = NULL;
  171. m_pEndEvent = NULL;
  172. m_pSetMarker = NULL;
  173. m_pSetOptions = NULL;
  174. FreeLibrary( m_hD3D9 );
  175. m_hD3D9 = NULL;
  176. }
  177. #endif
  178. if ( m_pD3D )
  179. {
  180. m_pD3D->Release();
  181. m_pD3D = 0;
  182. }
  183. #if defined ( DX_TO_GL_ABSTRACTION )
  184. ToGLDisconnectLibraries();
  185. #endif
  186. BaseClass::Disconnect();
  187. }
  188. //-----------------------------------------------------------------------------
  189. // Initialization
  190. //-----------------------------------------------------------------------------
  191. InitReturnVal_t CShaderDeviceMgrDx8::Init( )
  192. {
  193. // FIXME: Remove call to InitAdapterInfo once Steam startup issues are resolved.
  194. // Do it in Connect instead.
  195. InitAdapterInfo();
  196. return INIT_OK;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Shutdown
  200. //-----------------------------------------------------------------------------
  201. void CShaderDeviceMgrDx8::Shutdown( )
  202. {
  203. LOCK_SHADERAPI();
  204. // FIXME: Make PIX work
  205. // BeginPIXEvent( PIX_VALVE_ORANGE, "Shutdown" );
  206. if ( g_pShaderAPI )
  207. {
  208. g_pShaderAPI->OnDeviceShutdown();
  209. }
  210. if ( g_pShaderDevice )
  211. {
  212. g_pShaderDevice->ShutdownDevice();
  213. g_pMaterialSystemHardwareConfig = NULL;
  214. }
  215. // EndPIXEvent();
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Inline methods
  219. //-----------------------------------------------------------------------------
  220. #if !defined( _GAMECONSOLE )
  221. bool CShaderDeviceDx8::IsActive() const
  222. {
  223. return Dx9Device()->IsActive();
  224. }
  225. #endif
  226. //-----------------------------------------------------------------------------
  227. // Initialize adapter information
  228. //-----------------------------------------------------------------------------
  229. void CShaderDeviceMgrDx8::InitAdapterInfo()
  230. {
  231. if ( m_bAdapterInfoIntialized )
  232. return;
  233. m_bAdapterInfoIntialized = true;
  234. m_Adapters.RemoveAll();
  235. int nCount = m_pD3D->GetAdapterCount( );
  236. for( int i = 0; i < nCount; ++i )
  237. {
  238. int j = m_Adapters.AddToTail();
  239. AdapterInfo_t &info = m_Adapters[j];
  240. #ifdef _DEBUG
  241. memset( &info.m_ActualCaps, 0xDD, sizeof(info.m_ActualCaps) );
  242. #endif
  243. info.m_ActualCaps.m_bDeviceOk = ComputeCapsFromD3D( &info.m_ActualCaps, i );
  244. if ( !info.m_ActualCaps.m_bDeviceOk )
  245. continue;
  246. ReadDXSupportLevels( info.m_ActualCaps );
  247. // Read dxsupport.cfg which has config overrides for particular cards.
  248. ReadHardwareCaps( info.m_ActualCaps, info.m_ActualCaps.m_nMaxDXSupportLevel );
  249. // What's in "-shader" overrides dxsupport.cfg
  250. const char *pShaderParam = CommandLine()->ParmValue( "-shader" );
  251. if ( pShaderParam )
  252. {
  253. Q_strncpy( info.m_ActualCaps.m_pShaderDLL, pShaderParam, sizeof( info.m_ActualCaps.m_pShaderDLL ) );
  254. }
  255. }
  256. }
  257. //--------------------------------------------------------------------------------
  258. // Code to detect support for texture border color (widely supported but the caps
  259. // bit is messed up in drivers due to a stupid WHQL test that requires this to work
  260. // with float textures which we don't generally care about wrt this address mode)
  261. //--------------------------------------------------------------------------------
  262. void CShaderDeviceMgrDx8::CheckBorderColorSupport( HardwareCaps_t *pCaps, int nAdapter )
  263. {
  264. #ifdef DX_TO_GL_ABSTRACTION
  265. if( true )
  266. #else
  267. if( IsX360() )
  268. #endif
  269. {
  270. pCaps->m_bSupportsBorderColor = true;
  271. }
  272. else // Most PC parts do this, but let's not deal with that yet (JasonM)
  273. {
  274. pCaps->m_bSupportsBorderColor = false;
  275. }
  276. }
  277. //--------------------------------------------------------------------------------
  278. // Vendor-dependent code to detect support for various flavors of shadow mapping
  279. //--------------------------------------------------------------------------------
  280. void CShaderDeviceMgrDx8::CheckVendorDependentShadowMappingSupport( HardwareCaps_t *pCaps, int nAdapter )
  281. {
  282. // Set a default null texture format...may be overridden below by IHV-specific surface type
  283. pCaps->m_NullTextureFormat = IMAGE_FORMAT_ARGB8888;
  284. if ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_R5G6B5 ) == S_OK )
  285. {
  286. pCaps->m_NullTextureFormat = IMAGE_FORMAT_RGB565;
  287. }
  288. #if defined( _X360 )
  289. //pCaps->m_ShadowDepthTextureFormat = ReverseDepthOnX360() ? IMAGE_FORMAT_X360_DST24F : IMAGE_FORMAT_X360_DST24;
  290. pCaps->m_ShadowDepthTextureFormat = ReverseDepthOnX360() ? IMAGE_FORMAT_D24FS8 : IMAGE_FORMAT_D24S8;
  291. pCaps->m_bSupportsShadowDepthTextures = true;
  292. pCaps->m_bSupportsFetch4 = false;
  293. pCaps->m_HighPrecisionShadowDepthTextureFormat = pCaps->m_ShadowDepthTextureFormat;
  294. return;
  295. #elif defined ( _PS3 )
  296. pCaps->m_NullTextureFormat = IMAGE_FORMAT_ARGB8888;
  297. if ( CommandLine()->CheckParm( "-d24shadowbuffer" ) )
  298. {
  299. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D24S8;
  300. }
  301. else
  302. {
  303. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D16;
  304. }
  305. pCaps->m_bSupportsShadowDepthTextures = true;
  306. pCaps->m_bSupportsFetch4 = false;
  307. pCaps->m_HighPrecisionShadowDepthTextureFormat = pCaps->m_ShadowDepthTextureFormat;
  308. return;
  309. #elif defined ( DX_TO_GL_ABSTRACTION )
  310. // We may want to only do this on the higher-end Mac SKUs, since it's not free...
  311. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D16_SHADOW; // This format shunts us down the right shader combo path
  312. pCaps->m_bSupportsShadowDepthTextures = true;
  313. pCaps->m_bSupportsFetch4 = false;
  314. pCaps->m_HighPrecisionShadowDepthTextureFormat = pCaps->m_ShadowDepthTextureFormat;
  315. return;
  316. #endif
  317. if ( IsPC() )
  318. {
  319. bool bToolsMode = IsPlatformWindows() && ( CommandLine()->CheckParm( "-tools" ) != NULL );
  320. if ( ( pCaps->m_VendorID == VENDORID_NVIDIA ) && ( pCaps->m_SupportsShaderModel_3_0 ) ) // ps_3_0 parts from nVidia
  321. {
  322. // First, test for null texture support
  323. if ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, NVFMT_NULL ) == S_OK )
  324. {
  325. pCaps->m_NullTextureFormat = IMAGE_FORMAT_NULL;
  326. }
  327. //
  328. // NVIDIA has two no-PCF formats (these are not filtering modes, but surface formats
  329. // NVFMT_RAWZ is supported by NV4x (not supported here yet...requires a dp3 to reconstruct in shader code, which doesn't seem to work)
  330. // NVFMT_INTZ is supported on newer chips as of G8x (just read like ATI non-fetch4 mode)
  331. //
  332. /*
  333. if ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, NVFMT_INTZ ) == S_OK )
  334. {
  335. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_NV_INTZ;
  336. pCaps->m_bSupportsFetch4 = false;
  337. pCaps->m_bSupportsShadowDepthTextures = true;
  338. return;
  339. }
  340. */
  341. bool bSupports16Bit = ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_D16 ) == S_OK );
  342. bool bSupports24Bit = ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_D24S8 ) == S_OK );
  343. if ( bSupports24Bit || bSupports16Bit )
  344. {
  345. pCaps->m_bSupportsFetch4 = false;
  346. pCaps->m_bSupportsShadowDepthTextures = true;
  347. // Prefer 16-bit
  348. if ( bSupports16Bit )
  349. {
  350. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D16_SHADOW;
  351. pCaps->m_HighPrecisionShadowDepthTextureFormat = IMAGE_FORMAT_D16_SHADOW;
  352. if ( bSupports24Bit )
  353. {
  354. pCaps->m_HighPrecisionShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  355. if ( bToolsMode)
  356. {
  357. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  358. }
  359. }
  360. }
  361. else
  362. {
  363. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  364. pCaps->m_HighPrecisionShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  365. }
  366. return;
  367. }
  368. }
  369. else if ( ( pCaps->m_VendorID == VENDORID_ATI ) && pCaps->m_SupportsPixelShaders_2_b ) // ps_2_b parts from ATI
  370. {
  371. // Initially, check for Fetch4 (tied to ATIFMT_D24S8 support)
  372. pCaps->m_bSupportsFetch4 = false;
  373. if ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, ATIFMT_D24S8 ) == S_OK )
  374. {
  375. pCaps->m_bSupportsFetch4 = true;
  376. }
  377. // ATI prefers the NVIDIA PCF path on their DX10 parts:
  378. // http://developer.amd.com/gpu_assets/Advanced%20DX9%20Capabilities%20for%20ATI%20Radeon%20Cards_v2.pdf
  379. if ( !CommandLine()->CheckParm( "-forceatifetch4" ) )
  380. {
  381. if ( pCaps->m_bDX10Card )
  382. {
  383. pCaps->m_bSupportsFetch4 = false;
  384. }
  385. }
  386. bool bSupports16Bit = ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, ATIFMT_D16 ) == S_OK );
  387. bool bSupports24Bit = ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, ATIFMT_D24S8 ) == S_OK );
  388. if ( bSupports24Bit || bSupports16Bit )
  389. {
  390. pCaps->m_bSupportsShadowDepthTextures = true;
  391. // Prefer 16-bit
  392. if ( bSupports16Bit )
  393. {
  394. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D16_SHADOW;
  395. pCaps->m_HighPrecisionShadowDepthTextureFormat = IMAGE_FORMAT_D16_SHADOW;
  396. if ( bSupports24Bit )
  397. {
  398. pCaps->m_HighPrecisionShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  399. if ( bToolsMode)
  400. {
  401. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  402. }
  403. }
  404. }
  405. else
  406. {
  407. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  408. pCaps->m_HighPrecisionShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  409. }
  410. return;
  411. }
  412. }
  413. else if ( ( pCaps->m_VendorID == VENDORID_INTEL ) && pCaps->m_SupportsPixelShaders_2_b ) // ps_2_b parts from INTEL
  414. {
  415. if ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_D24S8 ) == S_OK )
  416. {
  417. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_D24X8_SHADOW;
  418. pCaps->m_bSupportsFetch4 = false;
  419. pCaps->m_bSupportsShadowDepthTextures = true;
  420. return;
  421. }
  422. }
  423. }
  424. // Other vendor or old hardware
  425. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_UNKNOWN;
  426. pCaps->m_bSupportsShadowDepthTextures = false;
  427. pCaps->m_bSupportsFetch4 = false;
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Vendor-dependent code to detect Alpha To Coverage Backdoors
  431. //-----------------------------------------------------------------------------
  432. void CShaderDeviceMgrDx8::CheckVendorDependentAlphaToCoverage( HardwareCaps_t *pCaps, int nAdapter )
  433. {
  434. pCaps->m_bSupportsAlphaToCoverage = false;
  435. // Bail out on OpenGL
  436. #ifdef DX_TO_GL_ABSTRACTION
  437. pCaps->m_bSupportsAlphaToCoverage = true;
  438. pCaps->m_AlphaToCoverageEnableValue = TRUE;
  439. pCaps->m_AlphaToCoverageDisableValue = FALSE;
  440. pCaps->m_AlphaToCoverageState = D3DRS_ADAPTIVETESS_Y; // Just match the NVIDIA state hackery
  441. return;
  442. #endif
  443. #ifdef _X360
  444. {
  445. pCaps->m_bSupportsAlphaToCoverage = true;
  446. pCaps->m_AlphaToCoverageEnableValue = TRUE;
  447. pCaps->m_AlphaToCoverageDisableValue = FALSE;
  448. pCaps->m_AlphaToCoverageState = D3DRS_ALPHATOMASKENABLE;
  449. return;
  450. }
  451. #endif // _X360
  452. if ( pCaps->m_VendorID == VENDORID_NVIDIA )
  453. {
  454. // nVidia has two modes...assume SSAA is superior to MSAA and hence more desirable (though it's probably not)
  455. //
  456. // Currently, they only seem to expose any of this on 7800 and up though older parts certainly
  457. // support at least the MSAA mode since they support it on OpenGL via the arb_multisample extension
  458. bool bNVIDIA_MSAA = false;
  459. bool bNVIDIA_SSAA = false;
  460. if ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, // Check MSAA version
  461. D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE,
  462. (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK )
  463. {
  464. bNVIDIA_MSAA = true;
  465. }
  466. if ( m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, // Check SSAA version
  467. D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE,
  468. (D3DFORMAT)MAKEFOURCC('S', 'S', 'A', 'A')) == S_OK )
  469. {
  470. bNVIDIA_SSAA = true;
  471. }
  472. // nVidia pitches SSAA but we prefer ATOC
  473. if ( bNVIDIA_MSAA )// || bNVIDIA_SSAA )
  474. {
  475. // if ( bNVIDIA_SSAA )
  476. // m_AlphaToCoverageEnableValue = MAKEFOURCC('S', 'S', 'A', 'A');
  477. // else
  478. pCaps->m_AlphaToCoverageEnableValue = MAKEFOURCC('A', 'T', 'O', 'C');
  479. pCaps->m_AlphaToCoverageState = D3DRS_ADAPTIVETESS_Y;
  480. pCaps->m_AlphaToCoverageDisableValue = (DWORD)D3DFMT_UNKNOWN;
  481. pCaps->m_bSupportsAlphaToCoverage = true;
  482. return;
  483. }
  484. }
  485. else if ( pCaps->m_VendorID == VENDORID_ATI )
  486. {
  487. // Supported on all ATI parts...just go ahead and set the state when appropriate
  488. pCaps->m_AlphaToCoverageState = D3DRS_POINTSIZE;
  489. pCaps->m_AlphaToCoverageEnableValue = MAKEFOURCC('A','2','M','1');
  490. pCaps->m_AlphaToCoverageDisableValue = MAKEFOURCC('A','2','M','0');
  491. pCaps->m_bSupportsAlphaToCoverage = true;
  492. return;
  493. }
  494. }
  495. //-----------------------------------------------------------------------------
  496. // Vendor-dependent code to detect support for optimal depth buffer rt resolve
  497. //-----------------------------------------------------------------------------
  498. #define FOURCC_RESZ ((D3DFORMAT)(MAKEFOURCC('R','E','S','Z')))
  499. #define FOURCC_INTZ ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')))
  500. void CShaderDeviceMgrDx8::CheckVendorDependentDepthResolveSupport( HardwareCaps_t *pCaps, int nAdapter )
  501. {
  502. // Bail out on OpenGL
  503. #ifdef DX_TO_GL_ABSTRACTION
  504. pCaps->m_bSupportsRESZ = false;
  505. pCaps->m_bSupportsINTZ = false;
  506. #endif
  507. HRESULT hr;
  508. hr = m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8,//D3DFMT_D24S8,
  509. D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE,
  510. FOURCC_RESZ );
  511. pCaps->m_bSupportsRESZ = (hr == D3D_OK);
  512. Msg( "RESZ %sSUPPORTED!\n", pCaps->m_bSupportsRESZ ? "" : "NOT " );
  513. hr = m_pD3D->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8,
  514. D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE,
  515. FOURCC_INTZ );
  516. pCaps->m_bSupportsINTZ = (hr == D3D_OK);
  517. Msg( "INTZ %sSUPPORTED!\n", pCaps->m_bSupportsINTZ ? "" : "NOT " );
  518. }
  519. ConVar mat_hdr_level( "mat_hdr_level", "2" );
  520. #if defined( _PS3 )
  521. #define SHADOWMAP_SLOPESCALEDEPTHBIAS_D24 "5"
  522. #define SHADOWMAP_DEPTHBIAS_D24 "2500"
  523. #define SHADOWMAP_SLOPESCALEDEPTHBIAS "2"
  524. #define SHADOWMAP_DEPTHBIAS ".25"
  525. #elif defined( DX_TO_GL_ABSTRACTION )
  526. #define SHADOWMAP_SLOPESCALEDEPTHBIAS "8"
  527. #define SHADOWMAP_DEPTHBIAS "20"
  528. #elif defined ( _X360 )
  529. #define SHADOWMAP_SLOPESCALEDEPTHBIAS "2.15"
  530. #define SHADOWMAP_DEPTHBIAS ".000032"
  531. #else
  532. #define SHADOWMAP_SLOPESCALEDEPTHBIAS "3"
  533. #define SHADOWMAP_DEPTHBIAS ".000025"
  534. #endif
  535. ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", SHADOWMAP_SLOPESCALEDEPTHBIAS, FCVAR_NONE );
  536. ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", SHADOWMAP_DEPTHBIAS, FCVAR_NONE );
  537. // For testing Fast Clip
  538. ConVar mat_fastclip( "mat_fastclip", "0", FCVAR_CHEAT );
  539. //-----------------------------------------------------------------------------
  540. // Determine capabilities
  541. //-----------------------------------------------------------------------------
  542. bool CShaderDeviceMgrDx8::ComputeCapsFromD3D( HardwareCaps_t *pCaps, int nAdapter )
  543. {
  544. D3DCAPS caps;
  545. D3DADAPTER_IDENTIFIER9 ident;
  546. HRESULT hr;
  547. // NOTE: When getting the caps, we want to be limited by the hardware
  548. // even if we're running with software T&L...
  549. hr = m_pD3D->GetDeviceCaps( nAdapter, DX8_DEVTYPE, &caps );
  550. if ( FAILED( hr ) )
  551. return false;
  552. hr = m_pD3D->GetAdapterIdentifier( nAdapter, D3DENUM_WHQL_LEVEL, &ident );
  553. if ( FAILED( hr ) )
  554. return false;
  555. if ( IsOpenGL() )
  556. {
  557. if ( !ident.DeviceId && !ident.VendorId )
  558. {
  559. ident.DeviceId = 1;
  560. ident.VendorId = 1;
  561. }
  562. }
  563. // Make sure mac users do not fake their graphic cards and bypass the mandatory
  564. // CSMs for high end GPUs
  565. #ifndef OSX
  566. // Intended for debugging only
  567. if ( CommandLine()->CheckParm( "-force_device_id" ) )
  568. {
  569. const char *pDevID = CommandLine()->ParmValue( "-force_device_id", "" );
  570. if ( pDevID )
  571. {
  572. int nDevID = V_atoi( pDevID ); // use V_atoi for hex support
  573. if ( nDevID > 0 )
  574. {
  575. ident.DeviceId = nDevID;
  576. }
  577. }
  578. }
  579. // Intended for debugging only
  580. if ( CommandLine()->CheckParm( "-force_vendor_id" ) )
  581. {
  582. const char *pVendorID = CommandLine()->ParmValue( "-force_vendor_id", "" );
  583. if ( pVendorID )
  584. {
  585. int nVendorID = V_atoi( pVendorID ); // use V_atoi for hex support
  586. if ( pVendorID > 0 )
  587. {
  588. ident.VendorId = nVendorID;
  589. }
  590. }
  591. }
  592. #endif
  593. Q_strncpy( pCaps->m_pDriverName, ident.Description, MATERIAL_ADAPTER_NAME_LENGTH );
  594. pCaps->m_VendorID = ident.VendorId;
  595. pCaps->m_DeviceID = ident.DeviceId;
  596. pCaps->m_SubSysID = ident.SubSysId;
  597. pCaps->m_Revision = ident.Revision;
  598. pCaps->m_nDriverVersionHigh = ident.DriverVersion.HighPart;
  599. pCaps->m_nDriverVersionLow = ident.DriverVersion.LowPart;
  600. pCaps->m_pShaderDLL[0] = 0;
  601. pCaps->m_nMaxViewports = 1;
  602. pCaps->m_PreferDynamicTextures = ( caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES ) ? 1 : 0;
  603. pCaps->m_HasSetDeviceGammaRamp = (caps.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA) != 0;
  604. Assert( ((caps.VertexShaderVersion >> 8) & 0xFF) >= 1 );
  605. Assert( ((caps.PixelShaderVersion >> 8) & 0xFF) >= 1 );
  606. pCaps->m_bScissorSupported = ( caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST ) != 0;
  607. #if defined( DX8_COMPATABILITY_MODE )
  608. pCaps->m_SupportsPixelShaders_2_b = false;
  609. pCaps->m_SupportsShaderModel_3_0 = false;
  610. pCaps->m_SupportsMipmappedCubemaps = false;
  611. #else
  612. Assert( ( caps.PixelShaderVersion & 0xffff ) >= 0x0200 );
  613. pCaps->m_SupportsPixelShaders_2_b = ( ( caps.PixelShaderVersion & 0xffff ) >= 0x0200) && (caps.PS20Caps.NumInstructionSlots >= 512); // More caps to this, but this will do
  614. Assert( ( caps.VertexShaderVersion & 0xffff ) >= 0x0200 );
  615. pCaps->m_SupportsShaderModel_3_0 = ( caps.PixelShaderVersion & 0xffff ) >= 0x0300;
  616. pCaps->m_SupportsMipmappedCubemaps = ( caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP ) ? true : false;
  617. #endif
  618. if ( IsOpenGL() )
  619. {
  620. pCaps->m_SupportsShaderModel_3_0 = true;
  621. }
  622. #if 0
  623. // Slam 3.0 shaders off for Intel
  624. // Don't do this anymore on CS:GO because we require shader model 3.0, and there are Intel chipsets with decent SM3 support now.
  625. if ( pCaps->m_VendorID == VENDORID_INTEL )
  626. {
  627. pCaps->m_SupportsShaderModel_3_0 = false;
  628. }
  629. #endif
  630. pCaps->m_MaxVertexShader30InstructionSlots = 0;
  631. pCaps->m_MaxPixelShader30InstructionSlots = 0;
  632. if ( pCaps->m_SupportsShaderModel_3_0 )
  633. {
  634. pCaps->m_MaxVertexShader30InstructionSlots = caps.MaxVertexShader30InstructionSlots;
  635. pCaps->m_MaxPixelShader30InstructionSlots = caps.MaxPixelShader30InstructionSlots;
  636. }
  637. pCaps->m_bSoftwareVertexProcessing = false;
  638. if ( IsPlatformWindows() && CommandLine()->CheckParm( "-mat_softwaretl" ) )
  639. {
  640. pCaps->m_bSoftwareVertexProcessing = true;
  641. }
  642. if ( IsPlatformWindows() && !( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) )
  643. {
  644. // no hardware t&l. . use software
  645. pCaps->m_bSoftwareVertexProcessing = true;
  646. }
  647. // Set mat_forcedynamic if software vertex processing since the software vp pipe has
  648. // problems with sparse vertex buffers (it transforms the whole thing.)
  649. if ( pCaps->m_bSoftwareVertexProcessing )
  650. {
  651. mat_forcedynamic.SetValue( 1 );
  652. }
  653. #ifdef _PS3
  654. pCaps->m_bSupportsStaticControlFlow = true;
  655. #elif defined DX_TO_GL_ABSTRACTION
  656. // On OSX, we can force ourselves down a static control flow path, but this only works with GLSL
  657. if ( IsOSX() )
  658. {
  659. pCaps->m_bSupportsStaticControlFlow = CommandLine()->CheckParm("-glslcontrolflow") != NULL;
  660. }
  661. else
  662. {
  663. pCaps->m_bSupportsStaticControlFlow = !CommandLine()->CheckParm("-noglslcontrolflow");
  664. }
  665. #else
  666. pCaps->m_bSupportsStaticControlFlow = true;
  667. #endif
  668. // NOTE: Texture stages is a fixed-function concept
  669. // NOTE: Normally, the number of texture units == the number of texture
  670. // stages except for NVidia hardware, which reports more stages than units.
  671. // The reason for this is because they expose the inner hardware pixel
  672. // pipeline through the extra stages. The only thing we use stages for
  673. // in the hardware is for configuring the color + alpha args + ops.
  674. pCaps->m_NumSamplers = caps.MaxSimultaneousTextures;
  675. pCaps->m_NumSamplers = 16;
  676. // Clamp
  677. pCaps->m_NumSamplers = MIN( pCaps->m_NumSamplers, MAX_SAMPLERS );
  678. pCaps->m_SupportsCompressedTextures = COMPRESSED_TEXTURES_ON;
  679. pCaps->m_bSupportsAnisotropicFiltering = (caps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) != 0;
  680. pCaps->m_bSupportsMagAnisotropicFiltering = (caps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) != 0;
  681. pCaps->m_nMaxAnisotropy = pCaps->m_bSupportsAnisotropicFiltering ? caps.MaxAnisotropy : 1;
  682. Assert( caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP );
  683. Assert( !( caps.TextureCaps & D3DPTEXTURECAPS_POW2 ) || ( caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL ) );
  684. Assert( caps.TextureCaps & D3DPTEXTURECAPS_PROJECTED );
  685. if ( pCaps->m_bSoftwareVertexProcessing )
  686. {
  687. // This should be pushed down based on pixel shaders.
  688. pCaps->m_NumVertexShaderConstants = 256;
  689. pCaps->m_NumBooleanVertexShaderConstants = 16; // 2.0 parts have 16 bool vs registers
  690. pCaps->m_NumBooleanPixelShaderConstants = 16; // 2.0 parts have 16 bool ps registers
  691. pCaps->m_NumIntegerVertexShaderConstants = 16; // 2.0 parts have 16 bool vs registers
  692. pCaps->m_NumIntegerPixelShaderConstants = 16; // 2.0 parts have 16 bool ps registers
  693. }
  694. else
  695. {
  696. pCaps->m_NumVertexShaderConstants = caps.MaxVertexShaderConst;
  697. if ( CommandLine()->FindParm( "-limitvsconst" ) )
  698. {
  699. pCaps->m_NumVertexShaderConstants = MIN( 256, pCaps->m_NumVertexShaderConstants );
  700. }
  701. pCaps->m_NumBooleanVertexShaderConstants = 16; // 2.0 parts have 16 bool vs registers
  702. pCaps->m_NumBooleanPixelShaderConstants = 16; // 2.0 parts have 16 bool ps registers
  703. // This is a little misleading...this is really 16 int4 registers
  704. pCaps->m_NumIntegerVertexShaderConstants = 16; // 2.0 parts have 16 bool vs registers
  705. pCaps->m_NumIntegerPixelShaderConstants = 16; // 2.0 parts have 16 bool ps registers
  706. }
  707. if ( IsX360() )
  708. {
  709. // NOTE! This is really 224, but we do an optimization that only blasts the first 32 always.
  710. if ( IsGPUOwnSupported() )
  711. {
  712. pCaps->m_NumPixelShaderConstants = 32;
  713. }
  714. else
  715. {
  716. pCaps->m_NumPixelShaderConstants = 224;
  717. }
  718. }
  719. else if ( IsPS3() )
  720. {
  721. pCaps->m_NumVertexShaderConstants = 256;
  722. #if defined( _PS3 )
  723. pCaps->m_NumPixelShaderConstants = MAX_FRAGMENT_PROGRAM_CONSTS; // this is somewhat of a lie... fragment shader constants are special on PS3 and we actually have a larger number of these
  724. #endif
  725. pCaps->m_NumIntegerVertexShaderConstants = pCaps->m_NumIntegerPixelShaderConstants = 0;
  726. pCaps->m_NumBooleanVertexShaderConstants = 32;
  727. pCaps->m_NumBooleanPixelShaderConstants = 0;
  728. }
  729. else
  730. {
  731. if ( pCaps->m_SupportsShaderModel_3_0 )
  732. {
  733. pCaps->m_NumPixelShaderConstants = 224;
  734. }
  735. else
  736. {
  737. pCaps->m_NumPixelShaderConstants = 32;
  738. }
  739. }
  740. pCaps->m_MaxNumLights = caps.MaxActiveLights;
  741. if ( pCaps->m_MaxNumLights > MAX_NUM_LIGHTS )
  742. {
  743. pCaps->m_MaxNumLights = MAX_NUM_LIGHTS;
  744. }
  745. // Set according to control flow bit on OpenGL
  746. if ( IsOpenGL() )
  747. {
  748. pCaps->m_MaxNumLights = pCaps->m_bSupportsStaticControlFlow ? 4 : 2;
  749. }
  750. if ( pCaps->m_bSoftwareVertexProcessing )
  751. {
  752. pCaps->m_MaxNumLights = 2;
  753. }
  754. pCaps->m_MaxTextureWidth = caps.MaxTextureWidth;
  755. pCaps->m_MaxTextureHeight = caps.MaxTextureHeight;
  756. pCaps->m_MaxTextureDepth = caps.MaxVolumeExtent ? caps.MaxVolumeExtent : 1;
  757. pCaps->m_MaxTextureAspectRatio = caps.MaxTextureAspectRatio;
  758. if ( pCaps->m_MaxTextureAspectRatio == 0 )
  759. {
  760. pCaps->m_MaxTextureAspectRatio = MAX( pCaps->m_MaxTextureWidth, pCaps->m_MaxTextureHeight);
  761. }
  762. pCaps->m_MaxPrimitiveCount = caps.MaxPrimitiveCount;
  763. pCaps->m_bNeedsATICentroidHack = false;
  764. pCaps->m_bDisableShaderOptimizations = false;
  765. pCaps->m_bPreferZPrepass = IsPS3(); // turn on ZPass on PS/3 by default
  766. pCaps->m_bSuppressPixelShaderCentroidHackFixup = false;
  767. pCaps->m_bPreferTexturesInHWMemory = true;
  768. pCaps->m_bPreferHardwareSync = IsPC();
  769. pCaps->m_bUnsupported = false;
  770. // Check if ZBias and SlopeScaleDepthBias are supported. .if not, tweak the projection matrix instead
  771. // for polyoffset.
  772. pCaps->m_ZBiasAndSlopeScaledDepthBiasSupported =
  773. ( ( caps.RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) != 0 ) &&
  774. ( ( caps.RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS ) != 0 );
  775. if ( IsX360() )
  776. {
  777. // driver lies, force it
  778. pCaps->m_ZBiasAndSlopeScaledDepthBiasSupported = true;
  779. }
  780. // How many user clip planes?
  781. pCaps->m_MaxUserClipPlanes = caps.MaxUserClipPlanes;
  782. if ( CommandLine()->CheckParm( "-nouserclip" ) /* || (IsOSXOpenGL() && (!CommandLine()->FindParm("-glslmode"))) || r_emulategl.GetBool() */ )
  783. {
  784. // rbarris 03Feb10: this now ignores POSIX / -glslmode / r_emulategl because we're defaulting GLSL mode "on".
  785. // so this will mean that the engine will always ask for user clip planes.
  786. // this will misbehave under ARB mode, since ARB shaders won't respect that state.
  787. // it's difficult to make this fluid without teaching the engine about a cap that could change during run.
  788. pCaps->m_MaxUserClipPlanes = 0;
  789. }
  790. if ( pCaps->m_MaxUserClipPlanes > MAXUSERCLIPPLANES )
  791. {
  792. pCaps->m_MaxUserClipPlanes = MAXUSERCLIPPLANES;
  793. }
  794. pCaps->m_FakeSRGBWrite = false;
  795. pCaps->m_CanDoSRGBReadFromRTs = true;
  796. pCaps->m_bSupportsGLMixedSizeTargets = false;
  797. #ifdef DX_TO_GL_ABSTRACTION
  798. // using #if because we're referencing fields in the RHS which don't exist in Windows headers for the caps9 struct
  799. pCaps->m_FakeSRGBWrite = caps.FakeSRGBWrite != 0;
  800. pCaps->m_CanDoSRGBReadFromRTs = caps.CanDoSRGBReadFromRTs != 0;
  801. pCaps->m_bSupportsGLMixedSizeTargets = caps.MixedSizeTargets != 0;
  802. #endif
  803. // Query for SRGB support as needed for our DX 9 stuff
  804. if ( IsPC() || !IsX360() )
  805. {
  806. pCaps->m_SupportsSRGB = ( D3D()->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE, D3DFMT_DXT1 ) == S_OK);
  807. if ( pCaps->m_SupportsSRGB )
  808. {
  809. pCaps->m_SupportsSRGB = ( D3D()->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8 ) == S_OK);
  810. }
  811. }
  812. else
  813. {
  814. // 360 does support it, but is queried in the wrong manner, so force it
  815. pCaps->m_SupportsSRGB = true;
  816. }
  817. if ( CommandLine()->CheckParm( "-nosrgb" ) )
  818. {
  819. pCaps->m_SupportsSRGB = false;
  820. }
  821. if ( IsOpenGL() )
  822. {
  823. // HACK HACK: A lot of code in various branches assumes vertex texture support == SM3, so we're going to set that to true in GL mode and just set m_nVertexTextureCount to 0.
  824. pCaps->m_bSupportsVertexTextures = true;
  825. pCaps->m_NumVertexSamplers = 0;
  826. }
  827. else
  828. {
  829. pCaps->m_bSupportsVertexTextures = ( D3D()->CheckDeviceFormat( nAdapter, DX8_DEVTYPE, D3DFMT_X8R8G8B8,
  830. D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R32F ) == S_OK );
  831. // FIXME: vs30 has a fixed setting here at 4.
  832. // Future hardware will need some other way of computing this.
  833. pCaps->m_NumVertexSamplers = pCaps->m_bSupportsVertexTextures ? 4 : 0;
  834. }
  835. // FIXME: How do I actually compute this?
  836. pCaps->m_nMaxVertexTextureDimension = pCaps->m_bSupportsVertexTextures ? 4096 : 0;
  837. // Does the device support filterable int16 textures?
  838. bool bSupportsInteger16Textures =
  839. ( D3D()->CheckDeviceFormat( nAdapter, DX8_DEVTYPE,
  840. D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER,
  841. D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16 ) == S_OK );
  842. // Does the device support filterable fp16 textures?
  843. bool bSupportsFloat16Textures =
  844. ( D3D()->CheckDeviceFormat( nAdapter, DX8_DEVTYPE,
  845. D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER,
  846. D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F ) == S_OK );
  847. // Does the device support blendable fp16 render targets?
  848. bool bSupportsFloat16RenderTargets =
  849. ( D3D()->CheckDeviceFormat( nAdapter, DX8_DEVTYPE,
  850. D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING | D3DUSAGE_RENDERTARGET,
  851. D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F ) == S_OK );
  852. // Essentially a proxy for a DX10 device running DX9 code path
  853. pCaps->m_bSupportsFloat32RenderTargets = ( D3D()->CheckDeviceFormat( nAdapter, DX8_DEVTYPE,
  854. D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING | D3DUSAGE_RENDERTARGET,
  855. D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F ) == S_OK );
  856. pCaps->m_bFogColorSpecifiedInLinearSpace = false;
  857. pCaps->m_bFogColorAlwaysLinearSpace = false;
  858. // Assume not DX10. Check below.
  859. pCaps->m_bDX10Card = false;
  860. pCaps->m_bDX10Blending = false;
  861. if ( IsOpenGL() )
  862. {
  863. if ( ( pCaps->m_VendorID <= 1 ) && ( pCaps->m_DeviceID <= 1 ) )
  864. {
  865. // HACK HACK - need to fix this once we get proper vendor/device ID's
  866. pCaps->m_bFogColorAlwaysLinearSpace = true;
  867. pCaps->m_bDX10Card = true;
  868. pCaps->m_bDX10Blending = true;
  869. }
  870. }
  871. if ( IsPC() && pCaps->m_SupportsSRGB )
  872. {
  873. if ( pCaps->m_VendorID == VENDORID_NVIDIA )
  874. {
  875. // NVidia wants fog color to be specified in linear space
  876. pCaps->m_bFogColorSpecifiedInLinearSpace = true;
  877. if ( IsOpenGL() )
  878. {
  879. // If we're not the Quadro 4500 or GeForce 7x000, we're an NVIDIA DX10 part on MacOS
  880. if ( !( (pCaps->m_DeviceID == 0x009d) || ( (pCaps->m_DeviceID >= 0x0391) && (pCaps->m_DeviceID <= 0x0395) ) ) )
  881. {
  882. pCaps->m_bFogColorAlwaysLinearSpace = true;
  883. pCaps->m_bDX10Card = true;
  884. pCaps->m_bDX10Blending = true;
  885. }
  886. }
  887. else
  888. {
  889. // On G80 and later, always specify in linear space
  890. if ( pCaps->m_bSupportsFloat32RenderTargets )
  891. {
  892. pCaps->m_bFogColorAlwaysLinearSpace = true;
  893. pCaps->m_bDX10Card = true;
  894. pCaps->m_bDX10Blending = true;
  895. }
  896. }
  897. }
  898. else if ( pCaps->m_VendorID == VENDORID_ATI )
  899. {
  900. if ( IsOpenGL() )
  901. {
  902. // If we're not a Radeon X1x00 (device IDs in this range), we're a DX10 chip
  903. if ( !( (pCaps->m_DeviceID >= 0x7109) && (pCaps->m_DeviceID <= 0x7291) ) )
  904. {
  905. pCaps->m_bFogColorSpecifiedInLinearSpace = true;
  906. pCaps->m_bFogColorAlwaysLinearSpace = true;
  907. pCaps->m_bDX10Card = true;
  908. pCaps->m_bDX10Blending = true;
  909. }
  910. }
  911. else
  912. {
  913. // Check for DX10 part
  914. pCaps->m_bDX10Card = pCaps->m_SupportsShaderModel_3_0 &&
  915. ( pCaps->m_MaxVertexShader30InstructionSlots > 1024 ) &&
  916. ( pCaps->m_MaxPixelShader30InstructionSlots > 512 ) ;
  917. // On ATI, DX10 card means DX10 blending
  918. pCaps->m_bDX10Blending = pCaps->m_bDX10Card;
  919. if( pCaps->m_bDX10Blending )
  920. {
  921. pCaps->m_bFogColorSpecifiedInLinearSpace = true;
  922. pCaps->m_bFogColorAlwaysLinearSpace = true;
  923. }
  924. }
  925. }
  926. else if ( pCaps->m_VendorID == VENDORID_INTEL )
  927. {
  928. // Intel does not have performant vertex textures
  929. pCaps->m_bDX10Card = false;
  930. bool bPostBlendSRGBConvert = true;
  931. // The source for these PCI IDs for Intel GPUs is the mesa driver source code:
  932. // https://cgit.freedesktop.org/mesa/mesa/tree/include/pci_ids
  933. // We are here detecting i915 (Gen3). Anything else is Gen4+ which supports DX10
  934. switch ( pCaps->m_DeviceID )
  935. {
  936. // From https://cgit.freedesktop.org/mesa/mesa/tree/include/pci_ids/i915_pci_ids.h
  937. case 0x3577: //Intel(R) 830M
  938. case 0x2562: //Intel(R) 845G
  939. case 0x3582: //Intel(R) 852GM/855GM
  940. case 0x2572: //Intel(R) 865G
  941. case 0x2582: //Intel(R) 915G
  942. case 0x258A: //Intel(R) E7221G (i915)
  943. case 0x2592: //Intel(R) 915GM
  944. case 0x2772: //Intel(R) 945G
  945. case 0x27A2: //Intel(R) 945GM
  946. case 0x27AE: //Intel(R) 945GME
  947. case 0x29B2: //Intel(R) Q35
  948. case 0x29C2: //Intel(R) G33
  949. case 0x29D2: //Intel(R) Q33
  950. case 0xA011: //Intel(R) Pineview M
  951. case 0xA001: //Intel(R) Pineview
  952. bPostBlendSRGBConvert = false;
  953. break;
  954. }
  955. pCaps->m_bDX10Blending = bPostBlendSRGBConvert;
  956. if( pCaps->m_bDX10Blending )
  957. {
  958. pCaps->m_bFogColorSpecifiedInLinearSpace = true;
  959. pCaps->m_bFogColorAlwaysLinearSpace = true;
  960. }
  961. }
  962. }
  963. // Do we have everything necessary to run with integer HDR? Note that
  964. // even if we don't support integer 16-bit/component textures, we
  965. // can still run in this mode if fp16 textures are supported.
  966. bool bSupportsIntegerHDR =
  967. // (caps.Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD) &&
  968. // (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) &&
  969. ( bSupportsInteger16Textures || bSupportsFloat16Textures ) &&
  970. pCaps->m_SupportsSRGB;
  971. // Do we have everything necessary to run with float HDR?
  972. bool bSupportsFloatHDR = pCaps->m_SupportsShaderModel_3_0 &&
  973. // (caps.Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD) &&
  974. // (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) &&
  975. bSupportsFloat16Textures &&
  976. bSupportsFloat16RenderTargets &&
  977. pCaps->m_SupportsSRGB &&
  978. !IsX360();
  979. pCaps->m_MaxHDRType = HDR_TYPE_NONE;
  980. if ( bSupportsFloatHDR )
  981. pCaps->m_MaxHDRType = HDR_TYPE_FLOAT;
  982. else
  983. if ( bSupportsIntegerHDR )
  984. pCaps->m_MaxHDRType = HDR_TYPE_INTEGER;
  985. if ( bSupportsFloatHDR && ( mat_hdr_level.GetInt() == 3 ) )
  986. {
  987. pCaps->m_HDRType = HDR_TYPE_FLOAT;
  988. }
  989. else if ( bSupportsIntegerHDR )
  990. {
  991. pCaps->m_HDRType = HDR_TYPE_INTEGER;
  992. }
  993. else
  994. {
  995. pCaps->m_HDRType = HDR_TYPE_NONE;
  996. }
  997. Assert( caps.MaxStreams > 1 );
  998. pCaps->m_bSupportsStreamOffset = ( caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET );
  999. pCaps->m_flMinGammaControlPoint = 0.0f;
  1000. pCaps->m_flMaxGammaControlPoint = 65535.0f;
  1001. pCaps->m_nGammaControlPointCount = 256;
  1002. // Compute the effective DX support level based on all the other caps
  1003. ComputeDXSupportLevel( *pCaps );
  1004. pCaps->m_nDXSupportLevel = pCaps->m_nMaxDXSupportLevel;
  1005. int nModelIndex = VERTEX_SHADER_MODEL;
  1006. pCaps->m_MaxVertexShaderBlendMatrices = (pCaps->m_NumVertexShaderConstants - nModelIndex) / 3;
  1007. if ( pCaps->m_MaxVertexShaderBlendMatrices > NUM_MODEL_TRANSFORMS )
  1008. {
  1009. pCaps->m_MaxVertexShaderBlendMatrices = NUM_MODEL_TRANSFORMS;
  1010. }
  1011. CheckBorderColorSupport( pCaps, nAdapter );
  1012. // This may get more complex if we start using multiple flavors of compressed vertex - for now it's "on or off"
  1013. pCaps->m_SupportsCompressedVertices = VERTEX_COMPRESSION_ON;
  1014. #if !defined( _GAMECONSOLE ) // Disabling vertex compression for Portal 2 to help PS3 perf
  1015. if ( CommandLine()->CheckParm( "-no_compressed_verts" ) )
  1016. #endif
  1017. {
  1018. pCaps->m_SupportsCompressedVertices = VERTEX_COMPRESSION_NONE;
  1019. }
  1020. // Various vendor-dependent checks...
  1021. CheckVendorDependentAlphaToCoverage( pCaps, nAdapter );
  1022. CheckVendorDependentShadowMappingSupport( pCaps, nAdapter );
  1023. CheckVendorDependentDepthResolveSupport( pCaps, nAdapter );
  1024. // Cascaded shadow mapping
  1025. // Note: dxsupport can only DISABLE CSM support, not enable it.
  1026. pCaps->m_nCSMQuality = CSMQUALITY_VERY_LOW;
  1027. pCaps->m_bSupportsCascadedShadowMapping = pCaps->m_bSupportsShadowDepthTextures;
  1028. // If we're not on a 3.0 part, these values are more appropriate (X800 & X850 parts from ATI do shadow mapping but not 3.0 )
  1029. if ( !IsOpenGL() )
  1030. {
  1031. if ( !pCaps->m_SupportsShaderModel_3_0 )
  1032. {
  1033. mat_slopescaledepthbias_shadowmap.SetValue( 5.9f );
  1034. mat_depthbias_shadowmap.SetValue( 0.003f );
  1035. }
  1036. }
  1037. #if defined( _PS3 )
  1038. if ( CommandLine()->CheckParm( "-d24shadowbuffer" ) )
  1039. {
  1040. // Slam in larger depth bias settings if we're using D24 shadow buffering (only used for comparison/profiling purposes).
  1041. mat_slopescaledepthbias_shadowmap.SetValue( SHADOWMAP_SLOPESCALEDEPTHBIAS_D24 );
  1042. mat_depthbias_shadowmap.SetValue( SHADOWMAP_DEPTHBIAS_D24 );
  1043. }
  1044. #endif
  1045. if( pCaps->m_MaxUserClipPlanes == 0 )
  1046. {
  1047. pCaps->m_UseFastClipping = true;
  1048. }
  1049. pCaps->m_MaxSimultaneousRenderTargets = caps.NumSimultaneousRTs;
  1050. return true;
  1051. }
  1052. //-----------------------------------------------------------------------------
  1053. // Compute the effective DX support level based on all the other caps
  1054. //-----------------------------------------------------------------------------
  1055. void CShaderDeviceMgrDx8::ComputeDXSupportLevel( HardwareCaps_t &caps )
  1056. {
  1057. // NOTE: Support level is actually DX level * 10 + subversion
  1058. // So, 70 = DX7, 80 = DX8, 81 = DX8 w/ 1.4 pixel shaders
  1059. // 90 = DX9 w/ 2.0 pixel shaders
  1060. // 92 = DX9 w/ 2.0b pixel shaders
  1061. // 95 = DX9 w/ 3.0 pixel shaders and vertex textures
  1062. // 98 = DX9 XBox360
  1063. // 100 = DX10 (but running on XP, using the DX9 API)
  1064. // NOTE: 82 = NVidia nv3x cards, which can't run dx9 fast
  1065. // FIXME: Improve this!! There should be a whole list of features
  1066. // we require in order to be considered a DX7 board, DX8 board, etc.
  1067. if ( IsX360() )
  1068. {
  1069. caps.m_nMinDXSupportLevel = 98;
  1070. caps.m_nMaxDXSupportLevel = 98;
  1071. return;
  1072. }
  1073. #if !defined( CSTRIKE15 )
  1074. if ( caps.m_bDX10Card ) // Note that we don't tie vertex textures to 30 shaders anymore
  1075. {
  1076. caps.m_nMinDXSupportLevel = 92;
  1077. caps.m_nMaxDXSupportLevel = 100;
  1078. return;
  1079. }
  1080. #endif
  1081. if ( caps.m_SupportsShaderModel_3_0 ) // Note that we don't tie vertex textures to 30 shaders anymore
  1082. {
  1083. caps.m_nMinDXSupportLevel = 90;
  1084. caps.m_nMaxDXSupportLevel = 95;
  1085. return;
  1086. }
  1087. if ( caps.m_SupportsPixelShaders_2_b )
  1088. {
  1089. caps.m_nMinDXSupportLevel = 90;
  1090. caps.m_nMaxDXSupportLevel = 92;
  1091. return;
  1092. }
  1093. // NOTE: sRGB is currently required for dx90 because it isn't doing
  1094. // gamma correctly if that feature doesn't exist
  1095. if ( caps.m_SupportsSRGB )
  1096. {
  1097. caps.m_nMinDXSupportLevel = 90;
  1098. caps.m_nMaxDXSupportLevel = 90;
  1099. return;
  1100. }
  1101. Assert( 0 );
  1102. // we don't support this!
  1103. caps.m_nMinDXSupportLevel = 90;
  1104. caps.m_nMaxDXSupportLevel = 90;
  1105. }
  1106. //-----------------------------------------------------------------------------
  1107. // Gets the number of adapters...
  1108. //-----------------------------------------------------------------------------
  1109. int CShaderDeviceMgrDx8::GetAdapterCount() const
  1110. {
  1111. // FIXME: Remove call to InitAdapterInfo once Steam startup issues are resolved.
  1112. const_cast<CShaderDeviceMgrDx8*>( this )->InitAdapterInfo();
  1113. return m_Adapters.Count();
  1114. }
  1115. //-----------------------------------------------------------------------------
  1116. // Returns info about each adapter
  1117. //-----------------------------------------------------------------------------
  1118. void CShaderDeviceMgrDx8::GetAdapterInfo( int nAdapter, MaterialAdapterInfo_t& info ) const
  1119. {
  1120. // FIXME: Remove call to InitAdapterInfo once Steam startup issues are resolved.
  1121. const_cast<CShaderDeviceMgrDx8*>( this )->InitAdapterInfo();
  1122. Assert( ( nAdapter >= 0 ) && ( nAdapter < m_Adapters.Count() ) );
  1123. const HardwareCaps_t &caps = m_Adapters[ nAdapter ].m_ActualCaps;
  1124. memcpy( &info, &caps, sizeof(MaterialAdapterInfo_t) );
  1125. }
  1126. //-----------------------------------------------------------------------------
  1127. // Sets the adapter
  1128. //-----------------------------------------------------------------------------
  1129. bool CShaderDeviceMgrDx8::SetAdapter( int nAdapter, int nAdapterFlags )
  1130. {
  1131. LOCK_SHADERAPI();
  1132. // FIXME:
  1133. // g_pShaderDeviceDx8->m_bReadPixelsEnabled = (nAdapterFlags & MATERIAL_INIT_READ_PIXELS_ENABLED) != 0;
  1134. // Set up hardware information for this adapter...
  1135. g_pShaderDeviceDx8->m_DeviceType = (nAdapterFlags & MATERIAL_INIT_REFERENCE_RASTERIZER) ?
  1136. D3DDEVTYPE_REF : D3DDEVTYPE_HAL;
  1137. g_pShaderDeviceDx8->m_DisplayAdapter = nAdapter;
  1138. if ( g_pShaderDeviceDx8->m_DisplayAdapter >= (UINT)GetAdapterCount() )
  1139. {
  1140. g_pShaderDeviceDx8->m_DisplayAdapter = 0;
  1141. }
  1142. #ifdef NVPERFHUD
  1143. // hack for nvperfhud
  1144. g_pShaderDeviceDx8->m_DisplayAdapter = m_pD3D->GetAdapterCount() - 1;
  1145. g_pShaderDeviceDx8->m_DeviceType = D3DDEVTYPE_REF;
  1146. #endif
  1147. // backward compat
  1148. if ( !g_pShaderDeviceDx8->OnAdapterSet() )
  1149. return false;
  1150. // if ( !g_pShaderDeviceDx8->Init() )
  1151. // {
  1152. // Warning( "Unable to initialize dx8 device!\n" );
  1153. // return false;
  1154. // }
  1155. g_pShaderDevice = g_pShaderDeviceDx8;
  1156. return true;
  1157. }
  1158. //-----------------------------------------------------------------------------
  1159. // Returns the screen resolution
  1160. //-----------------------------------------------------------------------------
  1161. void CShaderDeviceMgrDx8::GetDesktopResolution( int *pWidth, int *pHeight, int nAdapter ) const
  1162. {
  1163. #if defined ( _X360 )
  1164. #elif defined ( DX_TO_GL_ABSTRACTION )
  1165. D3DDISPLAYMODE d3dDisplayMode;
  1166. m_pD3D->GetAdapterDisplayMode( nAdapter, &d3dDisplayMode );
  1167. *pWidth = d3dDisplayMode.Width;
  1168. *pHeight = d3dDisplayMode.Height;
  1169. #elif defined( _X360 ) || defined( _PS3 ) || defined( POSIX )
  1170. // Empty
  1171. #else
  1172. HMONITOR hMonitor = m_pD3D->GetAdapterMonitor( nAdapter );
  1173. // *pWidth = ::GetDeviceCaps( hMonitor, HORZSIZE );
  1174. // *pHeight = ::GetDeviceCaps( hMonitor, VERTSIZE );
  1175. MONITORINFO monitorInfo;
  1176. memset( &monitorInfo, 0, sizeof(monitorInfo) );
  1177. monitorInfo.cbSize = sizeof(monitorInfo);
  1178. GetMonitorInfo( hMonitor, &monitorInfo );
  1179. *pWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
  1180. *pHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
  1181. #endif
  1182. }
  1183. //-----------------------------------------------------------------------------
  1184. // Returns the number of modes
  1185. //-----------------------------------------------------------------------------
  1186. int CShaderDeviceMgrDx8::GetModeCount( int nAdapter ) const
  1187. {
  1188. LOCK_SHADERAPI();
  1189. Assert( m_pD3D && (nAdapter < GetAdapterCount() ) );
  1190. #if !defined( _X360 )
  1191. // fixme - what format should I use here?
  1192. return m_pD3D->GetAdapterModeCount( nAdapter, D3DFMT_X8R8G8B8 );
  1193. #else
  1194. return 1; // Only one mode, which is the current mode set in the 360 dashboard. Going to fill it in with exactly what the 360 is set to.
  1195. #endif
  1196. }
  1197. #ifdef _PS3
  1198. static void PS3_GetVideoOutResolution( int *pWidth, int *pHeight, float *pAspectRatio )
  1199. {
  1200. *pWidth = 640;
  1201. *pHeight = 480;
  1202. CellVideoOutState videoOutState;
  1203. int ret = cellVideoOutGetState( CELL_VIDEO_OUT_PRIMARY, 0, &videoOutState);
  1204. if ( ret < CELL_OK )
  1205. return;
  1206. CellVideoOutResolution resolution;
  1207. ret = cellVideoOutGetResolution( videoOutState.displayMode.resolutionId, &resolution );
  1208. if ( ret < CELL_OK )
  1209. return;
  1210. *pWidth = resolution.width;
  1211. *pHeight = resolution.height;
  1212. #ifndef _CERT
  1213. static bool s_bPrintOnce = false;
  1214. if ( !s_bPrintOnce )
  1215. {
  1216. s_bPrintOnce = true;
  1217. char chDbg[512];
  1218. Q_snprintf( chDbg, sizeof( chDbg ),
  1219. "----- VIDEO MODE -----\n"
  1220. "STATE: %s\n"
  1221. "COLOR: %s\n"
  1222. "RES: %u x %u [#%d]\n"
  1223. "ASPECT: %s\n"
  1224. "RRATE: %s%s%s%s\n"
  1225. "SCAN: %s\n"
  1226. "----------------------\n",
  1227. (videoOutState.state == CELL_VIDEO_OUT_OUTPUT_STATE_ENABLED) ? "ENABLED" : "NOT READY",
  1228. (videoOutState.colorSpace == CELL_VIDEO_OUT_COLOR_SPACE_RGB) ? "RGB" : ( (videoOutState.colorSpace == CELL_VIDEO_OUT_COLOR_SPACE_YUV) ? "YUV" : "UNDEFINED" ),
  1229. resolution.width, resolution.height, videoOutState.displayMode.resolutionId,
  1230. (videoOutState.displayMode.aspect == CELL_VIDEO_OUT_ASPECT_4_3) ? "4x3" : ( (videoOutState.displayMode.aspect == CELL_VIDEO_OUT_ASPECT_16_9) ? "16x9" : "AUTO" ),
  1231. (videoOutState.displayMode.refreshRates & CELL_VIDEO_OUT_REFRESH_RATE_30HZ) ? " 30Hz" : "",
  1232. (videoOutState.displayMode.refreshRates & CELL_VIDEO_OUT_REFRESH_RATE_50HZ) ? " 50Hz" : "",
  1233. (videoOutState.displayMode.refreshRates & CELL_VIDEO_OUT_REFRESH_RATE_60HZ) ? " 60Hz" : "",
  1234. (videoOutState.displayMode.refreshRates & CELL_VIDEO_OUT_REFRESH_RATE_59_94HZ) ? " 59.94Hz" : "",
  1235. videoOutState.displayMode.scanMode ? "PROGRESSIVE" : "INTERLACED"
  1236. );
  1237. unsigned int dummy;
  1238. sys_tty_write( SYS_TTYP15, chDbg, Q_strlen( chDbg ), &dummy );
  1239. }
  1240. #endif
  1241. // Clamp 1080p resolution down to 720p
  1242. if ( resolution.height >= 720 && CommandLine()->FindParm( "-480p" ) )
  1243. {
  1244. *pWidth = 640;
  1245. *pHeight = 480;
  1246. }
  1247. else if ( resolution.height >= 1080 && !CommandLine()->FindParm( "-1080p" ) )
  1248. {
  1249. *pWidth = 1280;
  1250. *pHeight = 720;
  1251. }
  1252. switch ( videoOutState.displayMode.aspect )
  1253. {
  1254. case CELL_VIDEO_OUT_ASPECT_4_3:
  1255. *pAspectRatio = 4.0f/3.0f;
  1256. break;
  1257. case CELL_VIDEO_OUT_ASPECT_16_9:
  1258. *pAspectRatio = 16.0f/9.0f;
  1259. break;
  1260. default:
  1261. *pAspectRatio = float( *pWidth ) / float( *pHeight );
  1262. break;
  1263. }
  1264. }
  1265. #endif // _PS3
  1266. //-----------------------------------------------------------------------------
  1267. // Returns mode information..
  1268. //-----------------------------------------------------------------------------
  1269. void CShaderDeviceMgrDx8::GetModeInfo( ShaderDisplayMode_t* pInfo, int nAdapter, int nMode ) const
  1270. {
  1271. Assert( pInfo->m_nVersion == SHADER_DISPLAY_MODE_VERSION );
  1272. LOCK_SHADERAPI();
  1273. Assert( m_pD3D && (nAdapter < GetAdapterCount() ) );
  1274. Assert( nMode < GetModeCount( nAdapter ) );
  1275. #if defined( _PS3 )
  1276. PS3_GetVideoOutResolution( &pInfo->m_nWidth, &pInfo->m_nHeight, &pInfo->m_flAspectRatio );
  1277. pInfo->m_Format = ImageLoader::D3DFormatToImageFormat( D3DFMT_X8R8G8B8 );
  1278. pInfo->m_nRefreshRateNumerator = 60;
  1279. pInfo->m_nRefreshRateDenominator = 1;
  1280. #elif defined( _X360 )
  1281. pInfo->m_Format = ImageLoader::D3DFormatToImageFormat( D3DFMT_X8R8G8B8 );
  1282. pInfo->m_nRefreshRateNumerator = 60;
  1283. pInfo->m_nRefreshRateDenominator = 1;
  1284. pInfo->m_nWidth = GetSystemMetrics( SM_CXSCREEN );
  1285. pInfo->m_nHeight = GetSystemMetrics( SM_CYSCREEN );
  1286. #else
  1287. HRESULT hr;
  1288. D3DDISPLAYMODE d3dInfo;
  1289. // fixme - what format should I use here?
  1290. hr = D3D()->EnumAdapterModes( nAdapter, D3DFMT_X8R8G8B8, nMode, &d3dInfo );
  1291. Assert( !FAILED(hr) );
  1292. pInfo->m_nWidth = d3dInfo.Width;
  1293. pInfo->m_nHeight = d3dInfo.Height;
  1294. pInfo->m_Format = ImageLoader::D3DFormatToImageFormat( d3dInfo.Format );
  1295. pInfo->m_nRefreshRateNumerator = d3dInfo.RefreshRate;
  1296. pInfo->m_nRefreshRateDenominator = 1;
  1297. #endif
  1298. }
  1299. //-----------------------------------------------------------------------------
  1300. // Returns the current mode information for an adapter
  1301. //-----------------------------------------------------------------------------
  1302. void CShaderDeviceMgrDx8::GetCurrentModeInfo( ShaderDisplayMode_t* pInfo, int nAdapter ) const
  1303. {
  1304. Assert( pInfo->m_nVersion == SHADER_DISPLAY_MODE_VERSION );
  1305. LOCK_SHADERAPI();
  1306. Assert( D3D() );
  1307. HRESULT hr;
  1308. D3DDISPLAYMODE mode;
  1309. #if defined( _PS3 )
  1310. PS3_GetVideoOutResolution( ( int *)&mode.Width, ( int *)&mode.Height, &pInfo->m_flAspectRatio );
  1311. mode.Format = D3DFMT_X8R8G8B8;
  1312. mode.RefreshRate = 60;
  1313. #elif defined( _X360 )
  1314. if ( !m_pD3DDevice )
  1315. {
  1316. // the console has no prior display or mode until its created
  1317. mode.Width = GetSystemMetrics( SM_CXSCREEN );
  1318. mode.Height = GetSystemMetrics( SM_CYSCREEN );
  1319. mode.RefreshRate = 60;
  1320. mode.Format = D3DFMT_X8R8G8B8;
  1321. }
  1322. else
  1323. {
  1324. hr = m_pD3DDevice->GetDisplayMode( 0, &mode );
  1325. Assert( !FAILED(hr) );
  1326. }
  1327. #else
  1328. hr = D3D()->GetAdapterDisplayMode( nAdapter, &mode );
  1329. Assert( !FAILED(hr) );
  1330. #endif
  1331. pInfo->m_nWidth = mode.Width;
  1332. pInfo->m_nHeight = mode.Height;
  1333. pInfo->m_Format = ImageLoader::D3DFormatToImageFormat( mode.Format );
  1334. pInfo->m_nRefreshRateNumerator = mode.RefreshRate;
  1335. pInfo->m_nRefreshRateDenominator = 1;
  1336. }
  1337. //-----------------------------------------------------------------------------
  1338. // Sets the video mode
  1339. //-----------------------------------------------------------------------------
  1340. CreateInterfaceFn CShaderDeviceMgrDx8::SetMode( void *hWnd, int nAdapter, const ShaderDeviceInfo_t& mode )
  1341. {
  1342. LOCK_SHADERAPI();
  1343. Assert( nAdapter < GetAdapterCount() );
  1344. int nDXLevel = mode.m_nDXLevel != 0 ? mode.m_nDXLevel : m_Adapters[nAdapter].m_ActualCaps.m_nDXSupportLevel;
  1345. if ( nDXLevel > m_Adapters[nAdapter].m_ActualCaps.m_nMaxDXSupportLevel )
  1346. {
  1347. nDXLevel = m_Adapters[nAdapter].m_ActualCaps.m_nMaxDXSupportLevel;
  1348. }
  1349. nDXLevel = GetClosestActualDXLevel( nDXLevel );
  1350. if ( nDXLevel > 100 )
  1351. return NULL;
  1352. bool bReacquireResourcesNeeded = false;
  1353. if ( g_pShaderDevice )
  1354. {
  1355. bReacquireResourcesNeeded = IsPC();
  1356. g_pShaderDevice->ReleaseResources();
  1357. }
  1358. if ( g_pShaderAPI )
  1359. {
  1360. g_pShaderAPI->OnDeviceShutdown();
  1361. g_pShaderAPI = NULL;
  1362. }
  1363. if ( g_pShaderDevice )
  1364. {
  1365. g_pShaderDevice->ShutdownDevice();
  1366. g_pShaderDevice = NULL;
  1367. }
  1368. g_pShaderShadow = NULL;
  1369. ShaderDeviceInfo_t adjustedMode = mode;
  1370. adjustedMode.m_nDXLevel = nDXLevel;
  1371. if ( !g_pShaderDeviceDx8->InitDevice( hWnd, nAdapter, adjustedMode ) )
  1372. return NULL;
  1373. if ( !g_pShaderAPIDX8->OnDeviceInit() )
  1374. return NULL;
  1375. g_pShaderDevice = g_pShaderDeviceDx8;
  1376. g_pShaderAPI = g_pShaderAPIDX8;
  1377. g_pShaderShadow = g_pShaderShadowDx8;
  1378. if ( bReacquireResourcesNeeded )
  1379. {
  1380. g_pShaderDevice->ReacquireResources();
  1381. }
  1382. return ShaderInterfaceFactory;
  1383. }
  1384. //-----------------------------------------------------------------------------
  1385. // Validates the mode...
  1386. //-----------------------------------------------------------------------------
  1387. bool CShaderDeviceMgrDx8::ValidateMode( int nAdapter, const ShaderDeviceInfo_t &info ) const
  1388. {
  1389. if ( nAdapter >= (int)D3D()->GetAdapterCount() )
  1390. return false;
  1391. ShaderDisplayMode_t displayMode;
  1392. GetCurrentModeInfo( &displayMode, nAdapter );
  1393. if ( info.m_bWindowed )
  1394. {
  1395. // make sure the window fits within the current video mode
  1396. if ( ( info.m_DisplayMode.m_nWidth > displayMode.m_nWidth ) ||
  1397. ( info.m_DisplayMode.m_nHeight > displayMode.m_nHeight ) )
  1398. return false;
  1399. }
  1400. // Make sure the image format requested is valid
  1401. ImageFormat backBufferFormat = FindNearestSupportedBackBufferFormat( nAdapter,
  1402. DX8_DEVTYPE, displayMode.m_Format, info.m_DisplayMode.m_Format, info.m_bWindowed );
  1403. return ( backBufferFormat != IMAGE_FORMAT_UNKNOWN );
  1404. }
  1405. //-----------------------------------------------------------------------------
  1406. // Returns the amount of video memory in bytes for a particular adapter
  1407. //-----------------------------------------------------------------------------
  1408. int CShaderDeviceMgrDx8::GetVidMemBytes( int nAdapter ) const
  1409. {
  1410. #if defined( _X360 )
  1411. return 256*1024*1024;
  1412. #elif defined (DX_TO_GL_ABSTRACTION)
  1413. D3DADAPTER_IDENTIFIER9 devIndentifier;
  1414. D3D()->GetAdapterIdentifier( nAdapter, D3DENUM_WHQL_LEVEL, &devIndentifier );
  1415. return devIndentifier.VideoMemory;
  1416. #else
  1417. // FIXME: This currently ignores the adapter
  1418. return ::GetVidMemBytes();
  1419. #endif
  1420. }
  1421. //-----------------------------------------------------------------------------
  1422. //
  1423. // Shader device
  1424. //
  1425. //-----------------------------------------------------------------------------
  1426. #if 0
  1427. // FIXME: Enable after I've separated it out from shaderapidx8 a little better
  1428. static CShaderDeviceDx8 s_ShaderDeviceDX8;
  1429. CShaderDeviceDx8* g_pShaderDeviceDx8 = &s_ShaderDeviceDX8;
  1430. #endif
  1431. #if defined( _GAMECONSOLE )
  1432. IDirect3DDevice *m_pD3DDevice;
  1433. #endif
  1434. //-----------------------------------------------------------------------------
  1435. // Constructor, destructor
  1436. //-----------------------------------------------------------------------------
  1437. CShaderDeviceDx8::CShaderDeviceDx8()
  1438. {
  1439. m_pD3DDevice = NULL;
  1440. for ( int i = 0; i < ARRAYSIZE(m_pFrameSyncQueryObject); i++ )
  1441. {
  1442. m_pFrameSyncQueryObject[i] = NULL;
  1443. m_bQueryIssued[i] = false;
  1444. }
  1445. m_pFrameSyncTexture = NULL;
  1446. m_bQueuedDeviceLost = false;
  1447. m_DeviceState = DEVICE_STATE_OK;
  1448. m_bOtherAppInitializing = false;
  1449. m_IsResizing = false;
  1450. m_bPendingVideoModeChange = false;
  1451. m_DeviceSupportsCreateQuery = -1;
  1452. m_bUsingStencil = false;
  1453. m_bResourcesReleased = false;
  1454. m_iStencilBufferBits = 0;
  1455. m_NonInteractiveRefresh.m_Mode = MATERIAL_NON_INTERACTIVE_MODE_NONE;
  1456. m_NonInteractiveRefresh.m_pVertexShader = NULL;
  1457. m_NonInteractiveRefresh.m_pPixelShader = NULL;
  1458. m_NonInteractiveRefresh.m_pPixelShaderStartup = NULL;
  1459. m_NonInteractiveRefresh.m_pPixelShaderStartupPass2 = NULL;
  1460. m_NonInteractiveRefresh.m_pVertexDecl = NULL;
  1461. m_NonInteractiveRefresh.m_nPacifierFrame = 0;
  1462. m_numReleaseResourcesRefCount = 0;
  1463. }
  1464. CShaderDeviceDx8::~CShaderDeviceDx8()
  1465. {
  1466. }
  1467. //-----------------------------------------------------------------------------
  1468. // Computes device creation paramters
  1469. //-----------------------------------------------------------------------------
  1470. static DWORD ComputeDeviceCreationFlags( D3DCAPS& caps, bool bSoftwareVertexProcessing )
  1471. {
  1472. // Find out what type of device to make
  1473. bool bPureDeviceSupported = (caps.DevCaps & D3DDEVCAPS_PUREDEVICE) != 0;
  1474. DWORD nDeviceCreationFlags;
  1475. if ( !bSoftwareVertexProcessing )
  1476. {
  1477. nDeviceCreationFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  1478. if ( bPureDeviceSupported )
  1479. {
  1480. nDeviceCreationFlags |= D3DCREATE_PUREDEVICE;
  1481. }
  1482. }
  1483. else
  1484. {
  1485. nDeviceCreationFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  1486. }
  1487. nDeviceCreationFlags |= D3DCREATE_FPU_PRESERVE;
  1488. #ifdef _X360
  1489. nDeviceCreationFlags |= D3DCREATE_BUFFER_2_FRAMES;
  1490. #endif
  1491. return nDeviceCreationFlags;
  1492. }
  1493. //-----------------------------------------------------------------------------
  1494. // Computes the supersample flags
  1495. //-----------------------------------------------------------------------------
  1496. D3DMULTISAMPLE_TYPE CShaderDeviceDx8::ComputeMultisampleType( int nSampleCount )
  1497. {
  1498. switch (nSampleCount)
  1499. {
  1500. #if !defined( _X360 )
  1501. case 2: return D3DMULTISAMPLE_2_SAMPLES;
  1502. case 3: return D3DMULTISAMPLE_3_SAMPLES;
  1503. case 4: return D3DMULTISAMPLE_4_SAMPLES;
  1504. case 5: return D3DMULTISAMPLE_5_SAMPLES;
  1505. case 6: return D3DMULTISAMPLE_6_SAMPLES;
  1506. case 7: return D3DMULTISAMPLE_7_SAMPLES;
  1507. case 8: return D3DMULTISAMPLE_8_SAMPLES;
  1508. case 9: return D3DMULTISAMPLE_9_SAMPLES;
  1509. case 10: return D3DMULTISAMPLE_10_SAMPLES;
  1510. case 11: return D3DMULTISAMPLE_11_SAMPLES;
  1511. case 12: return D3DMULTISAMPLE_12_SAMPLES;
  1512. case 13: return D3DMULTISAMPLE_13_SAMPLES;
  1513. case 14: return D3DMULTISAMPLE_14_SAMPLES;
  1514. case 15: return D3DMULTISAMPLE_15_SAMPLES;
  1515. case 16: return D3DMULTISAMPLE_16_SAMPLES;
  1516. #else
  1517. case 2: return D3DMULTISAMPLE_2_SAMPLES;
  1518. case 4: return D3DMULTISAMPLE_4_SAMPLES;
  1519. #endif
  1520. default:
  1521. case 0:
  1522. case 1:
  1523. return D3DMULTISAMPLE_NONE;
  1524. }
  1525. }
  1526. void CShaderDeviceDx8::CalcBackBufferDimensions( const ShaderDisplayMode_t &mode, const ShaderDeviceInfo_t &info, int *pBackBufferWidth, int *pBackBufferHeight )
  1527. {
  1528. if ( IsX360() || !info.m_bWindowed )
  1529. {
  1530. // fullscreen
  1531. bool useDefault = ( info.m_DisplayMode.m_nWidth == 0 ) || ( info.m_DisplayMode.m_nHeight == 0 );
  1532. *pBackBufferWidth = useDefault ? mode.m_nWidth : info.m_DisplayMode.m_nWidth;
  1533. *pBackBufferHeight = useDefault ? mode.m_nHeight : info.m_DisplayMode.m_nHeight;
  1534. }
  1535. else
  1536. {
  1537. // windowed
  1538. if ( info.m_bResizing )
  1539. {
  1540. if ( info.m_bLimitWindowedSize &&
  1541. ( info.m_nWindowedSizeLimitWidth < mode.m_nWidth || info.m_nWindowedSizeLimitHeight < mode.m_nHeight ) )
  1542. {
  1543. // When using material system in windowed resizing apps, it's
  1544. // sometimes not a good idea to allocate stuff as big as the screen
  1545. // video cards can soo run out of resources
  1546. *pBackBufferWidth = info.m_nWindowedSizeLimitWidth;
  1547. *pBackBufferHeight = info.m_nWindowedSizeLimitHeight;
  1548. }
  1549. else
  1550. {
  1551. // When in resizing windowed mode,
  1552. // we want to allocate enough memory to deal with any resizing...
  1553. *pBackBufferWidth = mode.m_nWidth;
  1554. *pBackBufferHeight = mode.m_nHeight;
  1555. }
  1556. }
  1557. else
  1558. {
  1559. *pBackBufferWidth = info.m_DisplayMode.m_nWidth;
  1560. *pBackBufferHeight = info.m_DisplayMode.m_nHeight;
  1561. }
  1562. }
  1563. }
  1564. //-----------------------------------------------------------------------------
  1565. // Sets the present parameters
  1566. //-----------------------------------------------------------------------------
  1567. void CShaderDeviceDx8::SetPresentParameters( void* hWnd, int nAdapter, const ShaderDeviceInfo_t &info, bool bSetSymbolsOnly )
  1568. {
  1569. ShaderDisplayMode_t mode;
  1570. g_pShaderDeviceMgr->GetCurrentModeInfo( &mode, nAdapter );
  1571. int backBufferWidth = 0;
  1572. int backBufferHeight = 0;
  1573. CalcBackBufferDimensions( mode, info, &backBufferWidth, &backBufferHeight );
  1574. m_AspectRatioInfo.m_flFrameBufferAspectRatio = ( float )backBufferWidth / ( float )backBufferHeight;
  1575. m_AspectRatioInfo.m_flPhysicalAspectRatio = m_AspectRatioInfo.m_flFrameBufferAspectRatio;
  1576. m_AspectRatioInfo.m_flFrameBuffertoPhysicalScalar = 1.0f;
  1577. #ifdef _PS3
  1578. // Device physical aspect ratio / framebuffer pixel aspect ratio.
  1579. m_AspectRatioInfo.m_flPhysicalAspectRatio = mode.m_flAspectRatio;
  1580. m_AspectRatioInfo.m_flFrameBuffertoPhysicalScalar = m_AspectRatioInfo.m_flPhysicalAspectRatio / m_AspectRatioInfo.m_flFrameBufferAspectRatio;
  1581. #endif
  1582. m_AspectRatioInfo.m_flPhysicalToFrameBufferScalar = 1.0f / m_AspectRatioInfo.m_flFrameBuffertoPhysicalScalar;
  1583. m_AspectRatioInfo.m_bIsWidescreen = ( m_AspectRatioInfo.m_flPhysicalAspectRatio >= 1.5999f );
  1584. if ( IsGameConsole () )
  1585. {
  1586. m_AspectRatioInfo.m_bIsHidef = backBufferHeight > 480;
  1587. }
  1588. else
  1589. {
  1590. m_AspectRatioInfo.m_bIsHidef = backBufferHeight >= 720;
  1591. }
  1592. #ifdef DX_TO_GL_ABSTRACTION
  1593. {
  1594. m_AspectRatioInfo.m_bIsHidef = backBufferHeight >= 640;
  1595. }
  1596. #endif
  1597. m_AspectRatioInfo.m_bInitialized = true;
  1598. // Set kv conditional
  1599. KeyValuesSystem()->SetKeyValuesExpressionSymbol( "WIN32WIDE", IsGameConsole() ? false : m_AspectRatioInfo.m_bIsWidescreen );
  1600. KeyValuesSystem()->SetKeyValuesExpressionSymbol( "WIN32HIDEF", IsGameConsole() ? false : m_AspectRatioInfo.m_bIsHidef );
  1601. KeyValuesSystem()->SetKeyValuesExpressionSymbol( "WIN32LODEF", IsGameConsole() ? false : !m_AspectRatioInfo.m_bIsHidef );
  1602. #if defined( _X360 )
  1603. XVIDEO_MODE videoMode;
  1604. XGetVideoMode( &videoMode );
  1605. m_AspectRatioInfo.m_bIsWidescreen = videoMode.fIsWideScreen != 0;
  1606. #endif
  1607. // Set kv conditional
  1608. KeyValuesSystem()->SetKeyValuesExpressionSymbol( "GAMECONSOLEWIDE", IsGameConsole() ? m_AspectRatioInfo.m_bIsWidescreen : false );
  1609. KeyValuesSystem()->SetKeyValuesExpressionSymbol( "GAMECONSOLEHIDEF", IsGameConsole() ? m_AspectRatioInfo.m_bIsHidef : false );
  1610. KeyValuesSystem()->SetKeyValuesExpressionSymbol( "GAMECONSOLELODEF", IsGameConsole() ? !m_AspectRatioInfo.m_bIsHidef : false );
  1611. // UI needs to layout differently for lowdef anamorphic widescreen on PS3 since we don't have square pixels there, ie:
  1612. // 720x480 widescreen
  1613. // 720x576 widescreen
  1614. KeyValuesSystem()->SetKeyValuesExpressionSymbol( "ANAMORPHIC", IsPlatformPS3() && m_AspectRatioInfo.m_bIsWidescreen && ( backBufferWidth == 720 ) );
  1615. #if defined( _X360 )
  1616. // Commented out and using presentation interval to clamp to 30fps
  1617. //
  1618. // // want 30 for 60Hz, and 25 for 50Hz (PAL)
  1619. // int nNewFpsMax = ( ( int )( videoMode.RefreshRate + 0.5f ) ) >> 1;
  1620. // // slam to either 30 or 25 so that we don't end up with any other cases.
  1621. // if( nNewFpsMax < 26 )
  1622. // {
  1623. // nNewFpsMax = 25;
  1624. // }
  1625. // else
  1626. // {
  1627. // nNewFpsMax = 30;
  1628. // }
  1629. // DevMsg( "*******Monitor refresh is %f, setting fps_max to %d*********\n", videoMode.RefreshRate, nNewFpsMax );
  1630. // ConVarRef fps_max( "fps_max" );
  1631. // fps_max.SetValue( nNewFpsMax );
  1632. #endif
  1633. #ifdef _GAMECONSOLE
  1634. // This could probably be removed, but since we are changing fps_max above, I don't want to change the behavior.
  1635. // force these to resolve now, other systems at startup will peek at them
  1636. g_pCVar->ProcessQueuedMaterialThreadConVarSets();
  1637. #endif
  1638. if ( bSetSymbolsOnly )
  1639. {
  1640. // affect no state, just update KV symbols
  1641. return;
  1642. }
  1643. HRESULT hr;
  1644. ZeroMemory( &m_PresentParameters, sizeof( m_PresentParameters ) );
  1645. m_PresentParameters.Windowed = info.m_bWindowed;
  1646. m_PresentParameters.SwapEffect = info.m_bUsingMultipleWindows ? D3DSWAPEFFECT_COPY : D3DSWAPEFFECT_DISCARD;
  1647. // for 360, we want to create it ourselves for hierarchical z support
  1648. m_PresentParameters.EnableAutoDepthStencil = IsX360() ? FALSE : TRUE;
  1649. // What back-buffer format should we use?
  1650. ImageFormat backBufferFormat = FindNearestSupportedBackBufferFormat( nAdapter,
  1651. DX8_DEVTYPE, m_AdapterFormat, info.m_DisplayMode.m_Format, info.m_bWindowed );
  1652. // What depth format should we use?
  1653. m_bUsingStencil = info.m_bUseStencil;
  1654. if ( info.m_nDXLevel >= 80 )
  1655. {
  1656. // always stencil for dx9/hdr
  1657. m_bUsingStencil = true;
  1658. }
  1659. #if defined( _X360 )
  1660. D3DFORMAT nDepthFormat = ReverseDepthOnX360() ? D3DFMT_D24FS8 : D3DFMT_D24S8;
  1661. #else
  1662. D3DFORMAT nDepthFormat = m_bUsingStencil ? D3DFMT_D24S8 : D3DFMT_D24X8;
  1663. #endif
  1664. m_PresentParameters.AutoDepthStencilFormat = FindNearestSupportedDepthFormat(
  1665. nAdapter, m_AdapterFormat, backBufferFormat, nDepthFormat );
  1666. m_PresentParameters.hDeviceWindow = (VD3DHWND)hWnd;
  1667. // store how many stencil buffer bits we have available with the depth/stencil buffer
  1668. switch( m_PresentParameters.AutoDepthStencilFormat )
  1669. {
  1670. case D3DFMT_D24S8:
  1671. m_iStencilBufferBits = 8;
  1672. break;
  1673. #if defined( _X360 )
  1674. case D3DFMT_D24FS8:
  1675. m_iStencilBufferBits = 8;
  1676. break;
  1677. #else
  1678. case D3DFMT_D24X4S4:
  1679. m_iStencilBufferBits = 4;
  1680. break;
  1681. case D3DFMT_D15S1:
  1682. m_iStencilBufferBits = 1;
  1683. break;
  1684. #endif
  1685. default:
  1686. m_iStencilBufferBits = 0;
  1687. m_bUsingStencil = false; //couldn't acquire a stencil buffer
  1688. };
  1689. if ( IsX360() || !info.m_bWindowed ) // if fullscreen
  1690. {
  1691. bool useDefault = ( info.m_DisplayMode.m_nWidth == 0 ) || ( info.m_DisplayMode.m_nHeight == 0 );
  1692. m_PresentParameters.BackBufferWidth = useDefault ? mode.m_nWidth : info.m_DisplayMode.m_nWidth;
  1693. m_PresentParameters.BackBufferHeight = useDefault ? mode.m_nHeight : info.m_DisplayMode.m_nHeight;
  1694. m_PresentParameters.BackBufferFormat = ImageLoader::ImageFormatToD3DFormat( backBufferFormat );
  1695. #if defined( _X360 )
  1696. m_PresentParameters.FrontBufferFormat = D3DFMT_LE_X8R8G8B8;
  1697. #endif
  1698. if ( !info.m_bWaitForVSync || CommandLine()->FindParm( "-forcenovsync" ) )
  1699. {
  1700. // Not vsync'd so only double buffer
  1701. m_PresentParameters.BackBufferCount = 1;
  1702. m_PresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  1703. }
  1704. else
  1705. {
  1706. // We are vsync'd and fullscreen, so allow triple buffering
  1707. static ConVarRef mat_triplebuffered( "mat_triplebuffered" );
  1708. m_PresentParameters.BackBufferCount = mat_triplebuffered.GetInt() ? 2 : 1;
  1709. #if defined( _X360 )
  1710. m_PresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_TWO;
  1711. #else
  1712. m_PresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // this is temporary until it's correctly defined on the PS3
  1713. #endif
  1714. }
  1715. m_PresentParameters.FullScreen_RefreshRateInHz = info.m_DisplayMode.m_nRefreshRateDenominator ?
  1716. info.m_DisplayMode.m_nRefreshRateNumerator / info.m_DisplayMode.m_nRefreshRateDenominator : D3DPRESENT_RATE_DEFAULT;
  1717. #if defined( _X360 )
  1718. // setup hardware scaling - should be native 720p upsampling to 1080i
  1719. if ( info.m_bScaleToOutputResolution )
  1720. {
  1721. m_PresentParameters.VideoScalerParameters.ScalerSourceRect.x2 = m_PresentParameters.BackBufferWidth;
  1722. m_PresentParameters.VideoScalerParameters.ScalerSourceRect.y2 = m_PresentParameters.BackBufferHeight;
  1723. m_PresentParameters.VideoScalerParameters.ScaledOutputWidth = videoMode.dwDisplayWidth;
  1724. m_PresentParameters.VideoScalerParameters.ScaledOutputHeight = videoMode.dwDisplayHeight;
  1725. DevMsg( "VIDEO SCALING: scaling from %dx%d to %dx%d\n", ( int )m_PresentParameters.BackBufferWidth, ( int )m_PresentParameters.BackBufferHeight,
  1726. ( int )videoMode.dwDisplayWidth, ( int )videoMode.dwDisplayHeight );
  1727. }
  1728. else
  1729. {
  1730. DevMsg( "VIDEO SCALING: No scaling: %dx%d\n", ( int )m_PresentParameters.BackBufferWidth, ( int )m_PresentParameters.BackBufferHeight );
  1731. }
  1732. #endif
  1733. }
  1734. else // if windowed
  1735. {
  1736. // NJS: We are seeing a lot of time spent in present in some cases when this isn't set.
  1737. m_PresentParameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  1738. if ( info.m_bResizing )
  1739. {
  1740. if ( info.m_bLimitWindowedSize &&
  1741. ( info.m_nWindowedSizeLimitWidth < mode.m_nWidth || info.m_nWindowedSizeLimitHeight < mode.m_nHeight ) )
  1742. {
  1743. // When using material system in windowed resizing apps, it's
  1744. // sometimes not a good idea to allocate stuff as big as the screen
  1745. // video cards can soo run out of resources
  1746. m_PresentParameters.BackBufferWidth = info.m_nWindowedSizeLimitWidth;
  1747. m_PresentParameters.BackBufferHeight = info.m_nWindowedSizeLimitHeight;
  1748. }
  1749. else
  1750. {
  1751. // When in resizing windowed mode,
  1752. // we want to allocate enough memory to deal with any resizing...
  1753. m_PresentParameters.BackBufferWidth = mode.m_nWidth;
  1754. m_PresentParameters.BackBufferHeight = mode.m_nHeight;
  1755. }
  1756. }
  1757. else
  1758. {
  1759. m_PresentParameters.BackBufferWidth = info.m_DisplayMode.m_nWidth;
  1760. m_PresentParameters.BackBufferHeight = info.m_DisplayMode.m_nHeight;
  1761. }
  1762. m_PresentParameters.BackBufferFormat = ImageLoader::ImageFormatToD3DFormat( backBufferFormat );
  1763. m_PresentParameters.BackBufferCount = 1; // Windowed, so only double buffer
  1764. }
  1765. if ( info.m_nAASamples > 0 && ( m_PresentParameters.SwapEffect == D3DSWAPEFFECT_DISCARD ) )
  1766. {
  1767. D3DMULTISAMPLE_TYPE multiSampleType = ComputeMultisampleType( info.m_nAASamples );
  1768. DWORD nQualityLevel;
  1769. // FIXME: Should we add the quality level to the ShaderAdapterMode_t struct?
  1770. // 16x on nVidia refers to CSAA or "Coverage Sampled Antialiasing"
  1771. const HardwareCaps_t &adapterCaps = g_ShaderDeviceMgrDx8.GetHardwareCaps( nAdapter );
  1772. if ( ( info.m_nAASamples == 16 ) && ( adapterCaps.m_VendorID == VENDORID_NVIDIA ) )
  1773. {
  1774. multiSampleType = ComputeMultisampleType(4);
  1775. hr = D3D()->CheckDeviceMultiSampleType( nAdapter, DX8_DEVTYPE,
  1776. m_PresentParameters.BackBufferFormat, m_PresentParameters.Windowed,
  1777. multiSampleType, &nQualityLevel ); // 4x at highest quality level
  1778. if ( !FAILED( hr ) && ( nQualityLevel == 16 ) )
  1779. {
  1780. nQualityLevel = nQualityLevel - 1; // Highest quality level triggers 16x CSAA
  1781. }
  1782. else
  1783. {
  1784. nQualityLevel = 0; // No CSAA
  1785. }
  1786. }
  1787. else // Regular MSAA on any old vendor
  1788. {
  1789. hr = D3D()->CheckDeviceMultiSampleType( nAdapter, DX8_DEVTYPE,
  1790. m_PresentParameters.BackBufferFormat, m_PresentParameters.Windowed,
  1791. multiSampleType, &nQualityLevel );
  1792. nQualityLevel = 0;
  1793. }
  1794. if ( !FAILED( hr ) )
  1795. {
  1796. m_PresentParameters.MultiSampleType = multiSampleType;
  1797. m_PresentParameters.MultiSampleQuality = nQualityLevel;
  1798. }
  1799. }
  1800. else
  1801. {
  1802. m_PresentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
  1803. m_PresentParameters.MultiSampleQuality = 0;
  1804. }
  1805. }
  1806. //-----------------------------------------------------------------------------
  1807. // Initializes, shuts down the D3D device
  1808. //-----------------------------------------------------------------------------
  1809. bool CShaderDeviceDx8::InitDevice( void* hwnd, int nAdapter, const ShaderDeviceInfo_t &info )
  1810. {
  1811. //Debugger();
  1812. // good place to run some self tests.
  1813. //#if OSX
  1814. //{
  1815. // extern void GLMgrSelfTests( void );
  1816. // GLMgrSelfTests();
  1817. //}
  1818. //#endif
  1819. // windowed
  1820. if ( !CreateD3DDevice( (VD3DHWND)hwnd, nAdapter, info ) )
  1821. return false;
  1822. // Hook up our own windows proc to get at messages to tell us when
  1823. // other instances of the material system are trying to set the mode
  1824. InstallWindowHook( (VD3DHWND)m_hWnd );
  1825. return true;
  1826. }
  1827. void CShaderDeviceDx8::ShutdownDevice()
  1828. {
  1829. if ( ( IsPC() || IsPS3() ) && IsActive() )
  1830. {
  1831. Dx9Device()->Release();
  1832. #ifdef STUBD3D
  1833. delete ( CStubD3DDevice * )Dx9Device();
  1834. #endif
  1835. #if !defined( _X360 ) && !defined( _PS3 )
  1836. Dx9Device()->ShutDownDevice();
  1837. #endif
  1838. RemoveWindowHook( (VD3DHWND)m_hWnd );
  1839. m_hWnd = 0;
  1840. }
  1841. }
  1842. //-----------------------------------------------------------------------------
  1843. // Are we using graphics?
  1844. //-----------------------------------------------------------------------------
  1845. bool CShaderDeviceDx8::IsUsingGraphics() const
  1846. {
  1847. //*****LOCK_SHADERAPI();
  1848. return IsActive();
  1849. }
  1850. //-----------------------------------------------------------------------------
  1851. // Returns the current adapter in use
  1852. //-----------------------------------------------------------------------------
  1853. int CShaderDeviceDx8::GetCurrentAdapter() const
  1854. {
  1855. LOCK_SHADERAPI();
  1856. return m_DisplayAdapter;
  1857. }
  1858. //-----------------------------------------------------------------------------
  1859. // Use this to spew information about the 3D layer
  1860. //-----------------------------------------------------------------------------
  1861. void CShaderDeviceDx8::SpewDriverInfo() const
  1862. {
  1863. LOCK_SHADERAPI();
  1864. HRESULT hr;
  1865. D3DCAPS caps;
  1866. D3DADAPTER_IDENTIFIER9 ident;
  1867. RECORD_COMMAND( DX8_GET_DEVICE_CAPS, 0 );
  1868. RECORD_COMMAND( DX8_GET_ADAPTER_IDENTIFIER, 2 );
  1869. RECORD_INT( m_nAdapter );
  1870. RECORD_INT( 0 );
  1871. Dx9Device()->GetDeviceCaps( &caps );
  1872. hr = D3D()->GetAdapterIdentifier( m_nAdapter, D3DENUM_WHQL_LEVEL, &ident );
  1873. Warning("Shader API Driver Info:\n\nDriver : %s Version : %lld\n",
  1874. ident.Driver, ident.DriverVersion.QuadPart );
  1875. Warning("Driver Description : %s\n", ident.Description );
  1876. Warning("Chipset version %d %d %d %d\n\n",
  1877. ident.VendorId, ident.DeviceId, ident.SubSysId, ident.Revision );
  1878. ShaderDisplayMode_t mode;
  1879. g_pShaderDeviceMgr->GetCurrentModeInfo( &mode, m_nAdapter );
  1880. Warning("Display mode : %d x %d @%dHz (%s)\n",
  1881. mode.m_nWidth, mode.m_nHeight, mode.m_nRefreshRateNumerator, ImageLoader::GetName( mode.m_Format ) );
  1882. Warning("Vertex Shader Version : %d.%d Pixel Shader Version : %d.%d\n",
  1883. (caps.VertexShaderVersion >> 8) & 0xFF, caps.VertexShaderVersion & 0xFF,
  1884. (caps.PixelShaderVersion >> 8) & 0xFF, caps.PixelShaderVersion & 0xFF);
  1885. Warning("\nDevice Caps :\n");
  1886. Warning("CANBLTSYSTONONLOCAL %s CANRENDERAFTERFLIP %s HWRASTERIZATION %s\n",
  1887. (caps.DevCaps & D3DDEVCAPS_CANBLTSYSTONONLOCAL) ? " Y " : " N ",
  1888. (caps.DevCaps & D3DDEVCAPS_CANRENDERAFTERFLIP) ? " Y " : " N ",
  1889. (caps.DevCaps & D3DDEVCAPS_HWRASTERIZATION) ? " Y " : "*N*" );
  1890. Warning("HWTRANSFORMANDLIGHT %s NPATCHES %s PUREDEVICE %s\n",
  1891. (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? " Y " : " N ",
  1892. (caps.DevCaps & D3DDEVCAPS_NPATCHES) ? " Y " : " N ",
  1893. (caps.DevCaps & D3DDEVCAPS_PUREDEVICE) ? " Y " : " N " );
  1894. Warning("SEPARATETEXTUREMEMORIES %s TEXTURENONLOCALVIDMEM %s TEXTURESYSTEMMEMORY %s\n",
  1895. (caps.DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) ? "*Y*" : " N ",
  1896. (caps.DevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM) ? " Y " : " N ",
  1897. (caps.DevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY) ? " Y " : " N " );
  1898. Warning("TEXTUREVIDEOMEMORY %s TLVERTEXSYSTEMMEMORY %s TLVERTEXVIDEOMEMORY %s\n",
  1899. (caps.DevCaps & D3DDEVCAPS_TEXTUREVIDEOMEMORY) ? " Y " : "*N*",
  1900. (caps.DevCaps & D3DDEVCAPS_TLVERTEXSYSTEMMEMORY) ? " Y " : "*N*",
  1901. (caps.DevCaps & D3DDEVCAPS_TLVERTEXVIDEOMEMORY) ? " Y " : " N " );
  1902. Warning("\nPrimitive Caps :\n");
  1903. Warning("BLENDOP %s CLIPPLANESCALEDPOINTS %s CLIPTLVERTS %s\n",
  1904. (caps.PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP) ? " Y " : " N ",
  1905. (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPPLANESCALEDPOINTS) ? " Y " : " N ",
  1906. (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS) ? " Y " : " N " );
  1907. Warning("COLORWRITEENABLE %s MASKZ %s TSSARGTEMP %s\n",
  1908. (caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) ? " Y " : " N ",
  1909. (caps.PrimitiveMiscCaps & D3DPMISCCAPS_MASKZ) ? " Y " : "*N*",
  1910. (caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) ? " Y " : " N " );
  1911. Warning("\nRaster Caps :\n");
  1912. Warning("FOGRANGE %s FOGTABLE %s FOGVERTEX %s ZFOG %s WFOG %s\n",
  1913. (caps.RasterCaps & D3DPRASTERCAPS_FOGRANGE) ? " Y " : " N ",
  1914. (caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) ? " Y " : " N ",
  1915. (caps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) ? " Y " : " N ",
  1916. (caps.RasterCaps & D3DPRASTERCAPS_ZFOG) ? " Y " : " N ",
  1917. (caps.RasterCaps & D3DPRASTERCAPS_WFOG) ? " Y " : " N " );
  1918. Warning("MIPMAPLODBIAS %s WBUFFER %s ZBIAS %s ZTEST %s\n",
  1919. (caps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) ? " Y " : " N ",
  1920. (caps.RasterCaps & D3DPRASTERCAPS_WBUFFER) ? " Y " : " N ",
  1921. (caps.RasterCaps & D3DPRASTERCAPS_DEPTHBIAS) ? " Y " : " N ",
  1922. (caps.RasterCaps & D3DPRASTERCAPS_ZTEST) ? " Y " : "*N*" );
  1923. Warning("Size of Texture Memory : %d kb\n", g_pHardwareConfig->Caps().m_TextureMemorySize / 1024 );
  1924. Warning("Max Texture Dimensions : %d x %d\n",
  1925. caps.MaxTextureWidth, caps.MaxTextureHeight );
  1926. if (caps.MaxTextureAspectRatio != 0)
  1927. Warning("Max Texture Aspect Ratio : *%d*\n", caps.MaxTextureAspectRatio );
  1928. Warning("Max Textures : %d\n",
  1929. caps.MaxSimultaneousTextures );
  1930. Warning("\nTexture Caps :\n");
  1931. Warning("ALPHA %s CUBEMAP %s MIPCUBEMAP %s SQUAREONLY %s\n",
  1932. (caps.TextureCaps & D3DPTEXTURECAPS_ALPHA) ? " Y " : " N ",
  1933. (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) ? " Y " : " N ",
  1934. (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP) ? " Y " : " N ",
  1935. (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) ? "*Y*" : " N " );
  1936. Warning( "vendor id: 0x%x\n", g_pHardwareConfig->ActualCaps().m_VendorID );
  1937. Warning( "device id: 0x%x\n", g_pHardwareConfig->ActualCaps().m_DeviceID );
  1938. Warning( "SHADERAPI CAPS:\n" );
  1939. Warning( "m_NumSamplers: %d\n", g_pHardwareConfig->Caps().m_NumSamplers );
  1940. Warning( "m_NumVertexSamplers: %d\n", g_pHardwareConfig->Caps().m_NumVertexSamplers );
  1941. Warning( "m_HasSetDeviceGammaRamp: %s\n", g_pHardwareConfig->Caps().m_HasSetDeviceGammaRamp ? "yes" : "no" );
  1942. Warning( "m_SupportsPixelShaders_2_b: %s\n", g_pHardwareConfig->Caps().m_SupportsPixelShaders_2_b ? "yes" : "no" );
  1943. Warning( "m_SupportsShaderModel_3_0: %s\n", g_pHardwareConfig->Caps().m_SupportsShaderModel_3_0 ? "yes" : "no" );
  1944. Warning( "m_SupportsCompressedVertices: %d\n", g_pHardwareConfig->Caps().m_SupportsCompressedVertices );
  1945. Warning( "m_bSupportsAnisotropicFiltering: %s\n", g_pHardwareConfig->Caps().m_bSupportsAnisotropicFiltering ? "yes" : "no" );
  1946. Warning( "m_nMaxAnisotropy: %d\n", g_pHardwareConfig->Caps().m_nMaxAnisotropy );
  1947. Warning( "m_MaxTextureWidth: %d\n", g_pHardwareConfig->Caps().m_MaxTextureWidth );
  1948. Warning( "m_MaxTextureHeight: %d\n", g_pHardwareConfig->Caps().m_MaxTextureHeight );
  1949. Warning( "m_MaxTextureAspectRatio: %d\n", g_pHardwareConfig->Caps().m_MaxTextureAspectRatio );
  1950. Warning( "m_MaxPrimitiveCount: %d\n", g_pHardwareConfig->Caps().m_MaxPrimitiveCount );
  1951. Warning( "m_ZBiasAndSlopeScaledDepthBiasSupported: %s\n", g_pHardwareConfig->Caps().m_ZBiasAndSlopeScaledDepthBiasSupported ? "yes" : "no" );
  1952. Warning( "m_NumPixelShaderConstants: %d\n", g_pHardwareConfig->Caps().m_NumPixelShaderConstants );
  1953. Warning( "m_NumVertexShaderConstants: %d\n", g_pHardwareConfig->Caps().m_NumVertexShaderConstants );
  1954. Warning( "m_NumBooleanVertexShaderConstants: %d\n", g_pHardwareConfig->Caps().m_NumBooleanVertexShaderConstants );
  1955. Warning( "m_NumIntegerVertexShaderConstants: %d\n", g_pHardwareConfig->Caps().m_NumIntegerVertexShaderConstants );
  1956. Warning( "m_TextureMemorySize: %d\n", g_pHardwareConfig->Caps().m_TextureMemorySize );
  1957. Warning( "m_MaxNumLights: %d\n", g_pHardwareConfig->Caps().m_MaxNumLights );
  1958. Warning( "m_MaxVertexShaderBlendMatrices: %d\n", g_pHardwareConfig->Caps().m_MaxVertexShaderBlendMatrices );
  1959. Warning( "m_SupportsMipmappedCubemaps: %s\n", g_pHardwareConfig->Caps().m_SupportsMipmappedCubemaps ? "yes" : "no" );
  1960. Warning( "m_nDXSupportLevel: %d\n", g_pHardwareConfig->Caps().m_nDXSupportLevel );
  1961. Warning( "m_PreferDynamicTextures: %s\n", g_pHardwareConfig->Caps().m_PreferDynamicTextures ? "yes" : "no" );
  1962. Warning( "m_MaxUserClipPlanes: %d\n", g_pHardwareConfig->Caps().m_MaxUserClipPlanes );
  1963. Warning( "m_SupportsSRGB: %s\n", g_pHardwareConfig->Caps().m_SupportsSRGB ? "yes" : "no" );
  1964. switch( g_pHardwareConfig->Caps().m_HDRType )
  1965. {
  1966. case HDR_TYPE_NONE:
  1967. Warning( "m_HDRType: HDR_TYPE_NONE\n" );
  1968. break;
  1969. case HDR_TYPE_INTEGER:
  1970. Warning( "m_HDRType: HDR_TYPE_INTEGER\n" );
  1971. break;
  1972. case HDR_TYPE_FLOAT:
  1973. Warning( "m_HDRType: HDR_TYPE_FLOAT\n" );
  1974. break;
  1975. default:
  1976. Assert( 0 );
  1977. break;
  1978. }
  1979. Warning( "m_UseFastClipping: %s\n", g_pHardwareConfig->Caps().m_UseFastClipping ? "yes" : "no" );
  1980. Warning( "m_pShaderDLL: %s\n", g_pHardwareConfig->Caps().m_pShaderDLL );
  1981. Warning( "m_bNeedsATICentroidHack: %s\n", g_pHardwareConfig->Caps().m_bNeedsATICentroidHack ? "yes" : "no" );
  1982. Warning( "m_bDisableShaderOptimizations: %s\n", g_pHardwareConfig->Caps().m_bDisableShaderOptimizations ? "yes" : "no" );
  1983. Warning( "m_MaxSimultaneousRenderTargets: %d\n", g_pHardwareConfig->Caps().m_MaxSimultaneousRenderTargets );
  1984. Warning( "m_bPreferZPrepass: %s\n", g_pHardwareConfig->Caps().m_bPreferZPrepass ? "yes" : "no" );
  1985. Warning( "m_bSuppressPixelShaderCentroidHackFixup: %s\n", g_pHardwareConfig->Caps().m_bSuppressPixelShaderCentroidHackFixup ? "yes" : "no" );
  1986. Warning( "m_bPreferTexturesInHWMemory: %s\n", g_pHardwareConfig->Caps().m_bPreferTexturesInHWMemory ? "yes" : "no" );
  1987. Warning( "m_bPreferHardwareSync: %s\n", g_pHardwareConfig->Caps().m_bPreferHardwareSync ? "yes" : "no" );
  1988. Warning( "m_bUnsupported: %s\n", g_pHardwareConfig->Caps().m_bUnsupported ? "yes" : "no" );
  1989. }
  1990. //-----------------------------------------------------------------------------
  1991. // Back buffer information
  1992. //-----------------------------------------------------------------------------
  1993. ImageFormat CShaderDeviceDx8::GetBackBufferFormat() const
  1994. {
  1995. return ImageLoader::D3DFormatToImageFormat( m_PresentParameters.BackBufferFormat );
  1996. }
  1997. void CShaderDeviceDx8::GetBackBufferDimensions( int& width, int& height ) const
  1998. {
  1999. width = m_PresentParameters.BackBufferWidth;
  2000. height = m_PresentParameters.BackBufferHeight;
  2001. }
  2002. const AspectRatioInfo_t &CShaderDeviceDx8::GetAspectRatioInfo() const
  2003. {
  2004. Assert( m_AspectRatioInfo.m_bInitialized );
  2005. if ( !m_AspectRatioInfo.m_bInitialized )
  2006. {
  2007. Error( "GetAspectRatioInfo called before aspect ratio is initialized!\n" );
  2008. }
  2009. return m_AspectRatioInfo;
  2010. }
  2011. //-----------------------------------------------------------------------------
  2012. // Detects support for CreateQuery
  2013. //-----------------------------------------------------------------------------
  2014. void CShaderDeviceDx8::DetectQuerySupport( IDirect3DDevice9 *pD3DDevice )
  2015. {
  2016. // Do I need to detect whether this device supports CreateQuery before creating it?
  2017. if ( m_DeviceSupportsCreateQuery != -1 )
  2018. return;
  2019. IDirect3DQuery9 *pQueryObject = NULL;
  2020. // Detect whether query is supported by creating and releasing:
  2021. HRESULT hr = pD3DDevice->CreateQuery( D3DQUERYTYPE_EVENT, &pQueryObject );
  2022. if ( !FAILED(hr) && pQueryObject )
  2023. {
  2024. pQueryObject->Release();
  2025. m_DeviceSupportsCreateQuery = 1;
  2026. }
  2027. else
  2028. {
  2029. m_DeviceSupportsCreateQuery = 0;
  2030. }
  2031. }
  2032. #ifdef _X360
  2033. void GPUHangCallback( const char *pDescription )
  2034. {
  2035. if ( !pDescription )
  2036. {
  2037. #ifdef _CERT
  2038. XboxLaunch()->Launch();
  2039. #endif
  2040. return;
  2041. }
  2042. #ifndef _CERT
  2043. Warning( pDescription );
  2044. #endif
  2045. }
  2046. #endif
  2047. #if(DIRECT3D_VERSION < 0x0900)
  2048. #define D3DDEVTYPE_NULLREF ( D3DDEVTYPE )4
  2049. #endif
  2050. //-----------------------------------------------------------------------------
  2051. // Actually creates the D3D Device once the present parameters are set up
  2052. //-----------------------------------------------------------------------------
  2053. IDirect3DDevice9* CShaderDeviceDx8::InvokeCreateDevice( void* hWnd, int nAdapter, DWORD deviceCreationFlags )
  2054. {
  2055. IDirect3DDevice9 *pD3DDevice = NULL;
  2056. D3DDEVTYPE devType = DX8_DEVTYPE;
  2057. #if NVPERFHUD
  2058. nAdapter = D3D()->GetAdapterCount()-1;
  2059. devType = D3DDEVTYPE_REF;
  2060. deviceCreationFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_HARDWARE_VERTEXPROCESSING;
  2061. #endif
  2062. if ( !IsX360() )
  2063. {
  2064. // Create the device with multi-threaded safeguards if we're using mat_queue_mode 2.
  2065. // The logic to enable multithreaded rendering happens well after the device has been created,
  2066. // so we replicate some of that logic here.
  2067. ConVarRef mat_queue_mode( "mat_queue_mode" );
  2068. if ( mat_queue_mode.GetInt() == 2 ||
  2069. ( mat_queue_mode.GetInt() == -2 && GetCPUInformation().m_nPhysicalProcessors >= 2 ) ||
  2070. ( mat_queue_mode.GetInt() == -1 && GetCPUInformation().m_nPhysicalProcessors >= 2 ) )
  2071. {
  2072. deviceCreationFlags |= D3DCREATE_MULTITHREADED;
  2073. }
  2074. }
  2075. #ifdef ENABLE_NULLREF_DEVICE_SUPPORT
  2076. devType = CommandLine()->FindParm( "-nulldevice" ) ? D3DDEVTYPE_NULLREF: devType;
  2077. #endif
  2078. #if defined ( DX_TO_GL_ABSTRACTION )
  2079. gGL = GetOpenGLEntryPoints(0);
  2080. #endif
  2081. HRESULT hr = D3D()->CreateDevice( nAdapter, devType,
  2082. (VD3DHWND)hWnd, deviceCreationFlags, &m_PresentParameters, &pD3DDevice );
  2083. if (FAILED(hr) || !pD3DDevice)
  2084. {
  2085. if ( !IsPC() )
  2086. return NULL;
  2087. // try again, other applications may be taking their time
  2088. Sleep( 1000 );
  2089. hr = D3D()->CreateDevice( nAdapter, devType, (VD3DHWND)hWnd, deviceCreationFlags, &m_PresentParameters, &pD3DDevice );
  2090. if (FAILED(hr) || !pD3DDevice)
  2091. {
  2092. // in this case, we actually are allocating too much memory....
  2093. // This will cause us to use less buffers...
  2094. if ( m_PresentParameters.Windowed )
  2095. {
  2096. m_PresentParameters.SwapEffect = D3DSWAPEFFECT_COPY;
  2097. m_PresentParameters.BackBufferCount = 0;
  2098. hr = D3D()->CreateDevice( nAdapter, devType,
  2099. (VD3DHWND)hWnd, deviceCreationFlags, &m_PresentParameters, &pD3DDevice );
  2100. }
  2101. }
  2102. }
  2103. if ( !FAILED( hr ) && pD3DDevice )
  2104. {
  2105. g_pShaderDeviceMgr->InvokeDeviceResetNotifications( pD3DDevice, &m_PresentParameters, hWnd );
  2106. #ifdef _X360
  2107. pD3DDevice->SetHangCallback( GPUHangCallback );
  2108. #endif
  2109. }
  2110. else
  2111. {
  2112. // Otherwise we failed, show a message and shutdown
  2113. pD3DDevice = NULL;
  2114. Log_Warning( LOG_EngineInitialization, "Failed to create %s device! Please see the following for more info.\n"
  2115. "http://support.steampowered.com/cgi-bin/steampowered.cfg/php/enduser/std_adp.php?p_faqid=772\n", IsOpenGL() ? "OpenGL" : "D3D" );
  2116. }
  2117. return pD3DDevice;
  2118. }
  2119. //-----------------------------------------------------------------------------
  2120. // Creates the D3D Device
  2121. //-----------------------------------------------------------------------------
  2122. bool CShaderDeviceDx8::CreateD3DDevice( void* pHWnd, int nAdapter, const ShaderDeviceInfo_t &info )
  2123. {
  2124. Assert( info.m_nVersion == SHADER_DEVICE_INFO_VERSION );
  2125. MEM_ALLOC_CREDIT_( __FILE__ ": D3D Device" );
  2126. VD3DHWND hWnd = (VD3DHWND)pHWnd;
  2127. #if ( !defined( PIX_INSTRUMENTATION ) && !defined( _X360 ) && !defined( NVPERFHUD ) )
  2128. D3DPERF_SetOptions(1); // Explicitly disallow PIX instrumented profiling in external builds
  2129. #endif
  2130. // Get some caps....
  2131. D3DCAPS caps;
  2132. HRESULT hr = D3D()->GetDeviceCaps( nAdapter, DX8_DEVTYPE, &caps );
  2133. if ( FAILED( hr ) )
  2134. return false;
  2135. // Determine the adapter format
  2136. ShaderDisplayMode_t mode;
  2137. g_pShaderDeviceMgrDx8->GetCurrentModeInfo( &mode, nAdapter );
  2138. m_AdapterFormat = mode.m_Format;
  2139. // FIXME: Need to do this prior to SetPresentParameters. Fix.
  2140. // Make it part of HardwareCaps_t
  2141. InitializeColorInformation( nAdapter, DX8_DEVTYPE, m_AdapterFormat );
  2142. Assert( D3DSupportsCompressedTextures() );
  2143. const HardwareCaps_t &adapterCaps = g_ShaderDeviceMgrDx8.GetHardwareCaps( nAdapter );
  2144. DWORD deviceCreationFlags = ComputeDeviceCreationFlags( caps, adapterCaps.m_bSoftwareVertexProcessing );
  2145. SetPresentParameters( hWnd, nAdapter, info );
  2146. // Tell all other instances of the material system to let go of memory
  2147. SendIPCMessage( RELEASE_MESSAGE );
  2148. // Create a stereo texture updater so the nvidia dll's can init. Must be BEFORE device creation!
  2149. #if !defined( _GAMECONSOLE ) && !defined(DX_TO_GL_ABSTRACTION) && ( IS_WINDOWS_PC )
  2150. nv::stereo::HL2StereoD3D9 *pStereoD3D9 = new nv::stereo::HL2StereoD3D9;
  2151. #endif
  2152. // Creates the device
  2153. IDirect3DDevice9 *pD3DDevice = InvokeCreateDevice( pHWnd, nAdapter, deviceCreationFlags );
  2154. if ( !pD3DDevice )
  2155. {
  2156. #if !defined( _GAMECONSOLE ) && !defined(DX_TO_GL_ABSTRACTION) && ( IS_WINDOWS_PC )
  2157. delete pStereoD3D9;
  2158. #endif
  2159. return false;
  2160. }
  2161. DetectQuerySupport( pD3DDevice ); // Check to see if query is supported
  2162. // This must happen AFTER device creation
  2163. #if !defined( _GAMECONSOLE ) && !defined(DX_TO_GL_ABSTRACTION) && ( IS_WINDOWS_PC )
  2164. pStereoD3D9->Init( pD3DDevice );
  2165. #endif
  2166. #ifdef STUBD3D
  2167. Dx9Device() = new CStubD3DDevice( pD3DDevice, g_pFullFileSystem );
  2168. #elif !defined( _GAMECONSOLE )
  2169. Dx9Device()->SetDevicePtr( pD3DDevice, &m_PresentParameters, pHWnd );
  2170. #if !defined( _GAMECONSOLE ) && !defined(DX_TO_GL_ABSTRACTION) && ( IS_WINDOWS_PC )
  2171. // Give pointer to d3d_async layer (it will free the memory later)
  2172. Dx9Device()->SetStereoTextureUpdater( pStereoD3D9 );
  2173. #endif
  2174. #else
  2175. m_pD3DDevice = pD3DDevice;
  2176. #endif
  2177. #if defined( _X360 )
  2178. // Create the depth buffer, created manually to enable hierarchical z
  2179. {
  2180. D3DSURFACE_PARAMETERS DepthStencilParams;
  2181. V_memset( &DepthStencilParams, 0, sizeof( DepthStencilParams ) );
  2182. // Depth is immediately after the back buffer in EDRAM
  2183. // allocate the hierarchical z tiles at the end of the area so all other allocations can trivially allocate at 0
  2184. DepthStencilParams.Base = XGSurfaceSize(
  2185. m_PresentParameters.BackBufferWidth,
  2186. m_PresentParameters.BackBufferHeight,
  2187. m_PresentParameters.BackBufferFormat,
  2188. m_PresentParameters.MultiSampleType );
  2189. DepthStencilParams.ColorExpBias = 0;
  2190. DepthStencilParams.HierarchicalZBase = GPU_HIERARCHICAL_Z_TILES - XGHierarchicalZSize( m_PresentParameters.BackBufferWidth, m_PresentParameters.BackBufferHeight, m_PresentParameters.MultiSampleType );
  2191. DepthStencilParams.HiZFunc = D3DHIZFUNC_DEFAULT;
  2192. IDirect3DSurface *pDepthStencilSurface = NULL;
  2193. hr = Dx9Device()->CreateDepthStencilSurface(
  2194. m_PresentParameters.BackBufferWidth,
  2195. m_PresentParameters.BackBufferHeight,
  2196. m_PresentParameters.AutoDepthStencilFormat,
  2197. m_PresentParameters.MultiSampleType,
  2198. m_PresentParameters.MultiSampleQuality,
  2199. TRUE,
  2200. &pDepthStencilSurface,
  2201. &DepthStencilParams );
  2202. Assert( SUCCEEDED( hr ) );
  2203. if ( FAILED( hr ) )
  2204. return false;
  2205. hr = Dx9Device()->SetDepthStencilSurface( pDepthStencilSurface );
  2206. Assert( SUCCEEDED( hr ) );
  2207. if ( FAILED( hr ) )
  2208. return false;
  2209. }
  2210. // Initialize XUI, needed for TTF font rasterization
  2211. // xui requires and shares our d3d device
  2212. {
  2213. hr = XuiRenderInitShared( pD3DDevice, &m_PresentParameters, XuiD3DXTextureLoader );
  2214. if ( FAILED( hr ) )
  2215. return false;
  2216. XUIInitParams xuiInit;
  2217. XUI_INIT_PARAMS( xuiInit );
  2218. xuiInit.dwFlags = XUI_INIT_PARAMS_FLAGS_NONE;
  2219. xuiInit.pHooks = NULL;
  2220. hr = XuiInit( &xuiInit );
  2221. if ( FAILED( hr ) )
  2222. return false;
  2223. hr = XuiRenderCreateDC( &m_hDC );
  2224. if ( FAILED( hr ) )
  2225. return false;
  2226. }
  2227. #endif
  2228. // CheckDeviceLost();
  2229. // Tell all other instances of the material system it's ok to grab memory
  2230. SendIPCMessage( REACQUIRE_MESSAGE );
  2231. m_hWnd = pHWnd;
  2232. m_nAdapter = m_DisplayAdapter = nAdapter;
  2233. m_DeviceState = DEVICE_STATE_OK;
  2234. m_bIsMinimized = false;
  2235. m_bQueuedDeviceLost = false;
  2236. m_IsResizing = info.m_bWindowed && info.m_bResizing;
  2237. // This is our current view.
  2238. m_ViewHWnd = hWnd;
  2239. GetWindowSize( m_nWindowWidth, m_nWindowHeight );
  2240. g_pHardwareConfig->SetupHardwareCaps( info, g_ShaderDeviceMgrDx8.GetHardwareCaps( nAdapter ) );
  2241. g_pHardwareConfig->CapsForEdit().m_SupportsCompressedTextures = COMPRESSED_TEXTURES_ON;
  2242. return ( !FAILED( hr ) );
  2243. }
  2244. //-----------------------------------------------------------------------------
  2245. // Frame sync
  2246. //-----------------------------------------------------------------------------
  2247. void CShaderDeviceDx8::AllocFrameSyncTextureObject()
  2248. {
  2249. if ( IsGameConsole() || IsOSX() )
  2250. return;
  2251. FreeFrameSyncTextureObject();
  2252. // Create a tiny managed texture.
  2253. HRESULT hr = Dx9Device()->CreateTexture(
  2254. 1, 1, // width, height
  2255. 0, // levels
  2256. D3DUSAGE_DYNAMIC, // usage
  2257. D3DFMT_A8R8G8B8, // format
  2258. D3DPOOL_DEFAULT,
  2259. &m_pFrameSyncTexture,
  2260. NULL );
  2261. if ( FAILED( hr ) )
  2262. {
  2263. m_pFrameSyncTexture = NULL;
  2264. }
  2265. }
  2266. void CShaderDeviceDx8::FreeFrameSyncTextureObject()
  2267. {
  2268. if ( IsGameConsole() || IsOSX() )
  2269. return;
  2270. if ( m_pFrameSyncTexture )
  2271. {
  2272. m_pFrameSyncTexture->Release();
  2273. m_pFrameSyncTexture = NULL;
  2274. }
  2275. }
  2276. void CShaderDeviceDx8::AllocFrameSyncObjects( void )
  2277. {
  2278. if ( IsGameConsole() || IsOSX() )
  2279. return;
  2280. if ( mat_debugalttab.GetBool() )
  2281. {
  2282. Warning( "mat_debugalttab: CShaderAPIDX8::AllocFrameSyncObjects\n" );
  2283. }
  2284. // Allocate the texture for frame syncing in case we force that to be on.
  2285. AllocFrameSyncTextureObject();
  2286. if ( m_DeviceSupportsCreateQuery == 0 )
  2287. {
  2288. for ( int i = 0; i < ARRAYSIZE(m_pFrameSyncQueryObject); i++ )
  2289. {
  2290. m_pFrameSyncQueryObject[i] = NULL;
  2291. m_bQueryIssued[i] = false;
  2292. }
  2293. return;
  2294. }
  2295. // FIXME FIXME FIXME!!!!! Need to record this.
  2296. for ( int i = 0; i < ARRAYSIZE(m_pFrameSyncQueryObject); i++ )
  2297. {
  2298. HRESULT hr = Dx9Device()->CreateQuery( D3DQUERYTYPE_EVENT, &m_pFrameSyncQueryObject[i] );
  2299. if( hr == D3DERR_NOTAVAILABLE )
  2300. {
  2301. Warning( "D3DQUERYTYPE_EVENT not available on this driver\n" );
  2302. Assert( m_pFrameSyncQueryObject[i] == NULL );
  2303. }
  2304. else
  2305. {
  2306. Assert( hr == D3D_OK );
  2307. Assert( m_pFrameSyncQueryObject[i] );
  2308. m_pFrameSyncQueryObject[i]->Issue( D3DISSUE_END );
  2309. m_bQueryIssued[i] = true;
  2310. }
  2311. }
  2312. }
  2313. void CShaderDeviceDx8::FreeFrameSyncObjects( void )
  2314. {
  2315. if ( IsX360() || IsOSX() )
  2316. return;
  2317. if ( mat_debugalttab.GetBool() )
  2318. {
  2319. Warning( "mat_debugalttab: CShaderAPIDX8::FreeFrameSyncObjects\n" );
  2320. }
  2321. FreeFrameSyncTextureObject();
  2322. // FIXME FIXME FIXME!!!!! Need to record this.
  2323. for ( int i = 0; i < ARRAYSIZE(m_pFrameSyncQueryObject); i++ )
  2324. {
  2325. if ( m_pFrameSyncQueryObject[i] )
  2326. {
  2327. if ( m_bQueryIssued[i] )
  2328. {
  2329. double flStartTime = Plat_FloatTime();
  2330. BOOL dummyData = 0;
  2331. HRESULT hr = S_OK;
  2332. // Make every attempt (within 2 seconds) to get the result from the query. Doing so may prevent
  2333. // crashes in the driver if we try to release outstanding queries.
  2334. do
  2335. {
  2336. hr = m_pFrameSyncQueryObject[i]->GetData( &dummyData, sizeof( dummyData ), D3DGETDATA_FLUSH );
  2337. double flCurrTime = Plat_FloatTime();
  2338. // don't wait more than 2 seconds for these
  2339. if ( flCurrTime - flStartTime > 2.00 )
  2340. break;
  2341. } while ( hr == S_FALSE );
  2342. }
  2343. #ifdef DBGFLAG_ASSERT
  2344. int nRetVal =
  2345. #endif
  2346. m_pFrameSyncQueryObject[i]->Release();
  2347. Assert( nRetVal == 0 );
  2348. m_pFrameSyncQueryObject[i] = NULL;
  2349. m_bQueryIssued[i] = false;
  2350. }
  2351. }
  2352. }
  2353. //-----------------------------------------------------------------------------
  2354. // Occurs when another application is initializing
  2355. //-----------------------------------------------------------------------------
  2356. void CShaderDeviceDx8::OtherAppInitializing( bool initializing )
  2357. {
  2358. if ( !ThreadOwnsDevice() || !ThreadInMainThread() )
  2359. {
  2360. if ( initializing )
  2361. {
  2362. ShaderUtil()->OnThreadEvent( SHADER_THREAD_OTHER_APP_START );
  2363. }
  2364. else
  2365. {
  2366. ShaderUtil()->OnThreadEvent( SHADER_THREAD_OTHER_APP_END );
  2367. }
  2368. return;
  2369. }
  2370. Assert( m_bOtherAppInitializing != initializing );
  2371. if ( !IsDeactivated() )
  2372. {
  2373. Dx9Device()->EndScene();
  2374. }
  2375. // NOTE: OtherApp is set in this way because we need to know we're
  2376. // active as we release and restore everything
  2377. CheckDeviceLost( initializing );
  2378. if ( !IsDeactivated() )
  2379. {
  2380. Dx9Device()->BeginScene();
  2381. }
  2382. }
  2383. void CShaderDeviceDx8::HandleThreadEvent( uint32 threadEvent )
  2384. {
  2385. Assert(ThreadOwnsDevice());
  2386. switch ( threadEvent )
  2387. {
  2388. case SHADER_THREAD_OTHER_APP_START:
  2389. OtherAppInitializing(true);
  2390. break;
  2391. case SHADER_THREAD_RELEASE_RESOURCES:
  2392. ReleaseResources();
  2393. break;
  2394. case SHADER_THREAD_EVICT_RESOURCES:
  2395. EvictManagedResourcesInternal();
  2396. break;
  2397. case SHADER_THREAD_RESET_RENDER_STATE:
  2398. ResetRenderState();
  2399. break;
  2400. case SHADER_THREAD_ACQUIRE_RESOURCES:
  2401. ReacquireResources();
  2402. break;
  2403. case SHADER_THREAD_OTHER_APP_END:
  2404. OtherAppInitializing(false);
  2405. break;
  2406. }
  2407. }
  2408. //-----------------------------------------------------------------------------
  2409. // We lost the device, but we have a chance to recover
  2410. //-----------------------------------------------------------------------------
  2411. bool CShaderDeviceDx8::TryDeviceReset()
  2412. {
  2413. if ( IsX360() )
  2414. return true;
  2415. // Don't try to reset the device until we're sure our resources have been released
  2416. if ( !m_bResourcesReleased )
  2417. {
  2418. return false;
  2419. }
  2420. // FIXME: Make this rebuild the Dx9Device from scratch!
  2421. // Helps with compatibility
  2422. HRESULT hr = Dx9Device()->Reset( &m_PresentParameters );
  2423. bool bResetSuccess = !FAILED(hr);
  2424. if ( bResetSuccess )
  2425. {
  2426. m_bResourcesReleased = false;
  2427. #if !defined( _GAMECONSOLE )
  2428. Dx9Device()->ReportDeviceReset();
  2429. #endif
  2430. }
  2431. return bResetSuccess;
  2432. }
  2433. //-----------------------------------------------------------------------------
  2434. // Release, reacquire resources
  2435. //-----------------------------------------------------------------------------
  2436. void CShaderDeviceDx8::ReleaseResources( bool bReleaseManagedResources /*= true*/ )
  2437. {
  2438. if ( !ThreadOwnsDevice() || !ThreadInMainThread() )
  2439. {
  2440. // We shouldn't be asked to release resources but keep mananged resources around unless
  2441. // this thread owns the device.
  2442. Assert( bReleaseManagedResources == true );
  2443. // Set our resources as not being released yet.
  2444. // We reset this in two places since release resources can be called without a call to TryDeviceReset.
  2445. m_bResourcesReleased = false;
  2446. ShaderUtil()->OnThreadEvent( SHADER_THREAD_RELEASE_RESOURCES );
  2447. return;
  2448. }
  2449. // Only the initial "ReleaseResources" actually has effect
  2450. if ( m_numReleaseResourcesRefCount ++ != 0 )
  2451. {
  2452. Warning( "ReleaseResources has no effect, now at level %d.\n", m_numReleaseResourcesRefCount );
  2453. DevWarning( "ReleaseResources called twice is a bug: use IsDeactivated to check for a valid device.\n" );
  2454. Assert( 0 );
  2455. return;
  2456. }
  2457. LOCK_SHADERAPI();
  2458. CPixEvent( PIX_VALVE_ORANGE, "ReleaseResources" );
  2459. FreeFrameSyncObjects();
  2460. FreeNonInteractiveRefreshObjects();
  2461. int nRestoreFlags = bReleaseManagedResources ? MATERIAL_RESTORE_RELEASE_MANAGED_RESOURCES : 0;
  2462. ShaderUtil()->ReleaseShaderObjects( nRestoreFlags );
  2463. MeshMgr()->ReleaseBuffers();
  2464. g_pShaderAPI->ReleaseShaderObjects( bReleaseManagedResources );
  2465. #ifdef _DEBUG
  2466. if ( MeshMgr()->BufferCount() != 0 )
  2467. {
  2468. for( int i = 0; i < MeshMgr()->BufferCount(); i++ )
  2469. {
  2470. }
  2471. }
  2472. #endif
  2473. // All meshes cleaned up?
  2474. Assert( MeshMgr()->BufferCount() == 0 );
  2475. // Signal that our resources have been released so that we can try to reset the device
  2476. m_bResourcesReleased = true;
  2477. }
  2478. void CShaderDeviceDx8::ReacquireResources()
  2479. {
  2480. ReacquireResourcesInternal();
  2481. }
  2482. void CShaderDeviceDx8::ReacquireResourcesInternal( bool bResetState, bool bForceReacquire, char const *pszForceReason )
  2483. {
  2484. if ( !ThreadOwnsDevice() || !ThreadInMainThread() )
  2485. {
  2486. if ( bResetState )
  2487. {
  2488. ShaderUtil()->OnThreadEvent( SHADER_THREAD_RESET_RENDER_STATE );
  2489. }
  2490. ShaderUtil()->OnThreadEvent( SHADER_THREAD_ACQUIRE_RESOURCES );
  2491. return;
  2492. }
  2493. if ( bForceReacquire )
  2494. {
  2495. // If we are forcing reacquire then warn if release calls are remaining unpaired
  2496. if ( m_numReleaseResourcesRefCount > 1 )
  2497. {
  2498. Warning( "Forcefully resetting device (%s), resources release level was %d.\n", pszForceReason ? pszForceReason : "unspecified", m_numReleaseResourcesRefCount );
  2499. Assert( 0 );
  2500. }
  2501. m_numReleaseResourcesRefCount = 0;
  2502. }
  2503. else
  2504. {
  2505. // Only the final "ReacquireResources" actually has effect
  2506. if ( -- m_numReleaseResourcesRefCount != 0 )
  2507. {
  2508. Warning( "ReacquireResources has no effect, now at level %d.\n", m_numReleaseResourcesRefCount );
  2509. DevWarning( "ReacquireResources being discarded is a bug: use IsDeactivated to check for a valid device.\n" );
  2510. Assert( 0 );
  2511. if ( m_numReleaseResourcesRefCount < 0 )
  2512. {
  2513. m_numReleaseResourcesRefCount = 0;
  2514. }
  2515. return;
  2516. }
  2517. }
  2518. if ( bResetState )
  2519. {
  2520. ResetRenderState();
  2521. }
  2522. LOCK_SHADERAPI();
  2523. CPixEvent event( PIX_VALVE_ORANGE, "ReacquireResources" );
  2524. #ifdef VPROF_ENABLED
  2525. VPROF_INCREMENT_GROUP_COUNTER( "reacquire_resources", COUNTER_GROUP_NO_RESET, 1 );
  2526. #endif
  2527. g_pShaderAPI->RestoreShaderObjects();
  2528. AllocFrameSyncObjects();
  2529. AllocNonInteractiveRefreshObjects();
  2530. MeshMgr()->RestoreBuffers();
  2531. ShaderUtil()->RestoreShaderObjects( CShaderDeviceMgrBase::ShaderInterfaceFactory );
  2532. }
  2533. //-----------------------------------------------------------------------------
  2534. // Changes the window size
  2535. //-----------------------------------------------------------------------------
  2536. bool CShaderDeviceDx8::ResizeWindow( const ShaderDeviceInfo_t &info )
  2537. {
  2538. if ( IsGameConsole() )
  2539. return false;
  2540. m_bPendingVideoModeChange = false;
  2541. // We don't need to do crap if the window was set up to set up
  2542. // to be resizing...
  2543. if ( info.m_bResizing )
  2544. return false;
  2545. // needs to run prior to mode change cllbacks that has dependencies on this info
  2546. // this is not the "real" set, but an earlier call to just update the dependencies
  2547. SetPresentParameters( (HWND)m_hWnd, m_DisplayAdapter, info, true );
  2548. g_pShaderDeviceMgr->InvokeModeChangeCallbacks( info.m_DisplayMode.m_nWidth, info.m_DisplayMode.m_nHeight );
  2549. SetPresentParameters( (VD3DHWND)m_hWnd, m_DisplayAdapter, info );
  2550. g_pShaderDeviceMgr->InvokeDeviceLostNotifications();
  2551. // We were ok, now we're not. Release resources
  2552. ReleaseResources( ( g_pShaderUtil->GetThreadMode() != MATERIAL_QUEUED_THREADED ) );
  2553. m_DeviceState = DEVICE_STATE_NEEDS_RESET;
  2554. return true;
  2555. }
  2556. //-----------------------------------------------------------------------------
  2557. // Queue up the fact that the device was lost
  2558. //-----------------------------------------------------------------------------
  2559. void CShaderDeviceDx8::MarkDeviceLost( )
  2560. {
  2561. if ( IsX360() )
  2562. return;
  2563. m_bQueuedDeviceLost = true;
  2564. }
  2565. //-----------------------------------------------------------------------------
  2566. // Checks if the device was lost
  2567. //-----------------------------------------------------------------------------
  2568. #if defined( _DEBUG ) && !defined( _X360 )
  2569. ConVar mat_forcelostdevice( "mat_forcelostdevice", "0" );
  2570. #endif
  2571. void CShaderDeviceDx8::CheckDeviceLost( bool bOtherAppInitializing )
  2572. {
  2573. #if !defined( _X360 )
  2574. // FIXME: We could also queue up if WM_SIZE changes and look at that
  2575. // but that seems to only make sense if we have resizable windows where
  2576. // we do *not* allocate buffers as large as the entire current video mode
  2577. // which we're not doing
  2578. #ifdef _WIN32
  2579. m_bIsMinimized = ( static_cast<BOOL>(IsIconic( ( HWND )m_hWnd )) == (BOOL)TRUE );
  2580. #else
  2581. m_bIsMinimized = ( IsIconic( (VD3DHWND)m_hWnd ) == TRUE );
  2582. #endif
  2583. m_bOtherAppInitializing = bOtherAppInitializing;
  2584. RECORD_COMMAND( DX8_TEST_COOPERATIVE_LEVEL, 0 );
  2585. HRESULT hr = Dx9Device()->TestCooperativeLevel();
  2586. #ifdef _DEBUG
  2587. if ( mat_forcelostdevice.GetBool() )
  2588. {
  2589. mat_forcelostdevice.SetValue( 0 );
  2590. MarkDeviceLost();
  2591. }
  2592. #endif
  2593. // If some other call returned device lost previously in the frame, spoof the return value from TCL
  2594. if ( m_bQueuedDeviceLost )
  2595. {
  2596. hr = (hr != D3D_OK) ? hr : D3DERR_DEVICENOTRESET;
  2597. m_bQueuedDeviceLost = false;
  2598. }
  2599. if ( m_DeviceState == DEVICE_STATE_OK )
  2600. {
  2601. // Release managed resources if we're anything but in MATERIAL_QUEUED_THREADED. MATERIAL_QUEUED_THREADED is a proxy for whether
  2602. // we're actually running the game or in the middle of some loading or concommand that might load gpu resources. This isn't the best
  2603. // approach. What we really want is whether we're done loading managed resources or not. However, it's not entirely clear that
  2604. // we can bracket that. The upside of using the threadmode is that we are pretty much guaranteed that we don't be in the middle of
  2605. // loading. The downside is that on single core PCs, we'll always use the old and slow bReleaseManagedResources == true path that we
  2606. // had in l4d1 and previous titles.
  2607. bool bReleaseManagedResources = ( g_pShaderUtil->GetThreadMode() != MATERIAL_QUEUED_THREADED );
  2608. // We can transition out of ok if bOtherAppInitializing is set
  2609. // or if we become minimized, or if TCL returns anything other than D3D_OK.
  2610. if ( ( hr != D3D_OK ) || m_bIsMinimized )
  2611. {
  2612. // purge unreferenced materials
  2613. g_pShaderUtil->UncacheUnusedMaterials( true );
  2614. g_pShaderDeviceMgr->InvokeDeviceLostNotifications();
  2615. // We were ok, now we're not. Release resources
  2616. ReleaseResources( bReleaseManagedResources );
  2617. m_DeviceState = DEVICE_STATE_LOST_DEVICE;
  2618. }
  2619. else if ( bOtherAppInitializing )
  2620. {
  2621. // purge unreferenced materials
  2622. g_pShaderUtil->UncacheUnusedMaterials( true );
  2623. g_pShaderDeviceMgr->InvokeDeviceLostNotifications();
  2624. // We were ok, now we're not. Release resources
  2625. ReleaseResources( bReleaseManagedResources );
  2626. m_DeviceState = DEVICE_STATE_OTHER_APP_INIT;
  2627. }
  2628. }
  2629. // Immediately checking devicelost after ok helps in the case where we got D3DERR_DEVICENOTRESET
  2630. // in which case we want to immdiately try to switch out of DEVICE_STATE_LOST and into DEVICE_STATE_NEEDS_RESET
  2631. if ( m_DeviceState == DEVICE_STATE_LOST_DEVICE )
  2632. {
  2633. // We can only try to reset if we're not minimized and not lost
  2634. if ( !m_bIsMinimized && (hr != D3DERR_DEVICELOST) )
  2635. {
  2636. m_DeviceState = DEVICE_STATE_NEEDS_RESET;
  2637. }
  2638. }
  2639. // Immediately checking needs reset also helps for the case where we got D3DERR_DEVICENOTRESET
  2640. if ( m_DeviceState == DEVICE_STATE_NEEDS_RESET )
  2641. {
  2642. if ( ( hr == D3DERR_DEVICELOST ) || m_bIsMinimized )
  2643. {
  2644. m_DeviceState = DEVICE_STATE_LOST_DEVICE;
  2645. }
  2646. else
  2647. {
  2648. bool bResetSucceeded = TryDeviceReset();
  2649. if ( bResetSucceeded )
  2650. {
  2651. if ( !bOtherAppInitializing )
  2652. {
  2653. m_DeviceState = DEVICE_STATE_OK;
  2654. // purge unreferenced materials
  2655. g_pShaderUtil->UncacheUnusedMaterials( true );
  2656. // We were bad, now we're ok. Restore resources and reset render state.
  2657. ReacquireResourcesInternal( true, true, "NeedsReset" );
  2658. }
  2659. else
  2660. {
  2661. m_DeviceState = DEVICE_STATE_OTHER_APP_INIT;
  2662. }
  2663. }
  2664. }
  2665. }
  2666. if ( m_DeviceState == DEVICE_STATE_OTHER_APP_INIT )
  2667. {
  2668. if ( ( hr != D3D_OK ) || m_bIsMinimized )
  2669. {
  2670. m_DeviceState = DEVICE_STATE_LOST_DEVICE;
  2671. }
  2672. else if ( !bOtherAppInitializing )
  2673. {
  2674. m_DeviceState = DEVICE_STATE_OK;
  2675. // purge unreferenced materials
  2676. g_pShaderUtil->UncacheUnusedMaterials( true );
  2677. #if !defined( _GAMECONSOLE )
  2678. Dx9Device()->ReportDeviceReset();
  2679. #else
  2680. g_pShaderDeviceMgr->InvokeDeviceResetNotifications( m_pD3DDevice, &m_PresentParameters, m_hWnd );
  2681. #endif
  2682. // We were bad, now we're ok. Restore resources and reset render state.
  2683. ReacquireResourcesInternal( true, true, "OtherAppInit" );
  2684. }
  2685. }
  2686. // Do mode change if we have a video mode change.
  2687. if ( m_bPendingVideoModeChange && !IsDeactivated() )
  2688. {
  2689. #ifdef _DEBUG
  2690. Warning( "mode change!\n" );
  2691. #endif
  2692. ResizeWindow( m_PendingVideoModeChangeConfig );
  2693. }
  2694. #endif
  2695. }
  2696. bool CShaderDeviceDx8::BuildStaticShader( bool bVertexShader, void **ppShader, const char *pShaderName,
  2697. const char *strShaderProgram, const DWORD *shaderData, unsigned int shaderSize )
  2698. {
  2699. #if defined( X360_LINK_WITH_SHADER_COMPILE )
  2700. // Compile our shader from HLSL-in-a-string
  2701. ID3DXBuffer *pErrorMsg = NULL;
  2702. ID3DXBuffer *pShaderCode = NULL;
  2703. const char *shaderModel = bVertexShader ? "vs_2_0" : "ps_2_0";
  2704. HRESULT hr = D3DXCompileShader( strShaderProgram, (UINT)strlen( strShaderProgram ), NULL, NULL, "main", shaderModel, 0, &pShaderCode, &pErrorMsg, NULL );
  2705. if ( FAILED( hr ) )
  2706. return false;
  2707. // Check that our static shader data is valid
  2708. if ( ( shaderSize != pShaderCode->GetBufferSize() ) || memcmp( shaderData, pShaderCode->GetBufferPointer(), shaderSize ) )
  2709. {
  2710. // Use the fallback compiled-from-string data
  2711. shaderData = (DWORD*)pShaderCode->GetBufferPointer();
  2712. shaderSize = pShaderCode->GetBufferSize();
  2713. #if defined( _CERT )
  2714. #error "X360_LINK_WITH_SHADER_COMPILE should not be defined when _CERT is defined!! Only use it when revving XDK."
  2715. #endif
  2716. // Force a crash, so the user will attach a debugger and thus see the below spew
  2717. char *p = 0;
  2718. *p = 0;
  2719. // Shader data needs updating - allow me to spew it out for your cut'n'paste convenience
  2720. Plat_DebugString( "\n\nERROR: static shader data in RestorePersistedDisplay needs updating for new XDK/compiler version! (" );
  2721. Plat_DebugString( pShaderName );
  2722. Plat_DebugString( ")\nconst DWORD shaderData[] = {\n " );
  2723. int numLines = ( shaderSize + 31 ) / 32;
  2724. for ( int i = 0; i < numLines; i++ )
  2725. {
  2726. int numWords = MIN( 8, ( ( shaderSize / 4 ) - i*8 ) );
  2727. for ( int j = 0; j < numWords; j++ )
  2728. {
  2729. char wordBuffer[ 32 ];
  2730. V_snprintf( wordBuffer, sizeof( wordBuffer ), "0x%08x, ", shaderData[ i*8 + j ] );
  2731. Plat_DebugString( wordBuffer );
  2732. }
  2733. Plat_DebugString( "\n " );
  2734. }
  2735. Plat_DebugString( "};\n\n" );
  2736. }
  2737. #endif // defined( X360_LINK_WITH_SHADER_COMPILE )
  2738. if ( bVertexShader )
  2739. {
  2740. #ifdef _GAMECONSOLE
  2741. Dx9Device()->CreateVertexShader( shaderData, (IDirect3DVertexShader9 **)ppShader );
  2742. #else
  2743. Dx9Device()->CreateVertexShader( shaderData, (IDirect3DVertexShader9 **)ppShader, pShaderName );
  2744. #endif
  2745. }
  2746. else
  2747. {
  2748. #ifdef _GAMECONSOLE
  2749. Dx9Device()->CreatePixelShader( shaderData, (IDirect3DPixelShader9 **)ppShader );
  2750. #else
  2751. Dx9Device()->CreatePixelShader( shaderData, (IDirect3DPixelShader9 **)ppShader, pShaderName );
  2752. #endif
  2753. }
  2754. #if defined( X360_LINK_WITH_SHADER_COMPILE )
  2755. pShaderCode->Release();
  2756. pShaderCode = NULL;
  2757. if ( pErrorMsg )
  2758. {
  2759. pErrorMsg->Release();
  2760. pErrorMsg = NULL;
  2761. }
  2762. #endif // defined( X360_LINK_WITH_SHADER_COMPILE )
  2763. return true;
  2764. }
  2765. //-----------------------------------------------------------------------------
  2766. // Special method to refresh the screen on the XBox360
  2767. //-----------------------------------------------------------------------------
  2768. bool CShaderDeviceDx8::AllocNonInteractiveRefreshObjects()
  2769. {
  2770. #if defined( _GAMECONSOLE )
  2771. #if defined( _X360 )
  2772. // HLSL source for the refresh shaders:
  2773. const char *strVertexShaderProgram =
  2774. " float4x4 matWVP : register(c0);"
  2775. " struct VS_IN"
  2776. " {"
  2777. " float4 ObjPos : POSITION;"
  2778. " float2 TexCoord : TEXCOORD;"
  2779. " };"
  2780. " struct VS_OUT"
  2781. " {"
  2782. " float4 ProjPos : POSITION;"
  2783. " float2 TexCoord : TEXCOORD;"
  2784. " };"
  2785. " VS_OUT main( VS_IN In )"
  2786. " {"
  2787. " VS_OUT Out; "
  2788. " Out.ProjPos = mul( matWVP, In.ObjPos );"
  2789. " Out.TexCoord = In.TexCoord;"
  2790. " return Out;"
  2791. " }";
  2792. const char *strPixelShaderProgram =
  2793. " struct PS_IN"
  2794. " {"
  2795. " float2 TexCoord : TEXCOORD;"
  2796. " };"
  2797. " sampler detail : register( s0 );"
  2798. " float4 main( PS_IN In ) : COLOR"
  2799. " {"
  2800. " return tex2D( detail, In.TexCoord );"
  2801. " }";
  2802. const char *strPixelShaderProgram2 =
  2803. " struct PS_IN"
  2804. " {"
  2805. " float2 TexCoord : TEXCOORD;"
  2806. " };"
  2807. " sampler detail : register( s0 );"
  2808. " float4 main( PS_IN In ) : COLOR"
  2809. " {"
  2810. " return tex2D( detail, In.TexCoord );"
  2811. " }";
  2812. const char *strPixelShaderProgram3 =
  2813. " struct PS_IN"
  2814. " {"
  2815. " float2 TexCoord : TEXCOORD;"
  2816. " };"
  2817. " float SrgbGammaToLinear( float flSrgbGammaValue )"
  2818. " {"
  2819. " float x = saturate( flSrgbGammaValue );"
  2820. " return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) );"
  2821. " }"
  2822. " float X360LinearToGamma( float flLinearValue )"
  2823. " {"
  2824. " float fl360GammaValue;"
  2825. " flLinearValue = saturate( flLinearValue );"
  2826. " if ( flLinearValue < ( 128.0f / 1023.0f ) )"
  2827. " {"
  2828. " if ( flLinearValue < ( 64.0f / 1023.0f ) )"
  2829. " {"
  2830. " fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) );"
  2831. " }"
  2832. " else"
  2833. " {"
  2834. " fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f );"
  2835. " }"
  2836. " }"
  2837. " else"
  2838. " {"
  2839. " if ( flLinearValue < ( 512.0f / 1023.0f ) )"
  2840. " {"
  2841. " fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f );"
  2842. " }"
  2843. " else"
  2844. " {"
  2845. " fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f );"
  2846. " if ( fl360GammaValue > 1.0f )"
  2847. " {"
  2848. " fl360GammaValue = 1.0f;"
  2849. " }"
  2850. " }"
  2851. " }"
  2852. " fl360GammaValue = saturate( fl360GammaValue );"
  2853. " return fl360GammaValue;"
  2854. " }"
  2855. " sampler detail : register( s0 );"
  2856. " float4 main( PS_IN In ) : COLOR"
  2857. " {"
  2858. " float4 vTextureColor = tex2D( detail, In.TexCoord );"
  2859. // Only needed in TOB, not needed for L4D which had a corrected offline PWL processing
  2860. // " vTextureColor.r = X360LinearToGamma( SrgbGammaToLinear( vTextureColor.r ) );"
  2861. // " vTextureColor.g = X360LinearToGamma( SrgbGammaToLinear( vTextureColor.g ) );"
  2862. // " vTextureColor.b = X360LinearToGamma( SrgbGammaToLinear( vTextureColor.b ) );"
  2863. " return vTextureColor;"
  2864. " }";
  2865. // Hard-coded compiled shader data, so we don't have to bloat our DLLs
  2866. // with all the shader compilation stuff from the D3D libs (over 2 MB!)
  2867. #if defined( _X360 ) && ( _XDK_VER != 20764 )
  2868. // Make sure this hard-coded shader data gets updated with each XDK rev
  2869. #if !defined( JUNE_2009_XDK_ISSUES )
  2870. #error "Define X360_LINK_WITH_SHADER_COMPILE temporarily (to verify compiled static shader data, and spew out new data if necessary)"
  2871. #endif
  2872. #endif
  2873. DWORD vertexShaderData[] = {
  2874. 0x102a1101, 0x000000bc, 0x00000084, 0x00000000, 0x00000024, 0x00000000, 0x00000084, 0x00000000,
  2875. 0x00000000, 0x0000005c, 0x0000001c, 0x0000004f, 0xfffe0300, 0x00000001, 0x0000001c, 0x00000000,
  2876. 0x00000048, 0x00000030, 0x00020000, 0x00040000, 0x00000038, 0x00000000, 0x6d617457, 0x565000ab,
  2877. 0x00030003, 0x00040004, 0x00010000, 0x00000000, 0x76735f33, 0x5f300032, 0x2e302e32, 0x30373634,
  2878. 0x2e3000ab, 0x00000000, 0x00000084, 0x00010002, 0x00000000, 0x00000000, 0x00000821, 0x00000001,
  2879. 0x00000002, 0x00000001, 0x00000290, 0x00100003, 0x00305004, 0x00003050, 0x00001009, 0x30052003,
  2880. 0x00001200, 0xc2000000, 0x00004005, 0x00001200, 0xc4000000, 0x00001009, 0x00002200, 0x00000000,
  2881. 0x05f82000, 0x00000688, 0x00000000, 0x05f80000, 0x00000fc8, 0x00000000, 0xc80f0001, 0x001b8800,
  2882. 0xa1020300, 0xc80f0001, 0x00c68800, 0xab020201, 0xc80f0001, 0x00b13494, 0xab020101, 0xc80f803e,
  2883. 0x006c0034, 0xab020001, 0xc8038000, 0x00b0b000, 0xe2000000, 0x00000000, 0x00000000, 0x00000000,
  2884. };
  2885. DWORD pixelShaderData1[] = {
  2886. 0x102a1100, 0x000000a8, 0x0000003c, 0x00000000, 0x00000024, 0x00000000, 0x00000084, 0x00000000,
  2887. 0x00000000, 0x0000005c, 0x0000001c, 0x0000004f, 0xffff0300, 0x00000001, 0x0000001c, 0x00000000,
  2888. 0x00000048, 0x00000030, 0x00030000, 0x00010000, 0x00000038, 0x00000000, 0x64657461, 0x696c00ab,
  2889. 0x0004000c, 0x00010001, 0x00010000, 0x00000000, 0x70735f33, 0x5f300032, 0x2e302e32, 0x30373634,
  2890. 0x2e3000ab, 0x00000000, 0x0000003c, 0x10000000, 0x00000004, 0x00000000, 0x00000821, 0x00010001,
  2891. 0x00000001, 0x00003050, 0x00011002, 0x00001200, 0xc4000000, 0x00001003, 0x00002200, 0x00000000,
  2892. 0x10080001, 0x1f1ff688, 0x00004000, 0xc80f8000, 0x00000000, 0xe2000000, 0x00000000, 0x00000000,
  2893. 0x00000000,
  2894. };
  2895. DWORD pixelShaderData2[] = {
  2896. 0x102a1100, 0x000000a8, 0x0000003c, 0x00000000, 0x00000024, 0x00000000, 0x00000084, 0x00000000,
  2897. 0x00000000, 0x0000005c, 0x0000001c, 0x0000004f, 0xffff0300, 0x00000001, 0x0000001c, 0x00000000,
  2898. 0x00000048, 0x00000030, 0x00030000, 0x00010000, 0x00000038, 0x00000000, 0x64657461, 0x696c00ab,
  2899. 0x0004000c, 0x00010001, 0x00010000, 0x00000000, 0x70735f33, 0x5f300032, 0x2e302e32, 0x30373634,
  2900. 0x2e3000ab, 0x00000000, 0x0000003c, 0x10000000, 0x00000004, 0x00000000, 0x00000821, 0x00010001,
  2901. 0x00000001, 0x00003050, 0x00011002, 0x00001200, 0xc4000000, 0x00001003, 0x00002200, 0x00000000,
  2902. 0x10080001, 0x1f1ff688, 0x00004000, 0xc80f8000, 0x00000000, 0xe2000000, 0x00000000, 0x00000000,
  2903. 0x00000000,
  2904. };
  2905. DWORD pixelShaderData3[] = {
  2906. 0x102a1100, 0x000000a8, 0x0000003c, 0x00000000, 0x00000024, 0x00000000, 0x00000084, 0x00000000,
  2907. 0x00000000, 0x0000005c, 0x0000001c, 0x0000004f, 0xffff0300, 0x00000001, 0x0000001c, 0x00000000,
  2908. 0x00000048, 0x00000030, 0x00030000, 0x00010000, 0x00000038, 0x00000000, 0x64657461, 0x696c00ab,
  2909. 0x0004000c, 0x00010001, 0x00010000, 0x00000000, 0x70735f33, 0x5f300032, 0x2e302e32, 0x30373634,
  2910. 0x2e3000ab, 0x00000000, 0x0000003c, 0x10000000, 0x00000004, 0x00000000, 0x00000821, 0x00010001,
  2911. 0x00000001, 0x00003050, 0x00011002, 0x00001200, 0xc4000000, 0x00001003, 0x00002200, 0x00000000,
  2912. 0x10080001, 0x1f1ff688, 0x00004000, 0xc80f8000, 0x00000000, 0xe2000000, 0x00000000, 0x00000000,
  2913. 0x00000000,
  2914. };
  2915. // Build the requisite shaders:
  2916. if ( !BuildStaticShader( true, (void **)&m_NonInteractiveRefresh.m_pVertexShader, "m_pVertexShader",
  2917. strVertexShaderProgram, vertexShaderData, sizeof( vertexShaderData ) ) )
  2918. return false;
  2919. if ( !BuildStaticShader( false, (void **)&m_NonInteractiveRefresh.m_pPixelShader, "m_pPixelShader",
  2920. strPixelShaderProgram, pixelShaderData1, sizeof( pixelShaderData1 ) ) )
  2921. return false;
  2922. if ( !BuildStaticShader( false, (void **)&m_NonInteractiveRefresh.m_pPixelShaderStartup, "m_pPixelShaderStartup",
  2923. strPixelShaderProgram2, pixelShaderData2, sizeof( pixelShaderData2 ) ) )
  2924. return false;
  2925. if ( !BuildStaticShader( false, (void **)&m_NonInteractiveRefresh.m_pPixelShaderStartupPass2, "m_pPixelShaderStartupPass2",
  2926. strPixelShaderProgram3, pixelShaderData3, sizeof( pixelShaderData3 ) ) )
  2927. return false;
  2928. #elif defined( _PS3 )
  2929. extern uint32_t _binary_noninteractiveshader_vpo_start;
  2930. extern uint32_t _binary_noninteractiveshader_vpo_end;
  2931. extern uint32_t _binary_noninteractiveshader_fpo_start;
  2932. extern uint32_t _binary_noninteractiveshader_fpo_end;
  2933. extern uint32_t _binary_noninteractiveshaderstartup_fpo_start;
  2934. extern uint32_t _binary_noninteractiveshaderstartup_fpo_end;
  2935. extern uint32_t _binary_noninteractiveshaderstartuppass2_fpo_start;
  2936. extern uint32_t _binary_noninteractiveshaderstartuppass2_fpo_end;
  2937. Dx9Device()->CreateVertexShader( ( const DWORD* )&_binary_noninteractiveshader_vpo_start, &m_NonInteractiveRefresh.m_pVertexShader, "m_pVertexShader" );
  2938. Dx9Device()->CreatePixelShader( ( const DWORD* )&_binary_noninteractiveshader_fpo_start, &m_NonInteractiveRefresh.m_pPixelShader, "m_pPixelShader" );
  2939. Dx9Device()->CreatePixelShader( ( const DWORD* )&_binary_noninteractiveshaderstartup_fpo_start, &m_NonInteractiveRefresh.m_pPixelShaderStartup, "m_pPixelShaderStartup" );
  2940. Dx9Device()->CreatePixelShader( ( const DWORD* )&_binary_noninteractiveshaderstartuppass2_fpo_start, &m_NonInteractiveRefresh.m_pPixelShaderStartupPass2, "m_pPixelShaderStartupPass2" );
  2941. #endif
  2942. D3DVERTEXELEMENT9 VertexElements[4] =
  2943. {
  2944. { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
  2945. { 0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
  2946. D3DDECL_END()
  2947. };
  2948. // Create a vertex declaration from the element descriptions.
  2949. Dx9Device()->CreateVertexDeclaration( VertexElements, &m_NonInteractiveRefresh.m_pVertexDecl );
  2950. #endif
  2951. return true;
  2952. }
  2953. void CShaderDeviceDx8::FreeNonInteractiveRefreshObjects()
  2954. {
  2955. if ( m_NonInteractiveRefresh.m_pVertexShader )
  2956. {
  2957. m_NonInteractiveRefresh.m_pVertexShader->Release();
  2958. m_NonInteractiveRefresh.m_pVertexShader = NULL;
  2959. }
  2960. if ( m_NonInteractiveRefresh.m_pPixelShader )
  2961. {
  2962. m_NonInteractiveRefresh.m_pPixelShader->Release();
  2963. m_NonInteractiveRefresh.m_pPixelShader = NULL;
  2964. }
  2965. if ( m_NonInteractiveRefresh.m_pPixelShaderStartup )
  2966. {
  2967. m_NonInteractiveRefresh.m_pPixelShaderStartup->Release();
  2968. m_NonInteractiveRefresh.m_pPixelShaderStartup = NULL;
  2969. }
  2970. if ( m_NonInteractiveRefresh.m_pPixelShaderStartupPass2 )
  2971. {
  2972. m_NonInteractiveRefresh.m_pPixelShaderStartupPass2->Release();
  2973. m_NonInteractiveRefresh.m_pPixelShaderStartupPass2 = NULL;
  2974. }
  2975. if ( m_NonInteractiveRefresh.m_pVertexDecl )
  2976. {
  2977. m_NonInteractiveRefresh.m_pVertexDecl->Release();
  2978. m_NonInteractiveRefresh.m_pVertexDecl = NULL;
  2979. }
  2980. }
  2981. bool CShaderDeviceDx8::InNonInteractiveMode() const
  2982. {
  2983. return m_NonInteractiveRefresh.m_Mode != MATERIAL_NON_INTERACTIVE_MODE_NONE;
  2984. }
  2985. void CShaderDeviceDx8::EnableNonInteractiveMode( MaterialNonInteractiveMode_t mode, ShaderNonInteractiveInfo_t *pInfo )
  2986. {
  2987. if ( !IsGameConsole() )
  2988. return;
  2989. if ( pInfo && ( pInfo->m_hTempFullscreenTexture == INVALID_SHADERAPI_TEXTURE_HANDLE ) )
  2990. {
  2991. mode = MATERIAL_NON_INTERACTIVE_MODE_NONE;
  2992. }
  2993. if ( ( mode == MATERIAL_NON_INTERACTIVE_MODE_STARTUP ) && ( !pInfo || ( pInfo->m_nPacifierCount <= 0 ) ) )
  2994. {
  2995. Warning( "Badness! Non interactive startup mode wasn't given a pacifier texture!\n" );
  2996. }
  2997. m_NonInteractiveRefresh.m_Mode = mode;
  2998. if ( pInfo )
  2999. {
  3000. m_NonInteractiveRefresh.m_Info = *pInfo;
  3001. }
  3002. m_NonInteractiveRefresh.m_nPacifierFrame = 0;
  3003. if ( mode != MATERIAL_NON_INTERACTIVE_MODE_NONE )
  3004. {
  3005. ConVarRef mat_monitorgamma( "mat_monitorgamma" );
  3006. ConVarRef mat_monitorgamma_tv_range_min( "mat_monitorgamma_tv_range_min" );
  3007. ConVarRef mat_monitorgamma_tv_range_max( "mat_monitorgamma_tv_range_max" );
  3008. ConVarRef mat_monitorgamma_tv_exp( "mat_monitorgamma_tv_exp" );
  3009. ConVarRef mat_monitorgamma_tv_enabled( "mat_monitorgamma_tv_enabled" );
  3010. SetHardwareGammaRamp( mat_monitorgamma.GetFloat(), mat_monitorgamma_tv_range_min.GetFloat(), mat_monitorgamma_tv_range_max.GetFloat(),
  3011. mat_monitorgamma_tv_exp.GetFloat(), mat_monitorgamma_tv_enabled.GetBool() );
  3012. }
  3013. #ifdef _X360
  3014. if ( mode != MATERIAL_NON_INTERACTIVE_MODE_NONE )
  3015. {
  3016. // HACK: VSync off (prevents us wasting time blocking on VSync due to our irregular present intervals)
  3017. Dx9Device()->SetRenderState( D3DRS_PRESENTINTERVAL, D3DPRESENT_INTERVAL_IMMEDIATE );
  3018. }
  3019. else
  3020. {
  3021. // HACK: VSync on if we want it.
  3022. Dx9Device()->SetRenderState( D3DRS_PRESENTINTERVAL, m_PresentParameters.PresentationInterval );
  3023. }
  3024. #elif defined (_PS3)
  3025. if ( mode != MATERIAL_NON_INTERACTIVE_MODE_NONE )
  3026. {
  3027. // HACK: VSync off (prevents us wasting time blocking on VSync due to our irregular present intervals)
  3028. g_ps3gcmGlobalState.SetFastFlip(1);
  3029. }
  3030. else
  3031. {
  3032. // HACK: VSync on if we want it.
  3033. g_ps3gcmGlobalState.SetFastFlip(0);
  3034. }
  3035. #endif
  3036. // Msg( "Time elapsed: %.3f Peak %.3f Ave %.5f Count %d Count Above %d\n", Plat_FloatTime() - m_NonInteractiveRefresh.m_flStartTime,
  3037. // m_NonInteractiveRefresh.m_flPeakDt, m_NonInteractiveRefresh.m_flTotalDt / m_NonInteractiveRefresh.m_nSamples, m_NonInteractiveRefresh.m_nSamples, m_NonInteractiveRefresh.m_nCountAbove66 );
  3038. m_NonInteractiveRefresh.m_flStartTime = m_NonInteractiveRefresh.m_flLastPresentTime =
  3039. m_NonInteractiveRefresh.m_flLastPacifierTime = Plat_FloatTime();
  3040. m_NonInteractiveRefresh.m_flPeakDt = 0.0f;
  3041. m_NonInteractiveRefresh.m_flTotalDt = 0.0f;
  3042. m_NonInteractiveRefresh.m_nSamples = 0;
  3043. m_NonInteractiveRefresh.m_nCountAbove66 = 0;
  3044. }
  3045. void CShaderDeviceDx8::UpdatePresentStats()
  3046. {
  3047. float t = Plat_FloatTime();
  3048. float flActualDt = t - m_NonInteractiveRefresh.m_flLastPresentTime;
  3049. if ( flActualDt > m_NonInteractiveRefresh.m_flPeakDt )
  3050. {
  3051. m_NonInteractiveRefresh.m_flPeakDt = flActualDt;
  3052. }
  3053. if ( flActualDt > 0.066 )
  3054. {
  3055. ++m_NonInteractiveRefresh.m_nCountAbove66;
  3056. if ( mat_spew_long_frames.GetBool() )
  3057. {
  3058. Warning( "****LONG FRAME: %04d>66ms\n", ( int )( flActualDt * 1000 ) );
  3059. }
  3060. }
  3061. m_NonInteractiveRefresh.m_flTotalDt += flActualDt;
  3062. ++m_NonInteractiveRefresh.m_nSamples;
  3063. t = Plat_FloatTime();
  3064. m_NonInteractiveRefresh.m_flLastPresentTime = t;
  3065. }
  3066. // at least on PS/3, framerate is capped at 30 fps (33ms) and trying to Present every
  3067. // 15 ms will cause a backlog of frames to render, which will effectively stall every Present after the first 2 for 33ms
  3068. #define LOADING_PRESENT_UPDATE_INTERVAL 0.05f
  3069. float g_flLastUpdateTime = 0.0f;
  3070. bool g_bInSwap = false;
  3071. #ifdef _PS3
  3072. struct Vector4
  3073. {
  3074. Vector4(){}
  3075. Vector4( float fx, float fy, float fz, float fw) { x=fx;y=fy;z=fz;w=fw; }
  3076. float x,y,z,w;
  3077. };
  3078. struct Matrix4x4
  3079. {
  3080. Vector4 r[4];
  3081. };
  3082. Matrix4x4 Matrix4x4OrthographicOffCenterLH( float ViewLeft, float ViewRight, float ViewBottom, float ViewTop, float NearZ, float FarZ )
  3083. {
  3084. Matrix4x4 M;
  3085. float ReciprocalWidth = 1.0f / (ViewRight - ViewLeft);
  3086. float ReciprocalHeight = 1.0f / (ViewTop - ViewBottom);
  3087. M.r[0] = Vector4(2 * ReciprocalWidth, 0.0f, 0.0f, 0.0f);
  3088. M.r[1] = Vector4(0.0f, -2 * ReciprocalHeight, 0.0f, 0.0f);
  3089. M.r[2] = Vector4(0.0f, 0.0f, 1.0f / (FarZ - NearZ), 0.0f);
  3090. M.r[3] = Vector4(-(ViewLeft + ViewRight) * ReciprocalWidth,
  3091. (ViewTop + ViewBottom) * ReciprocalHeight,
  3092. -M.r[2].z * NearZ,
  3093. 1.0f);
  3094. return M;
  3095. }
  3096. #elif defined( _X360 )
  3097. #define Matrix4x4OrthographicOffCenterLH XMMatrixOrthographicOffCenterLH
  3098. #define Matrix4x4 XMMATRIX
  3099. #endif
  3100. #if ENABLE_MICRO_PROFILER
  3101. double g_time_PresentProfilerReset = 0;
  3102. CMicroProfiler g_mp_Present;
  3103. #endif
  3104. void CShaderDeviceDx8::OnDebugEvent( const char * pEvent )
  3105. {
  3106. #if ENABLE_MICRO_PROFILER
  3107. if( !IsCert() )
  3108. {
  3109. double timeNow = Plat_FloatTime(), timeDelta = timeNow - g_time_PresentProfilerReset;
  3110. double flSleepMilliseconds = g_mp_Present.GetTotalMilliseconds();
  3111. if( g_mp_Present.m_numCalls )
  3112. {
  3113. COM_TimestampedLog( "Present() Stats: %d flips / %.1f sec = ave %.1f fps. Sleep %.2f seconds = %.3fms/flip. %s\n", g_mp_Present.m_numCalls, timeDelta, timeDelta > 0.001 ? float( g_mp_Present.m_numCalls ) / timeDelta : 0.0f, flSleepMilliseconds * 1e-3f, g_mp_Present.m_numCalls ? flSleepMilliseconds / double( g_mp_Present.m_numCalls ) : 0.0f, pEvent );
  3114. }
  3115. else
  3116. {
  3117. COM_TimestampedLog( "Present() Stats: no flips / %.1f sec. %s\n", timeDelta, pEvent );
  3118. }
  3119. g_mp_Present.Reset();
  3120. g_time_PresentProfilerReset = timeNow;
  3121. }
  3122. #endif
  3123. }
  3124. void CShaderDeviceDx8::RefreshFrontBufferNonInteractive()
  3125. {
  3126. if ( !IsGameConsole() || !InNonInteractiveMode() )
  3127. return;
  3128. float flTimeBegin = Plat_FloatTime();
  3129. float dt = flTimeBegin - g_flLastUpdateTime;
  3130. #ifdef _PS3
  3131. // 7ltodo extern bool IsRsxReadyForNoninteractiveRefresh( );
  3132. // if( !IsRsxReadyForNoninteractiveRefresh( ) )
  3133. // {
  3134. // // why bother rendering anything if there are front buffers in the queue for flipping, or something was flipped 1 or less vblanks ago?
  3135. // // if we do bother to render in this case, we may enter a self-perpetuating bad state where we fill up the queue of front buffers to flip
  3136. // // and have to wait for up to 33 ms in every Present, effectively making this function stall for 33 ms for no good reason.
  3137. // return;
  3138. // }
  3139. #endif
  3140. if( dt < LOADING_PRESENT_UPDATE_INTERVAL || g_bInSwap || g_pMaterialSystem->IsInFrame() )
  3141. return;
  3142. g_bInSwap = true;
  3143. // Other code should not be talking to D3D at the same time as this
  3144. AUTO_LOCK_FM( m_nonInteractiveModeMutex );
  3145. #ifdef _GAMECONSOLE
  3146. g_pShaderAPI->OwnGPUResources( false );
  3147. IDirect3DBaseTexture *pTexture = g_pShaderAPI->GetD3DTexture( m_NonInteractiveRefresh.m_Info.m_hTempFullscreenTexture );
  3148. int w, h;
  3149. g_pShaderAPI->GetBackBufferDimensions( w, h );
  3150. Matrix4x4 matWVP = Matrix4x4OrthographicOffCenterLH( 0, (float)w, (float)h, 0, 0, 1 );
  3151. // Structure to hold vertex data.
  3152. struct TEXVERTEX
  3153. {
  3154. FLOAT Position[3];
  3155. FLOAT TexCoord[2];
  3156. };
  3157. TEXVERTEX Vertices[4];
  3158. float flPixelCenter = IsPS3() ? 0 : 0.5f;
  3159. bool bInStartupMode = ( m_NonInteractiveRefresh.m_Mode == MATERIAL_NON_INTERACTIVE_MODE_STARTUP );
  3160. #if defined( CSTRIKE15 )
  3161. if ( bInStartupMode )
  3162. {
  3163. // Render the initial vtf loading screen to match how we render our Scaleform backgrounds,
  3164. // so the transition between loading and Scaleform is seamless:
  3165. // HACK: These are the dimensions of the src background vtf
  3166. const float th = 1024.f;
  3167. const float tw = 1024.f;
  3168. // VTFs are forced to be square, even if the source texture is non 1:1. Rescale the
  3169. // texture to assume its actually in 16:9, as it was authored
  3170. float convertTH = th * 720.0f / 1280.0f;
  3171. // Now, determine the scale between the texture and the viewport in height
  3172. float heightScale = (float)h / convertTH;
  3173. int scaledTH = (int)( heightScale * (float) convertTH );
  3174. int scaledTW = (int)( heightScale * (float) tw );
  3175. float bgTop = (h / 2) - (scaledTH / 2) - flPixelCenter;
  3176. float bgLeft = (w / 2) - (scaledTW / 2) - flPixelCenter;
  3177. float bgBottom = (h / 2) + (scaledTH / 2) - flPixelCenter;
  3178. float bgRight = (w / 2) + (scaledTW / 2) - flPixelCenter;
  3179. Vertices[0].Position[0] = bgLeft;
  3180. Vertices[0].Position[1] = bgTop;
  3181. Vertices[0].Position[2] = 0;
  3182. Vertices[0].TexCoord[0] = 0;
  3183. Vertices[0].TexCoord[1] = 0;
  3184. Vertices[1].Position[0] = bgRight;
  3185. Vertices[1].Position[1] = bgTop;
  3186. Vertices[1].Position[2] = 0;
  3187. Vertices[1].TexCoord[0] = 1;
  3188. Vertices[1].TexCoord[1] = 0;
  3189. Vertices[2].Position[0] = bgRight;
  3190. Vertices[2].Position[1] = bgBottom;
  3191. Vertices[2].Position[2] = 0;
  3192. Vertices[2].TexCoord[0] = 1;
  3193. Vertices[2].TexCoord[1] = 1;
  3194. Vertices[3].Position[0] = bgLeft;
  3195. Vertices[3].Position[1] = bgBottom;
  3196. Vertices[3].Position[2] = 0;
  3197. Vertices[3].TexCoord[0] = 0;
  3198. Vertices[3].TexCoord[1] = 1;
  3199. }
  3200. else
  3201. #endif // !CSTRIKE15
  3202. {
  3203. Vertices[0].Position[0] = -flPixelCenter;
  3204. Vertices[0].Position[1] = -flPixelCenter;
  3205. Vertices[0].Position[2] = 0;
  3206. Vertices[0].TexCoord[0] = 0;
  3207. Vertices[0].TexCoord[1] = 0;
  3208. Vertices[1].Position[0] = w - flPixelCenter;
  3209. Vertices[1].Position[1] = -flPixelCenter;
  3210. Vertices[1].Position[2] = 0;
  3211. Vertices[1].TexCoord[0] = 1;
  3212. Vertices[1].TexCoord[1] = 0;
  3213. Vertices[2].Position[0] = w - flPixelCenter;
  3214. Vertices[2].Position[1] = h - flPixelCenter;
  3215. Vertices[2].Position[2] = 0;
  3216. Vertices[2].TexCoord[0] = 1;
  3217. Vertices[2].TexCoord[1] = 1;
  3218. Vertices[3].Position[0] = -flPixelCenter;
  3219. Vertices[3].Position[1] = h - flPixelCenter;
  3220. Vertices[3].Position[2] = 0;
  3221. Vertices[3].TexCoord[0] = 0;
  3222. Vertices[3].TexCoord[1] = 1;
  3223. }
  3224. D3DVIEWPORT9 viewport;
  3225. viewport.X = viewport.Y = 0;
  3226. viewport.Width = w; viewport.Height = h;
  3227. viewport.MinZ = ReverseDepthOnX360() ? 1.0f : 0.0f;
  3228. viewport.MaxZ = 1.0f - viewport.MinZ;
  3229. float flDepth = (ShaderUtil()->GetConfig().bReverseDepth ^ ReverseDepthOnX360()) ? 0.0f : 1.0f;
  3230. #ifdef _PS3
  3231. Dx9Device()->AntiAliasingHint( AA_HINT_MENU );
  3232. #endif
  3233. Dx9Device()->Clear( 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL | D3DCLEAR_TARGET0, 0, flDepth, 0L );
  3234. Dx9Device()->SetViewport( &viewport );
  3235. Dx9Device()->SetTexture( 0, pTexture );
  3236. Dx9Device()->SetVertexShader( m_NonInteractiveRefresh.m_pVertexShader );
  3237. Dx9Device()->SetPixelShader( bInStartupMode ? m_NonInteractiveRefresh.m_pPixelShaderStartup : m_NonInteractiveRefresh.m_pPixelShader );
  3238. Dx9Device()->SetVertexShaderConstantF( 0, (FLOAT*)&matWVP, 4 );
  3239. Dx9Device()->SetVertexDeclaration( m_NonInteractiveRefresh.m_pVertexDecl );
  3240. Dx9Device()->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
  3241. Dx9Device()->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
  3242. Dx9Device()->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  3243. Dx9Device()->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  3244. Dx9Device()->SetRenderState( D3DRS_ZENABLE, FALSE );
  3245. Dx9Device()->DrawPrimitiveUP( D3DPT_QUADLIST, 1, Vertices, sizeof( TEXVERTEX ) );
  3246. if ( bInStartupMode && m_NonInteractiveRefresh.m_Info.m_flLogoNormalizedW && m_NonInteractiveRefresh.m_Info.m_flLogoNormalizedH )
  3247. {
  3248. float flXPos = m_NonInteractiveRefresh.m_Info.m_flLogoNormalizedX;
  3249. float flYPos = m_NonInteractiveRefresh.m_Info.m_flLogoNormalizedY;
  3250. float flWidth = m_NonInteractiveRefresh.m_Info.m_flLogoNormalizedW;
  3251. float flHeight = m_NonInteractiveRefresh.m_Info.m_flLogoNormalizedH;
  3252. int x = w * flXPos;
  3253. int y = h * flYPos;
  3254. int logoW = w * flWidth;
  3255. int logoH = h * flHeight;
  3256. Vertices[0].Position[0] = x - flPixelCenter;
  3257. Vertices[0].Position[1] = y - flPixelCenter;
  3258. Vertices[1].Position[0] = x + logoW - flPixelCenter;
  3259. Vertices[1].Position[1] = y - flPixelCenter;
  3260. Vertices[2].Position[0] = x + logoW - flPixelCenter;
  3261. Vertices[2].Position[1] = y + logoH - flPixelCenter;
  3262. Vertices[3].Position[0] = x - flPixelCenter;
  3263. Vertices[3].Position[1] = y + logoH - flPixelCenter;
  3264. pTexture = g_pShaderAPI->GetD3DTexture( m_NonInteractiveRefresh.m_Info.m_hLogoTexture );
  3265. Dx9Device()->SetRenderState( D3DRS_ALPHABLENDENABLE, 1 );
  3266. Dx9Device()->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  3267. Dx9Device()->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  3268. Dx9Device()->SetTexture( 0, pTexture );
  3269. Dx9Device()->SetPixelShader( m_NonInteractiveRefresh.m_pPixelShaderStartupPass2 );
  3270. //Dx9Device()->SetVertexShaderConstantF( 0, (FLOAT*)&matWVP, 4 );
  3271. Dx9Device()->DrawPrimitiveUP( D3DPT_QUADLIST, 1, Vertices, sizeof( TEXVERTEX ) );
  3272. }
  3273. if ( bInStartupMode && ( m_NonInteractiveRefresh.m_Info.m_nPacifierCount > 0 ) )
  3274. {
  3275. float flXPos = m_NonInteractiveRefresh.m_Info.m_flNormalizedX;
  3276. float flYPos = m_NonInteractiveRefresh.m_Info.m_flNormalizedY;
  3277. float flHeight = m_NonInteractiveRefresh.m_Info.m_flNormalizedSize;
  3278. int nSize = h * flHeight;
  3279. int x = w * flXPos - nSize * 0.5f;
  3280. int y = h * flYPos - nSize * 0.5f;
  3281. Vertices[0].Position[0] = x - flPixelCenter;
  3282. Vertices[0].Position[1] = y - flPixelCenter;
  3283. Vertices[1].Position[0] = x + nSize - flPixelCenter;
  3284. Vertices[1].Position[1] = y - flPixelCenter;
  3285. Vertices[2].Position[0] = x + nSize - flPixelCenter;
  3286. Vertices[2].Position[1] = y + nSize - flPixelCenter;
  3287. Vertices[3].Position[0] = x - flPixelCenter;
  3288. Vertices[3].Position[1] = y + nSize - flPixelCenter;
  3289. float flDt = flTimeBegin - m_NonInteractiveRefresh.m_flLastPacifierTime;
  3290. // Even if we are drawing faster than 10 hertz (goal is 60 for this path), only animate the spinner at 10 hertz.
  3291. if ( flDt > 0.10f )
  3292. {
  3293. if ( ++m_NonInteractiveRefresh.m_nPacifierFrame >= m_NonInteractiveRefresh.m_Info.m_nPacifierCount )
  3294. {
  3295. m_NonInteractiveRefresh.m_nPacifierFrame = 0;
  3296. }
  3297. m_NonInteractiveRefresh.m_flLastPacifierTime = flTimeBegin;
  3298. }
  3299. pTexture = g_pShaderAPI->GetD3DTexture( m_NonInteractiveRefresh.m_Info.m_pPacifierTextures[ m_NonInteractiveRefresh.m_nPacifierFrame ] );
  3300. Dx9Device()->SetRenderState( D3DRS_ALPHABLENDENABLE, 1 );
  3301. Dx9Device()->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  3302. Dx9Device()->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  3303. Dx9Device()->SetTexture( 0, pTexture );
  3304. Dx9Device()->SetPixelShader( m_NonInteractiveRefresh.m_pPixelShaderStartupPass2 );
  3305. Dx9Device()->DrawPrimitiveUP( D3DPT_QUADLIST, 1, Vertices, sizeof( TEXVERTEX ) );
  3306. }
  3307. Dx9Device()->SetVertexShader( NULL );
  3308. Dx9Device()->SetPixelShader( NULL );
  3309. Dx9Device()->SetTexture( 0, NULL );
  3310. Dx9Device()->SetVertexDeclaration( NULL );
  3311. Dx9Device()->SetRenderState( D3DRS_ZENABLE, TRUE );
  3312. Dx9Device()->Present( 0, 0, 0, 0 );
  3313. g_pShaderAPI->QueueResetRenderState();
  3314. g_pShaderAPI->OwnGPUResources( true );
  3315. UpdatePresentStats();
  3316. #endif
  3317. g_bInSwap = false;
  3318. // NOTE: It is necessary to re-read time, since Refresh
  3319. // may block, and if it does, it'll force a refresh every allocation
  3320. // if we don't resample time after the block
  3321. g_flLastUpdateTime = Plat_FloatTime();
  3322. #if !defined( _CERT )
  3323. float flPresentCost = g_flLastUpdateTime - flTimeBegin;
  3324. if( flPresentCost > ( IsDebug() ? 1e-3f : 5e-3f ) )
  3325. {
  3326. COM_TimestampedLog( "RefreshFrontBufferNonInteractive %.3f ms", flPresentCost * 1000 );
  3327. }
  3328. #endif
  3329. if ( IsPS3() )
  3330. {
  3331. // We can't trust device state after a swap/present operation.
  3332. // Reset all render state after the underlying PS3 device wrapper has reset its own state.
  3333. g_pShaderAPI->ResetRenderState( 1 );
  3334. }
  3335. }
  3336. //-----------------------------------------------------------------------------
  3337. // Page flip
  3338. //-----------------------------------------------------------------------------
  3339. void CShaderDeviceDx8::Present()
  3340. {
  3341. LOCK_SHADERAPI();
  3342. // flush the dynamic buffer and execute the per-draw call queuene
  3343. g_pShaderAPI->OnPresent();
  3344. if ( !IsDeactivated() )
  3345. {
  3346. Dx9Device()->EndScene();
  3347. }
  3348. HRESULT hr = S_OK;
  3349. // if we're in queued mode, don't present if the device is already lost
  3350. bool bValidPresent = true;
  3351. bool bInMainThread = ThreadInMainThread();
  3352. if ( !bInMainThread )
  3353. {
  3354. // don't present if the device is in an invalid state and in queued mode
  3355. if ( m_DeviceState != DEVICE_STATE_OK )
  3356. {
  3357. bValidPresent = false;
  3358. }
  3359. // check for lost device early in threaded mode
  3360. CheckDeviceLost( m_bOtherAppInitializing );
  3361. if ( m_DeviceState != DEVICE_STATE_OK )
  3362. {
  3363. bValidPresent = false;
  3364. }
  3365. }
  3366. // Copy the back buffer into the non-interactive temp buffer
  3367. if ( m_NonInteractiveRefresh.m_Mode == MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD )
  3368. {
  3369. g_pShaderAPI->CopyRenderTargetToTextureEx( m_NonInteractiveRefresh.m_Info.m_hTempFullscreenTexture, 0, NULL, NULL );
  3370. }
  3371. // If we're not iconified, try to present (without this check, we can flicker when Alt-Tabbed away)
  3372. #ifdef _WIN32
  3373. if ( IsX360() || (IsIconic( ( HWND )m_hWnd ) == 0 && bValidPresent) )
  3374. #else
  3375. if ( IsX360() || (IsIconic( (VD3DHWND)m_hWnd ) == 0 && bValidPresent) )
  3376. #endif
  3377. {
  3378. if ( IsPC() && ( m_IsResizing || ( m_ViewHWnd != (VD3DHWND)m_hWnd ) ) )
  3379. {
  3380. RECT destRect;
  3381. #if !defined( DX_TO_GL_ABSTRACTION )
  3382. GetClientRect( ( HWND )m_ViewHWnd, &destRect );
  3383. #else
  3384. toglGetClientRect( (VD3DHWND)m_ViewHWnd, &destRect );
  3385. #endif
  3386. ShaderViewport_t viewport;
  3387. g_pShaderAPI->GetViewports( &viewport, 1 );
  3388. RECT srcRect;
  3389. srcRect.left = viewport.m_nTopLeftX;
  3390. srcRect.right = viewport.m_nTopLeftX + viewport.m_nWidth;
  3391. srcRect.top = viewport.m_nTopLeftY;
  3392. srcRect.bottom = viewport.m_nTopLeftY + viewport.m_nHeight;
  3393. MICRO_PROFILE( g_mp_Present );
  3394. hr = Dx9Device()->Present( &srcRect, &destRect, (VD3DHWND)m_ViewHWnd, 0 );
  3395. }
  3396. else
  3397. {
  3398. g_pShaderAPI->OwnGPUResources( false );
  3399. MICRO_PROFILE( g_mp_Present );
  3400. hr = Dx9Device()->Present( 0, 0, 0, 0 );
  3401. }
  3402. }
  3403. UpdatePresentStats();
  3404. if ( IsPlatformWindows() )
  3405. {
  3406. if ( hr == D3DERR_DRIVERINTERNALERROR )
  3407. {
  3408. /* Usually this bug means that the driver has run out of internal video
  3409. memory, due to leaking it slowly over several application restarts.
  3410. As of summer 2007, IE in particular seemed to leak a lot of driver
  3411. memory for every image context it created in the browser window. A
  3412. reboot clears out the leaked memory and will generally allow the game
  3413. to be run again; occasionally (but not frequently) it's necessary to
  3414. reduce video settings in the game as well to run. But, this is too
  3415. fine a distinction to explain in a dialog, so place the guilt on the
  3416. user and ask them to reduce video settings regardless.
  3417. */
  3418. Error( "Internal driver error at Present.\n"
  3419. "You're likely out of OS Paged Pool Memory! For more info, see\n"
  3420. "http://support.steampowered.com\n" );
  3421. }
  3422. if ( hr == D3DERR_DEVICELOST )
  3423. {
  3424. MarkDeviceLost();
  3425. }
  3426. }
  3427. MeshMgr()->DiscardVertexBuffers();
  3428. if ( bInMainThread )
  3429. {
  3430. CheckDeviceLost( m_bOtherAppInitializing );
  3431. }
  3432. if ( IsX360() )
  3433. {
  3434. // according to docs - "Mandatory Reset of GPU Registers"
  3435. // 360 must force the cached state to be dirty after any present()
  3436. g_pShaderAPI->ResetRenderState( false );
  3437. }
  3438. #ifdef RECORD_KEYFRAMES
  3439. static int frame = 0;
  3440. ++frame;
  3441. if (frame == KEYFRAME_INTERVAL)
  3442. {
  3443. RECORD_COMMAND( DX8_KEYFRAME, 0 );
  3444. g_pShaderAPI->ResetRenderState();
  3445. frame = 0;
  3446. }
  3447. #endif
  3448. g_pShaderAPI->AdvancePIXFrame();
  3449. if ( !IsDeactivated() )
  3450. {
  3451. #ifndef DX_TO_GL_ABSTRACTION
  3452. if ( ( ShaderUtil()->GetConfig().bMeasureFillRate || ShaderUtil()->GetConfig().bVisualizeFillRate ) )
  3453. {
  3454. g_pShaderAPI->ClearBuffers( true, true, true, -1, -1 );
  3455. }
  3456. #endif
  3457. Dx9Device()->BeginScene();
  3458. }
  3459. if ( IsPS3() )
  3460. {
  3461. // We can't trust device state after a swap/present operation.
  3462. // Reset all render state after the underlying PS3 device wrapper has reset its own state.
  3463. g_pShaderAPI->ResetRenderState( false );
  3464. }
  3465. }
  3466. // We need to scale our colors to the range [16, 235] to keep our colors within TV standards. Some colors might
  3467. // still be out of gamut if any of the R, G, or B channels are more than 191 units apart from each other in
  3468. // the 0-255 scale, but it looks like the 360 deals with this for us by lowering the bright saturated color components.
  3469. // NOTE: I'm leaving the max at 255 to retain whiter than whites. On most TV's, we seems a little dark in the bright colors
  3470. // compared to TV and movies when played in the same conditions. This keeps out brights on par with what customers are
  3471. // used to seeing.
  3472. // TV's generally have a 2.5 gamma, so we need to convert our 2.2 frame buffer into a 2.5 frame buffer for display on a TV
  3473. #if defined( CSTRIKE15 )
  3474. ConVar mat_monitorgamma_pwl2srgb( "mat_monitorgamma_pwl2srgb", "0" );
  3475. ConVar mat_monitorgamma_vganonpwlgamma( "mat_monitorgamma_vganonpwlgamma", "2.2" );
  3476. #else
  3477. ConVar mat_monitorgamma_pwl2srgb( "mat_monitorgamma_pwl2srgb", "1" );
  3478. ConVar mat_monitorgamma_vganonpwlgamma( "mat_monitorgamma_vganonpwlgamma", "2.11" );
  3479. #endif
  3480. ConVar mat_monitorgamma_force_480_full_tv_range( "mat_monitorgamma_force_480_full_tv_range", "1" );
  3481. void CShaderDeviceDx8::SetHardwareGammaRamp( float fGamma, float fGammaTVRangeMin, float fGammaTVRangeMax, float fGammaTVExponent, bool bTVEnabled )
  3482. {
  3483. DevMsg( 2, "SetHardwareGammaRamp( %f )\n", fGamma );
  3484. Assert( Dx9Device() );
  3485. if( !Dx9Device() )
  3486. return;
  3487. DevMsg( 2, "**** Gamma Ramp: fGamma: %f fGammaTVRangeMin: %f fGammaTVRangeMax: %f fGammaTVExponent: %f bTVEnabled: %u\n",
  3488. fGamma, fGammaTVRangeMin, fGammaTVRangeMax, fGammaTVExponent, bTVEnabled );
  3489. #ifdef _PS3
  3490. // input gamma driven by UI: 1.8 - 2.6
  3491. // On PS3 we assume that TV mode is defaulting UI 2.2 value to 2.2/2.5 HW value
  3492. float flHwGamma = 2.2f / 2.5f;
  3493. if ( fGamma < 2.2 )
  3494. {
  3495. // we remap the range [1.8-2.2] into [0.8-2.2/2.5]
  3496. flHwGamma = 0.8 + ( fGamma - 1.8 ) / ( 2.2 - 1.8 ) * ( 2.2/2.5 - 0.8 );
  3497. }
  3498. else
  3499. {
  3500. // we remap the range [2.2-2.6] into [2.2/2.5 - 1.2]
  3501. flHwGamma = 2.2/2.5 + ( fGamma - 2.2 ) / ( 2.6 - 2.2 ) * ( 1.2 - 2.2/2.5 );
  3502. }
  3503. // ps3 hardware gamma range allowed by specifications: 0.8 - 1.2
  3504. flHwGamma = clamp( flHwGamma, 0.8f, 1.2f );
  3505. cellVideoOutSetGamma( CELL_VIDEO_OUT_PRIMARY, flHwGamma );
  3506. #else
  3507. #ifdef PLATFORM_X360
  3508. // On X360, if we're in TV mode, and not high def and at 480P/I or less, then we disable our [16,235] (or equivalent) conversion because the X360's
  3509. // system software already applies this adjustment (as far as we can determine) in the "Standard" Black level mode in the X360 dashboard.
  3510. // See: System Settings->Console Settings->Display->Black Level
  3511. if ( ( bTVEnabled ) && ( mat_monitorgamma_force_480_full_tv_range.GetBool() ) )
  3512. {
  3513. XVIDEO_MODE xvideoMode;
  3514. XGetVideoMode( &xvideoMode );
  3515. if ( ( !xvideoMode.fIsHiDef ) && ( xvideoMode.dwDisplayHeight <= 480 ) )
  3516. {
  3517. fGammaTVRangeMin = 0;
  3518. fGammaTVRangeMax = 255;
  3519. //Warning( "CShaderDeviceDx8::SetHardwareGammaRamp: Forcing TV range min/max in 480I/P mode to [0,255]\n" );
  3520. }
  3521. }
  3522. #endif
  3523. D3DGAMMARAMP gammaRamp;
  3524. for ( int i = 0; i < 256; i++ )
  3525. {
  3526. float flInputValue = float( i ) / 255.0f;
  3527. // Since the 360's sRGB read/write is a piecewise linear approximation, we need to correct for the difference in gamma space here
  3528. // We're purposely want PWL adjustment *enabled* here, even though we're no longer using PWL adjusted textures. This adjusts for the distortion introduced
  3529. // into our overall signal transfer function at low linear light scales.
  3530. float flSrgbGammaValue;
  3531. if ( IsX360() && mat_monitorgamma_pwl2srgb.GetInt() )
  3532. {
  3533. // First undo the 360 broken sRGB curve by bringing the value back into linear space
  3534. float flLinearValue = X360GammaToLinear( flInputValue );
  3535. flLinearValue = clamp( flLinearValue, 0.0f, 1.0f );
  3536. // Now apply a true sRGB curve to mimic PC hardware
  3537. flSrgbGammaValue = SrgbLinearToGamma( flLinearValue ); // ( flLinearValue <= 0.0031308f ) ? ( flLinearValue * 12.92f ) : ( 1.055f * powf( flLinearValue, ( 1.0f / 2.4f ) ) ) - 0.055f;
  3538. flSrgbGammaValue = clamp( flSrgbGammaValue, 0.0f, 1.0f );
  3539. }
  3540. else
  3541. {
  3542. flSrgbGammaValue = flInputValue;
  3543. }
  3544. // Apply the user controlled exponent curve
  3545. float flCorrection = pow( flSrgbGammaValue, ( fGamma / 2.2f ) );
  3546. flCorrection = clamp( flCorrection, 0.0f, 1.0f );
  3547. // TV adjustment - Apply an exp and a scale and bias
  3548. if ( bTVEnabled )
  3549. {
  3550. // Adjust for TV gamma of 2.5 by applying an exponent of 2.2 / 2.5 = 0.88
  3551. flCorrection = pow( flCorrection, 2.2f / fGammaTVExponent );
  3552. flCorrection = clamp( flCorrection, 0.0f, 1.0f ) ;
  3553. // Scale and bias to fit into the 16-235 range for TV's
  3554. flCorrection = ( flCorrection * ( fGammaTVRangeMax - fGammaTVRangeMin ) / 255.0f ) + ( fGammaTVRangeMin / 255.0f );
  3555. flCorrection = clamp( flCorrection, 0.0f, 1.0f );
  3556. }
  3557. #if !defined( CSTRIKE15 )
  3558. else if ( IsX360() )
  3559. {
  3560. // Approximate compensation for not using PWL textures on 360 in "monitor" (VGA) mode. Without this the low-end of the ramp will appear too bright at high linear light scales.
  3561. float flVGANonPWLAdjustmentGamma = mat_monitorgamma_vganonpwlgamma.GetFloat();
  3562. flCorrection = pow( flCorrection, 2.2f / flVGANonPWLAdjustmentGamma );
  3563. flCorrection = clamp( flCorrection, 0.0f, 1.0f );
  3564. }
  3565. #endif
  3566. // Generate final int value
  3567. unsigned int val = ( int )( flCorrection * 65535.0f );
  3568. gammaRamp.red[i] = val;
  3569. gammaRamp.green[i] = val;
  3570. gammaRamp.blue[i] = val;
  3571. }
  3572. if ( !CommandLine()->FindParm( "-nogammaramp" ) )
  3573. {
  3574. Dx9Device()->SetGammaRamp( 0, D3DSGR_NO_CALIBRATION, &gammaRamp );
  3575. }
  3576. #endif
  3577. }
  3578. //-----------------------------------------------------------------------------
  3579. // Shader compilation
  3580. //-----------------------------------------------------------------------------
  3581. IShaderBuffer* CShaderDeviceDx8::CompileShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion )
  3582. {
  3583. return ShaderManager()->CompileShader( pProgram, nBufLen, pShaderVersion );
  3584. }
  3585. VertexShaderHandle_t CShaderDeviceDx8::CreateVertexShader( IShaderBuffer *pBuffer )
  3586. {
  3587. return ShaderManager()->CreateVertexShader( pBuffer );
  3588. }
  3589. void CShaderDeviceDx8::DestroyVertexShader( VertexShaderHandle_t hShader )
  3590. {
  3591. ShaderManager()->DestroyVertexShader( hShader );
  3592. }
  3593. GeometryShaderHandle_t CShaderDeviceDx8::CreateGeometryShader( IShaderBuffer* pShaderBuffer )
  3594. {
  3595. Assert( 0 );
  3596. return GEOMETRY_SHADER_HANDLE_INVALID;
  3597. }
  3598. void CShaderDeviceDx8::DestroyGeometryShader( GeometryShaderHandle_t hShader )
  3599. {
  3600. Assert( hShader == GEOMETRY_SHADER_HANDLE_INVALID );
  3601. }
  3602. PixelShaderHandle_t CShaderDeviceDx8::CreatePixelShader( IShaderBuffer *pBuffer )
  3603. {
  3604. return ShaderManager()->CreatePixelShader( pBuffer );
  3605. }
  3606. void CShaderDeviceDx8::DestroyPixelShader( PixelShaderHandle_t hShader )
  3607. {
  3608. ShaderManager()->DestroyPixelShader( hShader );
  3609. }
  3610. #ifdef DX_TO_GL_ABSTRACTION
  3611. void CShaderDeviceDx8::DoStartupShaderPreloading( void )
  3612. {
  3613. ShaderManager()->DoStartupShaderPreloading();
  3614. }
  3615. #endif
  3616. //-----------------------------------------------------------------------------
  3617. // Creates/destroys Mesh
  3618. // NOTE: Will be deprecated soon!
  3619. //-----------------------------------------------------------------------------
  3620. IMesh* CShaderDeviceDx8::CreateStaticMesh( VertexFormat_t vertexFormat, const char *pTextureBudgetGroup, IMaterial * pMaterial, VertexStreamSpec_t *pStreamSpec )
  3621. {
  3622. LOCK_SHADERAPI();
  3623. return MeshMgr()->CreateStaticMesh( vertexFormat, pTextureBudgetGroup, pMaterial, pStreamSpec );
  3624. }
  3625. void CShaderDeviceDx8::DestroyStaticMesh( IMesh* pMesh )
  3626. {
  3627. LOCK_SHADERAPI();
  3628. MeshMgr()->DestroyStaticMesh( pMesh );
  3629. }
  3630. //-----------------------------------------------------------------------------
  3631. // Creates/destroys vertex buffers + index buffers
  3632. //-----------------------------------------------------------------------------
  3633. IVertexBuffer *CShaderDeviceDx8::CreateVertexBuffer( ShaderBufferType_t type, VertexFormat_t fmt, int nVertexCount, const char *pBudgetGroup )
  3634. {
  3635. LOCK_SHADERAPI();
  3636. return MeshMgr()->CreateVertexBuffer( type, fmt, nVertexCount, pBudgetGroup );
  3637. }
  3638. void CShaderDeviceDx8::DestroyVertexBuffer( IVertexBuffer *pVertexBuffer )
  3639. {
  3640. LOCK_SHADERAPI();
  3641. MeshMgr()->DestroyVertexBuffer( pVertexBuffer );
  3642. }
  3643. IIndexBuffer *CShaderDeviceDx8::CreateIndexBuffer( ShaderBufferType_t bufferType, MaterialIndexFormat_t fmt, int nIndexCount, const char *pBudgetGroup )
  3644. {
  3645. LOCK_SHADERAPI();
  3646. return MeshMgr()->CreateIndexBuffer( bufferType, fmt, nIndexCount, pBudgetGroup );
  3647. }
  3648. void CShaderDeviceDx8::DestroyIndexBuffer( IIndexBuffer *pIndexBuffer )
  3649. {
  3650. LOCK_SHADERAPI();
  3651. MeshMgr()->DestroyIndexBuffer( pIndexBuffer );
  3652. }
  3653. IVertexBuffer *CShaderDeviceDx8::GetDynamicVertexBuffer( int streamID, VertexFormat_t vertexFormat, bool bBuffered )
  3654. {
  3655. LOCK_SHADERAPI();
  3656. return MeshMgr()->GetDynamicVertexBuffer( streamID, vertexFormat, bBuffered );
  3657. }
  3658. IIndexBuffer *CShaderDeviceDx8::GetDynamicIndexBuffer( )
  3659. {
  3660. LOCK_SHADERAPI();
  3661. return MeshMgr()->GetDynamicIndexBuffer( );
  3662. }
  3663. #ifdef _X360
  3664. void CShaderDeviceDx8::SpewVideoInfo360( const CCommand &args )
  3665. {
  3666. XVIDEO_MODE videoMode;
  3667. XGetVideoMode( &videoMode );
  3668. Warning( "back buffer size: %dx%d\n", m_PresentParameters.BackBufferWidth, m_PresentParameters.BackBufferHeight );
  3669. Warning( "display resolution: %dx%d %s\n", videoMode.dwDisplayWidth, videoMode.dwDisplayHeight, videoMode.fIsInterlaced ? "interlaced" : "progressive" );
  3670. Warning( "refresh rate: %f\n", videoMode.RefreshRate );
  3671. Warning( "aspect: %s\n", videoMode.fIsWideScreen ? "16x9 (widescreen)" : "4x3 (normal)" );
  3672. Warning( "%s\n", videoMode.fIsHiDef ? "hidef" : "lodef" );
  3673. switch( videoMode.VideoStandard )
  3674. {
  3675. case XC_VIDEO_STANDARD_NTSC_M:
  3676. Warning( "video standard: NTSC_M\n" );
  3677. break;
  3678. case XC_VIDEO_STANDARD_NTSC_J:
  3679. Warning( "video standard: NTSC_J\n" );
  3680. break;
  3681. case XC_VIDEO_STANDARD_PAL_I:
  3682. Warning( "video standard: PAL_I\n" );
  3683. break;
  3684. default:
  3685. Warning( "error: UNKNOWN VIDEO STANDARD!\n" );
  3686. Assert( 0 );
  3687. break;
  3688. }
  3689. ConVarRef fps_max( "fps_max" );
  3690. Warning( "fps_max: %f\n", fps_max.GetFloat() );
  3691. switch( m_PresentParameters.MultiSampleType )
  3692. {
  3693. case D3DMULTISAMPLE_NONE:
  3694. Warning( "multisample type: D3DMULTISAMPLE_NONE\n" );
  3695. break;
  3696. case D3DMULTISAMPLE_2_SAMPLES:
  3697. Warning( "multisample type: D3DMULTISAMPLE_2_SAMPLES\n" );
  3698. break;
  3699. case D3DMULTISAMPLE_4_SAMPLES:
  3700. Warning( "multisample type: D3DMULTISAMPLE_4_SAMPLES\n" );
  3701. break;
  3702. }
  3703. }
  3704. #endif