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.

1003 lines
31 KiB

  1. //===== Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include <d3d10.h>
  9. #include <d3dx10.h>
  10. #include "shaderdevicedx10.h"
  11. #include "shaderdevicedx8.h"
  12. #include "shaderapi/ishaderutil.h"
  13. #include "shaderapidx10.h"
  14. #include "shadershadowdx10.h"
  15. #include "meshdx10.h"
  16. #include "shaderapidx10_global.h"
  17. #include "tier1/keyvalues.h"
  18. #include "tier2/tier2.h"
  19. #include "tier0/icommandline.h"
  20. #include "inputlayoutdx10.h"
  21. #include "shaderapibase.h"
  22. // NOTE: This has to be the last file included!
  23. #include "tier0/memdbgon.h"
  24. //-----------------------------------------------------------------------------
  25. // Explicit instantiation of shader buffer implementation
  26. //-----------------------------------------------------------------------------
  27. template class CShaderBuffer< ID3D10Blob >;
  28. //-----------------------------------------------------------------------------
  29. //
  30. // Device manager
  31. //
  32. //-----------------------------------------------------------------------------
  33. static CShaderDeviceMgrDx10 g_ShaderDeviceMgrDx10;
  34. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderDeviceMgrDx10, IShaderDeviceMgr,
  35. SHADER_DEVICE_MGR_INTERFACE_VERSION, g_ShaderDeviceMgrDx10 )
  36. static CShaderDeviceDx10 g_ShaderDeviceDx10;
  37. CShaderDeviceDx10* g_pShaderDeviceDx10 = &g_ShaderDeviceDx10;
  38. //-----------------------------------------------------------------------------
  39. // constructor, destructor
  40. //-----------------------------------------------------------------------------
  41. CShaderDeviceMgrDx10::CShaderDeviceMgrDx10()
  42. {
  43. m_pDXGIFactory = NULL;
  44. }
  45. CShaderDeviceMgrDx10::~CShaderDeviceMgrDx10()
  46. {
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Connect, disconnect
  50. //-----------------------------------------------------------------------------
  51. bool CShaderDeviceMgrDx10::Connect( CreateInterfaceFn factory )
  52. {
  53. LOCK_SHADERAPI();
  54. if ( !BaseClass::Connect( factory ) )
  55. return false;
  56. HRESULT hr = CreateDXGIFactory( __uuidof(IDXGIFactory), (void**)(&m_pDXGIFactory) );
  57. if ( FAILED( hr ) )
  58. {
  59. Warning( "Failed to create the DXGI Factory!\n" );
  60. return false;
  61. }
  62. InitAdapterInfo();
  63. return true;
  64. }
  65. void CShaderDeviceMgrDx10::Disconnect()
  66. {
  67. LOCK_SHADERAPI();
  68. if ( m_pDXGIFactory )
  69. {
  70. m_pDXGIFactory->Release();
  71. m_pDXGIFactory = NULL;
  72. }
  73. BaseClass::Disconnect();
  74. }
  75. //-----------------------------------------------------------------------------
  76. // Initialization
  77. //-----------------------------------------------------------------------------
  78. InitReturnVal_t CShaderDeviceMgrDx10::Init( )
  79. {
  80. LOCK_SHADERAPI();
  81. return INIT_OK;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Shutdown
  85. //-----------------------------------------------------------------------------
  86. void CShaderDeviceMgrDx10::Shutdown( )
  87. {
  88. LOCK_SHADERAPI();
  89. if ( g_pShaderDevice )
  90. {
  91. g_pShaderDevice->ShutdownDevice();
  92. g_pShaderDevice = NULL;
  93. }
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Initialize adapter information
  97. //-----------------------------------------------------------------------------
  98. void CShaderDeviceMgrDx10::InitAdapterInfo()
  99. {
  100. m_Adapters.RemoveAll();
  101. IDXGIAdapter *pAdapter;
  102. for( UINT nCount = 0; m_pDXGIFactory->EnumAdapters( nCount, &pAdapter ) != DXGI_ERROR_NOT_FOUND; ++nCount )
  103. {
  104. int j = m_Adapters.AddToTail();
  105. AdapterInfo_t &info = m_Adapters[j];
  106. #ifdef _DEBUG
  107. memset( &info.m_ActualCaps, 0xDD, sizeof(info.m_ActualCaps) );
  108. #endif
  109. IDXGIOutput *pOutput = GetAdapterOutput( nCount );
  110. info.m_ActualCaps.m_bDeviceOk = ComputeCapsFromD3D( &info.m_ActualCaps, pAdapter, pOutput );
  111. if ( !info.m_ActualCaps.m_bDeviceOk )
  112. continue;
  113. ReadDXSupportLevels( info.m_ActualCaps );
  114. // Read dxsupport.cfg which has config overrides for particular cards.
  115. ReadHardwareCaps( info.m_ActualCaps, info.m_ActualCaps.m_nMaxDXSupportLevel );
  116. // What's in "-shader" overrides dxsupport.cfg
  117. const char *pShaderParam = CommandLine()->ParmValue( "-shader" );
  118. if ( pShaderParam )
  119. {
  120. Q_strncpy( info.m_ActualCaps.m_pShaderDLL, pShaderParam, sizeof( info.m_ActualCaps.m_pShaderDLL ) );
  121. }
  122. }
  123. }
  124. //-----------------------------------------------------------------------------
  125. // Determines hardware caps from D3D
  126. //-----------------------------------------------------------------------------
  127. bool CShaderDeviceMgrDx10::ComputeCapsFromD3D( HardwareCaps_t *pCaps, IDXGIAdapter *pAdapter, IDXGIOutput *pOutput )
  128. {
  129. HRESULT hr = pAdapter->CheckInterfaceSupport( __uuidof(ID3D10Device), NULL );
  130. if ( hr != S_OK )
  131. {
  132. // Fall back to Dx9
  133. return false;
  134. }
  135. DXGI_ADAPTER_DESC desc;
  136. hr = pAdapter->GetDesc( &desc );
  137. Assert( !FAILED( hr ) );
  138. if ( FAILED(hr) )
  139. return false;
  140. bool bForceFloatHDR = ( CommandLine()->CheckParm( "-floathdr" ) != NULL );
  141. // DX10 settings
  142. // NOTE: We'll need to have different settings for dx10.1 and dx11
  143. Q_UnicodeToUTF8( desc.Description, pCaps->m_pDriverName, MATERIAL_ADAPTER_NAME_LENGTH );
  144. pCaps->m_VendorID = desc.VendorId;
  145. pCaps->m_DeviceID = desc.DeviceId;
  146. pCaps->m_SubSysID = desc.SubSysId;
  147. pCaps->m_Revision = desc.Revision;
  148. pCaps->m_NumSamplers = 16;
  149. pCaps->m_HasSetDeviceGammaRamp = true;
  150. pCaps->m_bSoftwareVertexProcessing = false;
  151. pCaps->m_SupportsPixelShaders_2_b = false;
  152. pCaps->m_SupportsShaderModel_3_0 = false;
  153. pCaps->m_SupportsCompressedTextures = COMPRESSED_TEXTURES_ON;
  154. pCaps->m_SupportsCompressedVertices = VERTEX_COMPRESSION_ON;
  155. pCaps->m_bSupportsAnisotropicFiltering = true;
  156. pCaps->m_bSupportsMagAnisotropicFiltering = true;
  157. pCaps->m_bSupportsVertexTextures = true;
  158. pCaps->m_nMaxAnisotropy = 16;
  159. pCaps->m_MaxTextureWidth = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
  160. pCaps->m_MaxTextureHeight = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
  161. pCaps->m_MaxTextureDepth = D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
  162. pCaps->m_MaxTextureAspectRatio = 1024; // FIXME
  163. pCaps->m_MaxPrimitiveCount = 65536; // FIXME
  164. pCaps->m_ZBiasAndSlopeScaledDepthBiasSupported = true;
  165. pCaps->m_NumPixelShaderConstants = 1024; // FIXME
  166. pCaps->m_NumVertexShaderConstants = 1024; // FIXME
  167. pCaps->m_TextureMemorySize = desc.DedicatedVideoMemory;
  168. pCaps->m_MaxNumLights = 4;
  169. pCaps->m_MaxVertexShaderBlendMatrices = 53; // FIXME
  170. pCaps->m_SupportsMipmappedCubemaps = true;
  171. pCaps->m_nDXSupportLevel = 100;
  172. pCaps->m_PreferDynamicTextures = false;
  173. pCaps->m_MaxUserClipPlanes = 6; // FIXME
  174. pCaps->m_HDRType = bForceFloatHDR ? HDR_TYPE_FLOAT : HDR_TYPE_INTEGER;
  175. pCaps->m_SupportsSRGB = true;
  176. pCaps->m_FakeSRGBWrite = true;
  177. pCaps->m_CanDoSRGBReadFromRTs = true;
  178. pCaps->m_UseFastClipping = false;
  179. pCaps->m_pShaderDLL[0] = 0;
  180. pCaps->m_bNeedsATICentroidHack = false;
  181. pCaps->m_bSupportsStreamOffset = true;
  182. pCaps->m_nMinDXSupportLevel = 92;
  183. pCaps->m_nMaxDXSupportLevel = 100;
  184. pCaps->m_bFogColorSpecifiedInLinearSpace = ( desc.VendorId == VENDORID_NVIDIA );
  185. pCaps->m_NumVertexSamplers = 4;
  186. pCaps->m_nMaxVertexTextureDimension = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
  187. pCaps->m_bSupportsAlphaToCoverage = false; // FIXME
  188. pCaps->m_bSupportsShadowDepthTextures = true;
  189. pCaps->m_bSupportsFetch4 = ( desc.VendorId == VENDORID_ATI );
  190. pCaps->m_bSupportsBorderColor = true;
  191. pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_UNKNOWN;
  192. pCaps->m_nMaxViewports = 4;
  193. DXGI_GAMMA_CONTROL_CAPABILITIES gammaCaps;
  194. pOutput->GetGammaControlCapabilities( &gammaCaps );
  195. pCaps->m_flMinGammaControlPoint = gammaCaps.MinConvertedValue;
  196. pCaps->m_flMaxGammaControlPoint = gammaCaps.MaxConvertedValue;
  197. pCaps->m_nGammaControlPointCount = gammaCaps.NumGammaControlPoints;
  198. return true;
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Gets the number of adapters...
  202. //-----------------------------------------------------------------------------
  203. int CShaderDeviceMgrDx10::GetAdapterCount() const
  204. {
  205. return m_Adapters.Count();
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Returns info about each adapter
  209. //-----------------------------------------------------------------------------
  210. void CShaderDeviceMgrDx10::GetAdapterInfo( int nAdapter, MaterialAdapterInfo_t& info ) const
  211. {
  212. Assert( ( nAdapter >= 0 ) && ( nAdapter < m_Adapters.Count() ) );
  213. const HardwareCaps_t &caps = m_Adapters[ nAdapter ].m_ActualCaps;
  214. memcpy( &info, &caps, sizeof(MaterialAdapterInfo_t) );
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Returns the adapter interface for a particular adapter
  218. //-----------------------------------------------------------------------------
  219. IDXGIAdapter* CShaderDeviceMgrDx10::GetAdapter( int nAdapter ) const
  220. {
  221. Assert( m_pDXGIFactory && ( nAdapter < GetAdapterCount() ) );
  222. IDXGIAdapter *pAdapter;
  223. HRESULT hr = m_pDXGIFactory->EnumAdapters( nAdapter, &pAdapter );
  224. return ( FAILED(hr) ) ? NULL : pAdapter;
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Returns the screen resolution
  228. //-----------------------------------------------------------------------------
  229. void CShaderDeviceMgrDx10::GetDesktopResolution( int *pWidth, int *pHeight, int nAdapter ) const
  230. {
  231. /*
  232. HMONITOR hMonitor = m_pDXGIFactory->GetAdapterMonitor( nAdapter );
  233. MONITORINFO monitorInfo;
  234. memset( &monitorInfo, 0, sizeof(monitorInfo) );
  235. monitorInfo.cbSize = sizeof(monitorInfo);
  236. GetMonitorInfo( hMonitor, &monitorInfo );
  237. *pWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
  238. *pHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
  239. */
  240. *pWidth = 1024;
  241. *pHeight = 768;
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Returns the amount of video memory in bytes for a particular adapter
  245. //-----------------------------------------------------------------------------
  246. int CShaderDeviceMgrDx10::GetVidMemBytes( int nAdapter ) const
  247. {
  248. LOCK_SHADERAPI();
  249. IDXGIAdapter *pAdapter = GetAdapter( nAdapter );
  250. if ( !pAdapter )
  251. return 0;
  252. DXGI_ADAPTER_DESC desc;
  253. #ifdef _DEBUG
  254. HRESULT hr =
  255. #endif
  256. pAdapter->GetDesc( &desc );
  257. Assert( !FAILED( hr ) );
  258. return desc.DedicatedVideoMemory;
  259. }
  260. //-----------------------------------------------------------------------------
  261. // Returns the appropriate adapter output to use
  262. //-----------------------------------------------------------------------------
  263. IDXGIOutput* CShaderDeviceMgrDx10::GetAdapterOutput( int nAdapter ) const
  264. {
  265. LOCK_SHADERAPI();
  266. IDXGIAdapter *pAdapter = GetAdapter( nAdapter );
  267. if ( !pAdapter )
  268. return 0;
  269. IDXGIOutput *pOutput;
  270. for( UINT i = 0; pAdapter->EnumOutputs( i, &pOutput ) != DXGI_ERROR_NOT_FOUND; ++i )
  271. {
  272. DXGI_OUTPUT_DESC desc;
  273. HRESULT hr = pOutput->GetDesc( &desc );
  274. if ( FAILED( hr ) )
  275. continue;
  276. // FIXME: Is this what I want? Or should I be looking at other fields,
  277. // like DXGI_MODE_ROTATION_IDENTITY?
  278. if ( !desc.AttachedToDesktop )
  279. continue;
  280. return pOutput;
  281. }
  282. return NULL;
  283. }
  284. //-----------------------------------------------------------------------------
  285. // Returns the number of modes
  286. //-----------------------------------------------------------------------------
  287. int CShaderDeviceMgrDx10::GetModeCount( int nAdapter ) const
  288. {
  289. LOCK_SHADERAPI();
  290. Assert( m_pDXGIFactory && ( nAdapter < GetAdapterCount() ) );
  291. IDXGIOutput *pOutput = GetAdapterOutput( nAdapter );
  292. if ( !pOutput )
  293. return 0;
  294. UINT num = 0;
  295. DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; //desired color format
  296. UINT flags = 0; //desired scanline order and/or scaling
  297. // get the number of available display mode for the given format and scanline order
  298. HRESULT hr = pOutput->GetDisplayModeList( format, flags, &num, 0 );
  299. return ( FAILED(hr) ) ? 0 : num;
  300. }
  301. //-----------------------------------------------------------------------------
  302. // Returns mode information..
  303. //-----------------------------------------------------------------------------
  304. void CShaderDeviceMgrDx10::GetModeInfo( ShaderDisplayMode_t* pInfo, int nAdapter, int nMode ) const
  305. {
  306. // Default error state
  307. pInfo->m_nWidth = pInfo->m_nHeight = 0;
  308. pInfo->m_Format = IMAGE_FORMAT_UNKNOWN;
  309. pInfo->m_nRefreshRateNumerator = pInfo->m_nRefreshRateDenominator = 0;
  310. LOCK_SHADERAPI();
  311. Assert( m_pDXGIFactory && ( nAdapter < GetAdapterCount() ) );
  312. IDXGIOutput *pOutput = GetAdapterOutput( nAdapter );
  313. if ( !pOutput )
  314. return;
  315. UINT num = 0;
  316. DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; //desired color format
  317. UINT flags = DXGI_ENUM_MODES_INTERLACED; //desired scanline order and/or scaling
  318. // get the number of available display mode for the given format and scanline order
  319. HRESULT hr = pOutput->GetDisplayModeList( format, flags, &num, 0 );
  320. Assert( !FAILED( hr ) );
  321. if ( (UINT)nMode >= num )
  322. return;
  323. DXGI_MODE_DESC *pDescs = (DXGI_MODE_DESC*)_alloca( num * sizeof( DXGI_MODE_DESC ) );
  324. hr = pOutput->GetDisplayModeList( format, flags, &num, pDescs );
  325. Assert( !FAILED( hr ) );
  326. pInfo->m_nWidth = pDescs[nMode].Width;
  327. pInfo->m_nHeight = pDescs[nMode].Height;
  328. // pInfo->m_Format = ImageLoader::D3DFormatToImageFormat( pDescs[nMode].Format );
  329. pInfo->m_nRefreshRateNumerator = pDescs[nMode].RefreshRate.Numerator;
  330. pInfo->m_nRefreshRateDenominator = pDescs[nMode].RefreshRate.Denominator;
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Returns the current mode for an adapter
  334. //-----------------------------------------------------------------------------
  335. void CShaderDeviceMgrDx10::GetCurrentModeInfo( ShaderDisplayMode_t* pInfo, int nAdapter ) const
  336. {
  337. // FIXME: Implement!
  338. Assert( 0 );
  339. }
  340. //-----------------------------------------------------------------------------
  341. // Initialization, shutdown
  342. //-----------------------------------------------------------------------------
  343. bool CShaderDeviceMgrDx10::SetAdapter( int nAdapter, int nFlags )
  344. {
  345. /*
  346. if ( !g_pShaderDeviceDx10->Init() )
  347. {
  348. Warning( "Unable to initialize dx10 device!\n" );
  349. return false;
  350. }
  351. g_pMaterialSystemHardwareConfig = g_pShaderDeviceDx10;
  352. g_pShaderDevice = g_pShaderDeviceDx10;
  353. */
  354. return true;
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Sets the mode
  358. //-----------------------------------------------------------------------------
  359. CreateInterfaceFn CShaderDeviceMgrDx10::SetMode( void *hWnd, int nAdapter, const ShaderDeviceInfo_t& mode )
  360. {
  361. LOCK_SHADERAPI();
  362. Assert( nAdapter < GetAdapterCount() );
  363. int nDXLevel = mode.m_nDXLevel != 0 ? mode.m_nDXLevel : m_Adapters[nAdapter].m_ActualCaps.m_nDXSupportLevel;
  364. if ( nDXLevel > m_Adapters[nAdapter].m_ActualCaps.m_nMaxDXSupportLevel )
  365. {
  366. nDXLevel = m_Adapters[nAdapter].m_ActualCaps.m_nMaxDXSupportLevel;
  367. }
  368. nDXLevel = GetClosestActualDXLevel( nDXLevel );
  369. if ( nDXLevel < 100 )
  370. {
  371. // Fall back to the Dx9 implementations
  372. return g_pShaderDeviceMgrDx8->SetMode( hWnd, nAdapter, mode );
  373. }
  374. if ( g_pShaderAPI )
  375. {
  376. g_pShaderAPI->OnDeviceShutdown();
  377. g_pShaderAPI = NULL;
  378. }
  379. if ( g_pShaderDevice )
  380. {
  381. g_pShaderDevice->ShutdownDevice();
  382. g_pShaderDevice = NULL;
  383. }
  384. g_pShaderShadow = NULL;
  385. ShaderDeviceInfo_t adjustedMode = mode;
  386. adjustedMode.m_nDXLevel = nDXLevel;
  387. if ( !g_pShaderDeviceDx10->InitDevice( hWnd, nAdapter, adjustedMode ) )
  388. return NULL;
  389. if ( !g_pShaderAPIDx10->OnDeviceInit() )
  390. return NULL;
  391. g_pShaderDevice = g_pShaderDeviceDx10;
  392. g_pShaderAPI = g_pShaderAPIDx10;
  393. g_pShaderShadow = g_pShaderShadowDx10;
  394. return ShaderInterfaceFactory;
  395. }
  396. //-----------------------------------------------------------------------------
  397. //
  398. // Device
  399. //
  400. //-----------------------------------------------------------------------------
  401. //-----------------------------------------------------------------------------
  402. // constructor, destructor
  403. //-----------------------------------------------------------------------------
  404. CShaderDeviceDx10::CShaderDeviceDx10()
  405. {
  406. m_pDevice = NULL;
  407. m_pOutput = NULL;
  408. m_pSwapChain = NULL;
  409. m_pRenderTargetView = NULL;
  410. }
  411. CShaderDeviceDx10::~CShaderDeviceDx10()
  412. {
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Sets the mode
  416. //-----------------------------------------------------------------------------
  417. bool CShaderDeviceDx10::InitDevice( void *hWnd, int nAdapter, const ShaderDeviceInfo_t& mode )
  418. {
  419. // Make sure we've been shutdown previously
  420. if ( m_nAdapter != -1 )
  421. {
  422. Warning( "CShaderDeviceDx10::SetMode: Previous mode has not been shut down!\n" );
  423. return false;
  424. }
  425. LOCK_SHADERAPI();
  426. IDXGIAdapter *pAdapter = g_ShaderDeviceMgrDx10.GetAdapter( nAdapter );
  427. if ( !pAdapter )
  428. return false;
  429. m_pOutput = g_ShaderDeviceMgrDx10.GetAdapterOutput( nAdapter );
  430. if ( !m_pOutput )
  431. return false;
  432. m_pOutput->AddRef();
  433. DXGI_SWAP_CHAIN_DESC sd;
  434. ZeroMemory( &sd, sizeof(sd) );
  435. sd.BufferDesc.Width = mode.m_DisplayMode.m_nWidth;
  436. sd.BufferDesc.Height = mode.m_DisplayMode.m_nHeight;
  437. sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  438. sd.BufferDesc.RefreshRate.Numerator = mode.m_DisplayMode.m_nRefreshRateNumerator;
  439. sd.BufferDesc.RefreshRate.Denominator = mode.m_DisplayMode.m_nRefreshRateDenominator;
  440. sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  441. sd.BufferCount = mode.m_nBackBufferCount;
  442. sd.OutputWindow = (HWND)hWnd;
  443. sd.Windowed = mode.m_bWindowed ? TRUE : FALSE;
  444. sd.Flags = mode.m_bWindowed ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
  445. // NOTE: Having more than 1 back buffer disables MSAA!
  446. sd.SwapEffect = mode.m_nBackBufferCount > 1 ? DXGI_SWAP_EFFECT_SEQUENTIAL : DXGI_SWAP_EFFECT_DISCARD;
  447. // FIXME: Chicken + egg problem with SampleDesc.
  448. sd.SampleDesc.Count = mode.m_nAASamples ? mode.m_nAASamples : 1;
  449. sd.SampleDesc.Quality = mode.m_nAAQuality;
  450. UINT nDeviceFlags = 0;
  451. #ifdef _DEBUG
  452. nDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
  453. #endif
  454. HRESULT hr = D3D10CreateDeviceAndSwapChain( pAdapter, D3D10_DRIVER_TYPE_HARDWARE,
  455. NULL, nDeviceFlags, D3D10_SDK_VERSION, &sd, &m_pSwapChain, &m_pDevice );
  456. if ( FAILED( hr ) )
  457. return false;
  458. // Create a render target view
  459. ID3D10Texture2D *pBackBuffer;
  460. hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID*)&pBackBuffer );
  461. if ( FAILED( hr ) )
  462. return FALSE;
  463. hr = m_pDevice->CreateRenderTargetView( pBackBuffer, NULL, &m_pRenderTargetView );
  464. pBackBuffer->Release();
  465. if( FAILED( hr ) )
  466. return FALSE;
  467. m_pDevice->OMSetRenderTargets( 1, &m_pRenderTargetView, NULL );
  468. m_hWnd = hWnd;
  469. m_nAdapter = nAdapter;
  470. // This is our current view.
  471. m_ViewHWnd = hWnd;
  472. GetWindowSize( m_nWindowWidth, m_nWindowHeight );
  473. g_pHardwareConfig->SetupHardwareCaps( mode, g_ShaderDeviceMgrDx10.GetHardwareCaps( nAdapter ) );
  474. return true;
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Shuts down the mode
  478. //-----------------------------------------------------------------------------
  479. void CShaderDeviceDx10::ShutdownDevice()
  480. {
  481. if ( m_pRenderTargetView )
  482. {
  483. m_pRenderTargetView->Release();
  484. m_pRenderTargetView = NULL;
  485. }
  486. if ( m_pDevice )
  487. {
  488. m_pDevice->Release();
  489. m_pDevice = NULL;
  490. }
  491. if ( m_pSwapChain )
  492. {
  493. m_pSwapChain->Release();
  494. m_pSwapChain = NULL;
  495. }
  496. if ( m_pOutput )
  497. {
  498. m_pOutput->Release();
  499. m_pOutput = NULL;
  500. }
  501. m_hWnd = NULL;
  502. m_nAdapter = -1;
  503. }
  504. //-----------------------------------------------------------------------------
  505. // Are we using graphics?
  506. //-----------------------------------------------------------------------------
  507. bool CShaderDeviceDx10::IsUsingGraphics() const
  508. {
  509. return ( m_nAdapter >= 0 );
  510. }
  511. //-----------------------------------------------------------------------------
  512. // Returns the adapter
  513. //-----------------------------------------------------------------------------
  514. int CShaderDeviceDx10::GetCurrentAdapter() const
  515. {
  516. return m_nAdapter;
  517. }
  518. //-----------------------------------------------------------------------------
  519. // Get back buffer information
  520. //-----------------------------------------------------------------------------
  521. ImageFormat CShaderDeviceDx10::GetBackBufferFormat() const
  522. {
  523. return IMAGE_FORMAT_RGB888;
  524. }
  525. void CShaderDeviceDx10::GetBackBufferDimensions( int& width, int& height ) const
  526. {
  527. width = 1024;
  528. height = 768;
  529. }
  530. //-----------------------------------------------------------------------------
  531. // Use this to spew information about the 3D layer
  532. //-----------------------------------------------------------------------------
  533. void CShaderDeviceDx10::SpewDriverInfo() const
  534. {
  535. Warning( "Dx10 Driver!\n" );
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Swap buffers
  539. //-----------------------------------------------------------------------------
  540. void CShaderDeviceDx10::Present()
  541. {
  542. // FIXME: Deal with window occlusion, alt-tab, etc.
  543. HRESULT hr = m_pSwapChain->Present( 0, 0 );
  544. if ( FAILED(hr) )
  545. {
  546. Assert( 0 );
  547. }
  548. }
  549. //-----------------------------------------------------------------------------
  550. // Camma ramp
  551. //-----------------------------------------------------------------------------
  552. void CShaderDeviceDx10::SetHardwareGammaRamp( float fGamma, float fGammaTVRangeMin, float fGammaTVRangeMax, float fGammaTVExponent, bool bTVEnabled )
  553. {
  554. DevMsg( "SetHardwareGammaRamp( %f )\n", fGamma );
  555. Assert( m_pOutput );
  556. if( !m_pOutput )
  557. return;
  558. float flMin = g_pHardwareConfig->Caps().m_flMinGammaControlPoint;
  559. float flMax = g_pHardwareConfig->Caps().m_flMaxGammaControlPoint;
  560. int nGammaPoints = g_pHardwareConfig->Caps().m_nGammaControlPointCount;
  561. DXGI_GAMMA_CONTROL gammaControl;
  562. gammaControl.Scale.Red = gammaControl.Scale.Green = gammaControl.Scale.Blue = 1.0f;
  563. gammaControl.Offset.Red = gammaControl.Offset.Green = gammaControl.Offset.Blue = 0.0f;
  564. float flOOCount = 1.0f / ( nGammaPoints - 1 );
  565. for ( int i = 0; i < nGammaPoints; i++ )
  566. {
  567. float flGamma22 = i * flOOCount;
  568. float flCorrection = pow( flGamma22, fGamma / 2.2f );
  569. flCorrection = clamp( flCorrection, flMin, flMax );
  570. gammaControl.GammaCurve[i].Red = flCorrection;
  571. gammaControl.GammaCurve[i].Green = flCorrection;
  572. gammaControl.GammaCurve[i].Blue = flCorrection;
  573. }
  574. HRESULT hr = m_pOutput->SetGammaControl( &gammaControl );
  575. if ( FAILED(hr) )
  576. {
  577. Warning( "CShaderDeviceDx10::SetHardwareGammaRamp: Unable to set gamma controls!\n" );
  578. }
  579. }
  580. //-----------------------------------------------------------------------------
  581. // Compiles all manner of shaders
  582. //-----------------------------------------------------------------------------
  583. IShaderBuffer* CShaderDeviceDx10::CompileShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion )
  584. {
  585. int nCompileFlags = D3D10_SHADER_AVOID_FLOW_CONTROL;
  586. nCompileFlags |= D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY;
  587. #ifdef _DEBUG
  588. nCompileFlags |= D3D10_SHADER_DEBUG;
  589. #endif
  590. ID3D10Blob *pCompiledShader, *pErrorMessages;
  591. HRESULT hr = D3DX10CompileFromMemory( pProgram, nBufLen, "",
  592. NULL, NULL, "main", pShaderVersion, nCompileFlags, 0, NULL,
  593. &pCompiledShader, &pErrorMessages, NULL );
  594. if ( FAILED( hr ) )
  595. {
  596. if ( pErrorMessages )
  597. {
  598. const char *pErrorMessage = (const char *)pErrorMessages->GetBufferPointer();
  599. Warning( "Vertex shader compilation failed! Reported the following errors:\n%s\n", pErrorMessage );
  600. pErrorMessages->Release();
  601. }
  602. return NULL;
  603. }
  604. // NOTE: This uses small block heap allocator; so I'm not going
  605. // to bother creating a memory pool.
  606. CShaderBuffer< ID3D10Blob > *pShaderBuffer = new CShaderBuffer< ID3D10Blob >( pCompiledShader );
  607. if ( pErrorMessages )
  608. {
  609. pErrorMessages->Release();
  610. }
  611. return pShaderBuffer;
  612. }
  613. //-----------------------------------------------------------------------------
  614. // Release input layouts
  615. //-----------------------------------------------------------------------------
  616. void CShaderDeviceDx10::ReleaseInputLayouts( VertexShaderIndex_t nIndex )
  617. {
  618. InputLayoutDict_t &dict = m_VertexShaderDict[nIndex].m_InputLayouts;
  619. unsigned short hCurr = dict.FirstInorder();
  620. while( hCurr != dict.InvalidIndex() )
  621. {
  622. if ( dict[hCurr].m_pInputLayout )
  623. {
  624. dict[hCurr].m_pInputLayout->Release();
  625. dict[hCurr].m_pInputLayout = NULL;
  626. }
  627. hCurr = dict.NextInorder( hCurr );
  628. }
  629. }
  630. //-----------------------------------------------------------------------------
  631. // Create, destroy vertex shader
  632. //-----------------------------------------------------------------------------
  633. VertexShaderHandle_t CShaderDeviceDx10::CreateVertexShader( IShaderBuffer* pShaderBuffer )
  634. {
  635. // Create the vertex shader
  636. ID3D10VertexShader *pShader = NULL;
  637. HRESULT hr = m_pDevice->CreateVertexShader( pShaderBuffer->GetBits(),
  638. pShaderBuffer->GetSize(), &pShader );
  639. if ( FAILED( hr ) || !pShader )
  640. return VERTEX_SHADER_HANDLE_INVALID;
  641. ID3D10ShaderReflection *pInfo;
  642. hr = D3D10ReflectShader( pShaderBuffer->GetBits(), pShaderBuffer->GetSize(), &pInfo );
  643. if ( FAILED( hr ) || !pInfo )
  644. {
  645. pShader->Release();
  646. return VERTEX_SHADER_HANDLE_INVALID;
  647. }
  648. // Insert the shader into the dictionary of shaders
  649. VertexShaderIndex_t i = m_VertexShaderDict.AddToTail( );
  650. VertexShader_t &dict = m_VertexShaderDict[i];
  651. dict.m_pShader = pShader;
  652. dict.m_pInfo = pInfo;
  653. dict.m_nByteCodeLen = pShaderBuffer->GetSize();
  654. dict.m_pByteCode = new unsigned char[ dict.m_nByteCodeLen ];
  655. memcpy( dict.m_pByteCode, pShaderBuffer->GetBits(), dict.m_nByteCodeLen );
  656. return (VertexShaderHandle_t)i;
  657. }
  658. void CShaderDeviceDx10::DestroyVertexShader( VertexShaderHandle_t hShader )
  659. {
  660. if ( hShader == VERTEX_SHADER_HANDLE_INVALID )
  661. return;
  662. g_pShaderAPIDx10->Unbind( hShader );
  663. VertexShaderIndex_t i = (VertexShaderIndex_t)hShader;
  664. VertexShader_t &dict = m_VertexShaderDict[i];
  665. VerifyEquals( dict.m_pShader->Release(), 0 );
  666. VerifyEquals( dict.m_pInfo->Release(), 0 );
  667. delete[] dict.m_pByteCode;
  668. ReleaseInputLayouts( i );
  669. m_VertexShaderDict.Remove( i );
  670. }
  671. //-----------------------------------------------------------------------------
  672. // Create, destroy geometry shader
  673. //-----------------------------------------------------------------------------
  674. GeometryShaderHandle_t CShaderDeviceDx10::CreateGeometryShader( IShaderBuffer* pShaderBuffer )
  675. {
  676. // Create the geometry shader
  677. ID3D10GeometryShader *pShader = NULL;
  678. HRESULT hr = m_pDevice->CreateGeometryShader( pShaderBuffer->GetBits(),
  679. pShaderBuffer->GetSize(), &pShader );
  680. if ( FAILED( hr ) || !pShader )
  681. return GEOMETRY_SHADER_HANDLE_INVALID;
  682. ID3D10ShaderReflection *pInfo;
  683. hr = D3D10ReflectShader( pShaderBuffer->GetBits(), pShaderBuffer->GetSize(), &pInfo );
  684. if ( FAILED( hr ) || !pInfo )
  685. {
  686. pShader->Release();
  687. return GEOMETRY_SHADER_HANDLE_INVALID;
  688. }
  689. // Insert the shader into the dictionary of shaders
  690. GeometryShaderIndex_t i = m_GeometryShaderDict.AddToTail( );
  691. m_GeometryShaderDict[i].m_pShader = pShader;
  692. m_GeometryShaderDict[i].m_pInfo = pInfo;
  693. return (GeometryShaderHandle_t)i;
  694. }
  695. void CShaderDeviceDx10::DestroyGeometryShader( GeometryShaderHandle_t hShader )
  696. {
  697. if ( hShader == GEOMETRY_SHADER_HANDLE_INVALID )
  698. return;
  699. g_pShaderAPIDx10->Unbind( hShader );
  700. GeometryShaderIndex_t i = (GeometryShaderIndex_t)hShader;
  701. VerifyEquals( m_GeometryShaderDict[ i ].m_pShader->Release(), 0 );
  702. VerifyEquals( m_GeometryShaderDict[ i ].m_pInfo->Release(), 0 );
  703. m_GeometryShaderDict.Remove( i );
  704. }
  705. //-----------------------------------------------------------------------------
  706. // Create, destroy pixel shader
  707. //-----------------------------------------------------------------------------
  708. PixelShaderHandle_t CShaderDeviceDx10::CreatePixelShader( IShaderBuffer* pShaderBuffer )
  709. {
  710. // Create the pixel shader
  711. ID3D10PixelShader *pShader = NULL;
  712. HRESULT hr = m_pDevice->CreatePixelShader( pShaderBuffer->GetBits(),
  713. pShaderBuffer->GetSize(), &pShader );
  714. if ( FAILED( hr ) || !pShader )
  715. return PIXEL_SHADER_HANDLE_INVALID;
  716. ID3D10ShaderReflection *pInfo;
  717. hr = D3D10ReflectShader( pShaderBuffer->GetBits(), pShaderBuffer->GetSize(), &pInfo );
  718. if ( FAILED( hr ) || !pInfo )
  719. {
  720. pShader->Release();
  721. return PIXEL_SHADER_HANDLE_INVALID;
  722. }
  723. // Insert the shader into the dictionary of shaders
  724. PixelShaderIndex_t i = m_PixelShaderDict.AddToTail( );
  725. m_PixelShaderDict[i].m_pShader = pShader;
  726. m_PixelShaderDict[i].m_pInfo = pInfo;
  727. return (PixelShaderHandle_t)i;
  728. }
  729. void CShaderDeviceDx10::DestroyPixelShader( PixelShaderHandle_t hShader )
  730. {
  731. if ( hShader == PIXEL_SHADER_HANDLE_INVALID )
  732. return;
  733. g_pShaderAPIDx10->Unbind( hShader );
  734. PixelShaderIndex_t i = (PixelShaderIndex_t)hShader;
  735. VerifyEquals( m_PixelShaderDict[ i ].m_pShader->Release(), 0 );
  736. VerifyEquals( m_PixelShaderDict[ i ].m_pInfo->Release(), 0 );
  737. m_PixelShaderDict.Remove( i );
  738. }
  739. //-----------------------------------------------------------------------------
  740. // Finds or creates an input layout for a given vertex shader + stream format
  741. //-----------------------------------------------------------------------------
  742. ID3D10InputLayout* CShaderDeviceDx10::GetInputLayout( VertexShaderHandle_t hShader, VertexFormat_t format )
  743. {
  744. if ( hShader == VERTEX_SHADER_HANDLE_INVALID )
  745. return NULL;
  746. // FIXME: VertexFormat_t is not the appropriate way of specifying this
  747. // because it has no stream information
  748. InputLayout_t insert;
  749. insert.m_VertexFormat = format;
  750. VertexShaderIndex_t i = (VertexShaderIndex_t)hShader;
  751. InputLayoutDict_t &dict = m_VertexShaderDict[i].m_InputLayouts;
  752. unsigned short hIndex = dict.Find( insert );
  753. if ( hIndex != dict.InvalidIndex() )
  754. return dict[hIndex].m_pInputLayout;
  755. VertexShader_t &shader = m_VertexShaderDict[i];
  756. insert.m_pInputLayout = CreateInputLayout( format, shader.m_pInfo, shader.m_pByteCode, shader.m_nByteCodeLen );
  757. dict.Insert( insert );
  758. return insert.m_pInputLayout;
  759. }
  760. //-----------------------------------------------------------------------------
  761. // Creates/destroys Mesh
  762. //-----------------------------------------------------------------------------
  763. IMesh* CShaderDeviceDx10::CreateStaticMesh( VertexFormat_t vertexFormat, const char *pBudgetGroup, IMaterial * pMaterial, VertexStreamSpec_t *pStreamSpec )
  764. {
  765. LOCK_SHADERAPI();
  766. return NULL;
  767. }
  768. void CShaderDeviceDx10::DestroyStaticMesh( IMesh* pMesh )
  769. {
  770. LOCK_SHADERAPI();
  771. }
  772. //-----------------------------------------------------------------------------
  773. // Creates/destroys vertex buffers + index buffers
  774. //-----------------------------------------------------------------------------
  775. IVertexBuffer *CShaderDeviceDx10::CreateVertexBuffer( ShaderBufferType_t type, VertexFormat_t fmt, int nVertexCount, const char *pBudgetGroup )
  776. {
  777. LOCK_SHADERAPI();
  778. CVertexBufferDx10 *pVertexBuffer = new CVertexBufferDx10( type, fmt, nVertexCount, pBudgetGroup );
  779. return pVertexBuffer;
  780. }
  781. void CShaderDeviceDx10::DestroyVertexBuffer( IVertexBuffer *pVertexBuffer )
  782. {
  783. LOCK_SHADERAPI();
  784. if ( pVertexBuffer )
  785. {
  786. CVertexBufferDx10 *pVertexBufferBase = assert_cast<CVertexBufferDx10*>( pVertexBuffer );
  787. g_pShaderAPIDx10->UnbindVertexBuffer( pVertexBufferBase->GetDx10Buffer() );
  788. delete pVertexBufferBase;
  789. }
  790. }
  791. IIndexBuffer *CShaderDeviceDx10::CreateIndexBuffer( ShaderBufferType_t type, MaterialIndexFormat_t fmt, int nIndexCount, const char *pBudgetGroup )
  792. {
  793. LOCK_SHADERAPI();
  794. CIndexBufferDx10 *pIndexBuffer = new CIndexBufferDx10( type, fmt, nIndexCount, pBudgetGroup );
  795. return pIndexBuffer;
  796. }
  797. void CShaderDeviceDx10::DestroyIndexBuffer( IIndexBuffer *pIndexBuffer )
  798. {
  799. LOCK_SHADERAPI();
  800. if ( pIndexBuffer )
  801. {
  802. CIndexBufferDx10 *pIndexBufferBase = assert_cast<CIndexBufferDx10*>( pIndexBuffer );
  803. g_pShaderAPIDx10->UnbindIndexBuffer( pIndexBufferBase->GetDx10Buffer() );
  804. delete pIndexBufferBase;
  805. }
  806. }
  807. IVertexBuffer *CShaderDeviceDx10::GetDynamicVertexBuffer( int nStreamID, VertexFormat_t vertexFormat, bool bBuffered )
  808. {
  809. LOCK_SHADERAPI();
  810. return NULL;
  811. }
  812. IIndexBuffer *CShaderDeviceDx10::GetDynamicIndexBuffer( )
  813. {
  814. LOCK_SHADERAPI();
  815. return NULL;
  816. }