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

1002 lines
31 KiB

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