//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
# define DISABLE_PROTECTED_THINGS
# include "locald3dtypes.h"
# include "shaderdevicedx8.h"
# include "shaderapi/ishaderutil.h"
# include "shaderapidx8_global.h"
# include "filesystem.h"
# include "tier0/icommandline.h"
# include "tier2/tier2.h"
# include "shadershadowdx8.h"
# include "colorformatdx8.h"
# include "materialsystem/IShader.h"
# include "shaderapidx8.h"
# include "shaderapidx8_global.h"
# include "imeshdx8.h"
# include "materialsystem/materialsystem_config.h"
# include "vertexshaderdx8.h"
# include "recording.h"
# include "winutils.h"
# include "tier0/vprof_telemetry.h"
# if defined ( DX_TO_GL_ABSTRACTION )
// Placed here so inlines placed in dxabstract.h can access gGL
COpenGLEntryPoints * gGL = NULL ;
# endif
# define D3D_BATCH_PERF_ANALYSIS 0
# if D3D_BATCH_PERF_ANALYSIS
# if defined( DX_TO_GL_ABSTRACTION )
# error Cannot enable D3D_BATCH_PERF_ANALYSIS when using DX_TO_GL_ABSTRACTION, use GL_BATCH_PERF_ANALYSIS instead.
# endif
// Define this if you want all d3d9 interfaces hooked and run through the dx9hook.h shim interfaces. For profiling, etc.
# define DO_DX9_HOOK
# endif
# ifdef DO_DX9_HOOK
# if D3D_BATCH_PERF_ANALYSIS
ConVar d3d_batch_vis ( " d3d_batch_vis " , " 0 " ) ;
ConVar d3d_batch_vis_abs_scale ( " d3d_batch_vis_abs_scale " , " .050 " ) ;
ConVar d3d_present_vis_abs_scale ( " d3d_batch_vis_abs_scale " , " .050 " ) ;
ConVar d3d_batch_vis_y_scale ( " d3d_batch_vis_y_scale " , " 0.0 " ) ;
uint64 g_nTotalD3DCalls , g_nTotalD3DCycles ;
static double s_rdtsc_to_ms ;
# endif
# include "dx9hook.h"
# endif
# ifndef _X360
# include "wmi.h"
# endif
# if defined( _X360 )
# include "xbox/xbox_console.h"
# include "xbox/xbox_win32stubs.h"
# endif
//#define DX8_COMPATABILITY_MODE
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
static CShaderDeviceMgrDx8 g_ShaderDeviceMgrDx8 ;
CShaderDeviceMgrDx8 * g_pShaderDeviceMgrDx8 = & g_ShaderDeviceMgrDx8 ;
# ifndef SHADERAPIDX10
// In the shaderapidx10.dll, we use its version of IShaderDeviceMgr.
EXPOSE_SINGLE_INTERFACE_GLOBALVAR ( CShaderDeviceMgrDx8 , IShaderDeviceMgr ,
SHADER_DEVICE_MGR_INTERFACE_VERSION , g_ShaderDeviceMgrDx8 )
# endif
# if defined( _X360 )
IDirect3D9 * m_pD3D ;
# endif
IDirect3DDevice * g_pD3DDevice = NULL ;
# if defined(IS_WINDOWS_PC) && defined(SHADERAPIDX9)
// HACK: need to pass knowledge of D3D9Ex usage into callers of D3D Create* methods
// so they do not try to specify D3DPOOL_MANAGED, which is unsupported in D3D9Ex
bool g_ShaderDeviceUsingD3D9Ex = false ;
static ConVar mat_supports_d3d9ex ( " mat_supports_d3d9ex " , " 0 " , FCVAR_HIDDEN ) ;
# endif
// hook into mat_forcedynamic from the engine.
static ConVar mat_forcedynamic ( " mat_forcedynamic " , " 0 " , FCVAR_CHEAT ) ;
// this is hooked into the engines convar
ConVar mat_debugalttab ( " mat_debugalttab " , " 0 " , FCVAR_CHEAT ) ;
//-----------------------------------------------------------------------------
//
// Device manager
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CShaderDeviceMgrDx8 : : CShaderDeviceMgrDx8 ( )
{
m_pD3D = NULL ;
m_bObeyDxCommandlineOverride = true ;
m_bAdapterInfoIntialized = false ;
# if defined( PIX_INSTRUMENTATION ) && defined ( DX_TO_GL_ABSTRACTION ) && defined( _WIN32 )
m_hD3D9 = NULL ;
m_pBeginEvent = NULL ;
m_pEndEvent = NULL ;
m_pSetMarker = NULL ;
m_pSetOptions = NULL ;
# endif
}
CShaderDeviceMgrDx8 : : ~ CShaderDeviceMgrDx8 ( )
{
}
# ifdef OSX
# include <Carbon/Carbon.h>
# endif
//-----------------------------------------------------------------------------
// Connect, disconnect
//-----------------------------------------------------------------------------
bool CShaderDeviceMgrDx8 : : Connect ( CreateInterfaceFn factory )
{
LOCK_SHADERAPI ( ) ;
if ( ! BaseClass : : Connect ( factory ) )
return false ;
# if defined ( DX_TO_GL_ABSTRACTION )
gGL = ToGLConnectLibraries ( factory ) ;
# endif
# if defined(IS_WINDOWS_PC) && defined(SHADERAPIDX9) && !defined(RECORDING) && !defined( DX_TO_GL_ABSTRACTION )
m_pD3D = NULL ;
// Attempt to create a D3D9Ex device (Windows Vista and later) if possible
bool bD3D9ExForceDisable = ( CommandLine ( ) - > FindParm ( " -nod3d9ex " ) ! = 0 ) | |
( CommandLine ( ) - > ParmValue ( " -dxlevel " , 95 ) < 90 ) ;
bool bD3D9ExAvailable = false ;
if ( HMODULE hMod = : : LoadLibraryA ( " d3d9.dll " ) )
{
typedef HRESULT ( WINAPI * CreateD3D9ExFunc_t ) ( UINT , IUnknown * * ) ;
if ( CreateD3D9ExFunc_t pfnCreateD3D9Ex = ( CreateD3D9ExFunc_t ) : : GetProcAddress ( hMod , " Direct3DCreate9Ex " ) )
{
IUnknown * pD3D9Ex = NULL ;
if ( ( * pfnCreateD3D9Ex ) ( D3D_SDK_VERSION , & pD3D9Ex ) = = S_OK & & pD3D9Ex )
{
bD3D9ExAvailable = true ;
if ( bD3D9ExForceDisable )
{
pD3D9Ex - > Release ( ) ;
}
else
{
g_ShaderDeviceUsingD3D9Ex = true ;
// The following is more "correct" but incompatible with the Steam overlay:
//pD3D9Ex->QueryInterface( IID_IDirect3D9, (void**) &m_pD3D );
//pD3D9Ex->Release();
m_pD3D = static_cast < IDirect3D9 * > ( pD3D9Ex ) ;
}
}
}
: : FreeLibrary ( hMod ) ;
}
if ( ! m_pD3D )
{
g_ShaderDeviceUsingD3D9Ex = false ;
m_pD3D = Direct3DCreate9 ( D3D_SDK_VERSION ) ;
}
mat_supports_d3d9ex . SetValue ( bD3D9ExAvailable ? 1 : 0 ) ;
# else
# if defined( DO_DX9_HOOK )
m_pD3D = Direct3DCreate9Hook ( D3D_SDK_VERSION ) ;
# else
m_pD3D = Direct3DCreate9 ( D3D_SDK_VERSION ) ;
# endif
# endif
if ( ! m_pD3D )
{
Warning ( " Failed to create D3D9! \n " ) ;
return false ;
}
# if defined( PIX_INSTRUMENTATION ) && defined ( DX_TO_GL_ABSTRACTION ) && defined( _WIN32 )
// This is a little odd, but AMD PerfStudio hooks D3D9.DLL and intercepts all of the D3DPERF API's (even for OpenGL apps).
// So dynamically load d3d9.dll and get the address of these exported functions.
if ( ! m_hD3D9 )
{
m_hD3D9 = LoadLibraryA ( " d3d9.dll " ) ;
}
if ( m_hD3D9 )
{
Plat_DebugString ( " PIX_INSTRUMENTATION: Loaded d3d9.dll \n " ) ;
printf ( " PIX_INSTRUMENTATION: Loaded d3d9.dll \n " ) ;
m_pBeginEvent = ( D3DPERF_BeginEvent_FuncPtr ) GetProcAddress ( m_hD3D9 , " D3DPERF_BeginEvent " ) ;
m_pEndEvent = ( D3DPERF_EndEvent_FuncPtr ) GetProcAddress ( m_hD3D9 , " D3DPERF_EndEvent " ) ;
m_pSetMarker = ( D3DPERF_SetMarker_FuncPtr ) GetProcAddress ( m_hD3D9 , " D3DPERF_SetOptions " ) ;
m_pSetOptions = ( D3DPERF_SetOptions_FuncPtr ) GetProcAddress ( m_hD3D9 , " D3DPERF_SetMarker " ) ;
}
# endif
// FIXME: Want this to be here, but we can't because Steam
// hasn't had it's application ID set up yet.
// InitAdapterInfo();
return true ;
}
void CShaderDeviceMgrDx8 : : Disconnect ( )
{
LOCK_SHADERAPI ( ) ;
# if defined( PIX_INSTRUMENTATION ) && defined ( DX_TO_GL_ABSTRACTION ) && defined( _WIN32 )
if ( m_hD3D9 )
{
m_pBeginEvent = NULL ;
m_pEndEvent = NULL ;
m_pSetMarker = NULL ;
m_pSetOptions = NULL ;
FreeLibrary ( m_hD3D9 ) ;
m_hD3D9 = NULL ;
}
# endif
if ( m_pD3D )
{
m_pD3D - > Release ( ) ;
m_pD3D = 0 ;
}
# if defined ( DX_TO_GL_ABSTRACTION )
ToGLDisconnectLibraries ( ) ;
# endif
BaseClass : : Disconnect ( ) ;
}
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
InitReturnVal_t CShaderDeviceMgrDx8 : : Init ( )
{
// FIXME: Remove call to InitAdapterInfo once Steam startup issues are resolved.
// Do it in Connect instead.
InitAdapterInfo ( ) ;
return INIT_OK ;
}
//-----------------------------------------------------------------------------
// Shutdown
//-----------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : Shutdown ( )
{
LOCK_SHADERAPI ( ) ;
// FIXME: Make PIX work
// BeginPIXEvent( PIX_VALVE_ORANGE, "Shutdown" );
if ( g_pShaderAPI )
{
g_pShaderAPI - > OnDeviceShutdown ( ) ;
}
if ( g_pShaderDevice )
{
g_pShaderDevice - > ShutdownDevice ( ) ;
g_pMaterialSystemHardwareConfig = NULL ;
}
// EndPIXEvent();
}
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Initialize adapter information
//-----------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : InitAdapterInfo ( )
{
if ( m_bAdapterInfoIntialized )
return ;
m_bAdapterInfoIntialized = true ;
m_Adapters . RemoveAll ( ) ;
Assert ( m_pD3D ) ;
int nCount = m_pD3D - > GetAdapterCount ( ) ;
for ( int i = 0 ; i < nCount ; + + i )
{
int j = m_Adapters . AddToTail ( ) ;
AdapterInfo_t & info = m_Adapters [ j ] ;
# ifdef _DEBUG
memset ( & info . m_ActualCaps , 0xDD , sizeof ( info . m_ActualCaps ) ) ;
# endif
info . m_ActualCaps . m_bDeviceOk = ComputeCapsFromD3D ( & info . m_ActualCaps , i ) ;
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 ) ) ;
}
}
}
//--------------------------------------------------------------------------------
// Code to detect support for texture border color (widely supported but the caps
// bit is messed up in drivers due to a stupid WHQL test that requires this to work
// with float textures which we don't generally care about wrt this address mode)
//--------------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : CheckBorderColorSupport ( HardwareCaps_t * pCaps , int nAdapter )
{
# ifdef DX_TO_GL_ABSTRACTION
if ( true )
# else
if ( IsX360 ( ) )
# endif
{
pCaps - > m_bSupportsBorderColor = true ;
}
else // Most PC parts do this, but let's not deal with that yet (JasonM)
{
pCaps - > m_bSupportsBorderColor = false ;
}
}
//--------------------------------------------------------------------------------
// Vendor-dependent code to detect support for various flavors of shadow mapping
//--------------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : CheckVendorDependentShadowMappingSupport ( HardwareCaps_t * pCaps , int nAdapter )
{
// Set a default null texture format...may be overridden below by IHV-specific surface type
pCaps - > m_NullTextureFormat = IMAGE_FORMAT_ARGB8888 ;
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_RENDERTARGET , D3DRTYPE_TEXTURE , D3DFMT_R5G6B5 ) = = S_OK )
{
pCaps - > m_NullTextureFormat = IMAGE_FORMAT_RGB565 ;
}
# if defined( _X360 )
pCaps - > m_ShadowDepthTextureFormat = ReverseDepthOnX360 ( ) ? IMAGE_FORMAT_X360_DST24F : IMAGE_FORMAT_X360_DST24 ;
pCaps - > m_bSupportsShadowDepthTextures = true ;
pCaps - > m_bSupportsFetch4 = false ;
return ;
# elif defined ( DX_TO_GL_ABSTRACTION )
// We may want to only do this on the higher-end Mac SKUs, since it's not free...
pCaps - > m_ShadowDepthTextureFormat = IMAGE_FORMAT_NV_DST16 ; // This format shunts us down the right shader combo path
pCaps - > m_bSupportsShadowDepthTextures = true ;
pCaps - > m_bSupportsFetch4 = false ;
return ;
# endif
if ( IsPC ( ) | | ! IsX360 ( ) )
{
bool bToolsMode = IsWindows ( ) & & ( CommandLine ( ) - > CheckParm ( " -tools " ) ! = NULL ) ;
bool bFound16Bit = false ;
if ( ( pCaps - > m_VendorID = = VENDORID_NVIDIA ) & & ( pCaps - > m_SupportsShaderModel_3_0 ) ) // ps_3_0 parts from nVidia
{
// First, test for null texture support
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_RENDERTARGET , D3DRTYPE_TEXTURE , NVFMT_NULL ) = = S_OK )
{
pCaps - > m_NullTextureFormat = IMAGE_FORMAT_NV_NULL ;
}
//
// NVIDIA has two no-PCF formats (these are not filtering modes, but surface formats
// NVFMT_RAWZ is supported by NV4x (not supported here yet...requires a dp3 to reconstruct in shader code, which doesn't seem to work)
// NVFMT_INTZ is supported on newer chips as of G8x (just read like ATI non-fetch4 mode)
//
/*
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_RENDERTARGET , D3DRTYPE_TEXTURE , NVFMT_INTZ ) = = S_OK )
{
pCaps - > m_ShadowDepthTextureFormat = IMAGE_FORMAT_NV_INTZ ;
pCaps - > m_bSupportsFetch4 = false ;
pCaps - > m_bSupportsShadowDepthTextures = true ;
return ;
}
*/
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_DEPTHSTENCIL , D3DRTYPE_TEXTURE , D3DFMT_D16 ) = = S_OK )
{
pCaps - > m_ShadowDepthTextureFormat = IMAGE_FORMAT_NV_DST16 ;
pCaps - > m_bSupportsFetch4 = false ;
pCaps - > m_bSupportsShadowDepthTextures = true ;
bFound16Bit = true ;
if ( ! bToolsMode ) // Tools will continue on and try for 24 bit...
return ;
}
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_DEPTHSTENCIL , D3DRTYPE_TEXTURE , D3DFMT_D24S8 ) = = S_OK )
{
pCaps - > m_ShadowDepthTextureFormat = IMAGE_FORMAT_NV_DST24 ;
pCaps - > m_bSupportsFetch4 = false ;
pCaps - > m_bSupportsShadowDepthTextures = true ;
return ;
}
if ( bFound16Bit ) // Found 16 bit but not 24
return ;
}
else if ( ( pCaps - > m_VendorID = = VENDORID_ATI ) & & pCaps - > m_SupportsPixelShaders_2_b ) // ps_2_b parts from ATI
{
// Initially, check for Fetch4 (tied to ATIFMT_D24S8 support)
pCaps - > m_bSupportsFetch4 = false ;
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_DEPTHSTENCIL , D3DRTYPE_TEXTURE , ATIFMT_D24S8 ) = = S_OK )
{
pCaps - > m_bSupportsFetch4 = true ;
}
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_DEPTHSTENCIL , D3DRTYPE_TEXTURE , ATIFMT_D16 ) = = S_OK ) // Prefer 16-bit
{
pCaps - > m_ShadowDepthTextureFormat = IMAGE_FORMAT_ATI_DST16 ;
pCaps - > m_bSupportsShadowDepthTextures = true ;
bFound16Bit = true ;
if ( ! bToolsMode ) // Tools will continue on and try for 24 bit...
return ;
}
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_DEPTHSTENCIL , D3DRTYPE_TEXTURE , ATIFMT_D24S8 ) = = S_OK )
{
pCaps - > m_ShadowDepthTextureFormat = IMAGE_FORMAT_ATI_DST24 ;
pCaps - > m_bSupportsShadowDepthTextures = true ;
return ;
}
if ( bFound16Bit ) // Found 16 bit but not 24
return ;
}
}
// Other vendor or old hardware
pCaps - > m_ShadowDepthTextureFormat = IMAGE_FORMAT_UNKNOWN ;
pCaps - > m_bSupportsShadowDepthTextures = false ;
pCaps - > m_bSupportsFetch4 = false ;
}
//-----------------------------------------------------------------------------
// Vendor-dependent code to detect Alpha To Coverage Backdoors
//-----------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : CheckVendorDependentAlphaToCoverage ( HardwareCaps_t * pCaps , int nAdapter )
{
pCaps - > m_bSupportsAlphaToCoverage = false ;
// Bail out on OpenGL
# ifdef DX_TO_GL_ABSTRACTION
pCaps - > m_bSupportsAlphaToCoverage = true ;
pCaps - > m_AlphaToCoverageEnableValue = TRUE ;
pCaps - > m_AlphaToCoverageDisableValue = FALSE ;
pCaps - > m_AlphaToCoverageState = D3DRS_ADAPTIVETESS_Y ; // Just match the NVIDIA state hackery
return ;
# endif
if ( pCaps - > m_nDXSupportLevel < 90 )
return ;
# ifdef _X360
{
pCaps - > m_bSupportsAlphaToCoverage = true ;
pCaps - > m_AlphaToCoverageEnableValue = TRUE ;
pCaps - > m_AlphaToCoverageDisableValue = FALSE ;
pCaps - > m_AlphaToCoverageState = D3DRS_ALPHATOMASKENABLE ;
return ;
}
# endif // _X360
if ( pCaps - > m_VendorID = = VENDORID_NVIDIA )
{
// nVidia has two modes...assume SSAA is superior to MSAA and hence more desirable (though it's probably not)
//
// Currently, they only seem to expose any of this on 7800 and up though older parts certainly
// support at least the MSAA mode since they support it on OpenGL via the arb_multisample extension
bool bNVIDIA_MSAA = false ;
bool bNVIDIA_SSAA = false ;
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , // Check MSAA version
D3DFMT_X8R8G8B8 , 0 , D3DRTYPE_SURFACE ,
( D3DFORMAT ) MAKEFOURCC ( ' A ' , ' T ' , ' O ' , ' C ' ) ) = = S_OK )
{
bNVIDIA_MSAA = true ;
}
if ( m_pD3D - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , // Check SSAA version
D3DFMT_X8R8G8B8 , 0 , D3DRTYPE_SURFACE ,
( D3DFORMAT ) MAKEFOURCC ( ' S ' , ' S ' , ' A ' , ' A ' ) ) = = S_OK )
{
bNVIDIA_SSAA = true ;
}
// nVidia pitches SSAA but we prefer ATOC
if ( bNVIDIA_MSAA ) // || bNVIDIA_SSAA )
{
// if ( bNVIDIA_SSAA )
// m_AlphaToCoverageEnableValue = MAKEFOURCC('S', 'S', 'A', 'A');
// else
pCaps - > m_AlphaToCoverageEnableValue = MAKEFOURCC ( ' A ' , ' T ' , ' O ' , ' C ' ) ;
pCaps - > m_AlphaToCoverageState = D3DRS_ADAPTIVETESS_Y ;
pCaps - > m_AlphaToCoverageDisableValue = ( DWORD ) D3DFMT_UNKNOWN ;
pCaps - > m_bSupportsAlphaToCoverage = true ;
return ;
}
}
else if ( pCaps - > m_VendorID = = VENDORID_ATI )
{
// Supported on all ATI parts...just go ahead and set the state when appropriate
pCaps - > m_AlphaToCoverageState = D3DRS_POINTSIZE ;
pCaps - > m_AlphaToCoverageEnableValue = MAKEFOURCC ( ' A ' , ' 2 ' , ' M ' , ' 1 ' ) ;
pCaps - > m_AlphaToCoverageDisableValue = MAKEFOURCC ( ' A ' , ' 2 ' , ' M ' , ' 0 ' ) ;
pCaps - > m_bSupportsAlphaToCoverage = true ;
return ;
}
}
ConVar mat_hdr_level ( " mat_hdr_level " , " 2 " , FCVAR_ARCHIVE ) ;
ConVar mat_slopescaledepthbias_shadowmap ( " mat_slopescaledepthbias_shadowmap " , " 16 " , FCVAR_CHEAT ) ;
# ifdef DX_TO_GL_ABSTRACTION
ConVar mat_depthbias_shadowmap ( " mat_depthbias_shadowmap " , " 20 " , FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY ) ;
# else
ConVar mat_depthbias_shadowmap ( " mat_depthbias_shadowmap " , " 0.0005 " , FCVAR_CHEAT ) ;
# endif
// For testing Fast Clip
ConVar mat_fastclip ( " mat_fastclip " , " 0 " , FCVAR_CHEAT ) ;
//-----------------------------------------------------------------------------
// Determine capabilities
//-----------------------------------------------------------------------------
bool CShaderDeviceMgrDx8 : : ComputeCapsFromD3D ( HardwareCaps_t * pCaps , int nAdapter )
{
D3DCAPS caps ;
D3DADAPTER_IDENTIFIER9 ident ;
HRESULT hr ;
// NOTE: When getting the caps, we want to be limited by the hardware
// even if we're running with software T&L...
hr = m_pD3D - > GetDeviceCaps ( nAdapter , DX8_DEVTYPE , & caps ) ;
if ( FAILED ( hr ) )
return false ;
hr = m_pD3D - > GetAdapterIdentifier ( nAdapter , D3DENUM_WHQL_LEVEL , & ident ) ;
if ( FAILED ( hr ) )
return false ;
if ( IsOpenGL ( ) )
{
if ( ! ident . DeviceId & & ! ident . VendorId )
{
ident . DeviceId = 1 ; // fake default device/vendor ID for OpenGL
ident . VendorId = 1 ;
}
}
// Intended for debugging only
if ( CommandLine ( ) - > CheckParm ( " -force_device_id " ) )
{
const char * pDevID = CommandLine ( ) - > ParmValue ( " -force_device_id " , " " ) ;
if ( pDevID )
{
int nDevID = V_atoi ( pDevID ) ; // use V_atoi for hex support
if ( nDevID > 0 )
{
ident . DeviceId = nDevID ;
}
}
}
// Intended for debugging only
if ( CommandLine ( ) - > CheckParm ( " -force_vendor_id " ) )
{
const char * pVendorID = CommandLine ( ) - > ParmValue ( " -force_vendor_id " , " " ) ;
if ( pVendorID )
{
int nVendorID = V_atoi ( pVendorID ) ; // use V_atoi for hex support
if ( pVendorID )
ident . VendorId = nVendorID ;
}
}
Q_strncpy ( pCaps - > m_pDriverName , ident . Description , MATERIAL_ADAPTER_NAME_LENGTH ) ;
pCaps - > m_VendorID = ident . VendorId ;
pCaps - > m_DeviceID = ident . DeviceId ;
pCaps - > m_SubSysID = ident . SubSysId ;
pCaps - > m_Revision = ident . Revision ;
pCaps - > m_nDriverVersionHigh = ident . DriverVersion . HighPart ;
pCaps - > m_nDriverVersionLow = ident . DriverVersion . LowPart ;
pCaps - > m_pShaderDLL [ 0 ] = 0 ;
pCaps - > m_nMaxViewports = 1 ;
pCaps - > m_PreferDynamicTextures = ( caps . Caps2 & D3DCAPS2_DYNAMICTEXTURES ) ? 1 : 0 ;
pCaps - > m_HasProjectedBumpEnv = ( caps . TextureCaps & D3DPTEXTURECAPS_NOPROJECTEDBUMPENV ) = = 0 ;
pCaps - > m_HasSetDeviceGammaRamp = ( caps . Caps2 & D3DCAPS2_CANCALIBRATEGAMMA ) ! = 0 ;
pCaps - > m_SupportsVertexShaders = ( ( caps . VertexShaderVersion > > 8 ) & 0xFF ) > = 1 ;
pCaps - > m_SupportsPixelShaders = ( ( caps . PixelShaderVersion > > 8 ) & 0xFF ) > = 1 ;
pCaps - > m_bScissorSupported = ( caps . RasterCaps & D3DPRASTERCAPS_SCISSORTEST ) ! = 0 ;
# if defined( DX8_COMPATABILITY_MODE )
pCaps - > m_SupportsPixelShaders_1_4 = false ;
pCaps - > m_SupportsPixelShaders_2_0 = false ;
pCaps - > m_SupportsPixelShaders_2_b = false ;
pCaps - > m_SupportsVertexShaders_2_0 = false ;
pCaps - > m_SupportsShaderModel_3_0 = false ;
pCaps - > m_SupportsMipmappedCubemaps = false ;
# else
pCaps - > m_SupportsPixelShaders_1_4 = ( caps . PixelShaderVersion & 0xffff ) > = 0x0104 ;
pCaps - > m_SupportsPixelShaders_2_0 = ( caps . PixelShaderVersion & 0xffff ) > = 0x0200 ;
pCaps - > m_SupportsPixelShaders_2_b = ( ( caps . PixelShaderVersion & 0xffff ) > = 0x0200 ) & & ( caps . PS20Caps . NumInstructionSlots > = 512 ) ; // More caps to this, but this will do
pCaps - > m_SupportsVertexShaders_2_0 = ( caps . VertexShaderVersion & 0xffff ) > = 0x0200 ;
pCaps - > m_SupportsShaderModel_3_0 = ( caps . PixelShaderVersion & 0xffff ) > = 0x0300 ;
pCaps - > m_SupportsMipmappedCubemaps = ( caps . TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP ) ? true : false ;
# endif
// Slam this off for OpenGL
if ( IsOpenGL ( ) )
{
pCaps - > m_SupportsShaderModel_3_0 = false ;
}
// Slam 3.0 shaders off for Intel
if ( pCaps - > m_VendorID = = VENDORID_INTEL )
{
pCaps - > m_SupportsShaderModel_3_0 = false ;
}
pCaps - > m_MaxVertexShader30InstructionSlots = 0 ;
pCaps - > m_MaxPixelShader30InstructionSlots = 0 ;
if ( pCaps - > m_SupportsShaderModel_3_0 )
{
pCaps - > m_MaxVertexShader30InstructionSlots = caps . MaxVertexShader30InstructionSlots ;
pCaps - > m_MaxPixelShader30InstructionSlots = caps . MaxPixelShader30InstructionSlots ;
}
if ( CommandLine ( ) - > CheckParm ( " -nops2b " ) )
{
pCaps - > m_SupportsPixelShaders_2_b = false ;
}
pCaps - > m_bSoftwareVertexProcessing = false ;
if ( IsWindows ( ) & & CommandLine ( ) - > CheckParm ( " -mat_softwaretl " ) )
{
pCaps - > m_bSoftwareVertexProcessing = true ;
}
if ( IsWindows ( ) & & ! ( caps . DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) )
{
// no hardware t&l. . use software
pCaps - > m_bSoftwareVertexProcessing = true ;
}
// Set mat_forcedynamic if software vertex processing since the software vp pipe has
// problems with sparse vertex buffers (it transforms the whole thing.)
if ( pCaps - > m_bSoftwareVertexProcessing )
{
mat_forcedynamic . SetValue ( 1 ) ;
}
if ( pCaps - > m_bSoftwareVertexProcessing )
{
pCaps - > m_SupportsVertexShaders = true ;
pCaps - > m_SupportsVertexShaders_2_0 = true ;
}
# ifdef OSX
// Static control flow is disabled by default on OSX (the Mac version of togl has known bugs preventing this path from working properly that we've fixed in togl linux/win)
pCaps - > m_bSupportsStaticControlFlow = CommandLine ( ) - > CheckParm ( " -glslcontrolflow " ) ! = NULL ;
# else
pCaps - > m_bSupportsStaticControlFlow = ! CommandLine ( ) - > CheckParm ( " -noglslcontrolflow " ) ;
# endif
// NOTE: Texture stages is a fixed-function concept
// NOTE: Normally, the number of texture units == the number of texture
// stages except for NVidia hardware, which reports more stages than units.
// The reason for this is because they expose the inner hardware pixel
// pipeline through the extra stages. The only thing we use stages for
// in the hardware is for configuring the color + alpha args + ops.
pCaps - > m_NumSamplers = caps . MaxSimultaneousTextures ;
pCaps - > m_NumTextureStages = caps . MaxTextureBlendStages ;
if ( pCaps - > m_SupportsPixelShaders_2_0 )
{
pCaps - > m_NumSamplers = 16 ;
}
else
{
Assert ( pCaps - > m_NumSamplers < = pCaps - > m_NumTextureStages ) ;
}
// Clamp
pCaps - > m_NumSamplers = min ( pCaps - > m_NumSamplers , ( int ) MAX_SAMPLERS ) ;
pCaps - > m_NumTextureStages = min ( pCaps - > m_NumTextureStages , ( int ) MAX_TEXTURE_STAGES ) ;
if ( D3DSupportsCompressedTextures ( ) )
{
pCaps - > m_SupportsCompressedTextures = COMPRESSED_TEXTURES_ON ;
}
else
{
pCaps - > m_SupportsCompressedTextures = COMPRESSED_TEXTURES_OFF ;
}
pCaps - > m_bSupportsAnisotropicFiltering = ( caps . TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC ) ! = 0 ;
pCaps - > m_bSupportsMagAnisotropicFiltering = ( caps . TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC ) ! = 0 ;
// OpenGL does not support this--at least not on OSX which is the primary GL target, so just don't use that path on GL at all.
# if !defined( DX_TO_GL_ABSTRACTION )
pCaps - > m_bCanStretchRectFromTextures = ( ( caps . DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ) ! = 0 ) & & ( pCaps - > m_VendorID ! = VENDORID_INTEL ) ;
# else
pCaps - > m_bCanStretchRectFromTextures = false ;
# endif
pCaps - > m_nMaxAnisotropy = pCaps - > m_bSupportsAnisotropicFiltering ? caps . MaxAnisotropy : 1 ;
pCaps - > m_SupportsCubeMaps = ( caps . TextureCaps & D3DPTEXTURECAPS_CUBEMAP ) ? true : false ;
pCaps - > m_SupportsNonPow2Textures =
( ! ( caps . TextureCaps & D3DPTEXTURECAPS_POW2 ) | |
( caps . TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL ) ) ;
Assert ( caps . TextureCaps & D3DPTEXTURECAPS_PROJECTED ) ;
if ( pCaps - > m_bSoftwareVertexProcessing )
{
// This should be pushed down based on pixel shaders.
pCaps - > m_NumVertexShaderConstants = 256 ;
pCaps - > m_NumBooleanVertexShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool vs registers
pCaps - > m_NumBooleanPixelShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool ps registers
pCaps - > m_NumIntegerVertexShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool vs registers
pCaps - > m_NumIntegerPixelShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool ps registers
}
else
{
pCaps - > m_NumVertexShaderConstants = caps . MaxVertexShaderConst ;
if ( CommandLine ( ) - > FindParm ( " -limitvsconst " ) )
{
pCaps - > m_NumVertexShaderConstants = min ( 256 , pCaps - > m_NumVertexShaderConstants ) ;
}
pCaps - > m_NumBooleanVertexShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool vs registers
pCaps - > m_NumBooleanPixelShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool ps registers
// This is a little misleading...this is really 16 int4 registers
pCaps - > m_NumIntegerVertexShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool vs registers
pCaps - > m_NumIntegerPixelShaderConstants = pCaps - > m_SupportsPixelShaders_2_0 ? 16 : 0 ; // 2.0 parts have 16 bool ps registers
}
if ( pCaps - > m_SupportsPixelShaders )
{
if ( pCaps - > m_SupportsPixelShaders_2_0 )
{
pCaps - > m_NumPixelShaderConstants = 32 ;
}
else
{
pCaps - > m_NumPixelShaderConstants = 8 ;
}
}
else
{
pCaps - > m_NumPixelShaderConstants = 0 ;
}
pCaps - > m_SupportsHardwareLighting = ( caps . DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) ! = 0 ;
pCaps - > m_MaxNumLights = caps . MaxActiveLights ;
if ( pCaps - > m_MaxNumLights > MAX_NUM_LIGHTS )
{
pCaps - > m_MaxNumLights = MAX_NUM_LIGHTS ;
}
if ( IsOpenGL ( ) )
{
// Set according to control flow bit on OpenGL
pCaps - > m_MaxNumLights = MIN ( pCaps - > m_MaxNumLights , ( pCaps - > m_bSupportsStaticControlFlow & & pCaps - > m_SupportsPixelShaders_2_b ) ? MAX_NUM_LIGHTS : ( MAX_NUM_LIGHTS - 2 ) ) ;
}
if ( pCaps - > m_bSoftwareVertexProcessing )
{
pCaps - > m_SupportsHardwareLighting = true ;
pCaps - > m_MaxNumLights = 2 ;
}
pCaps - > m_MaxTextureWidth = caps . MaxTextureWidth ;
pCaps - > m_MaxTextureHeight = caps . MaxTextureHeight ;
pCaps - > m_MaxTextureDepth = caps . MaxVolumeExtent ? caps . MaxVolumeExtent : 1 ;
pCaps - > m_MaxTextureAspectRatio = caps . MaxTextureAspectRatio ;
if ( pCaps - > m_MaxTextureAspectRatio = = 0 )
{
pCaps - > m_MaxTextureAspectRatio = max ( pCaps - > m_MaxTextureWidth , pCaps - > m_MaxTextureHeight ) ;
}
pCaps - > m_MaxPrimitiveCount = caps . MaxPrimitiveCount ;
pCaps - > m_MaxBlendMatrices = caps . MaxVertexBlendMatrices ;
pCaps - > m_MaxBlendMatrixIndices = caps . MaxVertexBlendMatrixIndex ;
bool addSupported = ( caps . TextureOpCaps & D3DTEXOPCAPS_ADD ) ! = 0 ;
bool modSupported = ( caps . TextureOpCaps & D3DTEXOPCAPS_MODULATE2X ) ! = 0 ;
pCaps - > m_bNeedsATICentroidHack = false ;
pCaps - > m_bDisableShaderOptimizations = false ;
pCaps - > m_SupportsMipmapping = true ;
pCaps - > m_SupportsOverbright = true ;
// Thank you to all you driver writers who actually correctly return caps
if ( ! modSupported | | ! addSupported )
{
Assert ( 0 ) ;
pCaps - > m_SupportsOverbright = false ;
}
// Check if ZBias and SlopeScaleDepthBias are supported. .if not, tweak the projection matrix instead
// for polyoffset.
pCaps - > m_ZBiasAndSlopeScaledDepthBiasSupported =
( ( caps . RasterCaps & D3DPRASTERCAPS_DEPTHBIAS ) ! = 0 ) & &
( ( caps . RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS ) ! = 0 ) ;
if ( IsX360 ( ) )
{
// driver lies, force it
pCaps - > m_ZBiasAndSlopeScaledDepthBiasSupported = true ;
}
// Spheremapping supported?
pCaps - > m_bSupportsSpheremapping = ( caps . VertexProcessingCaps & D3DVTXPCAPS_TEXGEN_SPHEREMAP ) ! = 0 ;
// How many user clip planes?
pCaps - > m_MaxUserClipPlanes = caps . MaxUserClipPlanes ;
if ( CommandLine ( ) - > CheckParm ( " -nouserclip " ) /* || (IsOpenGL() && (!CommandLine()->FindParm("-glslmode"))) || r_emulategl.GetBool() */ )
{
// rbarris 03Feb10: this now ignores POSIX / -glslmode / r_emulategl because we're defaulting GLSL mode "on".
// so this will mean that the engine will always ask for user clip planes.
// this will misbehave under ARB mode, since ARB shaders won't respect that state.
// it's difficult to make this fluid without teaching the engine about a cap that could change during run.
pCaps - > m_MaxUserClipPlanes = 0 ;
}
if ( pCaps - > m_MaxUserClipPlanes > MAXUSERCLIPPLANES )
{
pCaps - > m_MaxUserClipPlanes = MAXUSERCLIPPLANES ;
}
pCaps - > m_FakeSRGBWrite = false ;
pCaps - > m_CanDoSRGBReadFromRTs = true ;
pCaps - > m_bSupportsGLMixedSizeTargets = false ;
# ifdef DX_TO_GL_ABSTRACTION
// using #if because we're referencing fields in the RHS which don't exist in Windows headers for the caps9 struct
pCaps - > m_FakeSRGBWrite = caps . FakeSRGBWrite ! = 0 ;
pCaps - > m_CanDoSRGBReadFromRTs = caps . CanDoSRGBReadFromRTs ! = 0 ;
pCaps - > m_bSupportsGLMixedSizeTargets = caps . MixedSizeTargets ! = 0 ;
# endif
// Query for SRGB support as needed for our DX 9 stuff
if ( IsPC ( ) | | ! IsX360 ( ) )
{
pCaps - > m_SupportsSRGB = ( D3D ( ) - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_QUERY_SRGBREAD , D3DRTYPE_TEXTURE , D3DFMT_DXT1 ) = = S_OK ) ;
if ( pCaps - > m_SupportsSRGB )
{
pCaps - > m_SupportsSRGB = ( D3D ( ) - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 , D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE , D3DRTYPE_TEXTURE , D3DFMT_A8R8G8B8 ) = = S_OK ) ;
}
}
else
{
// 360 does support it, but is queried in the wrong manner, so force it
pCaps - > m_SupportsSRGB = true ;
}
if ( CommandLine ( ) - > CheckParm ( " -nosrgb " ) )
{
pCaps - > m_SupportsSRGB = false ;
}
pCaps - > m_bSupportsVertexTextures = ( D3D ( ) - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE , D3DFMT_X8R8G8B8 ,
D3DUSAGE_QUERY_VERTEXTEXTURE , D3DRTYPE_TEXTURE , D3DFMT_R32F ) = = S_OK ) ;
if ( IsOpenGL ( ) )
{
pCaps - > m_bSupportsVertexTextures = false ;
}
// FIXME: vs30 has a fixed setting here at 4.
// Future hardware will need some other way of computing this.
pCaps - > m_nVertexTextureCount = pCaps - > m_bSupportsVertexTextures ? 4 : 0 ;
// FIXME: How do I actually compute this?
pCaps - > m_nMaxVertexTextureDimension = pCaps - > m_bSupportsVertexTextures ? 4096 : 0 ;
// Does the device support filterable int16 textures?
bool bSupportsInteger16Textures =
( D3D ( ) - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE ,
D3DFMT_X8R8G8B8 , D3DUSAGE_QUERY_FILTER ,
D3DRTYPE_TEXTURE , D3DFMT_A16B16G16R16 ) = = S_OK ) ;
// Does the device support filterable fp16 textures?
bool bSupportsFloat16Textures =
( D3D ( ) - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE ,
D3DFMT_X8R8G8B8 , D3DUSAGE_QUERY_FILTER ,
D3DRTYPE_TEXTURE , D3DFMT_A16B16G16R16F ) = = S_OK ) ;
// Does the device support blendable fp16 render targets?
bool bSupportsFloat16RenderTargets =
( D3D ( ) - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE ,
D3DFMT_X8R8G8B8 , D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING | D3DUSAGE_RENDERTARGET ,
D3DRTYPE_TEXTURE , D3DFMT_A16B16G16R16F ) = = S_OK ) ;
// Essentially a proxy for a DX10 device running DX9 code path
pCaps - > m_bSupportsFloat32RenderTargets = ( D3D ( ) - > CheckDeviceFormat ( nAdapter , DX8_DEVTYPE ,
D3DFMT_X8R8G8B8 , D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING | D3DUSAGE_RENDERTARGET ,
D3DRTYPE_TEXTURE , D3DFMT_A32B32G32R32F ) = = S_OK ) ;
pCaps - > m_bFogColorSpecifiedInLinearSpace = false ;
pCaps - > m_bFogColorAlwaysLinearSpace = false ;
// Assume not DX10. Check below.
pCaps - > m_bDX10Card = false ;
pCaps - > m_bDX10Blending = false ;
if ( IsOpenGL ( ) & & ( pCaps - > m_VendorID = = 1 ) )
{
// Linux/Win OpenGL - always assume the device supports DX10 style blending
pCaps - > m_bFogColorAlwaysLinearSpace = true ;
pCaps - > m_bDX10Card = true ;
pCaps - > m_bDX10Blending = true ;
}
// NVidia wants fog color to be specified in linear space
if ( IsPC ( ) & & pCaps - > m_SupportsSRGB )
{
if ( pCaps - > m_VendorID = = VENDORID_NVIDIA )
{
pCaps - > m_bFogColorSpecifiedInLinearSpace = true ;
if ( IsOpenGL ( ) )
{
// If we're not the Quadro 4500 or GeForce 7x000, we're an NVIDIA DX10 part on MacOS
if ( ! ( ( pCaps - > m_DeviceID = = 0x009d ) | | ( ( pCaps - > m_DeviceID > = 0x0391 ) & & ( pCaps - > m_DeviceID < = 0x0395 ) ) ) )
{
pCaps - > m_bFogColorAlwaysLinearSpace = true ;
pCaps - > m_bDX10Card = true ;
pCaps - > m_bDX10Blending = true ;
}
}
else
{
// On G80 and later, always specify in linear space
if ( pCaps - > m_bSupportsFloat32RenderTargets )
{
pCaps - > m_bFogColorAlwaysLinearSpace = true ;
pCaps - > m_bDX10Card = true ;
pCaps - > m_bDX10Blending = true ;
}
}
}
else if ( pCaps - > m_VendorID = = VENDORID_ATI )
{
if ( IsOpenGL ( ) )
{
// If we're not a Radeon X1x00 (device IDs in this range), we're a DX10 chip
if ( ! ( ( pCaps - > m_DeviceID > = 0x7109 ) & & ( pCaps - > m_DeviceID < = 0x7291 ) ) )
{
pCaps - > m_bFogColorSpecifiedInLinearSpace = true ;
pCaps - > m_bFogColorAlwaysLinearSpace = true ;
pCaps - > m_bDX10Card = true ;
pCaps - > m_bDX10Blending = true ;
}
}
else
{
// Check for DX10 part
pCaps - > m_bDX10Card = pCaps - > m_SupportsShaderModel_3_0 & &
( pCaps - > m_MaxVertexShader30InstructionSlots > 1024 ) & &
( pCaps - > m_MaxPixelShader30InstructionSlots > 512 ) ;
// On ATI, DX10 card means DX10 blending
pCaps - > m_bDX10Blending = pCaps - > m_bDX10Card ;
if ( pCaps - > m_bDX10Blending )
{
pCaps - > m_bFogColorSpecifiedInLinearSpace = true ;
pCaps - > m_bFogColorAlwaysLinearSpace = true ;
}
}
}
else if ( pCaps - > m_VendorID = = VENDORID_INTEL )
{
// Intel does not have performant vertex textures
pCaps - > m_bDX10Card = false ;
// Intel supports DX10 SRGB on Broadwater and better
// The two checks are for devices from GMA generation (0x29A2-0x2A43) and HD graphics (0x0042-0x2500)
pCaps - > m_bDX10Blending = ( ( pCaps - > m_DeviceID > = 0x29A2 ) & & ( pCaps - > m_DeviceID < = 0x2A43 ) ) | |
( ( pCaps - > m_DeviceID > = 0x0042 ) & & ( pCaps - > m_DeviceID < = 0x2500 ) ) ;
if ( pCaps - > m_bDX10Blending )
{
pCaps - > m_bFogColorSpecifiedInLinearSpace = true ;
pCaps - > m_bFogColorAlwaysLinearSpace = true ;
}
}
}
# ifdef TOGLES
bSupportsInteger16Textures = caps . SupportInt16Format ;
# endif
// Do we have everything necessary to run with integer HDR? Note that
// even if we don't support integer 16-bit/component textures, we
// can still run in this mode if fp16 textures are supported.
bool bSupportsIntegerHDR = pCaps - > m_SupportsPixelShaders_2_0 & &
pCaps - > m_SupportsVertexShaders_2_0 & &
// (caps.Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD) &&
// (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) &&
bSupportsInteger16Textures & &
pCaps - > m_SupportsSRGB ;
// Do we have everything necessary to run with float HDR?
bool bSupportsFloatHDR = pCaps - > m_SupportsShaderModel_3_0 & &
// (caps.Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD) &&
// (caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) &&
bSupportsFloat16Textures & &
bSupportsFloat16RenderTargets & &
pCaps - > m_SupportsSRGB & &
! IsX360 ( ) ;
pCaps - > m_MaxHDRType = HDR_TYPE_NONE ;
if ( bSupportsFloatHDR )
pCaps - > m_MaxHDRType = HDR_TYPE_FLOAT ;
else
if ( bSupportsIntegerHDR )
pCaps - > m_MaxHDRType = HDR_TYPE_INTEGER ;
if ( bSupportsFloatHDR & & ( mat_hdr_level . GetInt ( ) = = 3 ) )
{
pCaps - > m_HDRType = HDR_TYPE_FLOAT ;
}
else if ( bSupportsIntegerHDR )
{
pCaps - > m_HDRType = HDR_TYPE_INTEGER ;
}
else
{
pCaps - > m_HDRType = HDR_TYPE_NONE ;
}
pCaps - > m_bColorOnSecondStream = caps . MaxStreams > 1 ;
pCaps - > m_bSupportsStreamOffset = ( ( caps . DevCaps2 & D3DDEVCAPS2_STREAMOFFSET ) & & // Tie these caps together since we want to filter out
pCaps - > m_SupportsPixelShaders_2_0 ) ; // any DX8 parts which export D3DDEVCAPS2_STREAMOFFSET
pCaps - > m_flMinGammaControlPoint = 0.0f ;
pCaps - > m_flMaxGammaControlPoint = 65535.0f ;
pCaps - > m_nGammaControlPointCount = 256 ;
// Compute the effective DX support level based on all the other caps
ComputeDXSupportLevel ( * pCaps ) ;
int nCmdlineMaxDXLevel = CommandLine ( ) - > ParmValue ( " -maxdxlevel " , 0 ) ;
if ( IsOpenGL ( ) & & ( nCmdlineMaxDXLevel > 0 ) )
{
// Prevent customers from slamming us below DX level 90 in OpenGL mode.
nCmdlineMaxDXLevel = MAX ( nCmdlineMaxDXLevel , 90 ) ;
}
if ( nCmdlineMaxDXLevel > 0 )
{
pCaps - > m_nMaxDXSupportLevel = min ( pCaps - > m_nMaxDXSupportLevel , nCmdlineMaxDXLevel ) ;
}
pCaps - > m_nDXSupportLevel = pCaps - > m_nMaxDXSupportLevel ;
int nModelIndex = pCaps - > m_nDXSupportLevel < 90 ? VERTEX_SHADER_MODEL - 10 : VERTEX_SHADER_MODEL ;
pCaps - > m_MaxVertexShaderBlendMatrices = ( pCaps - > m_NumVertexShaderConstants - nModelIndex ) / 3 ;
if ( pCaps - > m_MaxVertexShaderBlendMatrices > NUM_MODEL_TRANSFORMS )
{
pCaps - > m_MaxVertexShaderBlendMatrices = NUM_MODEL_TRANSFORMS ;
}
CheckBorderColorSupport ( pCaps , nAdapter ) ;
// This may get more complex if we start using multiple flavors of compressed vertex - for now it's "on or off"
pCaps - > m_SupportsCompressedVertices = ( pCaps - > m_nDXSupportLevel > = 90 ) & & ( pCaps - > m_CanDoSRGBReadFromRTs ) ? VERTEX_COMPRESSION_ON : VERTEX_COMPRESSION_NONE ;
if ( CommandLine ( ) - > CheckParm ( " -no_compressed_verts " ) ) // m_CanDoSRGBReadFromRTs limits us to Snow Leopard or later on OSX
{
pCaps - > m_SupportsCompressedVertices = VERTEX_COMPRESSION_NONE ;
}
// Various vendor-dependent checks...
CheckVendorDependentAlphaToCoverage ( pCaps , nAdapter ) ;
CheckVendorDependentShadowMappingSupport ( pCaps , nAdapter ) ;
// If we're not on a 3.0 part, these values are more appropriate (X800 & X850 parts from ATI do shadow mapping but not 3.0 )
if ( ! IsOpenGL ( ) )
{
if ( ! pCaps - > m_SupportsShaderModel_3_0 )
{
mat_slopescaledepthbias_shadowmap . SetValue ( 5.9f ) ;
mat_depthbias_shadowmap . SetValue ( 0.003f ) ;
}
}
if ( pCaps - > m_MaxUserClipPlanes = = 0 )
{
pCaps - > m_UseFastClipping = true ;
}
pCaps - > m_MaxSimultaneousRenderTargets = caps . NumSimultaneousRTs ;
return true ;
}
//-----------------------------------------------------------------------------
// Compute the effective DX support level based on all the other caps
//-----------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : ComputeDXSupportLevel ( HardwareCaps_t & caps )
{
// NOTE: Support level is actually DX level * 10 + subversion
// So, 70 = DX7, 80 = DX8, 81 = DX8 w/ 1.4 pixel shaders
// 90 = DX9 w/ 2.0 pixel shaders
// 95 = DX9 w/ 3.0 pixel shaders and vertex textures
// 98 = DX9 XBox360
// NOTE: 82 = NVidia nv3x cards, which can't run dx9 fast
// FIXME: Improve this!! There should be a whole list of features
// we require in order to be considered a DX7 board, DX8 board, etc.
if ( IsX360 ( ) )
{
caps . m_nMaxDXSupportLevel = 98 ;
return ;
}
bool bIsOpenGL = IsOpenGL ( ) ;
if ( caps . m_SupportsShaderModel_3_0 & & ! bIsOpenGL ) // Note that we don't tie vertex textures to 30 shaders anymore
{
caps . m_nMaxDXSupportLevel = 95 ;
return ;
}
// NOTE: sRGB is currently required for DX90 because it isn't doing
// gamma correctly if that feature doesn't exist
if ( caps . m_SupportsVertexShaders_2_0 & & caps . m_SupportsPixelShaders_2_0 & & caps . m_SupportsSRGB )
{
caps . m_nMaxDXSupportLevel = 90 ;
return ;
}
if ( caps . m_SupportsPixelShaders & & caps . m_SupportsVertexShaders ) // && caps.m_bColorOnSecondStream)
{
if ( caps . m_SupportsPixelShaders_1_4 )
{
caps . m_nMaxDXSupportLevel = 81 ;
return ;
}
caps . m_nMaxDXSupportLevel = 80 ;
return ;
}
if ( caps . m_SupportsCubeMaps & & ( caps . m_MaxBlendMatrices > = 2 ) )
{
caps . m_nMaxDXSupportLevel = 70 ;
return ;
}
if ( ( caps . m_NumSamplers > = 2 ) & & caps . m_SupportsMipmapping )
{
caps . m_nMaxDXSupportLevel = 60 ;
return ;
}
Assert ( 0 ) ;
// we don't support this!
caps . m_nMaxDXSupportLevel = 50 ;
}
//-----------------------------------------------------------------------------
// Gets the number of adapters...
//-----------------------------------------------------------------------------
int CShaderDeviceMgrDx8 : : GetAdapterCount ( ) const
{
// FIXME: Remove call to InitAdapterInfo once Steam startup issues are resolved.
const_cast < CShaderDeviceMgrDx8 * > ( this ) - > InitAdapterInfo ( ) ;
return m_Adapters . Count ( ) ;
}
//-----------------------------------------------------------------------------
// Returns info about each adapter
//-----------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : GetAdapterInfo ( int nAdapter , MaterialAdapterInfo_t & info ) const
{
// FIXME: Remove call to InitAdapterInfo once Steam startup issues are resolved.
const_cast < CShaderDeviceMgrDx8 * > ( this ) - > InitAdapterInfo ( ) ;
Assert ( ( nAdapter > = 0 ) & & ( nAdapter < m_Adapters . Count ( ) ) ) ;
const HardwareCaps_t & caps = m_Adapters [ nAdapter ] . m_ActualCaps ;
memcpy ( & info , & caps , sizeof ( MaterialAdapterInfo_t ) ) ;
}
//-----------------------------------------------------------------------------
// Sets the adapter
//-----------------------------------------------------------------------------
bool CShaderDeviceMgrDx8 : : SetAdapter ( int nAdapter , int nAdapterFlags )
{
LOCK_SHADERAPI ( ) ;
// FIXME:
// g_pShaderDeviceDx8->m_bReadPixelsEnabled = (nAdapterFlags & MATERIAL_INIT_READ_PIXELS_ENABLED) != 0;
// Set up hardware information for this adapter...
g_pShaderDeviceDx8 - > m_DeviceType = ( nAdapterFlags & MATERIAL_INIT_REFERENCE_RASTERIZER ) ?
D3DDEVTYPE_REF : D3DDEVTYPE_HAL ;
g_pShaderDeviceDx8 - > m_DisplayAdapter = nAdapter ;
if ( g_pShaderDeviceDx8 - > m_DisplayAdapter > = ( UINT ) GetAdapterCount ( ) )
{
g_pShaderDeviceDx8 - > m_DisplayAdapter = 0 ;
}
# ifdef NVPERFHUD
// hack for nvperfhud
g_pShaderDeviceDx8 - > m_DisplayAdapter = m_pD3D - > GetAdapterCount ( ) - 1 ;
g_pShaderDeviceDx8 - > m_DeviceType = D3DDEVTYPE_REF ;
# endif
// backward compat
if ( ! g_pShaderDeviceDx8 - > OnAdapterSet ( ) )
return false ;
// if ( !g_pShaderDeviceDx8->Init() )
// {
// Warning( "Unable to initialize dx8 device!\n" );
// return false;
// }
g_pShaderDevice = g_pShaderDeviceDx8 ;
return true ;
}
//-----------------------------------------------------------------------------
// Returns the number of modes
//-----------------------------------------------------------------------------
int CShaderDeviceMgrDx8 : : GetModeCount ( int nAdapter ) const
{
LOCK_SHADERAPI ( ) ;
Assert ( m_pD3D & & ( nAdapter < GetAdapterCount ( ) ) ) ;
# if !defined( _X360 )
// fixme - what format should I use here?
return m_pD3D - > GetAdapterModeCount ( nAdapter , D3DFMT_X8R8G8B8 ) ;
# else
return 1 ; // Only one mode, which is the current mode set in the 360 dashboard. Going to fill it in with exactly what the 360 is set to.
# endif
}
//-----------------------------------------------------------------------------
// Returns mode information..
//-----------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : GetModeInfo ( ShaderDisplayMode_t * pInfo , int nAdapter , int nMode ) const
{
Assert ( pInfo - > m_nVersion = = SHADER_DISPLAY_MODE_VERSION ) ;
LOCK_SHADERAPI ( ) ;
Assert ( m_pD3D & & ( nAdapter < GetAdapterCount ( ) ) ) ;
Assert ( nMode < GetModeCount ( nAdapter ) ) ;
# if !defined( _X360 )
HRESULT hr ;
D3DDISPLAYMODE d3dInfo ;
// fixme - what format should I use here?
hr = D3D ( ) - > EnumAdapterModes ( nAdapter , D3DFMT_X8R8G8B8 , nMode , & d3dInfo ) ;
Assert ( ! FAILED ( hr ) ) ;
pInfo - > m_nWidth = d3dInfo . Width ;
pInfo - > m_nHeight = d3dInfo . Height ;
pInfo - > m_Format = ImageLoader : : D3DFormatToImageFormat ( d3dInfo . Format ) ;
pInfo - > m_nRefreshRateNumerator = d3dInfo . RefreshRate ;
pInfo - > m_nRefreshRateDenominator = 1 ;
# else
pInfo - > m_Format = ImageLoader : : D3DFormatToImageFormat ( D3DFMT_X8R8G8B8 ) ;
pInfo - > m_nRefreshRateNumerator = 60 ;
pInfo - > m_nRefreshRateDenominator = 1 ;
pInfo - > m_nWidth = GetSystemMetrics ( SM_CXSCREEN ) ;
pInfo - > m_nHeight = GetSystemMetrics ( SM_CYSCREEN ) ;
# endif
}
//-----------------------------------------------------------------------------
// Returns the current mode information for an adapter
//-----------------------------------------------------------------------------
void CShaderDeviceMgrDx8 : : GetCurrentModeInfo ( ShaderDisplayMode_t * pInfo , int nAdapter ) const
{
Assert ( pInfo - > m_nVersion = = SHADER_DISPLAY_MODE_VERSION ) ;
LOCK_SHADERAPI ( ) ;
Assert ( D3D ( ) ) ;
HRESULT hr ;
D3DDISPLAYMODE mode = { 0 } ;
# if !defined( _X360 )
hr = D3D ( ) - > GetAdapterDisplayMode ( nAdapter , & mode ) ;
Assert ( ! FAILED ( hr ) ) ;
# else
if ( ! g_pD3DDevice )
{
// the console has no prior display or mode until its created
mode . Width = GetSystemMetrics ( SM_CXSCREEN ) ;
mode . Height = GetSystemMetrics ( SM_CYSCREEN ) ;
mode . RefreshRate = 60 ;
mode . Format = D3DFMT_X8R8G8B8 ;
}
else
{
hr = g_pD3DDevice - > GetDisplayMode ( 0 , & mode ) ;
Assert ( ! FAILED ( hr ) ) ;
}
# endif
pInfo - > m_nWidth = mode . Width ;
pInfo - > m_nHeight = mode . Height ;
pInfo - > m_Format = ImageLoader : : D3DFormatToImageFormat ( mode . Format ) ;
pInfo - > m_nRefreshRateNumerator = mode . RefreshRate ;
pInfo - > m_nRefreshRateDenominator = 1 ;
}
//-----------------------------------------------------------------------------
// Sets the video mode
//-----------------------------------------------------------------------------
CreateInterfaceFn CShaderDeviceMgrDx8 : : 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 )
return NULL ;
bool bReacquireResourcesNeeded = false ;
if ( g_pShaderDevice )
{
bReacquireResourcesNeeded = IsPC ( ) ;
g_pShaderDevice - > ReleaseResources ( ) ;
}
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_pShaderDeviceDx8 - > InitDevice ( hWnd , nAdapter , adjustedMode ) )
return NULL ;
if ( ! g_pShaderAPIDX8 - > OnDeviceInit ( ) )
return NULL ;
g_pShaderDevice = g_pShaderDeviceDx8 ;
g_pShaderAPI = g_pShaderAPIDX8 ;
g_pShaderShadow = g_pShaderShadowDx8 ;
if ( bReacquireResourcesNeeded )
{
g_pShaderDevice - > ReacquireResources ( ) ;
}
return ShaderInterfaceFactory ;
}
//-----------------------------------------------------------------------------
// Validates the mode...
//-----------------------------------------------------------------------------
bool CShaderDeviceMgrDx8 : : ValidateMode ( int nAdapter , const ShaderDeviceInfo_t & info ) const
{
if ( nAdapter > = ( int ) D3D ( ) - > GetAdapterCount ( ) )
return false ;
ShaderDisplayMode_t displayMode ;
if ( info . m_bWindowed )
{
// windowed mode always appears on the primary display, so we should use that adapter's
// settings
GetCurrentModeInfo ( & displayMode , 0 ) ;
// make sure the window fits within the current video mode
if ( ( info . m_DisplayMode . m_nWidth > displayMode . m_nWidth ) | |
( info . m_DisplayMode . m_nHeight > displayMode . m_nHeight ) )
return false ;
}
else
{
GetCurrentModeInfo ( & displayMode , nAdapter ) ;
}
// Make sure the image format requested is valid
ImageFormat backBufferFormat = FindNearestSupportedBackBufferFormat ( nAdapter ,
DX8_DEVTYPE , displayMode . m_Format , info . m_DisplayMode . m_Format , info . m_bWindowed ) ;
return ( backBufferFormat ! = IMAGE_FORMAT_UNKNOWN ) ;
}
//-----------------------------------------------------------------------------
// Returns the amount of video memory in bytes for a particular adapter
//-----------------------------------------------------------------------------
int CShaderDeviceMgrDx8 : : GetVidMemBytes ( int nAdapter ) const
{
# if defined( _X360 )
return 256 * 1024 * 1024 ;
# elif defined (DX_TO_GL_ABSTRACTION)
D3DADAPTER_IDENTIFIER9 devIndentifier ;
D3D ( ) - > GetAdapterIdentifier ( nAdapter , D3DENUM_WHQL_LEVEL , & devIndentifier ) ;
return devIndentifier . VideoMemory ;
# else
// FIXME: This currently ignores the adapter
uint64 nBytes = : : GetVidMemBytes ( ) ;
if ( nBytes > INT_MAX )
return INT_MAX ;
return nBytes ;
# endif
}
//-----------------------------------------------------------------------------
//
// Shader device
//
//-----------------------------------------------------------------------------
#if 0
// FIXME: Enable after I've separated it out from shaderapidx8 a little better
static CShaderDeviceDx8 s_ShaderDeviceDX8 ;
CShaderDeviceDx8 * g_pShaderDeviceDx8 = & s_ShaderDeviceDX8 ;
# endif
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CShaderDeviceDx8 : : CShaderDeviceDx8 ( )
{
g_pD3DDevice = NULL ;
for ( int i = 0 ; i < ARRAYSIZE ( m_pFrameSyncQueryObject ) ; i + + )
{
m_pFrameSyncQueryObject [ i ] = NULL ;
m_bQueryIssued [ i ] = false ;
}
m_pFrameSyncTexture = NULL ;
m_bQueuedDeviceLost = false ;
m_DeviceState = DEVICE_STATE_OK ;
m_bOtherAppInitializing = false ;
m_IsResizing = false ;
m_bPendingVideoModeChange = false ;
m_DeviceSupportsCreateQuery = - 1 ;
m_bUsingStencil = false ;
m_bResourcesReleased = false ;
m_iStencilBufferBits = 0 ;
m_NonInteractiveRefresh . m_Mode = MATERIAL_NON_INTERACTIVE_MODE_NONE ;
m_NonInteractiveRefresh . m_pVertexShader = NULL ;
m_NonInteractiveRefresh . m_pPixelShader = NULL ;
m_NonInteractiveRefresh . m_pPixelShaderStartup = NULL ;
m_NonInteractiveRefresh . m_pPixelShaderStartupPass2 = NULL ;
m_NonInteractiveRefresh . m_pVertexDecl = NULL ;
m_NonInteractiveRefresh . m_nPacifierFrame = 0 ;
m_numReleaseResourcesRefCount = 0 ;
}
CShaderDeviceDx8 : : ~ CShaderDeviceDx8 ( )
{
}
//-----------------------------------------------------------------------------
// Computes device creation paramters
//-----------------------------------------------------------------------------
static DWORD ComputeDeviceCreationFlags ( D3DCAPS & caps , bool bSoftwareVertexProcessing )
{
// Find out what type of device to make
bool bPureDeviceSupported = ( caps . DevCaps & D3DDEVCAPS_PUREDEVICE ) ! = 0 ;
DWORD nDeviceCreationFlags ;
if ( ! bSoftwareVertexProcessing )
{
nDeviceCreationFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING ;
if ( bPureDeviceSupported )
{
nDeviceCreationFlags | = D3DCREATE_PUREDEVICE ;
}
}
else
{
nDeviceCreationFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING ;
}
nDeviceCreationFlags | = D3DCREATE_FPU_PRESERVE ;
# ifdef _X360
nDeviceCreationFlags | = D3DCREATE_BUFFER_2_FRAMES ;
# endif
return nDeviceCreationFlags ;
}
//-----------------------------------------------------------------------------
// Computes the supersample flags
//-----------------------------------------------------------------------------
D3DMULTISAMPLE_TYPE CShaderDeviceDx8 : : ComputeMultisampleType ( int nSampleCount )
{
switch ( nSampleCount )
{
# if !defined( _X360 )
case 2 : return D3DMULTISAMPLE_2_SAMPLES ;
case 3 : return D3DMULTISAMPLE_3_SAMPLES ;
case 4 : return D3DMULTISAMPLE_4_SAMPLES ;
case 5 : return D3DMULTISAMPLE_5_SAMPLES ;
case 6 : return D3DMULTISAMPLE_6_SAMPLES ;
case 7 : return D3DMULTISAMPLE_7_SAMPLES ;
case 8 : return D3DMULTISAMPLE_8_SAMPLES ;
case 9 : return D3DMULTISAMPLE_9_SAMPLES ;
case 10 : return D3DMULTISAMPLE_10_SAMPLES ;
case 11 : return D3DMULTISAMPLE_11_SAMPLES ;
case 12 : return D3DMULTISAMPLE_12_SAMPLES ;
case 13 : return D3DMULTISAMPLE_13_SAMPLES ;
case 14 : return D3DMULTISAMPLE_14_SAMPLES ;
case 15 : return D3DMULTISAMPLE_15_SAMPLES ;
case 16 : return D3DMULTISAMPLE_16_SAMPLES ;
# else
case 2 : return D3DMULTISAMPLE_2_SAMPLES ;
case 4 : return D3DMULTISAMPLE_4_SAMPLES ;
# endif
default :
case 0 :
case 1 :
return D3DMULTISAMPLE_NONE ;
}
}
//-----------------------------------------------------------------------------
// Sets the present parameters
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : SetPresentParameters ( void * hWnd , int nAdapter , const ShaderDeviceInfo_t & info )
{
ShaderDisplayMode_t mode ;
g_pShaderDeviceMgr - > GetCurrentModeInfo ( & mode , nAdapter ) ;
HRESULT hr ;
ZeroMemory ( & m_PresentParameters , sizeof ( m_PresentParameters ) ) ;
m_PresentParameters . Windowed = info . m_bWindowed ;
m_PresentParameters . SwapEffect = info . m_bUsingMultipleWindows ? D3DSWAPEFFECT_COPY : D3DSWAPEFFECT_DISCARD ;
// for 360, we want to create it ourselves for hierarchical z support
m_PresentParameters . EnableAutoDepthStencil = IsX360 ( ) ? FALSE : TRUE ;
// What back-buffer format should we use?
ImageFormat backBufferFormat = FindNearestSupportedBackBufferFormat ( nAdapter ,
DX8_DEVTYPE , m_AdapterFormat , info . m_DisplayMode . m_Format , info . m_bWindowed ) ;
// What depth format should we use?
m_bUsingStencil = info . m_bUseStencil ;
if ( info . m_nDXLevel > = 80 )
{
// always stencil for dx9/hdr
m_bUsingStencil = true ;
}
# if defined( _X360 )
D3DFORMAT nDepthFormat = ReverseDepthOnX360 ( ) ? D3DFMT_D24FS8 : D3DFMT_D24S8 ;
# else
D3DFORMAT nDepthFormat = m_bUsingStencil ? D3DFMT_D24S8 : D3DFMT_D24X8 ;
# endif
m_PresentParameters . AutoDepthStencilFormat = FindNearestSupportedDepthFormat (
nAdapter , m_AdapterFormat , backBufferFormat , nDepthFormat ) ;
m_PresentParameters . hDeviceWindow = ( VD3DHWND ) hWnd ;
// store how many stencil buffer bits we have available with the depth/stencil buffer
switch ( m_PresentParameters . AutoDepthStencilFormat )
{
case D3DFMT_D24S8 :
m_iStencilBufferBits = 8 ;
break ;
# if defined( _X360 )
case D3DFMT_D24FS8 :
m_iStencilBufferBits = 8 ;
break ;
# else
case D3DFMT_D24X4S4 :
m_iStencilBufferBits = 4 ;
break ;
case D3DFMT_D15S1 :
m_iStencilBufferBits = 1 ;
break ;
# endif
default :
m_iStencilBufferBits = 0 ;
m_bUsingStencil = false ; //couldn't acquire a stencil buffer
} ;
if ( IsX360 ( ) | | ! info . m_bWindowed )
{
bool useDefault = ( info . m_DisplayMode . m_nWidth = = 0 ) | | ( info . m_DisplayMode . m_nHeight = = 0 ) ;
m_PresentParameters . BackBufferCount = 1 ;
m_PresentParameters . BackBufferWidth = useDefault ? mode . m_nWidth : info . m_DisplayMode . m_nWidth ;
m_PresentParameters . BackBufferHeight = useDefault ? mode . m_nHeight : info . m_DisplayMode . m_nHeight ;
m_PresentParameters . BackBufferFormat = ImageLoader : : ImageFormatToD3DFormat ( backBufferFormat ) ;
# if defined( _X360 )
m_PresentParameters . FrontBufferFormat = D3DFMT_LE_X8R8G8B8 ;
# endif
if ( ! info . m_bWaitForVSync | | CommandLine ( ) - > FindParm ( " -forcenovsync " ) )
{
m_PresentParameters . PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;
}
else
{
m_PresentParameters . PresentationInterval = D3DPRESENT_INTERVAL_ONE ;
}
m_PresentParameters . FullScreen_RefreshRateInHz = info . m_DisplayMode . m_nRefreshRateDenominator ?
info . m_DisplayMode . m_nRefreshRateNumerator / info . m_DisplayMode . m_nRefreshRateDenominator : D3DPRESENT_RATE_DEFAULT ;
# if defined( _X360 )
XVIDEO_MODE videoMode ;
XGetVideoMode ( & videoMode ) ;
// want 30 for 60Hz, and 25 for 50Hz (PAL)
int nNewFpsMax = ( ( int ) ( videoMode . RefreshRate + 0.5f ) ) > > 1 ;
// slam to either 30 or 25 so that we don't end up with any other cases.
if ( nNewFpsMax < 26 )
{
nNewFpsMax = 25 ;
}
else
{
nNewFpsMax = 30 ;
}
DevMsg ( " *******Monitor refresh is %f, setting fps_max to %d********* \n " , videoMode . RefreshRate , nNewFpsMax ) ;
ConVarRef fps_max ( " fps_max " ) ;
fps_max . SetValue ( nNewFpsMax ) ;
// setup hardware scaling - should be native 720p upsampling to 1080i
if ( info . m_bScaleToOutputResolution )
{
m_PresentParameters . VideoScalerParameters . ScalerSourceRect . x2 = m_PresentParameters . BackBufferWidth ;
m_PresentParameters . VideoScalerParameters . ScalerSourceRect . y2 = m_PresentParameters . BackBufferHeight ;
m_PresentParameters . VideoScalerParameters . ScaledOutputWidth = videoMode . dwDisplayWidth ;
m_PresentParameters . VideoScalerParameters . ScaledOutputHeight = videoMode . dwDisplayHeight ;
DevMsg ( " VIDEO SCALING: scaling from %dx%d to %dx%d \n " , ( int ) m_PresentParameters . BackBufferWidth , ( int ) m_PresentParameters . BackBufferHeight ,
( int ) videoMode . dwDisplayWidth , ( int ) videoMode . dwDisplayHeight ) ;
}
else
{
DevMsg ( " VIDEO SCALING: No scaling: %dx%d \n " , ( int ) m_PresentParameters . BackBufferWidth , ( int ) m_PresentParameters . BackBufferHeight ) ;
}
# endif
}
else
{
// NJS: We are seeing a lot of time spent in present in some cases when this isn't set.
m_PresentParameters . PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE ;
if ( info . m_bResizing )
{
if ( info . m_bLimitWindowedSize & &
( info . m_nWindowedSizeLimitWidth < mode . m_nWidth | | info . m_nWindowedSizeLimitHeight < mode . m_nHeight ) )
{
// When using material system in windowed resizing apps, it's
// sometimes not a good idea to allocate stuff as big as the screen
// video cards can soo run out of resources
m_PresentParameters . BackBufferWidth = info . m_nWindowedSizeLimitWidth ;
m_PresentParameters . BackBufferHeight = info . m_nWindowedSizeLimitHeight ;
}
else
{
// When in resizing windowed mode,
// we want to allocate enough memory to deal with any resizing...
m_PresentParameters . BackBufferWidth = mode . m_nWidth ;
m_PresentParameters . BackBufferHeight = mode . m_nHeight ;
}
}
else
{
m_PresentParameters . BackBufferWidth = info . m_DisplayMode . m_nWidth ;
m_PresentParameters . BackBufferHeight = info . m_DisplayMode . m_nHeight ;
}
m_PresentParameters . BackBufferFormat = ImageLoader : : ImageFormatToD3DFormat ( backBufferFormat ) ;
m_PresentParameters . BackBufferCount = 1 ;
}
if ( info . m_nAASamples > 0 & & ( m_PresentParameters . SwapEffect = = D3DSWAPEFFECT_DISCARD ) )
{
D3DMULTISAMPLE_TYPE multiSampleType = ComputeMultisampleType ( info . m_nAASamples ) ;
DWORD nQualityLevel ;
// FIXME: Should we add the quality level to the ShaderAdapterMode_t struct?
// 16x on nVidia refers to CSAA or "Coverage Sampled Antialiasing"
const HardwareCaps_t & adapterCaps = g_ShaderDeviceMgrDx8 . GetHardwareCaps ( nAdapter ) ;
if ( ( info . m_nAASamples = = 16 ) & & ( adapterCaps . m_VendorID = = VENDORID_NVIDIA ) )
{
multiSampleType = ComputeMultisampleType ( 4 ) ;
hr = D3D ( ) - > CheckDeviceMultiSampleType ( nAdapter , DX8_DEVTYPE ,
m_PresentParameters . BackBufferFormat , m_PresentParameters . Windowed ,
multiSampleType , & nQualityLevel ) ; // 4x at highest quality level
if ( ! FAILED ( hr ) & & ( nQualityLevel = = 16 ) )
{
nQualityLevel = nQualityLevel - 1 ; // Highest quality level triggers 16x CSAA
}
else
{
nQualityLevel = 0 ; // No CSAA
}
}
else // Regular MSAA on any old vendor
{
hr = D3D ( ) - > CheckDeviceMultiSampleType ( nAdapter , DX8_DEVTYPE ,
m_PresentParameters . BackBufferFormat , m_PresentParameters . Windowed ,
multiSampleType , & nQualityLevel ) ;
nQualityLevel = 0 ;
}
if ( ! FAILED ( hr ) )
{
m_PresentParameters . MultiSampleType = multiSampleType ;
m_PresentParameters . MultiSampleQuality = nQualityLevel ;
}
}
else
{
m_PresentParameters . MultiSampleType = D3DMULTISAMPLE_NONE ;
m_PresentParameters . MultiSampleQuality = 0 ;
}
}
//-----------------------------------------------------------------------------
// Initializes, shuts down the D3D device
//-----------------------------------------------------------------------------
bool CShaderDeviceDx8 : : InitDevice ( void * hwnd , int nAdapter , const ShaderDeviceInfo_t & info )
{
//Debugger();
// good place to run some self tests.
//#if OSX
//{
// extern void GLMgrSelfTests( void );
// GLMgrSelfTests();
//}
//#endif
// windowed
if ( ! CreateD3DDevice ( ( VD3DHWND ) hwnd , nAdapter , info ) )
return false ;
// Hook up our own windows proc to get at messages to tell us when
// other instances of the material system are trying to set the mode
InstallWindowHook ( ( VD3DHWND ) m_hWnd ) ;
return true ;
}
void CShaderDeviceDx8 : : ShutdownDevice ( )
{
if ( IsPC ( ) & & IsActive ( ) )
{
Dx9Device ( ) - > Release ( ) ;
# ifdef STUBD3D
delete ( CStubD3DDevice * ) Dx9Device ( ) ;
# endif
g_pD3DDevice = NULL ;
RemoveWindowHook ( ( VD3DHWND ) m_hWnd ) ;
m_hWnd = 0 ;
}
}
//-----------------------------------------------------------------------------
// Are we using graphics?
//-----------------------------------------------------------------------------
bool CShaderDeviceDx8 : : IsUsingGraphics ( ) const
{
//*****LOCK_SHADERAPI();
return IsActive ( ) ;
}
//-----------------------------------------------------------------------------
// Returns the current adapter in use
//-----------------------------------------------------------------------------
int CShaderDeviceDx8 : : GetCurrentAdapter ( ) const
{
LOCK_SHADERAPI ( ) ;
return m_DisplayAdapter ;
}
//-----------------------------------------------------------------------------
// Returns the current adapter in use
//-----------------------------------------------------------------------------
char * CShaderDeviceDx8 : : GetDisplayDeviceName ( )
{
if ( m_sDisplayDeviceName . IsEmpty ( ) )
{
D3DADAPTER_IDENTIFIER9 ident ;
// On Win10, this function is getting called with m_nAdapter still initialized to -1.
// It's failing, and m_sDisplayDeviceName has garbage, and tf2 fails to launch.
// To repro this, run "hl2.exe -dev -fullscreen -game tf" on Win10.
HRESULT hr = D3D ( ) - > GetAdapterIdentifier ( Max ( m_nAdapter , 0 ) , 0 , & ident ) ;
if ( FAILED ( hr ) )
{
Assert ( false ) ;
ident . DeviceName [ 0 ] = 0 ;
}
m_sDisplayDeviceName = ident . DeviceName ;
}
return m_sDisplayDeviceName . GetForModify ( ) ;
}
//-----------------------------------------------------------------------------
// Use this to spew information about the 3D layer
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : SpewDriverInfo ( ) const
{
LOCK_SHADERAPI ( ) ;
HRESULT hr ;
D3DCAPS caps ;
D3DADAPTER_IDENTIFIER9 ident ;
RECORD_COMMAND ( DX8_GET_DEVICE_CAPS , 0 ) ;
RECORD_COMMAND ( DX8_GET_ADAPTER_IDENTIFIER , 2 ) ;
RECORD_INT ( m_nAdapter ) ;
RECORD_INT ( 0 ) ;
Dx9Device ( ) - > GetDeviceCaps ( & caps ) ;
hr = D3D ( ) - > GetAdapterIdentifier ( m_nAdapter , D3DENUM_WHQL_LEVEL , & ident ) ;
Warning ( " Shader API Driver Info: \n \n Driver : %s Version : %lld \n " ,
ident . Driver , ident . DriverVersion . QuadPart ) ;
Warning ( " Driver Description : %s \n " , ident . Description ) ;
Warning ( " Chipset version %d %d %d %d \n \n " ,
ident . VendorId , ident . DeviceId , ident . SubSysId , ident . Revision ) ;
ShaderDisplayMode_t mode ;
g_pShaderDeviceMgr - > GetCurrentModeInfo ( & mode , m_nAdapter ) ;
Warning ( " Display mode : %d x %d (%s) \n " ,
mode . m_nWidth , mode . m_nHeight , ImageLoader : : GetName ( mode . m_Format ) ) ;
Warning ( " Vertex Shader Version : %d.%d Pixel Shader Version : %d.%d \n " ,
( caps . VertexShaderVersion > > 8 ) & 0xFF , caps . VertexShaderVersion & 0xFF ,
( caps . PixelShaderVersion > > 8 ) & 0xFF , caps . PixelShaderVersion & 0xFF ) ;
Warning ( " \n Device Caps : \n " ) ;
Warning ( " CANBLTSYSTONONLOCAL %s CANRENDERAFTERFLIP %s HWRASTERIZATION %s \n " ,
( caps . DevCaps & D3DDEVCAPS_CANBLTSYSTONONLOCAL ) ? " Y " : " N " ,
( caps . DevCaps & D3DDEVCAPS_CANRENDERAFTERFLIP ) ? " Y " : " N " ,
( caps . DevCaps & D3DDEVCAPS_HWRASTERIZATION ) ? " Y " : " *N* " ) ;
Warning ( " HWTRANSFORMANDLIGHT %s NPATCHES %s PUREDEVICE %s \n " ,
( caps . DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) ? " Y " : " N " ,
( caps . DevCaps & D3DDEVCAPS_NPATCHES ) ? " Y " : " N " ,
( caps . DevCaps & D3DDEVCAPS_PUREDEVICE ) ? " Y " : " N " ) ;
Warning ( " SEPARATETEXTUREMEMORIES %s TEXTURENONLOCALVIDMEM %s TEXTURESYSTEMMEMORY %s \n " ,
( caps . DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES ) ? " *Y* " : " N " ,
( caps . DevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM ) ? " Y " : " N " ,
( caps . DevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY ) ? " Y " : " N " ) ;
Warning ( " TEXTUREVIDEOMEMORY %s TLVERTEXSYSTEMMEMORY %s TLVERTEXVIDEOMEMORY %s \n " ,
( caps . DevCaps & D3DDEVCAPS_TEXTUREVIDEOMEMORY ) ? " Y " : " *N* " ,
( caps . DevCaps & D3DDEVCAPS_TLVERTEXSYSTEMMEMORY ) ? " Y " : " *N* " ,
( caps . DevCaps & D3DDEVCAPS_TLVERTEXVIDEOMEMORY ) ? " Y " : " N " ) ;
Warning ( " \n Primitive Caps : \n " ) ;
Warning ( " BLENDOP %s CLIPPLANESCALEDPOINTS %s CLIPTLVERTS %s \n " ,
( caps . PrimitiveMiscCaps & D3DPMISCCAPS_BLENDOP ) ? " Y " : " N " ,
( caps . PrimitiveMiscCaps & D3DPMISCCAPS_CLIPPLANESCALEDPOINTS ) ? " Y " : " N " ,
( caps . PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS ) ? " Y " : " N " ) ;
Warning ( " COLORWRITEENABLE %s MASKZ %s TSSARGTEMP %s \n " ,
( caps . PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE ) ? " Y " : " N " ,
( caps . PrimitiveMiscCaps & D3DPMISCCAPS_MASKZ ) ? " Y " : " *N* " ,
( caps . PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP ) ? " Y " : " N " ) ;
Warning ( " \n Raster Caps : \n " ) ;
Warning ( " FOGRANGE %s FOGTABLE %s FOGVERTEX %s ZFOG %s WFOG %s \n " ,
( caps . RasterCaps & D3DPRASTERCAPS_FOGRANGE ) ? " Y " : " N " ,
( caps . RasterCaps & D3DPRASTERCAPS_FOGTABLE ) ? " Y " : " N " ,
( caps . RasterCaps & D3DPRASTERCAPS_FOGVERTEX ) ? " Y " : " N " ,
( caps . RasterCaps & D3DPRASTERCAPS_ZFOG ) ? " Y " : " N " ,
( caps . RasterCaps & D3DPRASTERCAPS_WFOG ) ? " Y " : " N " ) ;
Warning ( " MIPMAPLODBIAS %s WBUFFER %s ZBIAS %s ZTEST %s \n " ,
( caps . RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS ) ? " Y " : " N " ,
( caps . RasterCaps & D3DPRASTERCAPS_WBUFFER ) ? " Y " : " N " ,
( caps . RasterCaps & D3DPRASTERCAPS_DEPTHBIAS ) ? " Y " : " N " ,
( caps . RasterCaps & D3DPRASTERCAPS_ZTEST ) ? " Y " : " *N* " ) ;
Warning ( " Size of Texture Memory : %d kb \n " , g_pHardwareConfig - > Caps ( ) . m_TextureMemorySize / 1024 ) ;
Warning ( " Max Texture Dimensions : %d x %d \n " ,
caps . MaxTextureWidth , caps . MaxTextureHeight ) ;
if ( caps . MaxTextureAspectRatio ! = 0 )
Warning ( " Max Texture Aspect Ratio : *%d* \n " , caps . MaxTextureAspectRatio ) ;
Warning ( " Max Textures : %d Max Stages : %d \n " ,
caps . MaxSimultaneousTextures , caps . MaxTextureBlendStages ) ;
Warning ( " \n Texture Caps : \n " ) ;
Warning ( " ALPHA %s CUBEMAP %s MIPCUBEMAP %s SQUAREONLY %s \n " ,
( caps . TextureCaps & D3DPTEXTURECAPS_ALPHA ) ? " Y " : " N " ,
( caps . TextureCaps & D3DPTEXTURECAPS_CUBEMAP ) ? " Y " : " N " ,
( caps . TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP ) ? " Y " : " N " ,
( caps . TextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) ? " *Y* " : " N " ) ;
Warning ( " vendor id: 0x%x \n " , g_pHardwareConfig - > ActualCaps ( ) . m_VendorID ) ;
Warning ( " device id: 0x%x \n " , g_pHardwareConfig - > ActualCaps ( ) . m_DeviceID ) ;
Warning ( " SHADERAPI CAPS: \n " ) ;
Warning ( " m_NumSamplers: %d \n " , g_pHardwareConfig - > Caps ( ) . m_NumSamplers ) ;
Warning ( " m_NumTextureStages: %d \n " , g_pHardwareConfig - > Caps ( ) . m_NumTextureStages ) ;
Warning ( " m_HasSetDeviceGammaRamp: %s \n " , g_pHardwareConfig - > Caps ( ) . m_HasSetDeviceGammaRamp ? " yes " : " no " ) ;
Warning ( " m_SupportsVertexShaders (1.1): %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsVertexShaders ? " yes " : " no " ) ;
Warning ( " m_SupportsVertexShaders_2_0: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsVertexShaders_2_0 ? " yes " : " no " ) ;
Warning ( " m_SupportsPixelShaders (1.1): %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsPixelShaders ? " yes " : " no " ) ;
Warning ( " m_SupportsPixelShaders_1_4: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsPixelShaders_1_4 ? " yes " : " no " ) ;
Warning ( " m_SupportsPixelShaders_2_0: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsPixelShaders_2_0 ? " yes " : " no " ) ;
Warning ( " m_SupportsPixelShaders_2_b: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsPixelShaders_2_b ? " yes " : " no " ) ;
Warning ( " m_SupportsShaderModel_3_0: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsShaderModel_3_0 ? " yes " : " no " ) ;
switch ( g_pHardwareConfig - > Caps ( ) . m_SupportsCompressedTextures )
{
case COMPRESSED_TEXTURES_ON :
Warning ( " m_SupportsCompressedTextures: COMPRESSED_TEXTURES_ON \n " ) ;
break ;
case COMPRESSED_TEXTURES_OFF :
Warning ( " m_SupportsCompressedTextures: COMPRESSED_TEXTURES_ON \n " ) ;
break ;
case COMPRESSED_TEXTURES_NOT_INITIALIZED :
Warning ( " m_SupportsCompressedTextures: COMPRESSED_TEXTURES_NOT_INITIALIZED \n " ) ;
break ;
default :
Assert ( 0 ) ;
break ;
}
Warning ( " m_SupportsCompressedVertices: %d \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsCompressedVertices ) ;
Warning ( " m_bSupportsAnisotropicFiltering: %s \n " , g_pHardwareConfig - > Caps ( ) . m_bSupportsAnisotropicFiltering ? " yes " : " no " ) ;
Warning ( " m_nMaxAnisotropy: %d \n " , g_pHardwareConfig - > Caps ( ) . m_nMaxAnisotropy ) ;
Warning ( " m_MaxTextureWidth: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxTextureWidth ) ;
Warning ( " m_MaxTextureHeight: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxTextureHeight ) ;
Warning ( " m_MaxTextureAspectRatio: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxTextureAspectRatio ) ;
Warning ( " m_MaxPrimitiveCount: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxPrimitiveCount ) ;
Warning ( " m_ZBiasAndSlopeScaledDepthBiasSupported: %s \n " , g_pHardwareConfig - > Caps ( ) . m_ZBiasAndSlopeScaledDepthBiasSupported ? " yes " : " no " ) ;
Warning ( " m_SupportsMipmapping: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsMipmapping ? " yes " : " no " ) ;
Warning ( " m_SupportsOverbright: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsOverbright ? " yes " : " no " ) ;
Warning ( " m_SupportsCubeMaps: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsCubeMaps ? " yes " : " no " ) ;
Warning ( " m_NumPixelShaderConstants: %d \n " , g_pHardwareConfig - > Caps ( ) . m_NumPixelShaderConstants ) ;
Warning ( " m_NumVertexShaderConstants: %d \n " , g_pHardwareConfig - > Caps ( ) . m_NumVertexShaderConstants ) ;
Warning ( " m_NumBooleanVertexShaderConstants: %d \n " , g_pHardwareConfig - > Caps ( ) . m_NumBooleanVertexShaderConstants ) ;
Warning ( " m_NumIntegerVertexShaderConstants: %d \n " , g_pHardwareConfig - > Caps ( ) . m_NumIntegerVertexShaderConstants ) ;
Warning ( " m_TextureMemorySize: %d \n " , g_pHardwareConfig - > Caps ( ) . m_TextureMemorySize ) ;
Warning ( " m_MaxNumLights: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxNumLights ) ;
Warning ( " m_SupportsHardwareLighting: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsHardwareLighting ? " yes " : " no " ) ;
Warning ( " m_MaxBlendMatrices: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxBlendMatrices ) ;
Warning ( " m_MaxBlendMatrixIndices: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxBlendMatrixIndices ) ;
Warning ( " m_MaxVertexShaderBlendMatrices: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxVertexShaderBlendMatrices ) ;
Warning ( " m_SupportsMipmappedCubemaps: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsMipmappedCubemaps ? " yes " : " no " ) ;
Warning ( " m_SupportsNonPow2Textures: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsNonPow2Textures ? " yes " : " no " ) ;
Warning ( " m_nDXSupportLevel: %d \n " , g_pHardwareConfig - > Caps ( ) . m_nDXSupportLevel ) ;
Warning ( " m_PreferDynamicTextures: %s \n " , g_pHardwareConfig - > Caps ( ) . m_PreferDynamicTextures ? " yes " : " no " ) ;
Warning ( " m_HasProjectedBumpEnv: %s \n " , g_pHardwareConfig - > Caps ( ) . m_HasProjectedBumpEnv ? " yes " : " no " ) ;
Warning ( " m_MaxUserClipPlanes: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxUserClipPlanes ) ;
Warning ( " m_SupportsSRGB: %s \n " , g_pHardwareConfig - > Caps ( ) . m_SupportsSRGB ? " yes " : " no " ) ;
switch ( g_pHardwareConfig - > Caps ( ) . m_HDRType )
{
case HDR_TYPE_NONE :
Warning ( " m_HDRType: HDR_TYPE_NONE \n " ) ;
break ;
case HDR_TYPE_INTEGER :
Warning ( " m_HDRType: HDR_TYPE_INTEGER \n " ) ;
break ;
case HDR_TYPE_FLOAT :
Warning ( " m_HDRType: HDR_TYPE_FLOAT \n " ) ;
break ;
default :
Assert ( 0 ) ;
break ;
}
Warning ( " m_bSupportsSpheremapping: %s \n " , g_pHardwareConfig - > Caps ( ) . m_bSupportsSpheremapping ? " yes " : " no " ) ;
Warning ( " m_UseFastClipping: %s \n " , g_pHardwareConfig - > Caps ( ) . m_UseFastClipping ? " yes " : " no " ) ;
Warning ( " m_pShaderDLL: %s \n " , g_pHardwareConfig - > Caps ( ) . m_pShaderDLL ) ;
Warning ( " m_bNeedsATICentroidHack: %s \n " , g_pHardwareConfig - > Caps ( ) . m_bNeedsATICentroidHack ? " yes " : " no " ) ;
Warning ( " m_bDisableShaderOptimizations: %s \n " , g_pHardwareConfig - > Caps ( ) . m_bDisableShaderOptimizations ? " yes " : " no " ) ;
Warning ( " m_bColorOnSecondStream: %s \n " , g_pHardwareConfig - > Caps ( ) . m_bColorOnSecondStream ? " yes " : " no " ) ;
Warning ( " m_MaxSimultaneousRenderTargets: %d \n " , g_pHardwareConfig - > Caps ( ) . m_MaxSimultaneousRenderTargets ) ;
}
//-----------------------------------------------------------------------------
// Back buffer information
//-----------------------------------------------------------------------------
ImageFormat CShaderDeviceDx8 : : GetBackBufferFormat ( ) const
{
return ImageLoader : : D3DFormatToImageFormat ( m_PresentParameters . BackBufferFormat ) ;
}
void CShaderDeviceDx8 : : GetBackBufferDimensions ( int & width , int & height ) const
{
width = m_PresentParameters . BackBufferWidth ;
height = m_PresentParameters . BackBufferHeight ;
}
//-----------------------------------------------------------------------------
// Detects support for CreateQuery
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : DetectQuerySupport ( IDirect3DDevice9 * pD3DDevice )
{
// Do I need to detect whether this device supports CreateQuery before creating it?
if ( m_DeviceSupportsCreateQuery ! = - 1 )
return ;
IDirect3DQuery9 * pQueryObject = NULL ;
// Detect whether query is supported by creating and releasing:
HRESULT hr = pD3DDevice - > CreateQuery ( D3DQUERYTYPE_EVENT , & pQueryObject ) ;
if ( ! FAILED ( hr ) & & pQueryObject )
{
pQueryObject - > Release ( ) ;
m_DeviceSupportsCreateQuery = 1 ;
}
else
{
m_DeviceSupportsCreateQuery = 0 ;
}
}
const char * GetD3DErrorText ( HRESULT hr )
{
const char * pszMoreInfo = NULL ;
# if defined( _WIN32 ) && !defined(DX_TO_GL_ABSTRACTION)
switch ( hr )
{
case D3DERR_WRONGTEXTUREFORMAT :
pszMoreInfo = " D3DERR_WRONGTEXTUREFORMAT: The pixel format of the texture surface is not valid. " ;
break ;
case D3DERR_UNSUPPORTEDCOLOROPERATION :
pszMoreInfo = " D3DERR_UNSUPPORTEDCOLOROPERATION: The device does not support a specified texture-blending operation for color values. " ;
break ;
case D3DERR_UNSUPPORTEDCOLORARG :
pszMoreInfo = " D3DERR_UNSUPPORTEDCOLORARG: The device does not support a specified texture-blending argument for color values. " ;
break ;
case D3DERR_UNSUPPORTEDALPHAOPERATION :
pszMoreInfo = " D3DERR_UNSUPPORTEDALPHAOPERATION: The device does not support a specified texture-blending operation for the alpha channel. " ;
break ;
case D3DERR_UNSUPPORTEDALPHAARG :
pszMoreInfo = " D3DERR_UNSUPPORTEDALPHAARG: The device does not support a specified texture-blending argument for the alpha channel. " ;
break ;
case D3DERR_TOOMANYOPERATIONS :
pszMoreInfo = " D3DERR_TOOMANYOPERATIONS: The application is requesting more texture-filtering operations than the device supports. " ;
break ;
case D3DERR_CONFLICTINGTEXTUREFILTER :
pszMoreInfo = " D3DERR_CONFLICTINGTEXTUREFILTER: The current texture filters cannot be used together. " ;
break ;
case D3DERR_UNSUPPORTEDFACTORVALUE :
pszMoreInfo = " D3DERR_UNSUPPORTEDFACTORVALUE: The device does not support the specified texture factor value. " ;
break ;
case D3DERR_CONFLICTINGRENDERSTATE :
pszMoreInfo = " D3DERR_CONFLICTINGRENDERSTATE: The currently set render states cannot be used together. " ;
break ;
case D3DERR_UNSUPPORTEDTEXTUREFILTER :
pszMoreInfo = " D3DERR_UNSUPPORTEDTEXTUREFILTER: The device does not support the specified texture filter. " ;
break ;
case D3DERR_CONFLICTINGTEXTUREPALETTE :
pszMoreInfo = " D3DERR_CONFLICTINGTEXTUREPALETTE: The current textures cannot be used simultaneously. " ;
break ;
case D3DERR_DRIVERINTERNALERROR :
pszMoreInfo = " D3DERR_DRIVERINTERNALERROR: Internal driver error. " ;
break ;
case D3DERR_NOTFOUND :
pszMoreInfo = " D3DERR_NOTFOUND: The requested item was not found. " ;
break ;
case D3DERR_DEVICELOST :
pszMoreInfo = " D3DERR_DEVICELOST: The device has been lost but cannot be reset at this time. Therefore, rendering is not possible. " ;
break ;
case D3DERR_DEVICENOTRESET :
pszMoreInfo = " D3DERR_DEVICENOTRESET: The device has been lost. " ;
break ;
case D3DERR_NOTAVAILABLE :
pszMoreInfo = " D3DERR_NOTAVAILABLE: This device does not support the queried technique. " ;
break ;
case D3DERR_OUTOFVIDEOMEMORY :
pszMoreInfo = " D3DERR_OUTOFVIDEOMEMORY: Direct3D does not have enough display memory to perform the operation. The device is using more resources in a single scene than can fit simultaneously into video memory. " ;
break ;
case D3DERR_INVALIDDEVICE :
pszMoreInfo = " D3DERR_INVALIDDEVICE: The requested device type is not valid. " ;
break ;
case D3DERR_INVALIDCALL :
pszMoreInfo = " D3DERR_INVALIDCALL: The method call is invalid. " ;
break ;
case D3DERR_DRIVERINVALIDCALL :
pszMoreInfo = " D3DERR_DRIVERINVALIDCALL " ;
break ;
case D3DERR_WASSTILLDRAWING :
pszMoreInfo = " D3DERR_WASSTILLDRAWING: The previous blit operation that is transferring information to or from this surface is incomplete. " ;
break ;
}
# endif // _WIN32
return pszMoreInfo ;
}
//-----------------------------------------------------------------------------
// Actually creates the D3D Device once the present parameters are set up
//-----------------------------------------------------------------------------
IDirect3DDevice9 * CShaderDeviceDx8 : : InvokeCreateDevice ( void * hWnd , int nAdapter , DWORD deviceCreationFlags )
{
IDirect3DDevice9 * pD3DDevice = NULL ;
D3DDEVTYPE devType = DX8_DEVTYPE ;
# if NVPERFHUD
nAdapter = D3D ( ) - > GetAdapterCount ( ) - 1 ;
devType = D3DDEVTYPE_REF ;
deviceCreationFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_HARDWARE_VERTEXPROCESSING ;
# endif
# if 1 // with the changes for opengl to enable threading, we no longer need the d3d device to have threading guards
# ifndef _X360
// Create the device with multi-threaded safeguards if we're using mat_queue_mode 2.
// The logic to enable multithreaded rendering happens well after the device has been created,
// so we replicate some of that logic here.
ConVarRef mat_queue_mode ( " mat_queue_mode " ) ;
if ( mat_queue_mode . GetInt ( ) = = 2 | |
( mat_queue_mode . GetInt ( ) = = - 2 & & GetCPUInformation ( ) - > m_nPhysicalProcessors > = 2 ) | |
( mat_queue_mode . GetInt ( ) = = - 1 & & GetCPUInformation ( ) - > m_nPhysicalProcessors > = 2 ) )
{
deviceCreationFlags | = D3DCREATE_MULTITHREADED ;
}
# endif
# endif
# ifdef ENABLE_NULLREF_DEVICE_SUPPORT
devType = CommandLine ( ) - > FindParm ( " -nulldevice " ) ? D3DDEVTYPE_NULLREF : devType ;
# endif
HRESULT hr = D3D ( ) - > CreateDevice ( nAdapter , devType ,
( VD3DHWND ) hWnd , deviceCreationFlags , & m_PresentParameters , & pD3DDevice ) ;
if ( ! FAILED ( hr ) & & pD3DDevice )
return pD3DDevice ;
if ( ! IsPC ( ) )
return NULL ;
// try again, other applications may be taking their time
Sleep ( 1000 ) ;
hr = D3D ( ) - > CreateDevice ( nAdapter , devType ,
( VD3DHWND ) hWnd , deviceCreationFlags , & m_PresentParameters , & pD3DDevice ) ;
if ( ! FAILED ( hr ) & & pD3DDevice )
return pD3DDevice ;
// in this case, we actually are allocating too much memory....
// This will cause us to use less buffers...
if ( m_PresentParameters . Windowed )
{
m_PresentParameters . SwapEffect = D3DSWAPEFFECT_COPY ;
m_PresentParameters . BackBufferCount = 0 ;
hr = D3D ( ) - > CreateDevice ( nAdapter , devType ,
( VD3DHWND ) hWnd , deviceCreationFlags , & m_PresentParameters , & pD3DDevice ) ;
}
if ( ! FAILED ( hr ) & & pD3DDevice )
return pD3DDevice ;
const char * pszMoreInfo = NULL ;
switch ( hr )
{
# ifdef _WIN32
case D3DERR_INVALIDCALL :
// Override the error text for this error since it has a known meaning for CreateDevice failures.
pszMoreInfo = " D3DERR_INVALIDCALL: The device or the device driver may not support Direct3D or may not support the resolution or color depth specified. " ;
break ;
# endif // _WIN32
default :
pszMoreInfo = GetD3DErrorText ( hr ) ;
break ;
}
// Otherwise we failed, show a message and shutdown
if ( pszMoreInfo )
{
DWarning ( " init " , 0 , " Failed to create %s device! \n Error 0x%lX: %s \n \n Please see the following for more info. \n "
" http://support.steampowered.com/cgi-bin/steampowered.cfg/php/enduser/std_adp.php?p_faqid=772 \n " , IsOpenGL ( ) ? " OpenGL " : " D3D " , hr , pszMoreInfo ) ;
}
else
{
DWarning ( " init " , 0 , " Failed to create %s device! \n Error 0x%lX. \n \n Please see the following for more info. \n "
" http://support.steampowered.com/cgi-bin/steampowered.cfg/php/enduser/std_adp.php?p_faqid=772 \n " , IsOpenGL ( ) ? " OpenGL " : " D3D " , hr ) ;
}
return NULL ;
}
//-----------------------------------------------------------------------------
// Creates the D3D Device
//-----------------------------------------------------------------------------
bool CShaderDeviceDx8 : : CreateD3DDevice ( void * pHWnd , int nAdapter , const ShaderDeviceInfo_t & info )
{
Assert ( info . m_nVersion = = SHADER_DEVICE_INFO_VERSION ) ;
MEM_ALLOC_CREDIT_ ( __FILE__ " : D3D Device " ) ;
VD3DHWND hWnd = ( VD3DHWND ) pHWnd ;
# if ( !defined( PIX_INSTRUMENTATION ) && !defined( _X360 ) && !defined( NVPERFHUD ) )
D3DPERF_SetOptions ( 1 ) ; // Explicitly disallow PIX instrumented profiling in external builds
# endif
// Get some caps....
D3DCAPS caps ;
HRESULT hr = D3D ( ) - > GetDeviceCaps ( nAdapter , DX8_DEVTYPE , & caps ) ;
if ( FAILED ( hr ) )
return false ;
// Determine the adapter format
ShaderDisplayMode_t mode ;
g_pShaderDeviceMgrDx8 - > GetCurrentModeInfo ( & mode , nAdapter ) ;
m_AdapterFormat = mode . m_Format ;
// FIXME: Need to do this prior to SetPresentParameters. Fix.
// Make it part of HardwareCaps_t
InitializeColorInformation ( nAdapter , DX8_DEVTYPE , m_AdapterFormat ) ;
const HardwareCaps_t & adapterCaps = g_ShaderDeviceMgrDx8 . GetHardwareCaps ( nAdapter ) ;
DWORD deviceCreationFlags = ComputeDeviceCreationFlags ( caps , adapterCaps . m_bSoftwareVertexProcessing ) ;
SetPresentParameters ( hWnd , nAdapter , info ) ;
// Tell all other instances of the material system to let go of memory
SendIPCMessage ( RELEASE_MESSAGE ) ;
// Creates the device
IDirect3DDevice9 * pD3DDevice = InvokeCreateDevice ( pHWnd , nAdapter , deviceCreationFlags ) ;
if ( ! pD3DDevice )
return false ;
// Check to see if query is supported
DetectQuerySupport ( pD3DDevice ) ;
# ifdef STUBD3D
Dx9Device ( ) = new CStubD3DDevice ( pD3DDevice , g_pFullFileSystem ) ;
# else
g_pD3DDevice = pD3DDevice ;
# endif
# if defined( _X360 )
// Create the depth buffer, created manually to enable hierarchical z
{
D3DSURFACE_PARAMETERS DepthStencilParams ;
// Depth is immediately after the back buffer in EDRAM
// allocate the hierarchical z tiles at the end of the area so all other allocations can trivially allocate at 0
DepthStencilParams . Base = XGSurfaceSize (
m_PresentParameters . BackBufferWidth ,
m_PresentParameters . BackBufferHeight ,
m_PresentParameters . BackBufferFormat ,
m_PresentParameters . MultiSampleType ) ;
DepthStencilParams . ColorExpBias = 0 ;
DepthStencilParams . HierarchicalZBase = GPU_HIERARCHICAL_Z_TILES - XGHierarchicalZSize ( m_PresentParameters . BackBufferWidth , m_PresentParameters . BackBufferHeight , m_PresentParameters . MultiSampleType ) ;
IDirect3DSurface * pDepthStencilSurface = NULL ;
hr = Dx9Device ( ) - > CreateDepthStencilSurface (
m_PresentParameters . BackBufferWidth ,
m_PresentParameters . BackBufferHeight ,
m_PresentParameters . AutoDepthStencilFormat ,
m_PresentParameters . MultiSampleType ,
m_PresentParameters . MultiSampleQuality ,
TRUE ,
& pDepthStencilSurface ,
& DepthStencilParams ) ;
Assert ( SUCCEEDED ( hr ) ) ;
if ( FAILED ( hr ) )
return false ;
hr = Dx9Device ( ) - > SetDepthStencilSurface ( pDepthStencilSurface ) ;
Assert ( SUCCEEDED ( hr ) ) ;
if ( FAILED ( hr ) )
return false ;
}
// Initialize XUI, needed for TTF font rasterization
// xui requires and shares our d3d device
{
hr = XuiRenderInitShared ( pD3DDevice , & m_PresentParameters , XuiD3DXTextureLoader ) ;
if ( FAILED ( hr ) )
return false ;
XUIInitParams xuiInit ;
XUI_INIT_PARAMS ( xuiInit ) ;
xuiInit . dwFlags = XUI_INIT_PARAMS_FLAGS_NONE ;
xuiInit . pHooks = NULL ;
hr = XuiInit ( & xuiInit ) ;
if ( FAILED ( hr ) )
return false ;
hr = XuiRenderCreateDC ( & m_hDC ) ;
if ( FAILED ( hr ) )
return false ;
}
# endif
// CheckDeviceLost();
// Tell all other instances of the material system it's ok to grab memory
SendIPCMessage ( REACQUIRE_MESSAGE ) ;
m_hWnd = pHWnd ;
m_nAdapter = m_DisplayAdapter = nAdapter ;
m_DeviceState = DEVICE_STATE_OK ;
m_bIsMinimized = false ;
m_bQueuedDeviceLost = false ;
m_IsResizing = info . m_bWindowed & & info . m_bResizing ;
// This is our current view.
m_ViewHWnd = hWnd ;
GetWindowSize ( m_nWindowWidth , m_nWindowHeight ) ;
g_pHardwareConfig - > SetupHardwareCaps ( info , g_ShaderDeviceMgrDx8 . GetHardwareCaps ( nAdapter ) ) ;
// FIXME: Bake this into hardware config
// What texture formats do we support?
if ( D3DSupportsCompressedTextures ( ) )
{
g_pHardwareConfig - > ActualCapsForEdit ( ) . m_SupportsCompressedTextures = COMPRESSED_TEXTURES_ON ;
g_pHardwareConfig - > CapsForEdit ( ) . m_SupportsCompressedTextures = COMPRESSED_TEXTURES_ON ;
}
else
{
g_pHardwareConfig - > ActualCapsForEdit ( ) . m_SupportsCompressedTextures = COMPRESSED_TEXTURES_OFF ;
g_pHardwareConfig - > CapsForEdit ( ) . m_SupportsCompressedTextures = COMPRESSED_TEXTURES_OFF ;
}
return ( ! FAILED ( hr ) ) ;
}
//-----------------------------------------------------------------------------
// Frame sync
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : AllocFrameSyncTextureObject ( )
{
if ( IsX360 ( ) )
return ;
FreeFrameSyncTextureObject ( ) ;
// Create a tiny managed texture.
HRESULT hr = Dx9Device ( ) - > CreateTexture (
1 , 1 , // width, height
0 , // levels
D3DUSAGE_DYNAMIC , // usage
D3DFMT_A8R8G8B8 , // format
D3DPOOL_DEFAULT ,
& m_pFrameSyncTexture ,
NULL ) ;
if ( FAILED ( hr ) )
{
m_pFrameSyncTexture = NULL ;
}
}
void CShaderDeviceDx8 : : FreeFrameSyncTextureObject ( )
{
if ( IsX360 ( ) )
return ;
if ( m_pFrameSyncTexture )
{
m_pFrameSyncTexture - > Release ( ) ;
m_pFrameSyncTexture = NULL ;
}
}
void CShaderDeviceDx8 : : AllocFrameSyncObjects ( void )
{
if ( IsX360 ( ) )
return ;
if ( mat_debugalttab . GetBool ( ) )
{
Warning ( " mat_debugalttab: CShaderAPIDX8::AllocFrameSyncObjects \n " ) ;
}
// Allocate the texture for frame syncing in case we force that to be on.
AllocFrameSyncTextureObject ( ) ;
if ( m_DeviceSupportsCreateQuery = = 0 )
{
for ( int i = 0 ; i < ARRAYSIZE ( m_pFrameSyncQueryObject ) ; i + + )
{
m_pFrameSyncQueryObject [ i ] = NULL ;
m_bQueryIssued [ i ] = false ;
}
return ;
}
// FIXME FIXME FIXME!!!!! Need to record this.
for ( int i = 0 ; i < ARRAYSIZE ( m_pFrameSyncQueryObject ) ; i + + )
{
HRESULT hr = Dx9Device ( ) - > CreateQuery ( D3DQUERYTYPE_EVENT , & m_pFrameSyncQueryObject [ i ] ) ;
if ( hr = = D3DERR_NOTAVAILABLE )
{
Warning ( " D3DQUERYTYPE_EVENT not available on this driver \n " ) ;
Assert ( m_pFrameSyncQueryObject [ i ] = = NULL ) ;
}
else
{
Assert ( hr = = D3D_OK ) ;
Assert ( m_pFrameSyncQueryObject [ i ] ) ;
m_pFrameSyncQueryObject [ i ] - > Issue ( D3DISSUE_END ) ;
m_bQueryIssued [ i ] = true ;
}
}
}
void CShaderDeviceDx8 : : FreeFrameSyncObjects ( void )
{
if ( IsX360 ( ) )
return ;
if ( mat_debugalttab . GetBool ( ) )
{
Warning ( " mat_debugalttab: CShaderAPIDX8::FreeFrameSyncObjects \n " ) ;
}
FreeFrameSyncTextureObject ( ) ;
// FIXME FIXME FIXME!!!!! Need to record this.
for ( int i = 0 ; i < ARRAYSIZE ( m_pFrameSyncQueryObject ) ; i + + )
{
if ( m_pFrameSyncQueryObject [ i ] )
{
if ( m_bQueryIssued [ i ] )
{
tmZone ( TELEMETRY_LEVEL1 , TMZF_NONE , " D3DQueryGetData %t " , tmSendCallStack ( TELEMETRY_LEVEL0 , 0 ) ) ;
double flStartTime = Plat_FloatTime ( ) ;
BOOL dummyData = 0 ;
HRESULT hr = S_OK ;
// Make every attempt (within 2 seconds) to get the result from the query. Doing so may prevent
// crashes in the driver if we try to release outstanding queries.
do
{
hr = m_pFrameSyncQueryObject [ i ] - > GetData ( & dummyData , sizeof ( dummyData ) , D3DGETDATA_FLUSH ) ;
double flCurrTime = Plat_FloatTime ( ) ;
// don't wait more than 2 seconds for these
if ( flCurrTime - flStartTime > 2.00 )
break ;
} while ( hr = = S_FALSE ) ;
}
# ifdef DBGFLAG_ASSERT
int nRetVal =
# endif
m_pFrameSyncQueryObject [ i ] - > Release ( ) ;
Assert ( nRetVal = = 0 ) ;
m_pFrameSyncQueryObject [ i ] = NULL ;
m_bQueryIssued [ i ] = false ;
}
}
}
//-----------------------------------------------------------------------------
// Occurs when another application is initializing
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : OtherAppInitializing ( bool initializing )
{
if ( ! ThreadOwnsDevice ( ) | | ! ThreadInMainThread ( ) )
{
if ( initializing )
{
ShaderUtil ( ) - > OnThreadEvent ( SHADER_THREAD_OTHER_APP_START ) ;
}
else
{
ShaderUtil ( ) - > OnThreadEvent ( SHADER_THREAD_OTHER_APP_END ) ;
}
return ;
}
Assert ( m_bOtherAppInitializing ! = initializing ) ;
if ( ! IsDeactivated ( ) )
{
Dx9Device ( ) - > EndScene ( ) ;
}
// NOTE: OtherApp is set in this way because we need to know we're
// active as we release and restore everything
CheckDeviceLost ( initializing ) ;
if ( ! IsDeactivated ( ) )
{
Dx9Device ( ) - > BeginScene ( ) ;
}
}
void CShaderDeviceDx8 : : HandleThreadEvent ( uint32 threadEvent )
{
Assert ( ThreadOwnsDevice ( ) ) ;
switch ( threadEvent )
{
case SHADER_THREAD_OTHER_APP_START :
OtherAppInitializing ( true ) ;
break ;
case SHADER_THREAD_RELEASE_RESOURCES :
ReleaseResources ( ) ;
break ;
case SHADER_THREAD_EVICT_RESOURCES :
EvictManagedResourcesInternal ( ) ;
break ;
case SHADER_THREAD_RESET_RENDER_STATE :
ResetRenderState ( ) ;
break ;
case SHADER_THREAD_ACQUIRE_RESOURCES :
ReacquireResources ( ) ;
break ;
case SHADER_THREAD_OTHER_APP_END :
OtherAppInitializing ( false ) ;
break ;
}
}
//-----------------------------------------------------------------------------
// We lost the device, but we have a chance to recover
//-----------------------------------------------------------------------------
bool CShaderDeviceDx8 : : TryDeviceReset ( )
{
if ( IsX360 ( ) )
return true ;
// Don't try to reset the device until we're sure our resources have been released
if ( ! m_bResourcesReleased )
{
return false ;
}
// FIXME: Make this rebuild the Dx9Device from scratch!
// Helps with compatibility
HRESULT hr = Dx9Device ( ) - > Reset ( & m_PresentParameters ) ;
bool bResetSuccess = ! FAILED ( hr ) ;
# if defined(IS_WINDOWS_PC) && defined(SHADERAPIDX9)
if ( bResetSuccess & & g_ShaderDeviceUsingD3D9Ex )
{
bResetSuccess = SUCCEEDED ( Dx9Device ( ) - > TestCooperativeLevel ( ) ) ;
if ( bResetSuccess )
{
Warning ( " video driver has crashed and been reset, re-uploading resources now " ) ;
}
}
# endif
if ( bResetSuccess )
m_bResourcesReleased = false ;
return bResetSuccess ;
}
//-----------------------------------------------------------------------------
// Release, reacquire resources
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : ReleaseResources ( )
{
if ( ! ThreadOwnsDevice ( ) | | ! ThreadInMainThread ( ) )
{
// Set our resources as not being released yet.
// We reset this in two places since release resources can be called without a call to TryDeviceReset.
m_bResourcesReleased = false ;
ShaderUtil ( ) - > OnThreadEvent ( SHADER_THREAD_RELEASE_RESOURCES ) ;
return ;
}
// Only the initial "ReleaseResources" actually has effect
if ( m_numReleaseResourcesRefCount + + ! = 0 )
{
Warning ( " ReleaseResources has no effect, now at level %d. \n " , m_numReleaseResourcesRefCount ) ;
DevWarning ( " ReleaseResources called twice is a bug: use IsDeactivated to check for a valid device. \n " ) ;
Assert ( 0 ) ;
return ;
}
LOCK_SHADERAPI ( ) ;
CPixEvent ( PIX_VALVE_ORANGE , " ReleaseResources " ) ;
FreeFrameSyncObjects ( ) ;
FreeNonInteractiveRefreshObjects ( ) ;
ShaderUtil ( ) - > ReleaseShaderObjects ( ) ;
MeshMgr ( ) - > ReleaseBuffers ( ) ;
g_pShaderAPI - > ReleaseShaderObjects ( ) ;
# ifdef _DEBUG
if ( MeshMgr ( ) - > BufferCount ( ) ! = 0 )
{
for ( int i = 0 ; i < MeshMgr ( ) - > BufferCount ( ) ; i + + )
{
}
}
# endif
// All meshes cleaned up?
Assert ( MeshMgr ( ) - > BufferCount ( ) = = 0 ) ;
// Signal that our resources have been released so that we can try to reset the device
m_bResourcesReleased = true ;
}
void CShaderDeviceDx8 : : ReacquireResources ( )
{
ReacquireResourcesInternal ( ) ;
}
void CShaderDeviceDx8 : : ReacquireResourcesInternal ( bool bResetState , bool bForceReacquire , char const * pszForceReason )
{
if ( ! ThreadOwnsDevice ( ) | | ! ThreadInMainThread ( ) )
{
if ( bResetState )
{
ShaderUtil ( ) - > OnThreadEvent ( SHADER_THREAD_RESET_RENDER_STATE ) ;
}
ShaderUtil ( ) - > OnThreadEvent ( SHADER_THREAD_ACQUIRE_RESOURCES ) ;
return ;
}
if ( bForceReacquire )
{
// If we are forcing reacquire then warn if release calls are remaining unpaired
if ( m_numReleaseResourcesRefCount > 1 )
{
Warning ( " Forcefully resetting device (%s), resources release level was %d. \n " , pszForceReason ? pszForceReason : " unspecified " , m_numReleaseResourcesRefCount ) ;
Assert ( 0 ) ;
}
m_numReleaseResourcesRefCount = 0 ;
}
else
{
// Only the final "ReacquireResources" actually has effect
if ( - - m_numReleaseResourcesRefCount ! = 0 )
{
Warning ( " ReacquireResources has no effect, now at level %d. \n " , m_numReleaseResourcesRefCount ) ;
DevWarning ( " ReacquireResources being discarded is a bug: use IsDeactivated to check for a valid device. \n " ) ;
Assert ( 0 ) ;
if ( m_numReleaseResourcesRefCount < 0 )
{
m_numReleaseResourcesRefCount = 0 ;
}
return ;
}
}
if ( bResetState )
{
ResetRenderState ( ) ;
}
LOCK_SHADERAPI ( ) ;
CPixEvent event ( PIX_VALVE_ORANGE , " ReacquireResources " ) ;
g_pShaderAPI - > RestoreShaderObjects ( ) ;
AllocFrameSyncObjects ( ) ;
AllocNonInteractiveRefreshObjects ( ) ;
MeshMgr ( ) - > RestoreBuffers ( ) ;
ShaderUtil ( ) - > RestoreShaderObjects ( CShaderDeviceMgrBase : : ShaderInterfaceFactory ) ;
}
//-----------------------------------------------------------------------------
// Changes the window size
//-----------------------------------------------------------------------------
bool CShaderDeviceDx8 : : ResizeWindow ( const ShaderDeviceInfo_t & info )
{
if ( IsX360 ( ) )
return false ;
m_bPendingVideoModeChange = false ;
// We don't need to do crap if the window was set up to set up
// to be resizing...
if ( info . m_bResizing )
return false ;
g_pShaderDeviceMgr - > InvokeModeChangeCallbacks ( ) ;
ReleaseResources ( ) ;
SetPresentParameters ( ( VD3DHWND ) m_hWnd , m_DisplayAdapter , info ) ;
HRESULT hr = Dx9Device ( ) - > Reset ( & m_PresentParameters ) ;
if ( FAILED ( hr ) )
{
Warning ( " ResizeWindow: Reset failed, hr = 0x%08lX. \n " , hr ) ;
return false ;
}
else
{
ReacquireResourcesInternal ( true , true , " ResizeWindow " ) ;
}
return true ;
}
//-----------------------------------------------------------------------------
// Queue up the fact that the device was lost
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : MarkDeviceLost ( )
{
if ( IsX360 ( ) )
return ;
m_bQueuedDeviceLost = true ;
}
//-----------------------------------------------------------------------------
// Checks if the device was lost
//-----------------------------------------------------------------------------
# if defined( _DEBUG ) && !defined( _X360 )
ConVar mat_forcelostdevice ( " mat_forcelostdevice " , " 0 " ) ;
# endif
void CShaderDeviceDx8 : : CheckDeviceLost ( bool bOtherAppInitializing )
{
# if !defined( _X360 )
// FIXME: We could also queue up if WM_SIZE changes and look at that
// but that seems to only make sense if we have resizable windows where
// we do *not* allocate buffers as large as the entire current video mode
// which we're not doing
# ifdef _WIN32
m_bIsMinimized = ( static_cast < BOOL > ( IsIconic ( ( HWND ) m_hWnd ) ) = = ( BOOL ) TRUE ) ;
# else
m_bIsMinimized = ( IsIconic ( ( VD3DHWND ) m_hWnd ) = = TRUE ) ;
# endif
m_bOtherAppInitializing = bOtherAppInitializing ;
# ifdef _DEBUG
if ( mat_forcelostdevice . GetBool ( ) )
{
mat_forcelostdevice . SetValue ( 0 ) ;
MarkDeviceLost ( ) ;
}
# endif
HRESULT hr = D3D_OK ;
# if defined(IS_WINDOWS_PC) && defined(SHADERAPIDX9)
if ( g_ShaderDeviceUsingD3D9Ex & & m_DeviceState = = DEVICE_STATE_OK )
{
// Steady state - PresentEx return value will mark us lost if necessary.
// We do not care if we are minimized in this state.
m_bIsMinimized = false ;
}
else
# endif
{
RECORD_COMMAND ( DX8_TEST_COOPERATIVE_LEVEL , 0 ) ;
hr = Dx9Device ( ) - > TestCooperativeLevel ( ) ;
}
// If some other call returned device lost previously in the frame, spoof the return value from TCL
if ( m_bQueuedDeviceLost )
{
hr = ( hr ! = D3D_OK ) ? hr : D3DERR_DEVICENOTRESET ;
m_bQueuedDeviceLost = false ;
}
if ( m_DeviceState = = DEVICE_STATE_OK )
{
// We can transition out of ok if bOtherAppInitializing is set
// or if we become minimized, or if TCL returns anything other than D3D_OK.
if ( ( hr ! = D3D_OK ) | | m_bIsMinimized )
{
// purge unreferenced materials
g_pShaderUtil - > UncacheUnusedMaterials ( true ) ;
// We were ok, now we're not. Release resources
ReleaseResources ( ) ;
m_DeviceState = DEVICE_STATE_LOST_DEVICE ;
}
else if ( bOtherAppInitializing )
{
// purge unreferenced materials
g_pShaderUtil - > UncacheUnusedMaterials ( true ) ;
// We were ok, now we're not. Release resources
ReleaseResources ( ) ;
m_DeviceState = DEVICE_STATE_OTHER_APP_INIT ;
}
}
// Immediately checking devicelost after ok helps in the case where we got D3DERR_DEVICENOTRESET
// in which case we want to immdiately try to switch out of DEVICE_STATE_LOST and into DEVICE_STATE_NEEDS_RESET
if ( m_DeviceState = = DEVICE_STATE_LOST_DEVICE )
{
// We can only try to reset if we're not minimized and not lost
if ( ! m_bIsMinimized & & ( hr ! = D3DERR_DEVICELOST ) )
{
m_DeviceState = DEVICE_STATE_NEEDS_RESET ;
}
}
// Immediately checking needs reset also helps for the case where we got D3DERR_DEVICENOTRESET
if ( m_DeviceState = = DEVICE_STATE_NEEDS_RESET )
{
if ( ( hr = = D3DERR_DEVICELOST ) | | m_bIsMinimized )
{
m_DeviceState = DEVICE_STATE_LOST_DEVICE ;
}
else
{
bool bResetSucceeded = TryDeviceReset ( ) ;
if ( bResetSucceeded )
{
if ( ! bOtherAppInitializing )
{
m_DeviceState = DEVICE_STATE_OK ;
// We were bad, now we're ok. Restore resources and reset render state.
ReacquireResourcesInternal ( true , true , " NeedsReset " ) ;
}
else
{
m_DeviceState = DEVICE_STATE_OTHER_APP_INIT ;
}
}
}
}
if ( m_DeviceState = = DEVICE_STATE_OTHER_APP_INIT )
{
if ( ( hr ! = D3D_OK ) | | m_bIsMinimized )
{
m_DeviceState = DEVICE_STATE_LOST_DEVICE ;
}
else if ( ! bOtherAppInitializing )
{
m_DeviceState = DEVICE_STATE_OK ;
// We were bad, now we're ok. Restore resources and reset render state.
ReacquireResourcesInternal ( true , true , " OtherAppInit " ) ;
}
}
// Do mode change if we have a video mode change.
if ( m_bPendingVideoModeChange & & ! IsDeactivated ( ) )
{
# ifdef _DEBUG
Warning ( " mode change! \n " ) ;
# endif
// now purge unreferenced materials
g_pShaderUtil - > UncacheUnusedMaterials ( true ) ;
ResizeWindow ( m_PendingVideoModeChangeConfig ) ;
}
# endif
}
//-----------------------------------------------------------------------------
// Special method to refresh the screen on the XBox360
//-----------------------------------------------------------------------------
bool CShaderDeviceDx8 : : AllocNonInteractiveRefreshObjects ( )
{
# if defined( _X360 )
const char * strVertexShaderProgram =
" float4x4 matWVP : register(c0); "
" struct VS_IN "
" { "
" float4 ObjPos : POSITION; "
" float2 TexCoord : TEXCOORD; "
" }; "
" struct VS_OUT "
" { "
" float4 ProjPos : POSITION; "
" float2 TexCoord : TEXCOORD; "
" }; "
" VS_OUT main( VS_IN In ) "
" { "
" VS_OUT Out; "
" Out.ProjPos = mul( matWVP, In.ObjPos ); "
" Out.TexCoord = In.TexCoord; "
" return Out; "
" } " ;
const char * strPixelShaderProgram =
" struct PS_IN "
" { "
" float2 TexCoord : TEXCOORD; "
" }; "
" sampler detail : register( s0 ); "
" float4 main( PS_IN In ) : COLOR "
" { "
" return tex2D( detail, In.TexCoord ); "
" } " ;
const char * strPixelShaderProgram2 =
" struct PS_IN "
" { "
" float2 TexCoord : TEXCOORD; "
" }; "
" sampler detail : register( s0 ); "
" float4 main( PS_IN In ) : COLOR "
" { "
" return tex2D( detail, In.TexCoord ); "
" } " ;
const char * strPixelShaderProgram3 =
" struct PS_IN "
" { "
" float2 TexCoord : TEXCOORD; "
" }; "
" float SrgbGammaToLinear( float flSrgbGammaValue ) "
" { "
" float x = saturate( flSrgbGammaValue ); "
" return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) ); "
" } "
" float X360LinearToGamma( float flLinearValue ) "
" { "
" float fl360GammaValue; "
" "
" flLinearValue = saturate( flLinearValue ); "
" if ( flLinearValue < ( 128.0f / 1023.0f ) ) "
" { "
" if ( flLinearValue < ( 64.0f / 1023.0f ) ) "
" { "
" fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) ); "
" } "
" else "
" { "
" fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f ); "
" } "
" } "
" else "
" { "
" if ( flLinearValue < ( 512.0f / 1023.0f ) ) "
" { "
" fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f ); "
" } "
" else "
" { "
" fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); "
" if ( fl360GammaValue > 1.0f ) "
" { "
" fl360GammaValue = 1.0f; "
" } "
" } "
" } "
" "
" fl360GammaValue = saturate( fl360GammaValue ); "
" return fl360GammaValue; "
" } "
" sampler detail : register( s0 ); "
" float4 main( PS_IN In ) : COLOR "
" { "
" float4 vTextureColor = tex2D( detail, In.TexCoord ); "
" vTextureColor.r = X360LinearToGamma( SrgbGammaToLinear( vTextureColor.r ) ); "
" vTextureColor.g = X360LinearToGamma( SrgbGammaToLinear( vTextureColor.g ) ); "
" vTextureColor.b = X360LinearToGamma( SrgbGammaToLinear( vTextureColor.b ) ); "
" return vTextureColor; "
" } " ;
D3DVERTEXELEMENT9 VertexElements [ 4 ] =
{
{ 0 , 0 , D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_POSITION , 0 } ,
{ 0 , 12 , D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_TEXCOORD , 0 } ,
D3DDECL_END ( )
} ;
ID3DXBuffer * pErrorMsg = NULL ;
ID3DXBuffer * pShaderCode = NULL ;
HRESULT hr = D3DXCompileShader ( strVertexShaderProgram , ( UINT ) strlen ( strVertexShaderProgram ) , NULL , NULL , " main " , " vs_2_0 " , 0 , & pShaderCode , & pErrorMsg , NULL ) ;
if ( FAILED ( hr ) )
return false ;
Dx9Device ( ) - > CreateVertexShader ( ( DWORD * ) pShaderCode - > GetBufferPointer ( ) , & m_NonInteractiveRefresh . m_pVertexShader ) ;
pShaderCode - > Release ( ) ;
pShaderCode = NULL ;
if ( pErrorMsg )
{
pErrorMsg - > Release ( ) ;
pErrorMsg = NULL ;
}
hr = D3DXCompileShader ( strPixelShaderProgram , ( UINT ) strlen ( strPixelShaderProgram ) , NULL , NULL , " main " , " ps_2_0 " , 0 , & pShaderCode , & pErrorMsg , NULL ) ;
if ( FAILED ( hr ) )
return false ;
Dx9Device ( ) - > CreatePixelShader ( ( DWORD * ) pShaderCode - > GetBufferPointer ( ) , & m_NonInteractiveRefresh . m_pPixelShader ) ;
pShaderCode - > Release ( ) ;
if ( pErrorMsg )
{
pErrorMsg - > Release ( ) ;
pErrorMsg = NULL ;
}
hr = D3DXCompileShader ( strPixelShaderProgram3 , ( UINT ) strlen ( strPixelShaderProgram3 ) , NULL , NULL , " main " , " ps_2_0 " , 0 , & pShaderCode , & pErrorMsg , NULL ) ;
if ( FAILED ( hr ) )
return false ;
Dx9Device ( ) - > CreatePixelShader ( ( DWORD * ) pShaderCode - > GetBufferPointer ( ) , & m_NonInteractiveRefresh . m_pPixelShaderStartup ) ;
pShaderCode - > Release ( ) ;
if ( pErrorMsg )
{
pErrorMsg - > Release ( ) ;
pErrorMsg = NULL ;
}
hr = D3DXCompileShader ( strPixelShaderProgram2 , ( UINT ) strlen ( strPixelShaderProgram2 ) , NULL , NULL , " main " , " ps_2_0 " , 0 , & pShaderCode , & pErrorMsg , NULL ) ;
if ( FAILED ( hr ) )
return false ;
Dx9Device ( ) - > CreatePixelShader ( ( DWORD * ) pShaderCode - > GetBufferPointer ( ) , & m_NonInteractiveRefresh . m_pPixelShaderStartupPass2 ) ;
pShaderCode - > Release ( ) ;
if ( pErrorMsg )
{
pErrorMsg - > Release ( ) ;
pErrorMsg = NULL ;
}
// Create a vertex declaration from the element descriptions.
Dx9Device ( ) - > CreateVertexDeclaration ( VertexElements , & m_NonInteractiveRefresh . m_pVertexDecl ) ;
# endif
return true ;
}
void CShaderDeviceDx8 : : FreeNonInteractiveRefreshObjects ( )
{
if ( m_NonInteractiveRefresh . m_pVertexShader )
{
m_NonInteractiveRefresh . m_pVertexShader - > Release ( ) ;
m_NonInteractiveRefresh . m_pVertexShader = NULL ;
}
if ( m_NonInteractiveRefresh . m_pPixelShader )
{
m_NonInteractiveRefresh . m_pPixelShader - > Release ( ) ;
m_NonInteractiveRefresh . m_pPixelShader = NULL ;
}
if ( m_NonInteractiveRefresh . m_pPixelShaderStartup )
{
m_NonInteractiveRefresh . m_pPixelShaderStartup - > Release ( ) ;
m_NonInteractiveRefresh . m_pPixelShaderStartup = NULL ;
}
if ( m_NonInteractiveRefresh . m_pPixelShaderStartupPass2 )
{
m_NonInteractiveRefresh . m_pPixelShaderStartupPass2 - > Release ( ) ;
m_NonInteractiveRefresh . m_pPixelShaderStartupPass2 = NULL ;
}
if ( m_NonInteractiveRefresh . m_pVertexDecl )
{
m_NonInteractiveRefresh . m_pVertexDecl - > Release ( ) ;
m_NonInteractiveRefresh . m_pVertexDecl = NULL ;
}
}
bool CShaderDeviceDx8 : : InNonInteractiveMode ( ) const
{
return m_NonInteractiveRefresh . m_Mode ! = MATERIAL_NON_INTERACTIVE_MODE_NONE ;
}
void CShaderDeviceDx8 : : EnableNonInteractiveMode ( MaterialNonInteractiveMode_t mode , ShaderNonInteractiveInfo_t * pInfo )
{
if ( ! IsX360 ( ) )
return ;
if ( pInfo & & ( pInfo - > m_hTempFullscreenTexture = = INVALID_SHADERAPI_TEXTURE_HANDLE ) )
{
mode = MATERIAL_NON_INTERACTIVE_MODE_NONE ;
}
m_NonInteractiveRefresh . m_Mode = mode ;
if ( pInfo )
{
m_NonInteractiveRefresh . m_Info = * pInfo ;
}
m_NonInteractiveRefresh . m_nPacifierFrame = 0 ;
if ( mode ! = MATERIAL_NON_INTERACTIVE_MODE_NONE )
{
ConVarRef mat_monitorgamma ( " mat_monitorgamma " ) ;
ConVarRef mat_monitorgamma_tv_range_min ( " mat_monitorgamma_tv_range_min " ) ;
ConVarRef mat_monitorgamma_tv_range_max ( " mat_monitorgamma_tv_range_max " ) ;
ConVarRef mat_monitorgamma_tv_exp ( " mat_monitorgamma_tv_exp " ) ;
ConVarRef mat_monitorgamma_tv_enabled ( " mat_monitorgamma_tv_enabled " ) ;
SetHardwareGammaRamp ( mat_monitorgamma . GetFloat ( ) , mat_monitorgamma_tv_range_min . GetFloat ( ) , mat_monitorgamma_tv_range_max . GetFloat ( ) ,
mat_monitorgamma_tv_exp . GetFloat ( ) , mat_monitorgamma_tv_enabled . GetBool ( ) ) ;
}
# ifdef _X360
if ( mode ! = MATERIAL_NON_INTERACTIVE_MODE_NONE )
{
// HACK: VSync off (prevents us wasting time blocking on VSync due to our irregular present intervals)
Dx9Device ( ) - > SetRenderState ( D3DRS_PRESENTINTERVAL , D3DPRESENT_INTERVAL_IMMEDIATE ) ;
}
else
{
// HACK: VSync on (defaulting to on on 360 is fine, but really should save+restore this state)
Dx9Device ( ) - > SetRenderState ( D3DRS_PRESENTINTERVAL , D3DPRESENT_INTERVAL_ONE ) ;
}
# endif
// Msg( "Time elapsed: %.3f Peak %.3f Ave %.5f Count %d Count Above %d\n", Plat_FloatTime() - m_NonInteractiveRefresh.m_flStartTime,
// m_NonInteractiveRefresh.m_flPeakDt, m_NonInteractiveRefresh.m_flTotalDt / m_NonInteractiveRefresh.m_nSamples, m_NonInteractiveRefresh.m_nSamples, m_NonInteractiveRefresh.m_nCountAbove66 );
m_NonInteractiveRefresh . m_flStartTime = m_NonInteractiveRefresh . m_flLastPresentTime =
m_NonInteractiveRefresh . m_flLastPacifierTime = Plat_FloatTime ( ) ;
m_NonInteractiveRefresh . m_flPeakDt = 0.0f ;
m_NonInteractiveRefresh . m_flTotalDt = 0.0f ;
m_NonInteractiveRefresh . m_nSamples = 0 ;
m_NonInteractiveRefresh . m_nCountAbove66 = 0 ;
}
void CShaderDeviceDx8 : : UpdatePresentStats ( )
{
float t = Plat_FloatTime ( ) ;
float flActualDt = t - m_NonInteractiveRefresh . m_flLastPresentTime ;
if ( flActualDt > m_NonInteractiveRefresh . m_flPeakDt )
{
m_NonInteractiveRefresh . m_flPeakDt = flActualDt ;
}
if ( flActualDt > 0.066 )
{
+ + m_NonInteractiveRefresh . m_nCountAbove66 ;
}
m_NonInteractiveRefresh . m_flTotalDt + = flActualDt ;
+ + m_NonInteractiveRefresh . m_nSamples ;
t = Plat_FloatTime ( ) ;
m_NonInteractiveRefresh . m_flLastPresentTime = t ;
}
void CShaderDeviceDx8 : : RefreshFrontBufferNonInteractive ( )
{
if ( ! IsX360 ( ) | | ! InNonInteractiveMode ( ) )
return ;
// Other code should not be talking to D3D at the same time as this
AUTO_LOCK ( m_nonInteractiveModeMutex ) ;
# ifdef _X360
g_pShaderAPI - > OwnGPUResources ( false ) ;
IDirect3DBaseTexture * pTexture = g_pShaderAPI - > GetD3DTexture ( m_NonInteractiveRefresh . m_Info . m_hTempFullscreenTexture ) ;
int w , h ;
g_pShaderAPI - > GetBackBufferDimensions ( w , h ) ;
XMMATRIX matWVP = XMMatrixOrthographicOffCenterLH ( 0 , ( FLOAT ) w , ( FLOAT ) h , 0 , 0 , 1 ) ;
// Structure to hold vertex data.
struct TEXVERTEX
{
FLOAT Position [ 3 ] ;
FLOAT TexCoord [ 2 ] ;
} ;
TEXVERTEX Vertices [ 4 ] ;
Vertices [ 0 ] . Position [ 0 ] = - 0.5f ;
Vertices [ 0 ] . Position [ 1 ] = - 0.5f ;
Vertices [ 0 ] . Position [ 2 ] = 0 ;
Vertices [ 0 ] . TexCoord [ 0 ] = 0 ;
Vertices [ 0 ] . TexCoord [ 1 ] = 0 ;
Vertices [ 1 ] . Position [ 0 ] = w - 0.5f ;
Vertices [ 1 ] . Position [ 1 ] = - 0.5f ;
Vertices [ 1 ] . Position [ 2 ] = 0 ;
Vertices [ 1 ] . TexCoord [ 0 ] = 1 ;
Vertices [ 1 ] . TexCoord [ 1 ] = 0 ;
Vertices [ 2 ] . Position [ 0 ] = w - 0.5f ;
Vertices [ 2 ] . Position [ 1 ] = h - 0.5f ;
Vertices [ 2 ] . Position [ 2 ] = 0 ;
Vertices [ 2 ] . TexCoord [ 0 ] = 1 ;
Vertices [ 2 ] . TexCoord [ 1 ] = 1 ;
Vertices [ 3 ] . Position [ 0 ] = - 0.5f ;
Vertices [ 3 ] . Position [ 1 ] = h - 0.5f ;
Vertices [ 3 ] . Position [ 2 ] = 0 ;
Vertices [ 3 ] . TexCoord [ 0 ] = 0 ;
Vertices [ 3 ] . TexCoord [ 1 ] = 1 ;
D3DVIEWPORT9 viewport ;
viewport . X = viewport . Y = 0 ;
viewport . Width = w ; viewport . Height = h ;
viewport . MinZ = ReverseDepthOnX360 ( ) ? 1.0f : 0.0f ;
viewport . MaxZ = 1.0f - viewport . MinZ ;
bool bInStartupMode = ( m_NonInteractiveRefresh . m_Mode = = MATERIAL_NON_INTERACTIVE_MODE_STARTUP ) ;
float flDepth = ( ShaderUtil ( ) - > GetConfig ( ) . bReverseDepth ^ ReverseDepthOnX360 ( ) ) ? 0.0f : 1.0f ;
Dx9Device ( ) - > Clear ( 0 , NULL , D3DCLEAR_ZBUFFER , 0 , flDepth , 0L ) ;
Dx9Device ( ) - > SetViewport ( & viewport ) ;
Dx9Device ( ) - > SetTexture ( 0 , pTexture ) ;
Dx9Device ( ) - > SetVertexShader ( m_NonInteractiveRefresh . m_pVertexShader ) ;
Dx9Device ( ) - > SetPixelShader ( bInStartupMode ? m_NonInteractiveRefresh . m_pPixelShaderStartup : m_NonInteractiveRefresh . m_pPixelShader ) ;
Dx9Device ( ) - > SetVertexShaderConstantF ( 0 , ( FLOAT * ) & matWVP , 4 ) ;
Dx9Device ( ) - > SetVertexDeclaration ( m_NonInteractiveRefresh . m_pVertexDecl ) ;
Dx9Device ( ) - > SetSamplerState ( 0 , D3DSAMP_ADDRESSU , D3DTADDRESS_CLAMP ) ;
Dx9Device ( ) - > SetSamplerState ( 0 , D3DSAMP_ADDRESSV , D3DTADDRESS_CLAMP ) ;
Dx9Device ( ) - > SetSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR ) ;
Dx9Device ( ) - > SetSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR ) ;
tmZone ( TELEMETRY_LEVEL1 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
Dx9Device ( ) - > DrawPrimitiveUP ( D3DPT_QUADLIST , 1 , Vertices , sizeof ( TEXVERTEX ) ) ;
if ( bInStartupMode )
{
float flXPos = m_NonInteractiveRefresh . m_Info . m_flNormalizedX ;
float flYPos = m_NonInteractiveRefresh . m_Info . m_flNormalizedY ;
float flHeight = m_NonInteractiveRefresh . m_Info . m_flNormalizedSize ;
int nSize = h * flHeight ;
int x = w * flXPos - nSize * 0.5f ;
int y = h * flYPos - nSize * 0.5f ;
w = h = nSize ;
Vertices [ 0 ] . Position [ 0 ] = x - 0.5f ;
Vertices [ 0 ] . Position [ 1 ] = y - 0.5f ;
Vertices [ 1 ] . Position [ 0 ] = x + w - 0.5f ;
Vertices [ 1 ] . Position [ 1 ] = y - 0.5f ;
Vertices [ 2 ] . Position [ 0 ] = x + w - 0.5f ;
Vertices [ 2 ] . Position [ 1 ] = y + h - 0.5f ;
Vertices [ 3 ] . Position [ 0 ] = x - 0.5f ;
Vertices [ 3 ] . Position [ 1 ] = y + h - 0.5f ;
float t = Plat_FloatTime ( ) ;
float flDt = t - m_NonInteractiveRefresh . m_flLastPacifierTime ;
if ( flDt > 0.030f )
{
if ( + + m_NonInteractiveRefresh . m_nPacifierFrame > = m_NonInteractiveRefresh . m_Info . m_nPacifierCount )
{
m_NonInteractiveRefresh . m_nPacifierFrame = 0 ;
}
m_NonInteractiveRefresh . m_flLastPacifierTime = t ;
}
pTexture = g_pShaderAPI - > GetD3DTexture ( m_NonInteractiveRefresh . m_Info . m_pPacifierTextures [ m_NonInteractiveRefresh . m_nPacifierFrame ] ) ;
Dx9Device ( ) - > SetRenderState ( D3DRS_ALPHABLENDENABLE , 1 ) ;
Dx9Device ( ) - > SetRenderState ( D3DRS_SRCBLEND , D3DBLEND_SRCALPHA ) ;
Dx9Device ( ) - > SetRenderState ( D3DRS_DESTBLEND , D3DBLEND_INVSRCALPHA ) ;
Dx9Device ( ) - > SetTexture ( 0 , pTexture ) ;
Dx9Device ( ) - > SetPixelShader ( m_NonInteractiveRefresh . m_pPixelShaderStartupPass2 ) ;
Dx9Device ( ) - > DrawPrimitiveUP ( D3DPT_QUADLIST , 1 , Vertices , sizeof ( TEXVERTEX ) ) ;
}
Dx9Device ( ) - > SetVertexShader ( NULL ) ;
Dx9Device ( ) - > SetPixelShader ( NULL ) ;
Dx9Device ( ) - > SetTexture ( 0 , NULL ) ;
Dx9Device ( ) - > SetVertexDeclaration ( NULL ) ;
tmZone ( TELEMETRY_LEVEL1 , TMZF_NONE , " D3DPresent " ) ;
Dx9Device ( ) - > Present ( 0 , 0 , 0 , 0 ) ;
g_pShaderAPI - > QueueResetRenderState ( ) ;
g_pShaderAPI - > OwnGPUResources ( true ) ;
UpdatePresentStats ( ) ;
# endif
}
//-----------------------------------------------------------------------------
// Page flip
//-----------------------------------------------------------------------------
void CShaderDeviceDx8 : : Present ( )
{
LOCK_SHADERAPI ( ) ;
// need to flush the dynamic buffer
g_pShaderAPI - > FlushBufferedPrimitives ( ) ;
if ( ! IsDeactivated ( ) )
{
Dx9Device ( ) - > EndScene ( ) ;
}
HRESULT hr = S_OK ;
// if we're in queued mode, don't present if the device is already lost
bool bValidPresent = true ;
bool bInMainThread = ThreadInMainThread ( ) ;
if ( ! bInMainThread )
{
// don't present if the device is in an invalid state and in queued mode
if ( m_DeviceState ! = DEVICE_STATE_OK )
{
bValidPresent = false ;
}
// check for lost device early in threaded mode
CheckDeviceLost ( m_bOtherAppInitializing ) ;
if ( m_DeviceState ! = DEVICE_STATE_OK )
{
bValidPresent = false ;
}
}
// Copy the back buffer into the non-interactive temp buffer
if ( m_NonInteractiveRefresh . m_Mode = = MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD )
{
g_pShaderAPI - > CopyRenderTargetToTextureEx ( m_NonInteractiveRefresh . m_Info . m_hTempFullscreenTexture , 0 , NULL , NULL ) ;
}
// If we're not iconified, try to present (without this check, we can flicker when Alt-Tabbed away)
# ifdef _WIN32
if ( IsX360 ( ) | | ( IsIconic ( ( HWND ) m_hWnd ) = = 0 & & bValidPresent ) )
# else
if ( IsX360 ( ) | | ( IsIconic ( ( VD3DHWND ) m_hWnd ) = = 0 & & bValidPresent ) )
# endif
{
if ( IsPC ( ) & & ( m_IsResizing | | ( m_ViewHWnd ! = ( VD3DHWND ) m_hWnd ) ) )
{
RECT destRect ;
# ifndef DX_TO_GL_ABSTRACTION
GetClientRect ( ( HWND ) m_ViewHWnd , & destRect ) ;
# else
toglGetClientRect ( ( VD3DHWND ) m_ViewHWnd , & destRect ) ;
# endif
ShaderViewport_t viewport ;
g_pShaderAPI - > GetViewports ( & viewport , 1 ) ;
RECT srcRect ;
srcRect . left = viewport . m_nTopLeftX ;
srcRect . right = viewport . m_nTopLeftX + viewport . m_nWidth ;
srcRect . top = viewport . m_nTopLeftY ;
srcRect . bottom = viewport . m_nTopLeftY + viewport . m_nHeight ;
hr = Dx9Device ( ) - > Present ( & srcRect , & destRect , ( VD3DHWND ) m_ViewHWnd , 0 ) ;
}
else
{
g_pShaderAPI - > OwnGPUResources ( false ) ;
hr = Dx9Device ( ) - > Present ( 0 , 0 , 0 , 0 ) ;
}
}
UpdatePresentStats ( ) ;
if ( IsWindows ( ) )
{
if ( hr = = D3DERR_DRIVERINTERNALERROR )
{
/* Usually this bug means that the driver has run out of internal video
memory , due to leaking it slowly over several application restarts .
As of summer 2007 , IE in particular seemed to leak a lot of driver
memory for every image context it created in the browser window . A
reboot clears out the leaked memory and will generally allow the game
to be run again ; occasionally ( but not frequently ) it ' s necessary to
reduce video settings in the game as well to run . But , this is too
fine a distinction to explain in a dialog , so place the guilt on the
user and ask them to reduce video settings regardless .
*/
Error ( " Internal driver error at Present. \n "
" You're likely out of OS Paged Pool Memory! For more info, see \n "
" http://support.steampowered.com/cgi-bin/steampowered.cfg/php/enduser/std_adp.php?p_faqid=150 \n " ) ;
}
if ( hr = = D3DERR_DEVICELOST )
{
MarkDeviceLost ( ) ;
}
}
MeshMgr ( ) - > DiscardVertexBuffers ( ) ;
if ( bInMainThread )
{
CheckDeviceLost ( m_bOtherAppInitializing ) ;
}
if ( IsX360 ( ) )
{
// according to docs - "Mandatory Reset of GPU Registers"
// 360 must force the cached state to be dirty after any present()
g_pShaderAPI - > ResetRenderState ( false ) ;
}
# ifdef RECORD_KEYFRAMES
static int frame = 0 ;
+ + frame ;
if ( frame = = KEYFRAME_INTERVAL )
{
RECORD_COMMAND ( DX8_KEYFRAME , 0 ) ;
g_pShaderAPI - > ResetRenderState ( ) ;
frame = 0 ;
}
# endif
g_pShaderAPI - > AdvancePIXFrame ( ) ;
if ( ! IsDeactivated ( ) )
{
# ifndef DX_TO_GL_ABSTRACTION
if ( ( ShaderUtil ( ) - > GetConfig ( ) . bMeasureFillRate | | ShaderUtil ( ) - > GetConfig ( ) . bVisualizeFillRate ) )
{
g_pShaderAPI - > ClearBuffers ( true , true , true , - 1 , - 1 ) ;
}
# endif
Dx9Device ( ) - > BeginScene ( ) ;
}
}
// We need to scale our colors to the range [16, 235] to keep our colors within TV standards. Some colors might
// still be out of gamut if any of the R, G, or B channels are more than 191 units apart from each other in
// the 0-255 scale, but it looks like the 360 deals with this for us by lowering the bright saturated color components.
// NOTE: I'm leaving the max at 255 to retain whiter than whites. On most TV's, we seems a little dark in the bright colors
// compared to TV and movies when played in the same conditions. This keeps out brights on par with what customers are
// used to seeing.
// TV's generally have a 2.5 gamma, so we need to convert our 2.2 frame buffer into a 2.5 frame buffer for display on a TV
void CShaderDeviceDx8 : : SetHardwareGammaRamp ( float fGamma , float fGammaTVRangeMin , float fGammaTVRangeMax , float fGammaTVExponent , bool bTVEnabled )
{
DevMsg ( 2 , " SetHardwareGammaRamp( %f ) \n " , fGamma ) ;
Assert ( Dx9Device ( ) ) ;
if ( ! Dx9Device ( ) )
return ;
D3DGAMMARAMP gammaRamp ;
for ( int i = 0 ; i < 256 ; i + + )
{
float flInputValue = float ( i ) / 255.0f ;
// Since the 360's sRGB read/write is a piecewise linear approximation, we need to correct for the difference in gamma space here
float flSrgbGammaValue ;
if ( IsX360 ( ) ) // Should we also do this for the PS3?
{
// First undo the 360 broken sRGB curve by bringing the value back into linear space
float flLinearValue = X360GammaToLinear ( flInputValue ) ;
flLinearValue = clamp ( flLinearValue , 0.0f , 1.0f ) ;
// Now apply a true sRGB curve to mimic PC hardware
flSrgbGammaValue = SrgbLinearToGamma ( flLinearValue ) ; // ( flLinearValue <= 0.0031308f ) ? ( flLinearValue * 12.92f ) : ( 1.055f * powf( flLinearValue, ( 1.0f / 2.4f ) ) ) - 0.055f;
flSrgbGammaValue = clamp ( flSrgbGammaValue , 0.0f , 1.0f ) ;
}
else
{
flSrgbGammaValue = flInputValue ;
}
// Apply the user controlled exponent curve
float flCorrection = pow ( flSrgbGammaValue , ( fGamma / 2.2f ) ) ;
flCorrection = clamp ( flCorrection , 0.0f , 1.0f ) ;
// TV adjustment - Apply an exp and a scale and bias
if ( bTVEnabled )
{
// Adjust for TV gamma of 2.5 by applying an exponent of 2.2 / 2.5 = 0.88
flCorrection = pow ( flCorrection , 2.2f / fGammaTVExponent ) ;
flCorrection = clamp ( flCorrection , 0.0f , 1.0f ) ;
// Scale and bias to fit into the 16-235 range for TV's
flCorrection = ( flCorrection * ( fGammaTVRangeMax - fGammaTVRangeMin ) / 255.0f ) + ( fGammaTVRangeMin / 255.0f ) ;
flCorrection = clamp ( flCorrection , 0.0f , 1.0f ) ;
}
// Generate final int value
unsigned int val = ( int ) ( flCorrection * 65535.0f ) ;
gammaRamp . red [ i ] = val ;
gammaRamp . green [ i ] = val ;
gammaRamp . blue [ i ] = val ;
}
Dx9Device ( ) - > SetGammaRamp ( 0 , D3DSGR_NO_CALIBRATION , & gammaRamp ) ;
}
//-----------------------------------------------------------------------------
// Shader compilation
//-----------------------------------------------------------------------------
IShaderBuffer * CShaderDeviceDx8 : : CompileShader ( const char * pProgram , size_t nBufLen , const char * pShaderVersion )
{
return ShaderManager ( ) - > CompileShader ( pProgram , nBufLen , pShaderVersion ) ;
}
VertexShaderHandle_t CShaderDeviceDx8 : : CreateVertexShader ( IShaderBuffer * pBuffer )
{
return ShaderManager ( ) - > CreateVertexShader ( pBuffer ) ;
}
void CShaderDeviceDx8 : : DestroyVertexShader ( VertexShaderHandle_t hShader )
{
ShaderManager ( ) - > DestroyVertexShader ( hShader ) ;
}
GeometryShaderHandle_t CShaderDeviceDx8 : : CreateGeometryShader ( IShaderBuffer * pShaderBuffer )
{
Assert ( 0 ) ;
return GEOMETRY_SHADER_HANDLE_INVALID ;
}
void CShaderDeviceDx8 : : DestroyGeometryShader ( GeometryShaderHandle_t hShader )
{
Assert ( hShader = = GEOMETRY_SHADER_HANDLE_INVALID ) ;
}
PixelShaderHandle_t CShaderDeviceDx8 : : CreatePixelShader ( IShaderBuffer * pBuffer )
{
return ShaderManager ( ) - > CreatePixelShader ( pBuffer ) ;
}
void CShaderDeviceDx8 : : DestroyPixelShader ( PixelShaderHandle_t hShader )
{
ShaderManager ( ) - > DestroyPixelShader ( hShader ) ;
}
# ifdef DX_TO_GL_ABSTRACTION
void CShaderDeviceDx8 : : DoStartupShaderPreloading ( void )
{
ShaderManager ( ) - > DoStartupShaderPreloading ( ) ;
}
# endif
//-----------------------------------------------------------------------------
// Creates/destroys Mesh
// NOTE: Will be deprecated soon!
//-----------------------------------------------------------------------------
IMesh * CShaderDeviceDx8 : : CreateStaticMesh ( VertexFormat_t vertexFormat , const char * pTextureBudgetGroup , IMaterial * pMaterial )
{
LOCK_SHADERAPI ( ) ;
return MeshMgr ( ) - > CreateStaticMesh ( vertexFormat , pTextureBudgetGroup , pMaterial ) ;
}
void CShaderDeviceDx8 : : DestroyStaticMesh ( IMesh * pMesh )
{
LOCK_SHADERAPI ( ) ;
MeshMgr ( ) - > DestroyStaticMesh ( pMesh ) ;
}
//-----------------------------------------------------------------------------
// Creates/destroys vertex buffers + index buffers
//-----------------------------------------------------------------------------
IVertexBuffer * CShaderDeviceDx8 : : CreateVertexBuffer ( ShaderBufferType_t type , VertexFormat_t fmt , int nVertexCount , const char * pBudgetGroup )
{
LOCK_SHADERAPI ( ) ;
return MeshMgr ( ) - > CreateVertexBuffer ( type , fmt , nVertexCount , pBudgetGroup ) ;
}
void CShaderDeviceDx8 : : DestroyVertexBuffer ( IVertexBuffer * pVertexBuffer )
{
LOCK_SHADERAPI ( ) ;
MeshMgr ( ) - > DestroyVertexBuffer ( pVertexBuffer ) ;
}
IIndexBuffer * CShaderDeviceDx8 : : CreateIndexBuffer ( ShaderBufferType_t bufferType , MaterialIndexFormat_t fmt , int nIndexCount , const char * pBudgetGroup )
{
LOCK_SHADERAPI ( ) ;
return MeshMgr ( ) - > CreateIndexBuffer ( bufferType , fmt , nIndexCount , pBudgetGroup ) ;
}
void CShaderDeviceDx8 : : DestroyIndexBuffer ( IIndexBuffer * pIndexBuffer )
{
LOCK_SHADERAPI ( ) ;
MeshMgr ( ) - > DestroyIndexBuffer ( pIndexBuffer ) ;
}
IVertexBuffer * CShaderDeviceDx8 : : GetDynamicVertexBuffer ( int streamID , VertexFormat_t vertexFormat , bool bBuffered )
{
LOCK_SHADERAPI ( ) ;
return MeshMgr ( ) - > GetDynamicVertexBuffer ( streamID , vertexFormat , bBuffered ) ;
}
IIndexBuffer * CShaderDeviceDx8 : : GetDynamicIndexBuffer ( MaterialIndexFormat_t fmt , bool bBuffered )
{
LOCK_SHADERAPI ( ) ;
return MeshMgr ( ) - > GetDynamicIndexBuffer ( fmt , bBuffered ) ;
}
# ifdef _X360
void CShaderDeviceDx8 : : SpewVideoInfo360 ( const CCommand & args )
{
XVIDEO_MODE videoMode ;
XGetVideoMode ( & videoMode ) ;
Warning ( " back buffer size: %dx%d \n " , m_PresentParameters . BackBufferWidth , m_PresentParameters . BackBufferHeight ) ;
Warning ( " display resolution: %dx%d %s \n " , videoMode . dwDisplayWidth , videoMode . dwDisplayHeight , videoMode . fIsInterlaced ? " interlaced " : " progressive " ) ;
Warning ( " refresh rate: %f \n " , videoMode . RefreshRate ) ;
Warning ( " aspect: %s \n " , videoMode . fIsWideScreen ? " 16x9 (widescreen) " : " 4x3 (normal) " ) ;
Warning ( " %s \n " , videoMode . fIsHiDef ? " hidef " : " lodef " ) ;
switch ( videoMode . VideoStandard )
{
case XC_VIDEO_STANDARD_NTSC_M :
Warning ( " video standard: NTSC_M \n " ) ;
break ;
case XC_VIDEO_STANDARD_NTSC_J :
Warning ( " video standard: NTSC_J \n " ) ;
break ;
case XC_VIDEO_STANDARD_PAL_I :
Warning ( " video standard: PAL_I \n " ) ;
break ;
default :
Warning ( " error: UNKNOWN VIDEO STANDARD! \n " ) ;
Assert ( 0 ) ;
break ;
}
ConVarRef fps_max ( " fps_max " ) ;
Warning ( " fps_max: %f \n " , fps_max . GetFloat ( ) ) ;
switch ( m_PresentParameters . MultiSampleType )
{
case D3DMULTISAMPLE_NONE :
Warning ( " multisample type: D3DMULTISAMPLE_NONE \n " ) ;
break ;
case D3DMULTISAMPLE_2_SAMPLES :
Warning ( " multisample type: D3DMULTISAMPLE_2_SAMPLES \n " ) ;
break ;
case D3DMULTISAMPLE_4_SAMPLES :
Warning ( " multisample type: D3DMULTISAMPLE_4_SAMPLES \n " ) ;
break ;
}
}
# endif