diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /materialsystem/shaderapidx9/shaderdevicedx10.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'materialsystem/shaderapidx9/shaderdevicedx10.cpp')
| -rw-r--r-- | materialsystem/shaderapidx9/shaderdevicedx10.cpp | 1002 |
1 files changed, 1002 insertions, 0 deletions
diff --git a/materialsystem/shaderapidx9/shaderdevicedx10.cpp b/materialsystem/shaderapidx9/shaderdevicedx10.cpp new file mode 100644 index 0000000..39de5a1 --- /dev/null +++ b/materialsystem/shaderapidx9/shaderdevicedx10.cpp @@ -0,0 +1,1002 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//===========================================================================// + +#include <d3d10.h> +#include <d3dx10.h> + +#include "shaderdevicedx10.h" +#include "shaderdevicedx8.h" +#include "shaderapi/ishaderutil.h" +#include "shaderapidx10.h" +#include "shadershadowdx10.h" +#include "meshdx10.h" +#include "shaderapidx10_global.h" +#include "tier1/KeyValues.h" +#include "tier2/tier2.h" +#include "tier0/icommandline.h" +#include "inputlayoutdx10.h" +#include "shaderapibase.h" + + +//----------------------------------------------------------------------------- +// Explicit instantiation of shader buffer implementation +//----------------------------------------------------------------------------- +template class CShaderBuffer< ID3D10Blob >; + + +//----------------------------------------------------------------------------- +// +// Device manager +// +//----------------------------------------------------------------------------- +static CShaderDeviceMgrDx10 g_ShaderDeviceMgrDx10; + +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderDeviceMgrDx10, IShaderDeviceMgr, + SHADER_DEVICE_MGR_INTERFACE_VERSION, g_ShaderDeviceMgrDx10 ) + +static CShaderDeviceDx10 g_ShaderDeviceDx10; +CShaderDeviceDx10* g_pShaderDeviceDx10 = &g_ShaderDeviceDx10; + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- +CShaderDeviceMgrDx10::CShaderDeviceMgrDx10() +{ + m_pDXGIFactory = NULL; + m_bObeyDxCommandlineOverride = true; +} + +CShaderDeviceMgrDx10::~CShaderDeviceMgrDx10() +{ +} + + +//----------------------------------------------------------------------------- +// Connect, disconnect +//----------------------------------------------------------------------------- +bool CShaderDeviceMgrDx10::Connect( CreateInterfaceFn factory ) +{ + LOCK_SHADERAPI(); + + if ( !BaseClass::Connect( factory ) ) + return false; + + HRESULT hr = CreateDXGIFactory( __uuidof(IDXGIFactory), (void**)(&m_pDXGIFactory) ); + if ( FAILED( hr ) ) + { + Warning( "Failed to create the DXGI Factory!\n" ); + return false; + } + + InitAdapterInfo(); + return true; +} + +void CShaderDeviceMgrDx10::Disconnect() +{ + LOCK_SHADERAPI(); + + if ( m_pDXGIFactory ) + { + m_pDXGIFactory->Release(); + m_pDXGIFactory = NULL; + } + + BaseClass::Disconnect(); +} + + +//----------------------------------------------------------------------------- +// Initialization +//----------------------------------------------------------------------------- +InitReturnVal_t CShaderDeviceMgrDx10::Init( ) +{ + LOCK_SHADERAPI(); + + return INIT_OK; +} + + +//----------------------------------------------------------------------------- +// Shutdown +//----------------------------------------------------------------------------- +void CShaderDeviceMgrDx10::Shutdown( ) +{ + LOCK_SHADERAPI(); + + if ( g_pShaderDevice ) + { + g_pShaderDevice->ShutdownDevice(); + g_pShaderDevice = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Initialize adapter information +//----------------------------------------------------------------------------- +void CShaderDeviceMgrDx10::InitAdapterInfo() +{ + m_Adapters.RemoveAll(); + + IDXGIAdapter *pAdapter; + for( UINT nCount = 0; m_pDXGIFactory->EnumAdapters( nCount, &pAdapter ) != DXGI_ERROR_NOT_FOUND; ++nCount ) + { + int j = m_Adapters.AddToTail(); + AdapterInfo_t &info = m_Adapters[j]; + +#ifdef _DEBUG + memset( &info.m_ActualCaps, 0xDD, sizeof(info.m_ActualCaps) ); +#endif + + IDXGIOutput *pOutput = GetAdapterOutput( nCount ); + info.m_ActualCaps.m_bDeviceOk = ComputeCapsFromD3D( &info.m_ActualCaps, pAdapter, pOutput ); + if ( !info.m_ActualCaps.m_bDeviceOk ) + continue; + + ReadDXSupportLevels( info.m_ActualCaps ); + + // Read dxsupport.cfg which has config overrides for particular cards. + ReadHardwareCaps( info.m_ActualCaps, info.m_ActualCaps.m_nMaxDXSupportLevel ); + + // What's in "-shader" overrides dxsupport.cfg + const char *pShaderParam = CommandLine()->ParmValue( "-shader" ); + if ( pShaderParam ) + { + Q_strncpy( info.m_ActualCaps.m_pShaderDLL, pShaderParam, sizeof( info.m_ActualCaps.m_pShaderDLL ) ); + } + } +} + + +//----------------------------------------------------------------------------- +// Determines hardware caps from D3D +//----------------------------------------------------------------------------- +bool CShaderDeviceMgrDx10::ComputeCapsFromD3D( HardwareCaps_t *pCaps, IDXGIAdapter *pAdapter, IDXGIOutput *pOutput ) +{ + HRESULT hr = pAdapter->CheckInterfaceSupport( __uuidof(ID3D10Device), NULL ); + if ( hr != S_OK ) + { + // Fall back to Dx9 + return false; + } + + DXGI_ADAPTER_DESC desc; + hr = pAdapter->GetDesc( &desc ); + Assert( !FAILED( hr ) ); + if ( FAILED(hr) ) + return false; + + bool bForceFloatHDR = ( CommandLine()->CheckParm( "-floathdr" ) != NULL ); + + // DX10 settings + // NOTE: We'll need to have different settings for dx10.1 and dx11 + Q_UnicodeToUTF8( desc.Description, pCaps->m_pDriverName, MATERIAL_ADAPTER_NAME_LENGTH ); + pCaps->m_VendorID = desc.VendorId; + pCaps->m_DeviceID = desc.DeviceId; + pCaps->m_SubSysID = desc.SubSysId; + pCaps->m_Revision = desc.Revision; + pCaps->m_NumSamplers = 16; + pCaps->m_NumTextureStages = 0; + pCaps->m_HasSetDeviceGammaRamp = true; + pCaps->m_bSoftwareVertexProcessing = false; + pCaps->m_SupportsVertexShaders = true; + pCaps->m_SupportsVertexShaders_2_0 = false; + pCaps->m_SupportsPixelShaders = true; + pCaps->m_SupportsPixelShaders_1_4 = false; + pCaps->m_SupportsPixelShaders_2_0 = false; + pCaps->m_SupportsPixelShaders_2_b = false; + pCaps->m_SupportsShaderModel_3_0 = false; + pCaps->m_SupportsCompressedTextures = COMPRESSED_TEXTURES_ON; + pCaps->m_SupportsCompressedVertices = VERTEX_COMPRESSION_ON; + pCaps->m_bSupportsAnisotropicFiltering = true; + pCaps->m_bSupportsMagAnisotropicFiltering = true; + pCaps->m_bSupportsVertexTextures = true; + pCaps->m_nMaxAnisotropy = 16; + pCaps->m_MaxTextureWidth = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + pCaps->m_MaxTextureHeight = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + pCaps->m_MaxTextureDepth = D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + pCaps->m_MaxTextureAspectRatio = 1024; // FIXME + pCaps->m_MaxPrimitiveCount = 65536; // FIXME + pCaps->m_ZBiasAndSlopeScaledDepthBiasSupported = true; + pCaps->m_SupportsMipmapping = true; + pCaps->m_SupportsOverbright = true; + pCaps->m_SupportsCubeMaps = true; + pCaps->m_NumPixelShaderConstants = 1024; // FIXME + pCaps->m_NumVertexShaderConstants = 1024; // FIXME + pCaps->m_TextureMemorySize = desc.DedicatedVideoMemory; + pCaps->m_MaxNumLights = 4; + pCaps->m_SupportsHardwareLighting = false; + pCaps->m_MaxBlendMatrices = 0; + pCaps->m_MaxBlendMatrixIndices = 0; + pCaps->m_MaxVertexShaderBlendMatrices = 53; // FIXME + pCaps->m_SupportsMipmappedCubemaps = true; + pCaps->m_SupportsNonPow2Textures = true; + pCaps->m_nDXSupportLevel = 100; + pCaps->m_PreferDynamicTextures = false; + pCaps->m_HasProjectedBumpEnv = true; + pCaps->m_MaxUserClipPlanes = 6; // FIXME + pCaps->m_HDRType = bForceFloatHDR ? HDR_TYPE_FLOAT : HDR_TYPE_INTEGER; + pCaps->m_SupportsSRGB = true; + pCaps->m_FakeSRGBWrite = true; + pCaps->m_CanDoSRGBReadFromRTs = true; + pCaps->m_bSupportsSpheremapping = true; + pCaps->m_UseFastClipping = false; + pCaps->m_pShaderDLL[0] = 0; + pCaps->m_bNeedsATICentroidHack = false; + pCaps->m_bColorOnSecondStream = true; + pCaps->m_bSupportsStreamOffset = true; + pCaps->m_nMaxDXSupportLevel = 100; + pCaps->m_bFogColorSpecifiedInLinearSpace = ( desc.VendorId == VENDORID_NVIDIA ); + pCaps->m_nVertexTextureCount = 16; + pCaps->m_nMaxVertexTextureDimension = D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + pCaps->m_bSupportsAlphaToCoverage = false; // FIXME + pCaps->m_bSupportsShadowDepthTextures = true; + pCaps->m_bSupportsFetch4 = ( desc.VendorId == VENDORID_ATI ); + pCaps->m_bSupportsBorderColor = true; + pCaps->m_ShadowDepthTextureFormat = IMAGE_FORMAT_UNKNOWN; + pCaps->m_nMaxViewports = 4; + + DXGI_GAMMA_CONTROL_CAPABILITIES gammaCaps; + pOutput->GetGammaControlCapabilities( &gammaCaps ); + pCaps->m_flMinGammaControlPoint = gammaCaps.MinConvertedValue; + pCaps->m_flMaxGammaControlPoint = gammaCaps.MaxConvertedValue; + pCaps->m_nGammaControlPointCount = gammaCaps.NumGammaControlPoints; + pCaps->m_bCanStretchRectFromTextures = true; + return true; +} + + +//----------------------------------------------------------------------------- +// Gets the number of adapters... +//----------------------------------------------------------------------------- +int CShaderDeviceMgrDx10::GetAdapterCount() const +{ + return m_Adapters.Count(); +} + + +//----------------------------------------------------------------------------- +// Returns info about each adapter +//----------------------------------------------------------------------------- +void CShaderDeviceMgrDx10::GetAdapterInfo( int nAdapter, MaterialAdapterInfo_t& info ) const +{ + Assert( ( nAdapter >= 0 ) && ( nAdapter < m_Adapters.Count() ) ); + const HardwareCaps_t &caps = m_Adapters[ nAdapter ].m_ActualCaps; + memcpy( &info, &caps, sizeof(MaterialAdapterInfo_t) ); +} + + +//----------------------------------------------------------------------------- +// Returns the adapter interface for a particular adapter +//----------------------------------------------------------------------------- +IDXGIAdapter* CShaderDeviceMgrDx10::GetAdapter( int nAdapter ) const +{ + Assert( m_pDXGIFactory && ( nAdapter < GetAdapterCount() ) ); + + IDXGIAdapter *pAdapter; + HRESULT hr = m_pDXGIFactory->EnumAdapters( nAdapter, &pAdapter ); + return ( FAILED(hr) ) ? NULL : pAdapter; +} + + +//----------------------------------------------------------------------------- +// Returns the amount of video memory in bytes for a particular adapter +//----------------------------------------------------------------------------- +int CShaderDeviceMgrDx10::GetVidMemBytes( int nAdapter ) const +{ + LOCK_SHADERAPI(); + IDXGIAdapter *pAdapter = GetAdapter( nAdapter ); + if ( !pAdapter ) + return 0; + + DXGI_ADAPTER_DESC desc; + +#ifdef DBGFLAG_ASSERT + HRESULT hr = +#endif + pAdapter->GetDesc( &desc ); + Assert( !FAILED( hr ) ); + return desc.DedicatedVideoMemory; +} + + +//----------------------------------------------------------------------------- +// Returns the appropriate adapter output to use +//----------------------------------------------------------------------------- +IDXGIOutput* CShaderDeviceMgrDx10::GetAdapterOutput( int nAdapter ) const +{ + LOCK_SHADERAPI(); + IDXGIAdapter *pAdapter = GetAdapter( nAdapter ); + if ( !pAdapter ) + return 0; + + IDXGIOutput *pOutput; + for( UINT i = 0; pAdapter->EnumOutputs( i, &pOutput ) != DXGI_ERROR_NOT_FOUND; ++i ) + { + DXGI_OUTPUT_DESC desc; + HRESULT hr = pOutput->GetDesc( &desc ); + if ( FAILED( hr ) ) + continue; + + // FIXME: Is this what I want? Or should I be looking at other fields, + // like DXGI_MODE_ROTATION_IDENTITY? + if ( !desc.AttachedToDesktop ) + continue; + + return pOutput; + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// Returns the number of modes +//----------------------------------------------------------------------------- +int CShaderDeviceMgrDx10::GetModeCount( int nAdapter ) const +{ + LOCK_SHADERAPI(); + Assert( m_pDXGIFactory && ( nAdapter < GetAdapterCount() ) ); + + IDXGIOutput *pOutput = GetAdapterOutput( nAdapter ); + if ( !pOutput ) + return 0; + + UINT num = 0; + DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; //desired color format + UINT flags = 0; //desired scanline order and/or scaling + + // get the number of available display mode for the given format and scanline order + HRESULT hr = pOutput->GetDisplayModeList( format, flags, &num, 0 ); + return ( FAILED(hr) ) ? 0 : num; +} + + +//----------------------------------------------------------------------------- +// Returns mode information.. +//----------------------------------------------------------------------------- +void CShaderDeviceMgrDx10::GetModeInfo( ShaderDisplayMode_t* pInfo, int nAdapter, int nMode ) const +{ + // Default error state + pInfo->m_nWidth = pInfo->m_nHeight = 0; + pInfo->m_Format = IMAGE_FORMAT_UNKNOWN; + pInfo->m_nRefreshRateNumerator = pInfo->m_nRefreshRateDenominator = 0; + + LOCK_SHADERAPI(); + Assert( m_pDXGIFactory && ( nAdapter < GetAdapterCount() ) ); + + IDXGIOutput *pOutput = GetAdapterOutput( nAdapter ); + if ( !pOutput ) + return; + + UINT num = 0; + DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; //desired color format + UINT flags = DXGI_ENUM_MODES_INTERLACED; //desired scanline order and/or scaling + + // get the number of available display mode for the given format and scanline order + HRESULT hr = pOutput->GetDisplayModeList( format, flags, &num, 0 ); + Assert( !FAILED( hr ) ); + + if ( (UINT)nMode >= num ) + return; + + DXGI_MODE_DESC *pDescs = (DXGI_MODE_DESC*)_alloca( num * sizeof( DXGI_MODE_DESC ) ); + hr = pOutput->GetDisplayModeList( format, flags, &num, pDescs ); + Assert( !FAILED( hr ) ); + + pInfo->m_nWidth = pDescs[nMode].Width; + pInfo->m_nHeight = pDescs[nMode].Height; +// pInfo->m_Format = ImageLoader::D3DFormatToImageFormat( pDescs[nMode].Format ); + pInfo->m_nRefreshRateNumerator = pDescs[nMode].RefreshRate.Numerator; + pInfo->m_nRefreshRateDenominator = pDescs[nMode].RefreshRate.Denominator; +} + + +//----------------------------------------------------------------------------- +// Returns the current mode for an adapter +//----------------------------------------------------------------------------- +void CShaderDeviceMgrDx10::GetCurrentModeInfo( ShaderDisplayMode_t* pInfo, int nAdapter ) const +{ + // FIXME: Implement! + Assert( 0 ); +} + + +//----------------------------------------------------------------------------- +// Initialization, shutdown +//----------------------------------------------------------------------------- +bool CShaderDeviceMgrDx10::SetAdapter( int nAdapter, int nFlags ) +{ + /* + if ( !g_pShaderDeviceDx10->Init() ) + { + Warning( "Unable to initialize dx10 device!\n" ); + return false; + } + + g_pMaterialSystemHardwareConfig = g_pShaderDeviceDx10; + g_pShaderDevice = g_pShaderDeviceDx10; + */ + return true; +} + + +//----------------------------------------------------------------------------- +// Sets the mode +//----------------------------------------------------------------------------- +CreateInterfaceFn CShaderDeviceMgrDx10::SetMode( void *hWnd, int nAdapter, const ShaderDeviceInfo_t& mode ) +{ + LOCK_SHADERAPI(); + + Assert( nAdapter < GetAdapterCount() ); + int nDXLevel = mode.m_nDXLevel != 0 ? mode.m_nDXLevel : m_Adapters[nAdapter].m_ActualCaps.m_nDXSupportLevel; + if ( m_bObeyDxCommandlineOverride ) + { + nDXLevel = CommandLine()->ParmValue( "-dxlevel", nDXLevel ); + m_bObeyDxCommandlineOverride = false; + } + if ( nDXLevel > m_Adapters[nAdapter].m_ActualCaps.m_nMaxDXSupportLevel ) + { + nDXLevel = m_Adapters[nAdapter].m_ActualCaps.m_nMaxDXSupportLevel; + } + nDXLevel = GetClosestActualDXLevel( nDXLevel ); + + if ( nDXLevel < 100 ) + { + // Fall back to the Dx9 implementations + return g_pShaderDeviceMgrDx8->SetMode( hWnd, nAdapter, mode ); + } + + if ( g_pShaderAPI ) + { + g_pShaderAPI->OnDeviceShutdown(); + g_pShaderAPI = NULL; + } + + if ( g_pShaderDevice ) + { + g_pShaderDevice->ShutdownDevice(); + g_pShaderDevice = NULL; + } + + g_pShaderShadow = NULL; + + ShaderDeviceInfo_t adjustedMode = mode; + adjustedMode.m_nDXLevel = nDXLevel; + if ( !g_pShaderDeviceDx10->InitDevice( hWnd, nAdapter, adjustedMode ) ) + return NULL; + + if ( !g_pShaderAPIDx10->OnDeviceInit() ) + return NULL; + + g_pShaderDevice = g_pShaderDeviceDx10; + g_pShaderAPI = g_pShaderAPIDx10; + g_pShaderShadow = g_pShaderShadowDx10; + + return ShaderInterfaceFactory; +} + + +//----------------------------------------------------------------------------- +// +// Device +// +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- +CShaderDeviceDx10::CShaderDeviceDx10() +{ + m_pDevice = NULL; + m_pOutput = NULL; + m_pSwapChain = NULL; + m_pRenderTargetView = NULL; +} + +CShaderDeviceDx10::~CShaderDeviceDx10() +{ +} + + +//----------------------------------------------------------------------------- +// Sets the mode +//----------------------------------------------------------------------------- +bool CShaderDeviceDx10::InitDevice( void *hWnd, int nAdapter, const ShaderDeviceInfo_t& mode ) +{ + // Make sure we've been shutdown previously + if ( m_nAdapter != -1 ) + { + Warning( "CShaderDeviceDx10::SetMode: Previous mode has not been shut down!\n" ); + return false; + } + + LOCK_SHADERAPI(); + IDXGIAdapter *pAdapter = g_ShaderDeviceMgrDx10.GetAdapter( nAdapter ); + if ( !pAdapter ) + return false; + + m_pOutput = g_ShaderDeviceMgrDx10.GetAdapterOutput( nAdapter ); + if ( !m_pOutput ) + return false; + m_pOutput->AddRef(); + + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory( &sd, sizeof(sd) ); + sd.BufferDesc.Width = mode.m_DisplayMode.m_nWidth; + sd.BufferDesc.Height = mode.m_DisplayMode.m_nHeight; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = mode.m_DisplayMode.m_nRefreshRateNumerator; + sd.BufferDesc.RefreshRate.Denominator = mode.m_DisplayMode.m_nRefreshRateDenominator; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.BufferCount = mode.m_nBackBufferCount; + sd.OutputWindow = (HWND)hWnd; + sd.Windowed = mode.m_bWindowed ? TRUE : FALSE; + sd.Flags = mode.m_bWindowed ? 0 : DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + // NOTE: Having more than 1 back buffer disables MSAA! + sd.SwapEffect = mode.m_nBackBufferCount > 1 ? DXGI_SWAP_EFFECT_SEQUENTIAL : DXGI_SWAP_EFFECT_DISCARD; + + // FIXME: Chicken + egg problem with SampleDesc. + sd.SampleDesc.Count = mode.m_nAASamples ? mode.m_nAASamples : 1; + sd.SampleDesc.Quality = mode.m_nAAQuality; + + UINT nDeviceFlags = 0; +#ifdef _DEBUG + nDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; +#endif + + HRESULT hr = D3D10CreateDeviceAndSwapChain( pAdapter, D3D10_DRIVER_TYPE_HARDWARE, + NULL, nDeviceFlags, D3D10_SDK_VERSION, &sd, &m_pSwapChain, &m_pDevice ); + + if ( FAILED( hr ) ) + return false; + + // Create a render target view + ID3D10Texture2D *pBackBuffer; + hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID*)&pBackBuffer ); + if ( FAILED( hr ) ) + return FALSE; + + hr = m_pDevice->CreateRenderTargetView( pBackBuffer, NULL, &m_pRenderTargetView ); + pBackBuffer->Release(); + if( FAILED( hr ) ) + return FALSE; + + m_pDevice->OMSetRenderTargets( 1, &m_pRenderTargetView, NULL ); + + m_hWnd = hWnd; + m_nAdapter = nAdapter; + + // This is our current view. + m_ViewHWnd = hWnd; + GetWindowSize( m_nWindowWidth, m_nWindowHeight ); + + g_pHardwareConfig->SetupHardwareCaps( mode, g_ShaderDeviceMgrDx10.GetHardwareCaps( nAdapter ) ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Shuts down the mode +//----------------------------------------------------------------------------- +void CShaderDeviceDx10::ShutdownDevice() +{ + if ( m_pRenderTargetView ) + { + m_pRenderTargetView->Release(); + m_pRenderTargetView = NULL; + } + + if ( m_pDevice ) + { + m_pDevice->Release(); + m_pDevice = NULL; + } + + if ( m_pSwapChain ) + { + m_pSwapChain->Release(); + m_pSwapChain = NULL; + } + + if ( m_pOutput ) + { + m_pOutput->Release(); + m_pOutput = NULL; + } + + m_hWnd = NULL; + m_nAdapter = -1; +} + + +//----------------------------------------------------------------------------- +// Are we using graphics? +//----------------------------------------------------------------------------- +bool CShaderDeviceDx10::IsUsingGraphics() const +{ + return ( m_nAdapter >= 0 ); +} + + +//----------------------------------------------------------------------------- +// Returns the adapter +//----------------------------------------------------------------------------- +int CShaderDeviceDx10::GetCurrentAdapter() const +{ + return m_nAdapter; +} + + +//----------------------------------------------------------------------------- +// Get back buffer information +//----------------------------------------------------------------------------- +ImageFormat CShaderDeviceDx10::GetBackBufferFormat() const +{ + return IMAGE_FORMAT_RGB888; +} + +void CShaderDeviceDx10::GetBackBufferDimensions( int& width, int& height ) const +{ + width = 1024; + height = 768; +} + + +//----------------------------------------------------------------------------- +// Use this to spew information about the 3D layer +//----------------------------------------------------------------------------- +void CShaderDeviceDx10::SpewDriverInfo() const +{ + Warning( "Dx10 Driver!\n" ); +} + + + +//----------------------------------------------------------------------------- +// Swap buffers +//----------------------------------------------------------------------------- +void CShaderDeviceDx10::Present() +{ + // FIXME: Deal with window occlusion, alt-tab, etc. + HRESULT hr = m_pSwapChain->Present( 0, 0 ); + if ( FAILED(hr) ) + { + Assert( 0 ); + } +} + + +//----------------------------------------------------------------------------- +// Camma ramp +//----------------------------------------------------------------------------- +void CShaderDeviceDx10::SetHardwareGammaRamp( float fGamma, float fGammaTVRangeMin, float fGammaTVRangeMax, float fGammaTVExponent, bool bTVEnabled ) +{ + DevMsg( "SetHardwareGammaRamp( %f )\n", fGamma ); + + Assert( m_pOutput ); + if( !m_pOutput ) + return; + + float flMin = g_pHardwareConfig->Caps().m_flMinGammaControlPoint; + float flMax = g_pHardwareConfig->Caps().m_flMaxGammaControlPoint; + int nGammaPoints = g_pHardwareConfig->Caps().m_nGammaControlPointCount; + + DXGI_GAMMA_CONTROL gammaControl; + gammaControl.Scale.Red = gammaControl.Scale.Green = gammaControl.Scale.Blue = 1.0f; + gammaControl.Offset.Red = gammaControl.Offset.Green = gammaControl.Offset.Blue = 0.0f; + float flOOCount = 1.0f / ( nGammaPoints - 1 ); + for ( int i = 0; i < nGammaPoints; i++ ) + { + float flGamma22 = i * flOOCount; + float flCorrection = pow( flGamma22, fGamma / 2.2f ); + flCorrection = clamp( flCorrection, flMin, flMax ); + + gammaControl.GammaCurve[i].Red = flCorrection; + gammaControl.GammaCurve[i].Green = flCorrection; + gammaControl.GammaCurve[i].Blue = flCorrection; + } + + HRESULT hr = m_pOutput->SetGammaControl( &gammaControl ); + if ( FAILED(hr) ) + { + Warning( "CShaderDeviceDx10::SetHardwareGammaRamp: Unable to set gamma controls!\n" ); + } +} + + +//----------------------------------------------------------------------------- +// Compiles all manner of shaders +//----------------------------------------------------------------------------- +IShaderBuffer* CShaderDeviceDx10::CompileShader( const char *pProgram, size_t nBufLen, const char *pShaderVersion ) +{ + int nCompileFlags = D3D10_SHADER_AVOID_FLOW_CONTROL; + nCompileFlags |= D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY; + +#ifdef _DEBUG + nCompileFlags |= D3D10_SHADER_DEBUG; +#endif + + ID3D10Blob *pCompiledShader, *pErrorMessages; + HRESULT hr = D3DX10CompileFromMemory( pProgram, nBufLen, "", + NULL, NULL, "main", pShaderVersion, nCompileFlags, 0, NULL, + &pCompiledShader, &pErrorMessages, NULL ); + + if ( FAILED( hr ) ) + { + if ( pErrorMessages ) + { + const char *pErrorMessage = (const char *)pErrorMessages->GetBufferPointer(); + Warning( "Vertex shader compilation failed! Reported the following errors:\n%s\n", pErrorMessage ); + pErrorMessages->Release(); + } + return NULL; + } + + // NOTE: This uses small block heap allocator; so I'm not going + // to bother creating a memory pool. + CShaderBuffer< ID3D10Blob > *pShaderBuffer = new CShaderBuffer< ID3D10Blob >( pCompiledShader ); + if ( pErrorMessages ) + { + pErrorMessages->Release(); + } + + return pShaderBuffer; +} + + +//----------------------------------------------------------------------------- +// Release input layouts +//----------------------------------------------------------------------------- +void CShaderDeviceDx10::ReleaseInputLayouts( VertexShaderIndex_t nIndex ) +{ + InputLayoutDict_t &dict = m_VertexShaderDict[nIndex].m_InputLayouts; + unsigned short hCurr = dict.FirstInorder(); + while( hCurr != dict.InvalidIndex() ) + { + if ( dict[hCurr].m_pInputLayout ) + { + dict[hCurr].m_pInputLayout->Release(); + dict[hCurr].m_pInputLayout = NULL; + } + hCurr = dict.NextInorder( hCurr ); + } +} + + +//----------------------------------------------------------------------------- +// Create, destroy vertex shader +//----------------------------------------------------------------------------- +VertexShaderHandle_t CShaderDeviceDx10::CreateVertexShader( IShaderBuffer* pShaderBuffer ) +{ + // Create the vertex shader + ID3D10VertexShader *pShader = NULL; + HRESULT hr = m_pDevice->CreateVertexShader( pShaderBuffer->GetBits(), + pShaderBuffer->GetSize(), &pShader ); + + if ( FAILED( hr ) || !pShader ) + return VERTEX_SHADER_HANDLE_INVALID; + + ID3D10ShaderReflection *pInfo; + hr = D3D10ReflectShader( pShaderBuffer->GetBits(), pShaderBuffer->GetSize(), &pInfo ); + if ( FAILED( hr ) || !pInfo ) + { + pShader->Release(); + return VERTEX_SHADER_HANDLE_INVALID; + } + + // Insert the shader into the dictionary of shaders + VertexShaderIndex_t i = m_VertexShaderDict.AddToTail( ); + VertexShader_t &dict = m_VertexShaderDict[i]; + dict.m_pShader = pShader; + dict.m_pInfo = pInfo; + dict.m_nByteCodeLen = pShaderBuffer->GetSize(); + dict.m_pByteCode = new unsigned char[ dict.m_nByteCodeLen ]; + memcpy( dict.m_pByteCode, pShaderBuffer->GetBits(), dict.m_nByteCodeLen ); + return (VertexShaderHandle_t)i; +} + +void CShaderDeviceDx10::DestroyVertexShader( VertexShaderHandle_t hShader ) +{ + if ( hShader == VERTEX_SHADER_HANDLE_INVALID ) + return; + + g_pShaderAPIDx10->Unbind( hShader ); + + VertexShaderIndex_t i = (VertexShaderIndex_t)hShader; + VertexShader_t &dict = m_VertexShaderDict[i]; + VerifyEquals( dict.m_pShader->Release(), 0 ); + VerifyEquals( dict.m_pInfo->Release(), 0 ); + delete[] dict.m_pByteCode; + ReleaseInputLayouts( i ); + m_VertexShaderDict.Remove( i ); +} + + +//----------------------------------------------------------------------------- +// Create, destroy geometry shader +//----------------------------------------------------------------------------- +GeometryShaderHandle_t CShaderDeviceDx10::CreateGeometryShader( IShaderBuffer* pShaderBuffer ) +{ + // Create the geometry shader + ID3D10GeometryShader *pShader = NULL; + HRESULT hr = m_pDevice->CreateGeometryShader( pShaderBuffer->GetBits(), + pShaderBuffer->GetSize(), &pShader ); + + if ( FAILED( hr ) || !pShader ) + return GEOMETRY_SHADER_HANDLE_INVALID; + + ID3D10ShaderReflection *pInfo; + hr = D3D10ReflectShader( pShaderBuffer->GetBits(), pShaderBuffer->GetSize(), &pInfo ); + if ( FAILED( hr ) || !pInfo ) + { + pShader->Release(); + return GEOMETRY_SHADER_HANDLE_INVALID; + } + + // Insert the shader into the dictionary of shaders + GeometryShaderIndex_t i = m_GeometryShaderDict.AddToTail( ); + m_GeometryShaderDict[i].m_pShader = pShader; + m_GeometryShaderDict[i].m_pInfo = pInfo; + return (GeometryShaderHandle_t)i; +} + +void CShaderDeviceDx10::DestroyGeometryShader( GeometryShaderHandle_t hShader ) +{ + if ( hShader == GEOMETRY_SHADER_HANDLE_INVALID ) + return; + + g_pShaderAPIDx10->Unbind( hShader ); + + GeometryShaderIndex_t i = (GeometryShaderIndex_t)hShader; + VerifyEquals( m_GeometryShaderDict[ i ].m_pShader->Release(), 0 ); + VerifyEquals( m_GeometryShaderDict[ i ].m_pInfo->Release(), 0 ); + m_GeometryShaderDict.Remove( i ); +} + + +//----------------------------------------------------------------------------- +// Create, destroy pixel shader +//----------------------------------------------------------------------------- +PixelShaderHandle_t CShaderDeviceDx10::CreatePixelShader( IShaderBuffer* pShaderBuffer ) +{ + // Create the pixel shader + ID3D10PixelShader *pShader = NULL; + HRESULT hr = m_pDevice->CreatePixelShader( pShaderBuffer->GetBits(), + pShaderBuffer->GetSize(), &pShader ); + + if ( FAILED( hr ) || !pShader ) + return PIXEL_SHADER_HANDLE_INVALID; + + ID3D10ShaderReflection *pInfo; + hr = D3D10ReflectShader( pShaderBuffer->GetBits(), pShaderBuffer->GetSize(), &pInfo ); + if ( FAILED( hr ) || !pInfo ) + { + pShader->Release(); + return PIXEL_SHADER_HANDLE_INVALID; + } + + // Insert the shader into the dictionary of shaders + PixelShaderIndex_t i = m_PixelShaderDict.AddToTail( ); + m_PixelShaderDict[i].m_pShader = pShader; + m_PixelShaderDict[i].m_pInfo = pInfo; + return (PixelShaderHandle_t)i; +} + +void CShaderDeviceDx10::DestroyPixelShader( PixelShaderHandle_t hShader ) +{ + if ( hShader == PIXEL_SHADER_HANDLE_INVALID ) + return; + + g_pShaderAPIDx10->Unbind( hShader ); + + PixelShaderIndex_t i = (PixelShaderIndex_t)hShader; + VerifyEquals( m_PixelShaderDict[ i ].m_pShader->Release(), 0 ); + VerifyEquals( m_PixelShaderDict[ i ].m_pInfo->Release(), 0 ); + m_PixelShaderDict.Remove( i ); +} + + +//----------------------------------------------------------------------------- +// Finds or creates an input layout for a given vertex shader + stream format +//----------------------------------------------------------------------------- +ID3D10InputLayout* CShaderDeviceDx10::GetInputLayout( VertexShaderHandle_t hShader, VertexFormat_t format ) +{ + if ( hShader == VERTEX_SHADER_HANDLE_INVALID ) + return NULL; + + // FIXME: VertexFormat_t is not the appropriate way of specifying this + // because it has no stream information + InputLayout_t insert; + insert.m_VertexFormat = format; + + VertexShaderIndex_t i = (VertexShaderIndex_t)hShader; + InputLayoutDict_t &dict = m_VertexShaderDict[i].m_InputLayouts; + unsigned short hIndex = dict.Find( insert ); + if ( hIndex != dict.InvalidIndex() ) + return dict[hIndex].m_pInputLayout; + + VertexShader_t &shader = m_VertexShaderDict[i]; + insert.m_pInputLayout = CreateInputLayout( format, shader.m_pInfo, shader.m_pByteCode, shader.m_nByteCodeLen ); + dict.Insert( insert ); + return insert.m_pInputLayout; +} + + +//----------------------------------------------------------------------------- +// Creates/destroys Mesh +//----------------------------------------------------------------------------- +IMesh* CShaderDeviceDx10::CreateStaticMesh( VertexFormat_t vertexFormat, const char *pBudgetGroup, IMaterial * pMaterial ) +{ + LOCK_SHADERAPI(); + return NULL; +} + +void CShaderDeviceDx10::DestroyStaticMesh( IMesh* pMesh ) +{ + LOCK_SHADERAPI(); +} + + +//----------------------------------------------------------------------------- +// Creates/destroys vertex buffers + index buffers +//----------------------------------------------------------------------------- +IVertexBuffer *CShaderDeviceDx10::CreateVertexBuffer( ShaderBufferType_t type, VertexFormat_t fmt, int nVertexCount, const char *pBudgetGroup ) +{ + LOCK_SHADERAPI(); + CVertexBufferDx10 *pVertexBuffer = new CVertexBufferDx10( type, fmt, nVertexCount, pBudgetGroup ); + return pVertexBuffer; +} + +void CShaderDeviceDx10::DestroyVertexBuffer( IVertexBuffer *pVertexBuffer ) +{ + LOCK_SHADERAPI(); + if ( pVertexBuffer ) + { + CVertexBufferDx10 *pVertexBufferBase = assert_cast<CVertexBufferDx10*>( pVertexBuffer ); + g_pShaderAPIDx10->UnbindVertexBuffer( pVertexBufferBase->GetDx10Buffer() ); + delete pVertexBufferBase; + } +} + +IIndexBuffer *CShaderDeviceDx10::CreateIndexBuffer( ShaderBufferType_t type, MaterialIndexFormat_t fmt, int nIndexCount, const char *pBudgetGroup ) +{ + LOCK_SHADERAPI(); + CIndexBufferDx10 *pIndexBuffer = new CIndexBufferDx10( type, fmt, nIndexCount, pBudgetGroup ); + return pIndexBuffer; +} + +void CShaderDeviceDx10::DestroyIndexBuffer( IIndexBuffer *pIndexBuffer ) +{ + LOCK_SHADERAPI(); + if ( pIndexBuffer ) + { + CIndexBufferDx10 *pIndexBufferBase = assert_cast<CIndexBufferDx10*>( pIndexBuffer ); + g_pShaderAPIDx10->UnbindIndexBuffer( pIndexBufferBase->GetDx10Buffer() ); + delete pIndexBufferBase; + } +} + +IVertexBuffer *CShaderDeviceDx10::GetDynamicVertexBuffer( int nStreamID, VertexFormat_t vertexFormat, bool bBuffered ) +{ + LOCK_SHADERAPI(); + return NULL; +} + +IIndexBuffer *CShaderDeviceDx10::GetDynamicIndexBuffer( MaterialIndexFormat_t fmt, bool bBuffered ) +{ + LOCK_SHADERAPI(); + return NULL; +} + + + |