summaryrefslogtreecommitdiff
path: root/test/d3d10/common/DXUTenum.cpp
diff options
context:
space:
mode:
authorJason Maskell <[email protected]>2016-05-09 10:39:54 +0200
committerJason Maskell <[email protected]>2016-05-09 10:39:54 +0200
commit79b3462799c28af8ba586349bd671b1b56e72353 (patch)
tree3b06e36c390254c0dc7f3733a0d32af213d87293 /test/d3d10/common/DXUTenum.cpp
downloadwaveworks_archive-79b3462799c28af8ba586349bd671b1b56e72353.tar.xz
waveworks_archive-79b3462799c28af8ba586349bd671b1b56e72353.zip
Initial commit with PS4 and XBone stuff trimmed.
Diffstat (limited to 'test/d3d10/common/DXUTenum.cpp')
-rw-r--r--test/d3d10/common/DXUTenum.cpp4159
1 files changed, 4159 insertions, 0 deletions
diff --git a/test/d3d10/common/DXUTenum.cpp b/test/d3d10/common/DXUTenum.cpp
new file mode 100644
index 0000000..4c9a2c3
--- /dev/null
+++ b/test/d3d10/common/DXUTenum.cpp
@@ -0,0 +1,4159 @@
+// This code contains NVIDIA Confidential Information and is disclosed
+// under the Mutual Non-Disclosure Agreement.
+//
+// Notice
+// ALL NVIDIA DESIGN SPECIFICATIONS AND CODE ("MATERIALS") ARE PROVIDED "AS IS" NVIDIA MAKES
+// NO REPRESENTATIONS, WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. No third party distribution is allowed unless
+// expressly authorized by NVIDIA. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright � 2008- 2013 NVIDIA Corporation. All rights reserved.
+//
+// NVIDIA Corporation and its licensors retain all intellectual property and proprietary
+// rights in and to this software and related documentation and any modifications thereto.
+// Any use, reproduction, disclosure or distribution of this software and related
+// documentation without an express license agreement from NVIDIA Corporation is
+// strictly prohibited.
+//
+
+//--------------------------------------------------------------------------------------
+// File: DXUTEnum.cpp
+//
+// Enumerates D3D adapters, devices, modes, etc.
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+#include "dxstdafx.h"
+#include "DXUT.h"
+#undef min // use __min instead
+#undef max // use __max instead
+
+//--------------------------------------------------------------------------------------
+// Forward declarations
+//--------------------------------------------------------------------------------------
+extern void DXUTGetCallbackD3D9DeviceAcceptable( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable,
+ void** ppUserContext );
+extern void DXUTGetCallbackD3D10DeviceAcceptable( LPDXUTCALLBACKISD3D10DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable,
+ void** ppUserContext );
+
+HRESULT DXUTFindValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOut, DXUTD3D9DeviceSettings* pIn,
+ DXUTMatchOptions* pMatchOptions, DXUTD3D9DeviceSettings* pOptimal );
+void DXUTBuildOptimalD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOptimalDeviceSettings,
+ DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions );
+bool DXUTDoesD3D9DeviceComboMatchPreserveOptions( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D9DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions );
+float DXUTRankD3D9DeviceCombo( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D9DeviceSettings* pOptimalDeviceSettings,
+ D3DDISPLAYMODE* pAdapterDesktopDisplayMode );
+void DXUTBuildValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pValidDeviceSettings,
+ CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ DXUTD3D9DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions );
+HRESULT DXUTFindValidD3D9Resolution( CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ D3DDISPLAYMODE displayModeIn, D3DDISPLAYMODE* pBestDisplayMode );
+
+HRESULT DXUTFindValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOut, DXUTD3D10DeviceSettings* pIn,
+ DXUTMatchOptions* pMatchOptions, DXUTD3D10DeviceSettings* pOptimal );
+void DXUTBuildOptimalD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOptimalDeviceSettings,
+ DXUTD3D10DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions );
+bool DXUTDoesD3D10DeviceComboMatchPreserveOptions( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D10DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions );
+float DXUTRankD3D10DeviceCombo( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D10DeviceSettings* pOptimalDeviceSettings, DXGI_MODE_DESC* pAdapterDisplayMode );
+void DXUTBuildValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pValidDeviceSettings,
+ CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ DXUTD3D10DeviceSettings* pDeviceSettingsIn, DXUTMatchOptions* pMatchOptions );
+HRESULT DXUTFindValidD3D10Resolution( CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ DXGI_MODE_DESC displayModeIn, DXGI_MODE_DESC* pBestDisplayMode );
+
+static int __cdecl SortModesCallback( const void* arg1, const void* arg2 );
+
+
+//======================================================================================
+//======================================================================================
+// General Direct3D section
+//======================================================================================
+//======================================================================================
+
+
+//--------------------------------------------------------------------------------------
+// This function tries to find valid device settings based upon the input device settings
+// struct and the match options. For each device setting a match option in the
+// DXUTMatchOptions struct specifies how the function makes decisions. For example, if
+// the caller wants a HAL device with a back buffer format of D3DFMT_A2B10G10R10 but the
+// HAL device on the system does not support D3DFMT_A2B10G10R10 however a REF device is
+// installed that does, then the function has a choice to either use REF or to change to
+// a back buffer format to compatible with the HAL device. The match options lets the
+// caller control how these choices are made.
+//
+// Each match option must be one of the following types:
+// DXUTMT_IGNORE_INPUT: Uses the closest valid value to a default
+// DXUTMT_PRESERVE_INPUT: Uses the input without change, but may cause no valid device to be found
+// DXUTMT_CLOSEST_TO_INPUT: Uses the closest valid value to the input
+//
+// If pMatchOptions is NULL then, all of the match options are assumed to be DXUTMT_IGNORE_INPUT.
+// The function returns failure if no valid device settings can be found otherwise
+// the function returns success and the valid device settings are written to pOut.
+//--------------------------------------------------------------------------------------
+HRESULT WINAPI DXUTFindValidDeviceSettings( DXUTDeviceSettings* pOut, DXUTDeviceSettings* pIn,
+ DXUTMatchOptions* pMatchOptions )
+{
+ HRESULT hr = S_OK;
+
+ if( pOut == NULL )
+ return DXUT_ERR_MSGBOX( L"DXUTFindValidDeviceSettings", E_INVALIDARG );
+
+ // Default to DXUTMT_IGNORE_INPUT for everything unless pMatchOptions isn't NULL
+ DXUTMatchOptions defaultMatchOptions;
+ if( NULL == pMatchOptions )
+ {
+ ZeroMemory( &defaultMatchOptions, sizeof( DXUTMatchOptions ) );
+ pMatchOptions = &defaultMatchOptions;
+ }
+
+ bool bAppSupportsD3D9 = DXUTDoesAppSupportD3D9();
+ bool bAppSupportsD3D10 = DXUTDoesAppSupportD3D10();
+
+ if( !bAppSupportsD3D9 && !bAppSupportsD3D10 )
+ {
+ bAppSupportsD3D9 = true;
+ bAppSupportsD3D10 = true;
+ }
+
+ bool bAvoidD3D9 = false;
+ bool bAvoidD3D10 = false;
+ if( pMatchOptions->eAPIVersion == DXUTMT_PRESERVE_INPUT && pIn && pIn->ver == DXUT_D3D10_DEVICE )
+ bAvoidD3D9 = true;
+ if( pMatchOptions->eAPIVersion == DXUTMT_PRESERVE_INPUT && pIn && pIn->ver == DXUT_D3D9_DEVICE )
+ bAvoidD3D10 = true;
+
+ bool bPreferD3D9 = false;
+ if( pMatchOptions->eAPIVersion != DXUTMT_IGNORE_INPUT && pIn && pIn->ver == DXUT_D3D9_DEVICE )
+ bPreferD3D9 = true;
+
+ // Build an optimal device settings structure based upon the match
+ // options. If the match option is set to ignore, then a optimal default value is used.
+ // The default value may not exist on the system, but later this will be taken
+ // into account.
+ bool bFoundValidD3D10 = false;
+ bool bFoundValidD3D9 = false;
+
+ DXUTDeviceSettings validDeviceSettings;
+ CopyMemory( &validDeviceSettings, pIn, sizeof( DXUTDeviceSettings ) );
+ DXUTDeviceSettings optimalDeviceSettings;
+
+ if( bAppSupportsD3D10 && !bPreferD3D9 && !bAvoidD3D10 )
+ {
+ bool bD3D10Available = DXUTIsD3D10Available();
+ if( bD3D10Available )
+ {
+ // Force an enumeration with the IsDeviceAcceptable callback
+ DXUTGetD3D10Enumeration( false );
+
+ DXUTD3D10DeviceSettings d3d10In;
+ ZeroMemory( &d3d10In, sizeof( DXUTD3D10DeviceSettings ) );
+ if( pIn )
+ {
+ if( pIn->ver == DXUT_D3D9_DEVICE )
+ DXUTConvertDeviceSettings9to10( &pIn->d3d9, &d3d10In );
+ else
+ d3d10In = pIn->d3d10;
+ }
+
+ optimalDeviceSettings.ver = DXUT_D3D10_DEVICE;
+ DXUTBuildOptimalD3D10DeviceSettings( &optimalDeviceSettings.d3d10, &d3d10In, pMatchOptions );
+
+ validDeviceSettings.ver = DXUT_D3D10_DEVICE;
+ hr = DXUTFindValidD3D10DeviceSettings( &validDeviceSettings.d3d10, &d3d10In,
+ pMatchOptions, &optimalDeviceSettings.d3d10 );
+ if( SUCCEEDED( hr ) )
+ bFoundValidD3D10 = true;
+ }
+ else
+ {
+ if( bAvoidD3D9 )
+ hr = DXUTERR_NOCOMPATIBLEDEVICES;
+ else
+ hr = DXUTERR_NODIRECT3D;
+ }
+ }
+
+ if( bAppSupportsD3D9 && !bFoundValidD3D10 && !bAvoidD3D9 )
+ {
+ // Force an enumeration with the IsDeviceAcceptable callback
+ DXUTGetD3D9Enumeration( false );
+
+ DXUTD3D9DeviceSettings d3d9In;
+ ZeroMemory( &d3d9In, sizeof( DXUTD3D9DeviceSettings ) );
+ if( pIn )
+ {
+ if( pIn->ver == DXUT_D3D10_DEVICE )
+ DXUTConvertDeviceSettings10to9( &pIn->d3d10, &d3d9In );
+ else
+ d3d9In = pIn->d3d9;
+ }
+
+ optimalDeviceSettings.ver = DXUT_D3D9_DEVICE;
+ DXUTBuildOptimalD3D9DeviceSettings( &optimalDeviceSettings.d3d9, &d3d9In, pMatchOptions );
+
+ validDeviceSettings.ver = DXUT_D3D9_DEVICE;
+ hr = DXUTFindValidD3D9DeviceSettings( &validDeviceSettings.d3d9, &d3d9In,
+ pMatchOptions, &optimalDeviceSettings.d3d9 );
+ if( SUCCEEDED( hr ) )
+ bFoundValidD3D9 = true;
+ }
+
+ if( bFoundValidD3D10 || bFoundValidD3D9 )
+ {
+ *pOut = validDeviceSettings;
+ return S_OK;
+ }
+ else
+ {
+ return DXUT_ERR( L"DXUTFindValidDeviceSettings", hr );
+ }
+}
+
+
+//======================================================================================
+//======================================================================================
+// Direct3D 9 section
+//======================================================================================
+//======================================================================================
+CD3D9Enumeration* g_pDXUTD3D9Enumeration = NULL;
+
+HRESULT WINAPI DXUTCreateD3D9Enumeration()
+{
+ if( g_pDXUTD3D9Enumeration == NULL )
+ {
+ g_pDXUTD3D9Enumeration = new CD3D9Enumeration();
+ if( NULL == g_pDXUTD3D9Enumeration )
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+}
+
+void WINAPI DXUTDestroyD3D9Enumeration()
+{
+ SAFE_DELETE( g_pDXUTD3D9Enumeration );
+}
+
+class DXUTMemoryHelperD3D9Enum
+{
+public:
+DXUTMemoryHelperD3D9Enum()
+{
+ DXUTCreateD3D9Enumeration();
+}
+~DXUTMemoryHelperD3D9Enum()
+{
+ DXUTDestroyD3D9Enumeration();
+}
+};
+
+//--------------------------------------------------------------------------------------
+CD3D9Enumeration* WINAPI DXUTGetD3D9Enumeration( bool bForceEnumerate )
+{
+ // Using an static class with accessor function to allow control of the construction order
+ static DXUTMemoryHelperD3D9Enum d3d9enumMemory;
+
+ if( g_pDXUTD3D9Enumeration && ( !g_pDXUTD3D9Enumeration->HasEnumerated() || bForceEnumerate ) )
+ {
+ LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE pCallbackIsDeviceAcceptable;
+ void* pUserContext;
+ DXUTGetCallbackD3D9DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext );
+ g_pDXUTD3D9Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext );
+ }
+
+ return g_pDXUTD3D9Enumeration;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D9Enumeration::CD3D9Enumeration()
+{
+ m_bHasEnumerated = false;
+ m_pD3D = NULL;
+ m_IsD3D9DeviceAcceptableFunc = NULL;
+ m_pIsD3D9DeviceAcceptableFuncUserContext = NULL;
+ m_bRequirePostPixelShaderBlending = true;
+
+ m_nMinWidth = 640;
+ m_nMinHeight = 480;
+ m_nMaxWidth = UINT_MAX;
+ m_nMaxHeight = UINT_MAX;
+
+ m_nRefreshMin = 0;
+ m_nRefreshMax = UINT_MAX;
+
+ m_nMultisampleQualityMax = 0xFFFF;
+
+ ResetPossibleDepthStencilFormats();
+ ResetPossibleMultisampleTypeList();
+ ResetPossiblePresentIntervalList();
+ SetPossibleVertexProcessingList( true, true, true, false );
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D9Enumeration::~CD3D9Enumeration()
+{
+ ClearAdapterInfoList();
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Enumerate for each adapter all of the supported display modes,
+// device types, adapter formats, back buffer formats, window/full screen support,
+// depth stencil formats, multisampling types/qualities, and presentations intervals.
+//
+// For each combination of device type (HAL/REF), adapter format, back buffer format, and
+// IsWindowed it will call the app's ConfirmDevice callback. This allows the app
+// to reject or allow that combination based on its caps/etc. It also allows the
+// app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP
+// if supported otherwise it will default to SWVP, however the app can change this
+// through the ConfirmDevice callback.
+//--------------------------------------------------------------------------------------
+HRESULT CD3D9Enumeration::Enumerate( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE IsD3D9DeviceAcceptableFunc,
+ void* pIsD3D9DeviceAcceptableFuncUserContext )
+{
+ CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D9 Enumeration" );
+ IDirect3D9* pD3D = DXUTGetD3D9Object();
+ if( pD3D == NULL )
+ {
+ pD3D = DXUTGetD3D9Object();
+ if( pD3D == NULL )
+ return DXUTERR_NODIRECT3D;
+ }
+
+ m_bHasEnumerated = true;
+ m_pD3D = pD3D;
+ m_IsD3D9DeviceAcceptableFunc = IsD3D9DeviceAcceptableFunc;
+ m_pIsD3D9DeviceAcceptableFuncUserContext = pIsD3D9DeviceAcceptableFuncUserContext;
+
+ HRESULT hr;
+ ClearAdapterInfoList();
+ CGrowableArray <D3DFORMAT> adapterFormatList;
+
+ const D3DFORMAT allowedAdapterFormatArray[] =
+ {
+ D3DFMT_X8R8G8B8,
+ D3DFMT_X1R5G5B5,
+ D3DFMT_R5G6B5,
+ D3DFMT_A2R10G10B10
+ };
+ const UINT allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof
+ ( allowedAdapterFormatArray[0] );
+
+ UINT numAdapters = pD3D->GetAdapterCount();
+ for( UINT adapterOrdinal = 0; adapterOrdinal < numAdapters; adapterOrdinal++ )
+ {
+ CD3D9EnumAdapterInfo* pAdapterInfo = new CD3D9EnumAdapterInfo;
+ if( pAdapterInfo == NULL )
+ return E_OUTOFMEMORY;
+
+ pAdapterInfo->AdapterOrdinal = adapterOrdinal;
+ pD3D->GetAdapterIdentifier( adapterOrdinal, 0, &pAdapterInfo->AdapterIdentifier );
+
+ // Get list of all display modes on this adapter.
+ // Also build a temporary list of all display adapter formats.
+ adapterFormatList.RemoveAll();
+
+ for( UINT iFormatList = 0; iFormatList < allowedAdapterFormatArrayCount; iFormatList++ )
+ {
+ D3DFORMAT allowedAdapterFormat = allowedAdapterFormatArray[iFormatList];
+ UINT numAdapterModes = pD3D->GetAdapterModeCount( adapterOrdinal, allowedAdapterFormat );
+ for( UINT mode = 0; mode < numAdapterModes; mode++ )
+ {
+ D3DDISPLAYMODE displayMode;
+ pD3D->EnumAdapterModes( adapterOrdinal, allowedAdapterFormat, mode, &displayMode );
+
+ if( displayMode.Width < m_nMinWidth ||
+ displayMode.Height < m_nMinHeight ||
+ displayMode.Width > m_nMaxWidth ||
+ displayMode.Height > m_nMaxHeight ||
+ displayMode.RefreshRate < m_nRefreshMin ||
+ displayMode.RefreshRate > m_nRefreshMax )
+ {
+ continue;
+ }
+
+ pAdapterInfo->displayModeList.Add( displayMode );
+
+ if( !adapterFormatList.Contains( displayMode.Format ) )
+ adapterFormatList.Add( displayMode.Format );
+ }
+
+ }
+
+ D3DDISPLAYMODE displayMode;
+ pD3D->GetAdapterDisplayMode( adapterOrdinal, &displayMode );
+ if( !adapterFormatList.Contains( displayMode.Format ) )
+ adapterFormatList.Add( displayMode.Format );
+
+ // Sort displaymode list
+ qsort( pAdapterInfo->displayModeList.GetData(),
+ pAdapterInfo->displayModeList.GetSize(), sizeof( D3DDISPLAYMODE ),
+ SortModesCallback );
+
+ // Get info for each device on this adapter
+ if( FAILED( EnumerateDevices( pAdapterInfo, &adapterFormatList ) ) )
+ {
+ delete pAdapterInfo;
+ continue;
+ }
+
+ // If at least one device on this adapter is available and compatible
+ // with the app, add the adapterInfo to the list
+ if( pAdapterInfo->deviceInfoList.GetSize() > 0 )
+ {
+ hr = m_AdapterInfoList.Add( pAdapterInfo );
+ if( FAILED( hr ) )
+ return hr;
+ }
+ else
+ delete pAdapterInfo;
+ }
+
+ //
+ // Check for 2 or more adapters with the same name. Append the name
+ // with some instance number if that's the case to help distinguish
+ // them.
+ //
+ bool bUniqueDesc = true;
+ CD3D9EnumAdapterInfo* pAdapterInfo;
+ for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
+ {
+ CD3D9EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt( i );
+
+ for( int j = i + 1; j < m_AdapterInfoList.GetSize(); j++ )
+ {
+ CD3D9EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt( j );
+ if( _stricmp( pAdapterInfo1->AdapterIdentifier.Description,
+ pAdapterInfo2->AdapterIdentifier.Description ) == 0 )
+ {
+ bUniqueDesc = false;
+ break;
+ }
+ }
+
+ if( !bUniqueDesc )
+ break;
+ }
+
+ for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
+ {
+ pAdapterInfo = m_AdapterInfoList.GetAt( i );
+
+ MultiByteToWideChar( CP_ACP, 0,
+ pAdapterInfo->AdapterIdentifier.Description, -1,
+ pAdapterInfo->szUniqueDescription, 100 );
+ pAdapterInfo->szUniqueDescription[100] = 0;
+
+ if( !bUniqueDesc )
+ {
+ WCHAR sz[100];
+ swprintf_s( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal );
+ wcscat_s( pAdapterInfo->szUniqueDescription, 256, sz );
+
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Enumerates D3D devices for a particular adapter.
+//--------------------------------------------------------------------------------------
+HRESULT CD3D9Enumeration::EnumerateDevices( CD3D9EnumAdapterInfo* pAdapterInfo,
+ CGrowableArray <D3DFORMAT>* pAdapterFormatList )
+{
+ HRESULT hr;
+
+ const D3DDEVTYPE devTypeArray[] =
+ {
+ D3DDEVTYPE_HAL,
+ D3DDEVTYPE_SW,
+ D3DDEVTYPE_REF
+ };
+ const UINT devTypeArrayCount = sizeof( devTypeArray ) / sizeof( devTypeArray[0] );
+
+ // Enumerate each Direct3D device type
+ for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ )
+ {
+ CD3D9EnumDeviceInfo* pDeviceInfo = new CD3D9EnumDeviceInfo;
+ if( pDeviceInfo == NULL )
+ return E_OUTOFMEMORY;
+
+ // Fill struct w/ AdapterOrdinal and D3DDEVTYPE
+ pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal;
+ pDeviceInfo->DeviceType = devTypeArray[iDeviceType];
+
+ // Store device caps
+ if( FAILED( hr = m_pD3D->GetDeviceCaps( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType,
+ &pDeviceInfo->Caps ) ) )
+ {
+ delete pDeviceInfo;
+ continue;
+ }
+
+ if( pDeviceInfo->DeviceType != D3DDEVTYPE_HAL )
+ {
+ // Create a temp device to verify that it is really possible to create a REF device
+ // [the developer DirectX redist has to be installed]
+ D3DDISPLAYMODE Mode;
+ m_pD3D->GetAdapterDisplayMode( 0, &Mode );
+ D3DPRESENT_PARAMETERS pp;
+ ZeroMemory( &pp, sizeof( D3DPRESENT_PARAMETERS ) );
+ pp.BackBufferWidth = 1;
+ pp.BackBufferHeight = 1;
+ pp.BackBufferFormat = Mode.Format;
+ pp.BackBufferCount = 1;
+ pp.SwapEffect = D3DSWAPEFFECT_COPY;
+ pp.Windowed = TRUE;
+ pp.hDeviceWindow = DXUTGetHWNDFocus();
+ IDirect3DDevice9* pDevice = NULL;
+ if( FAILED( hr = m_pD3D->CreateDevice( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType,
+ DXUTGetHWNDFocus(),
+ D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &pp,
+ &pDevice ) ) )
+ {
+ delete pDeviceInfo;
+ continue;
+ }
+ SAFE_RELEASE( pDevice );
+ }
+
+ // Get info for each devicecombo on this device
+ if( FAILED( hr = EnumerateDeviceCombos( pAdapterInfo, pDeviceInfo, pAdapterFormatList ) ) )
+ {
+ delete pDeviceInfo;
+ continue;
+ }
+
+ // If at least one devicecombo for this device is found,
+ // add the deviceInfo to the list
+ if( pDeviceInfo->deviceSettingsComboList.GetSize() > 0 )
+ pAdapterInfo->deviceInfoList.Add( pDeviceInfo );
+ else
+ delete pDeviceInfo;
+ }
+
+ return S_OK;
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Enumerates DeviceCombos for a particular device.
+//--------------------------------------------------------------------------------------
+HRESULT CD3D9Enumeration::EnumerateDeviceCombos( CD3D9EnumAdapterInfo* pAdapterInfo, CD3D9EnumDeviceInfo* pDeviceInfo,
+ CGrowableArray <D3DFORMAT>* pAdapterFormatList )
+{
+ const D3DFORMAT backBufferFormatArray[] =
+ {
+ D3DFMT_A8R8G8B8,
+ D3DFMT_X8R8G8B8,
+ D3DFMT_A2R10G10B10,
+ D3DFMT_R5G6B5,
+ D3DFMT_A1R5G5B5,
+ D3DFMT_X1R5G5B5
+ };
+ const UINT backBufferFormatArrayCount = sizeof( backBufferFormatArray ) / sizeof( backBufferFormatArray[0] );
+
+ // See which adapter formats are supported by this device
+ for( int iFormat = 0; iFormat < pAdapterFormatList->GetSize(); iFormat++ )
+ {
+ D3DFORMAT adapterFormat = pAdapterFormatList->GetAt( iFormat );
+
+ for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ )
+ {
+ D3DFORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat];
+
+ for( int nWindowed = 0; nWindowed < 2; nWindowed++ )
+ {
+ if( !nWindowed && pAdapterInfo->displayModeList.GetSize() == 0 )
+ continue;
+
+ if( FAILED( m_pD3D->CheckDeviceType( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType,
+ adapterFormat, backBufferFormat, nWindowed ) ) )
+ {
+ continue;
+ }
+
+ if( m_bRequirePostPixelShaderBlending )
+ {
+ // If the backbuffer format doesn't support D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+ // then alpha test, pixel fog, render-target blending, color write enable, and dithering.
+ // are not supported.
+ if( FAILED( m_pD3D->CheckDeviceFormat( pAdapterInfo->AdapterOrdinal, pDeviceInfo->DeviceType,
+ adapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
+ D3DRTYPE_TEXTURE, backBufferFormat ) ) )
+ {
+ continue;
+ }
+ }
+
+ // If an application callback function has been provided, make sure this device
+ // is acceptable to the app.
+ if( m_IsD3D9DeviceAcceptableFunc != NULL )
+ {
+ if( !m_IsD3D9DeviceAcceptableFunc( &pDeviceInfo->Caps, adapterFormat, backBufferFormat,
+ FALSE != nWindowed, m_pIsD3D9DeviceAcceptableFuncUserContext ) )
+ continue;
+ }
+
+ // At this point, we have an adapter/device/adapterformat/backbufferformat/iswindowed
+ // DeviceCombo that is supported by the system and acceptable to the app. We still
+ // need to find one or more suitable depth/stencil buffer format,
+ // multisample type, and present interval.
+ CD3D9EnumDeviceSettingsCombo* pDeviceCombo = new CD3D9EnumDeviceSettingsCombo;
+ if( pDeviceCombo == NULL )
+ return E_OUTOFMEMORY;
+
+ pDeviceCombo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal;
+ pDeviceCombo->DeviceType = pDeviceInfo->DeviceType;
+ pDeviceCombo->AdapterFormat = adapterFormat;
+ pDeviceCombo->BackBufferFormat = backBufferFormat;
+ pDeviceCombo->Windowed = ( nWindowed != 0 );
+
+ BuildDepthStencilFormatList( pDeviceCombo );
+ BuildMultiSampleTypeList( pDeviceCombo );
+ if( pDeviceCombo->multiSampleTypeList.GetSize() == 0 )
+ {
+ delete pDeviceCombo;
+ continue;
+ }
+ BuildDSMSConflictList( pDeviceCombo );
+ BuildPresentIntervalList( pDeviceInfo, pDeviceCombo );
+ pDeviceCombo->pAdapterInfo = pAdapterInfo;
+ pDeviceCombo->pDeviceInfo = pDeviceInfo;
+
+ if( FAILED( pDeviceInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) )
+ delete pDeviceCombo;
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Adds all depth/stencil formats that are compatible with the device
+// and app to the given D3DDeviceCombo.
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::BuildDepthStencilFormatList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo )
+{
+ D3DFORMAT depthStencilFmt;
+ for( int idsf = 0; idsf < m_DepthStencilPossibleList.GetSize(); idsf++ )
+ {
+ depthStencilFmt = m_DepthStencilPossibleList.GetAt( idsf );
+ if( SUCCEEDED( m_pD3D->CheckDeviceFormat( pDeviceCombo->AdapterOrdinal,
+ pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat,
+ D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFmt ) ) )
+ {
+ if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( pDeviceCombo->AdapterOrdinal,
+ pDeviceCombo->DeviceType, pDeviceCombo->AdapterFormat,
+ pDeviceCombo->BackBufferFormat, depthStencilFmt ) ) )
+ {
+ pDeviceCombo->depthStencilFormatList.Add( depthStencilFmt );
+ }
+ }
+ }
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Adds all multisample types that are compatible with the device and app to
+// the given D3DDeviceCombo.
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::BuildMultiSampleTypeList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo )
+{
+ D3DMULTISAMPLE_TYPE msType;
+ DWORD msQuality;
+ for( int imst = 0; imst < m_MultiSampleTypeList.GetSize(); imst++ )
+ {
+ msType = m_MultiSampleTypeList.GetAt( imst );
+ if( SUCCEEDED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal,
+ pDeviceCombo->DeviceType, pDeviceCombo->BackBufferFormat,
+ pDeviceCombo->Windowed, msType, &msQuality ) ) )
+ {
+ pDeviceCombo->multiSampleTypeList.Add( msType );
+ if( msQuality > m_nMultisampleQualityMax + 1 )
+ msQuality = m_nMultisampleQualityMax + 1;
+ pDeviceCombo->multiSampleQualityList.Add( msQuality );
+ }
+ }
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Find any conflicts between the available depth/stencil formats and
+// multisample types.
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::BuildDSMSConflictList( CD3D9EnumDeviceSettingsCombo* pDeviceCombo )
+{
+ CD3D9EnumDSMSConflict DSMSConflict;
+
+ for( int iDS = 0; iDS < pDeviceCombo->depthStencilFormatList.GetSize(); iDS++ )
+ {
+ D3DFORMAT dsFmt = pDeviceCombo->depthStencilFormatList.GetAt( iDS );
+
+ for( int iMS = 0; iMS < pDeviceCombo->multiSampleTypeList.GetSize(); iMS++ )
+ {
+ D3DMULTISAMPLE_TYPE msType = pDeviceCombo->multiSampleTypeList.GetAt( iMS );
+
+ if( FAILED( m_pD3D->CheckDeviceMultiSampleType( pDeviceCombo->AdapterOrdinal, pDeviceCombo->DeviceType,
+ dsFmt, pDeviceCombo->Windowed, msType, NULL ) ) )
+ {
+ DSMSConflict.DSFormat = dsFmt;
+ DSMSConflict.MSType = msType;
+ pDeviceCombo->DSMSConflictList.Add( DSMSConflict );
+ }
+ }
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Adds all present intervals that are compatible with the device and app
+// to the given D3DDeviceCombo.
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::BuildPresentIntervalList( CD3D9EnumDeviceInfo* pDeviceInfo,
+ CD3D9EnumDeviceSettingsCombo* pDeviceCombo )
+{
+ UINT pi;
+ for( int ipi = 0; ipi < m_PresentIntervalList.GetSize(); ipi++ )
+ {
+ pi = m_PresentIntervalList.GetAt( ipi );
+ if( pDeviceCombo->Windowed )
+ {
+ if( pi == D3DPRESENT_INTERVAL_TWO ||
+ pi == D3DPRESENT_INTERVAL_THREE ||
+ pi == D3DPRESENT_INTERVAL_FOUR )
+ {
+ // These intervals are not supported in windowed mode.
+ continue;
+ }
+ }
+ // Note that D3DPRESENT_INTERVAL_DEFAULT is zero, so you
+ // can't do a caps check for it -- it is always available.
+ if( pi == D3DPRESENT_INTERVAL_DEFAULT ||
+ ( pDeviceInfo->Caps.PresentationIntervals & pi ) )
+ {
+ pDeviceCombo->presentIntervalList.Add( pi );
+ }
+ }
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Release all the allocated CD3D9EnumAdapterInfo objects and empty the list
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::ClearAdapterInfoList()
+{
+ CD3D9EnumAdapterInfo* pAdapterInfo;
+ for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
+ {
+ pAdapterInfo = m_AdapterInfoList.GetAt( i );
+ delete pAdapterInfo;
+ }
+
+ m_AdapterInfoList.RemoveAll();
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Call GetAdapterInfoList() after Enumerate() to get a STL vector of
+// CD3D9EnumAdapterInfo*
+//--------------------------------------------------------------------------------------
+CGrowableArray <CD3D9EnumAdapterInfo*>* CD3D9Enumeration::GetAdapterInfoList()
+{
+ return &m_AdapterInfoList;
+}
+
+
+
+//--------------------------------------------------------------------------------------
+CD3D9EnumAdapterInfo* CD3D9Enumeration::GetAdapterInfo( UINT AdapterOrdinal )
+{
+ for( int iAdapter = 0; iAdapter < m_AdapterInfoList.GetSize(); iAdapter++ )
+ {
+ CD3D9EnumAdapterInfo* pAdapterInfo = m_AdapterInfoList.GetAt( iAdapter );
+ if( pAdapterInfo->AdapterOrdinal == AdapterOrdinal )
+ return pAdapterInfo;
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D9EnumDeviceInfo* CD3D9Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType )
+{
+ CD3D9EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
+ if( pAdapterInfo )
+ {
+ for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ )
+ {
+ CD3D9EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo );
+ if( pDeviceInfo->DeviceType == DeviceType )
+ return pDeviceInfo;
+ }
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------------
+//
+//--------------------------------------------------------------------------------------
+CD3D9EnumDeviceSettingsCombo* CD3D9Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType,
+ D3DFORMAT AdapterFormat,
+ D3DFORMAT BackBufferFormat, BOOL bWindowed )
+{
+ CD3D9EnumDeviceInfo* pDeviceInfo = GetDeviceInfo( AdapterOrdinal, DeviceType );
+ if( pDeviceInfo )
+ {
+ for( int iDeviceCombo = 0; iDeviceCombo < pDeviceInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ )
+ {
+ CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt(
+ iDeviceCombo );
+ if( pDeviceSettingsCombo->AdapterFormat == AdapterFormat &&
+ pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat &&
+ pDeviceSettingsCombo->Windowed == bWindowed )
+ return pDeviceSettingsCombo;
+ }
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns the number of color channel bits in the specified D3DFORMAT
+//--------------------------------------------------------------------------------------
+UINT WINAPI DXUTGetD3D9ColorChannelBits( D3DFORMAT fmt )
+{
+ switch( fmt )
+ {
+ case D3DFMT_R8G8B8:
+ return 8;
+ case D3DFMT_A8R8G8B8:
+ return 8;
+ case D3DFMT_X8R8G8B8:
+ return 8;
+ case D3DFMT_R5G6B5:
+ return 5;
+ case D3DFMT_X1R5G5B5:
+ return 5;
+ case D3DFMT_A1R5G5B5:
+ return 5;
+ case D3DFMT_A4R4G4B4:
+ return 4;
+ case D3DFMT_R3G3B2:
+ return 2;
+ case D3DFMT_A8R3G3B2:
+ return 2;
+ case D3DFMT_X4R4G4B4:
+ return 4;
+ case D3DFMT_A2B10G10R10:
+ return 10;
+ case D3DFMT_A8B8G8R8:
+ return 8;
+ case D3DFMT_A2R10G10B10:
+ return 10;
+ case D3DFMT_A16B16G16R16:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns the number of alpha channel bits in the specified D3DFORMAT
+//--------------------------------------------------------------------------------------
+UINT WINAPI DXUTGetAlphaChannelBits( D3DFORMAT fmt )
+{
+ switch( fmt )
+ {
+ case D3DFMT_R8G8B8:
+ return 0;
+ case D3DFMT_A8R8G8B8:
+ return 8;
+ case D3DFMT_X8R8G8B8:
+ return 0;
+ case D3DFMT_R5G6B5:
+ return 0;
+ case D3DFMT_X1R5G5B5:
+ return 0;
+ case D3DFMT_A1R5G5B5:
+ return 1;
+ case D3DFMT_A4R4G4B4:
+ return 4;
+ case D3DFMT_R3G3B2:
+ return 0;
+ case D3DFMT_A8R3G3B2:
+ return 8;
+ case D3DFMT_X4R4G4B4:
+ return 0;
+ case D3DFMT_A2B10G10R10:
+ return 2;
+ case D3DFMT_A8B8G8R8:
+ return 8;
+ case D3DFMT_A2R10G10B10:
+ return 2;
+ case D3DFMT_A16B16G16R16:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns the number of depth bits in the specified D3DFORMAT
+//--------------------------------------------------------------------------------------
+UINT WINAPI DXUTGetDepthBits( D3DFORMAT fmt )
+{
+ switch( fmt )
+ {
+ case D3DFMT_D32F_LOCKABLE:
+ case D3DFMT_D32:
+ return 32;
+
+ case D3DFMT_D24X8:
+ case D3DFMT_D24S8:
+ case D3DFMT_D24X4S4:
+ case D3DFMT_D24FS8:
+ return 24;
+
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D16:
+ return 16;
+
+ case D3DFMT_D15S1:
+ return 15;
+
+ default:
+ return 0;
+ }
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+// Returns the number of stencil bits in the specified D3DFORMAT
+//--------------------------------------------------------------------------------------
+UINT WINAPI DXUTGetStencilBits( D3DFORMAT fmt )
+{
+ switch( fmt )
+ {
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D16:
+ case D3DFMT_D32F_LOCKABLE:
+ case D3DFMT_D32:
+ case D3DFMT_D24X8:
+ return 0;
+
+ case D3DFMT_D15S1:
+ return 1;
+
+ case D3DFMT_D24X4S4:
+ return 4;
+
+ case D3DFMT_D24S8:
+ case D3DFMT_D24FS8:
+ return 8;
+
+ default:
+ return 0;
+ }
+}
+
+
+
+//--------------------------------------------------------------------------------------
+// Used to sort D3DDISPLAYMODEs
+//--------------------------------------------------------------------------------------
+static int __cdecl SortModesCallback( const void* arg1, const void* arg2 )
+{
+ D3DDISPLAYMODE* pdm1 = ( D3DDISPLAYMODE* )arg1;
+ D3DDISPLAYMODE* pdm2 = ( D3DDISPLAYMODE* )arg2;
+
+ if( pdm1->Width > pdm2->Width )
+ return 1;
+ if( pdm1->Width < pdm2->Width )
+ return -1;
+ if( pdm1->Height > pdm2->Height )
+ return 1;
+ if( pdm1->Height < pdm2->Height )
+ return -1;
+ if( pdm1->Format > pdm2->Format )
+ return 1;
+ if( pdm1->Format < pdm2->Format )
+ return -1;
+ if( pdm1->RefreshRate > pdm2->RefreshRate )
+ return 1;
+ if( pdm1->RefreshRate < pdm2->RefreshRate )
+ return -1;
+ return 0;
+}
+
+
+
+//--------------------------------------------------------------------------------------
+CD3D9EnumAdapterInfo::~CD3D9EnumAdapterInfo( void )
+{
+ CD3D9EnumDeviceInfo* pDeviceInfo;
+ for( int i = 0; i < deviceInfoList.GetSize(); i++ )
+ {
+ pDeviceInfo = deviceInfoList.GetAt( i );
+ delete pDeviceInfo;
+ }
+ deviceInfoList.RemoveAll();
+}
+
+
+
+
+//--------------------------------------------------------------------------------------
+CD3D9EnumDeviceInfo::~CD3D9EnumDeviceInfo( void )
+{
+ CD3D9EnumDeviceSettingsCombo* pDeviceCombo;
+ for( int i = 0; i < deviceSettingsComboList.GetSize(); i++ )
+ {
+ pDeviceCombo = deviceSettingsComboList.GetAt( i );
+ delete pDeviceCombo;
+ }
+ deviceSettingsComboList.RemoveAll();
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::ResetPossibleDepthStencilFormats()
+{
+ m_DepthStencilPossibleList.RemoveAll();
+ m_DepthStencilPossibleList.Add( D3DFMT_D16 );
+ m_DepthStencilPossibleList.Add( D3DFMT_D15S1 );
+ m_DepthStencilPossibleList.Add( D3DFMT_D24X8 );
+ m_DepthStencilPossibleList.Add( D3DFMT_D24S8 );
+ m_DepthStencilPossibleList.Add( D3DFMT_D24X4S4 );
+ m_DepthStencilPossibleList.Add( D3DFMT_D32 );
+}
+
+
+//--------------------------------------------------------------------------------------
+CGrowableArray <D3DFORMAT>* CD3D9Enumeration::GetPossibleDepthStencilFormatList()
+{
+ return &m_DepthStencilPossibleList;
+}
+
+
+//--------------------------------------------------------------------------------------
+CGrowableArray <D3DMULTISAMPLE_TYPE>* CD3D9Enumeration::GetPossibleMultisampleTypeList()
+{
+ return &m_MultiSampleTypeList;
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::ResetPossibleMultisampleTypeList()
+{
+ m_MultiSampleTypeList.RemoveAll();
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONE );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_NONMASKABLE );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_2_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_3_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_4_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_5_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_6_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_7_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_8_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_9_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_10_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_11_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_12_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_13_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_14_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_15_SAMPLES );
+ m_MultiSampleTypeList.Add( D3DMULTISAMPLE_16_SAMPLES );
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::GetPossibleVertexProcessingList( bool* pbSoftwareVP, bool* pbHardwareVP, bool* pbPureHarewareVP,
+ bool* pbMixedVP )
+{
+ *pbSoftwareVP = m_bSoftwareVP;
+ *pbHardwareVP = m_bHardwareVP;
+ *pbPureHarewareVP = m_bPureHarewareVP;
+ *pbMixedVP = m_bMixedVP;
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::SetPossibleVertexProcessingList( bool bSoftwareVP, bool bHardwareVP, bool bPureHarewareVP,
+ bool bMixedVP )
+{
+ m_bSoftwareVP = bSoftwareVP;
+ m_bHardwareVP = bHardwareVP;
+ m_bPureHarewareVP = bPureHarewareVP;
+ m_bMixedVP = bMixedVP;
+}
+
+
+//--------------------------------------------------------------------------------------
+CGrowableArray <UINT>* CD3D9Enumeration::GetPossiblePresentIntervalList()
+{
+ return &m_PresentIntervalList;
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::ResetPossiblePresentIntervalList()
+{
+ m_PresentIntervalList.RemoveAll();
+ m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_IMMEDIATE );
+ m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_DEFAULT );
+ m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_ONE );
+ m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_TWO );
+ m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_THREE );
+ m_PresentIntervalList.Add( D3DPRESENT_INTERVAL_FOUR );
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::SetResolutionMinMax( UINT nMinWidth, UINT nMinHeight,
+ UINT nMaxWidth, UINT nMaxHeight )
+{
+ m_nMinWidth = nMinWidth;
+ m_nMinHeight = nMinHeight;
+ m_nMaxWidth = nMaxWidth;
+ m_nMaxHeight = nMaxHeight;
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::SetRefreshMinMax( UINT nMin, UINT nMax )
+{
+ m_nRefreshMin = nMin;
+ m_nRefreshMax = nMax;
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D9Enumeration::SetMultisampleQualityMax( UINT nMax )
+{
+ if( nMax > 0xFFFF )
+ nMax = 0xFFFF;
+ m_nMultisampleQualityMax = nMax;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT DXUTFindValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOut, DXUTD3D9DeviceSettings* pIn,
+ DXUTMatchOptions* pMatchOptions, DXUTD3D9DeviceSettings* pOptimal )
+{
+ // Find the best combination of:
+ // Adapter Ordinal
+ // Device Type
+ // Adapter Format
+ // Back Buffer Format
+ // Windowed
+ // given what's available on the system and the match options combined with the device settings input.
+ // This combination of settings is encapsulated by the CD3D9EnumDeviceSettingsCombo class.
+ float fBestRanking = -1.0f;
+ CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo = NULL;
+ D3DDISPLAYMODE adapterDesktopDisplayMode;
+
+ IDirect3D9* pD3D = DXUTGetD3D9Object();
+ CD3D9Enumeration* pd3dEnum = DXUTGetD3D9Enumeration( false );
+ CGrowableArray <CD3D9EnumAdapterInfo*>* pAdapterList = pd3dEnum->GetAdapterInfoList();
+ for( int iAdapter = 0; iAdapter < pAdapterList->GetSize(); iAdapter++ )
+ {
+ CD3D9EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt( iAdapter );
+
+ // Get the desktop display mode of adapter
+ pD3D->GetAdapterDisplayMode( pAdapterInfo->AdapterOrdinal, &adapterDesktopDisplayMode );
+
+ // Enum all the device types supported by this adapter to find the best device settings
+ for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ )
+ {
+ CD3D9EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo );
+
+ // Enum all the device settings combinations. A device settings combination is
+ // a unique set of an adapter format, back buffer format, and IsWindowed.
+ for( int iDeviceCombo = 0; iDeviceCombo < pDeviceInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ )
+ {
+ CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo = pDeviceInfo->deviceSettingsComboList.GetAt(
+ iDeviceCombo );
+
+ // If windowed mode the adapter format has to be the same as the desktop
+ // display mode format so skip any that don't match
+ if( pDeviceSettingsCombo->Windowed &&
+ ( pDeviceSettingsCombo->AdapterFormat != adapterDesktopDisplayMode.Format ) )
+ continue;
+
+ // Skip any combo that doesn't meet the preserve match options
+ if( false == DXUTDoesD3D9DeviceComboMatchPreserveOptions( pDeviceSettingsCombo, pIn, pMatchOptions ) )
+ continue;
+
+ // Get a ranking number that describes how closely this device combo matches the optimal combo
+ float fCurRanking = DXUTRankD3D9DeviceCombo( pDeviceSettingsCombo,
+ pOptimal, &adapterDesktopDisplayMode );
+
+ // If this combo better matches the input device settings then save it
+ if( fCurRanking > fBestRanking )
+ {
+ pBestDeviceSettingsCombo = pDeviceSettingsCombo;
+ fBestRanking = fCurRanking;
+ }
+ }
+ }
+ }
+
+ // If no best device combination was found then fail
+ if( pBestDeviceSettingsCombo == NULL )
+ return DXUTERR_NOCOMPATIBLEDEVICES;
+
+ // Using the best device settings combo found, build valid device settings taking heed of
+ // the match options and the input device settings
+ DXUTD3D9DeviceSettings validDeviceSettings;
+ DXUTBuildValidD3D9DeviceSettings( &validDeviceSettings, pBestDeviceSettingsCombo, pIn, pMatchOptions );
+ *pOut = validDeviceSettings;
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Internal helper function to build a D3D9 device settings structure based upon the match
+// options. If the match option is set to ignore, then a optimal default value is used.
+// The default value may not exist on the system, but later this will be taken
+// into account.
+//--------------------------------------------------------------------------------------
+void DXUTBuildOptimalD3D9DeviceSettings( DXUTD3D9DeviceSettings* pOptimalDeviceSettings,
+ DXUTD3D9DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions )
+{
+ IDirect3D9* pD3D = DXUTGetD3D9Object();
+ D3DDISPLAYMODE adapterDesktopDisplayMode;
+
+ ZeroMemory( pOptimalDeviceSettings, sizeof( DXUTD3D9DeviceSettings ) );
+
+ //---------------------
+ // Adapter ordinal
+ //---------------------
+ if( pMatchOptions->eAdapterOrdinal == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->AdapterOrdinal = D3DADAPTER_DEFAULT;
+ else
+ pOptimalDeviceSettings->AdapterOrdinal = pDeviceSettingsIn->AdapterOrdinal;
+
+ //---------------------
+ // Device type
+ //---------------------
+ if( pMatchOptions->eDeviceType == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->DeviceType = D3DDEVTYPE_HAL;
+ else
+ pOptimalDeviceSettings->DeviceType = pDeviceSettingsIn->DeviceType;
+
+ //---------------------
+ // Windowed
+ //---------------------
+ if( pMatchOptions->eWindowed == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->pp.Windowed = TRUE;
+ else
+ pOptimalDeviceSettings->pp.Windowed = pDeviceSettingsIn->pp.Windowed;
+
+ //---------------------
+ // Adapter format
+ //---------------------
+ if( pMatchOptions->eAdapterFormat == DXUTMT_IGNORE_INPUT )
+ {
+ // If windowed, default to the desktop display mode
+ // If fullscreen, default to the desktop display mode for quick mode change or
+ // default to D3DFMT_X8R8G8B8 if the desktop display mode is < 32bit
+ pD3D->GetAdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, &adapterDesktopDisplayMode );
+ if( pOptimalDeviceSettings->pp.Windowed || DXUTGetD3D9ColorChannelBits( adapterDesktopDisplayMode.Format ) >=
+ 8 )
+ pOptimalDeviceSettings->AdapterFormat = adapterDesktopDisplayMode.Format;
+ else
+ pOptimalDeviceSettings->AdapterFormat = D3DFMT_X8R8G8B8;
+ }
+ else
+ {
+ pOptimalDeviceSettings->AdapterFormat = pDeviceSettingsIn->AdapterFormat;
+ }
+
+ //---------------------
+ // Vertex processing
+ //---------------------
+ if( pMatchOptions->eVertexProcessing == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ else
+ pOptimalDeviceSettings->BehaviorFlags = pDeviceSettingsIn->BehaviorFlags;
+
+ //---------------------
+ // Resolution
+ //---------------------
+ if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT )
+ {
+ // If windowed, default to 640x480
+ // If fullscreen, default to the desktop res for quick mode change
+ if( pOptimalDeviceSettings->pp.Windowed )
+ {
+ pOptimalDeviceSettings->pp.BackBufferWidth = 640;
+ pOptimalDeviceSettings->pp.BackBufferHeight = 480;
+ }
+ else
+ {
+ pD3D->GetAdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, &adapterDesktopDisplayMode );
+ pOptimalDeviceSettings->pp.BackBufferWidth = adapterDesktopDisplayMode.Width;
+ pOptimalDeviceSettings->pp.BackBufferHeight = adapterDesktopDisplayMode.Height;
+ }
+ }
+ else
+ {
+ pOptimalDeviceSettings->pp.BackBufferWidth = pDeviceSettingsIn->pp.BackBufferWidth;
+ pOptimalDeviceSettings->pp.BackBufferHeight = pDeviceSettingsIn->pp.BackBufferHeight;
+ }
+
+ //---------------------
+ // Back buffer format
+ //---------------------
+ if( pMatchOptions->eBackBufferFormat == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->pp.BackBufferFormat = pOptimalDeviceSettings->AdapterFormat; // Default to match the adapter format
+ else
+ pOptimalDeviceSettings->pp.BackBufferFormat = pDeviceSettingsIn->pp.BackBufferFormat;
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->pp.BackBufferCount = 1; // Default to double buffering. Causes less latency than triple buffering
+ else
+ pOptimalDeviceSettings->pp.BackBufferCount = pDeviceSettingsIn->pp.BackBufferCount;
+
+ //---------------------
+ // Multisample
+ //---------------------
+ if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT )
+ {
+ // Default to no multisampling
+ pOptimalDeviceSettings->pp.MultiSampleType = D3DMULTISAMPLE_NONE;
+ pOptimalDeviceSettings->pp.MultiSampleQuality = 0;
+ }
+ else
+ {
+ pOptimalDeviceSettings->pp.MultiSampleType = pDeviceSettingsIn->pp.MultiSampleType;
+ pOptimalDeviceSettings->pp.MultiSampleQuality = pDeviceSettingsIn->pp.MultiSampleQuality;
+ }
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ else
+ pOptimalDeviceSettings->pp.SwapEffect = pDeviceSettingsIn->pp.SwapEffect;
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT &&
+ pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT )
+ {
+ UINT nBackBufferBits = DXUTGetD3D9ColorChannelBits( pOptimalDeviceSettings->pp.BackBufferFormat );
+ if( nBackBufferBits >= 8 )
+ pOptimalDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D32;
+ else
+ pOptimalDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D16;
+ }
+ else
+ {
+ pOptimalDeviceSettings->pp.AutoDepthStencilFormat = pDeviceSettingsIn->pp.AutoDepthStencilFormat;
+ }
+
+ //---------------------
+ // Present flags
+ //---------------------
+ if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->pp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
+ else
+ pOptimalDeviceSettings->pp.Flags = pDeviceSettingsIn->pp.Flags;
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz = 0;
+ else
+ pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz;
+
+ //---------------------
+ // Present interval
+ //---------------------
+ if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT )
+ {
+ // For windowed and fullscreen, default to D3DPRESENT_INTERVAL_DEFAULT
+ // which will wait for the vertical retrace period to prevent tearing.
+ // For benchmarking, use D3DPRESENT_INTERVAL_IMMEDIATE which will
+ // will wait not for the vertical retrace period but may introduce tearing.
+ pOptimalDeviceSettings->pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ else
+ {
+ pOptimalDeviceSettings->pp.PresentationInterval = pDeviceSettingsIn->pp.PresentationInterval;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns false for any CD3D9EnumDeviceSettingsCombo that doesn't meet the preserve
+// match options against the input pDeviceSettingsIn.
+//--------------------------------------------------------------------------------------
+bool DXUTDoesD3D9DeviceComboMatchPreserveOptions( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D9DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions )
+{
+ //---------------------
+ // Adapter ordinal
+ //---------------------
+ if( pMatchOptions->eAdapterOrdinal == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->AdapterOrdinal != pDeviceSettingsIn->AdapterOrdinal ) )
+ return false;
+
+ //---------------------
+ // Device type
+ //---------------------
+ if( pMatchOptions->eDeviceType == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->DeviceType != pDeviceSettingsIn->DeviceType ) )
+ return false;
+
+ //---------------------
+ // Windowed
+ //---------------------
+ if( pMatchOptions->eWindowed == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->Windowed != pDeviceSettingsIn->pp.Windowed ) )
+ return false;
+
+ //---------------------
+ // Adapter format
+ //---------------------
+ if( pMatchOptions->eAdapterFormat == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->AdapterFormat != pDeviceSettingsIn->AdapterFormat ) )
+ return false;
+
+ //---------------------
+ // Vertex processing
+ //---------------------
+ // If keep VP and input has HWVP, then skip if this combo doesn't have HWTL
+ if( pMatchOptions->eVertexProcessing == DXUTMT_PRESERVE_INPUT &&
+ ( ( pDeviceSettingsIn->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) != 0 ) &&
+ ( ( pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == 0 ) )
+ return false;
+
+ //---------------------
+ // Resolution
+ //---------------------
+ // If keep resolution then check that width and height supported by this combo
+ if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT )
+ {
+ bool bFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); i++ )
+ {
+ D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( i );
+ if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
+ continue; // Skip this display mode if it doesn't match the combo's adapter format
+
+ if( displayMode.Width == pDeviceSettingsIn->pp.BackBufferWidth &&
+ displayMode.Height == pDeviceSettingsIn->pp.BackBufferHeight )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ // If the width and height are not supported by this combo, return false
+ if( !bFound )
+ return false;
+ }
+
+ //---------------------
+ // Back buffer format
+ //---------------------
+ if( pMatchOptions->eBackBufferFormat == DXUTMT_PRESERVE_INPUT &&
+ pDeviceSettingsCombo->BackBufferFormat != pDeviceSettingsIn->pp.BackBufferFormat )
+ return false;
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ // No caps for the back buffer count
+
+ //---------------------
+ // Multisample
+ //---------------------
+ if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT )
+ {
+ bool bFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ )
+ {
+ D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt( i );
+ DWORD msQuality = pDeviceSettingsCombo->multiSampleQualityList.GetAt( i );
+
+ if( msType == pDeviceSettingsIn->pp.MultiSampleType &&
+ msQuality > pDeviceSettingsIn->pp.MultiSampleQuality )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ // If multisample type/quality not supported by this combo, then return false
+ if( !bFound )
+ return false;
+ }
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ // No caps for swap effects
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ // If keep depth stencil format then check that the depth stencil format is supported by this combo
+ if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT &&
+ pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT )
+ {
+ if( pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN &&
+ !pDeviceSettingsCombo->depthStencilFormatList.Contains( pDeviceSettingsIn->pp.AutoDepthStencilFormat ) )
+ return false;
+ }
+
+ // If keep depth format then check that the depth format is supported by this combo
+ if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT &&
+ pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN )
+ {
+ bool bFound = false;
+ UINT dwDepthBits = DXUTGetDepthBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
+ for( int i = 0; i < pDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
+ {
+ D3DFORMAT depthStencilFmt = pDeviceSettingsCombo->depthStencilFormatList.GetAt( i );
+ UINT dwCurDepthBits = DXUTGetDepthBits( depthStencilFmt );
+ if( dwCurDepthBits - dwDepthBits == 0 )
+ bFound = true;
+ }
+
+ if( !bFound )
+ return false;
+ }
+
+ // If keep depth format then check that the depth format is supported by this combo
+ if( pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT &&
+ pDeviceSettingsIn->pp.AutoDepthStencilFormat != D3DFMT_UNKNOWN )
+ {
+ bool bFound = false;
+ UINT dwStencilBits = DXUTGetStencilBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
+ for( int i = 0; i < pDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
+ {
+ D3DFORMAT depthStencilFmt = pDeviceSettingsCombo->depthStencilFormatList.GetAt( i );
+ UINT dwCurStencilBits = DXUTGetStencilBits( depthStencilFmt );
+ if( dwCurStencilBits - dwStencilBits == 0 )
+ bFound = true;
+ }
+
+ if( !bFound )
+ return false;
+ }
+
+ //---------------------
+ // Present flags
+ //---------------------
+ // No caps for the present flags
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ // If keep refresh rate then check that the resolution is supported by this combo
+ if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT )
+ {
+ bool bFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); i++ )
+ {
+ D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( i );
+ if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
+ continue;
+ if( displayMode.RefreshRate == pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ // If refresh rate not supported by this combo, then return false
+ if( !bFound )
+ return false;
+ }
+
+ //---------------------
+ // Present interval
+ //---------------------
+ // If keep present interval then check that the present interval is supported by this combo
+ if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT &&
+ !pDeviceSettingsCombo->presentIntervalList.Contains( pDeviceSettingsIn->pp.PresentationInterval ) )
+ return false;
+
+ return true;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns a ranking number that describes how closely this device
+// combo matches the optimal combo based on the match options and the optimal device settings
+//--------------------------------------------------------------------------------------
+float DXUTRankD3D9DeviceCombo( CD3D9EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D9DeviceSettings* pOptimalDeviceSettings,
+ D3DDISPLAYMODE* pAdapterDesktopDisplayMode )
+{
+ float fCurRanking = 0.0f;
+
+ // Arbitrary weights. Gives preference to the ordinal, device type, and windowed
+ const float fAdapterOrdinalWeight = 1000.0f;
+ const float fDeviceTypeWeight = 100.0f;
+ const float fWindowWeight = 10.0f;
+ const float fAdapterFormatWeight = 1.0f;
+ const float fVertexProcessingWeight = 1.0f;
+ const float fResolutionWeight = 1.0f;
+ const float fBackBufferFormatWeight = 1.0f;
+ const float fMultiSampleWeight = 1.0f;
+ const float fDepthStencilWeight = 1.0f;
+ const float fRefreshRateWeight = 1.0f;
+ const float fPresentIntervalWeight = 1.0f;
+
+ //---------------------
+ // Adapter ordinal
+ //---------------------
+ if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal )
+ fCurRanking += fAdapterOrdinalWeight;
+
+ //---------------------
+ // Device type
+ //---------------------
+ if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DeviceType )
+ fCurRanking += fDeviceTypeWeight;
+ // Slightly prefer HAL
+ if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL )
+ fCurRanking += 0.1f;
+
+ //---------------------
+ // Windowed
+ //---------------------
+ if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->pp.Windowed )
+ fCurRanking += fWindowWeight;
+
+ //---------------------
+ // Adapter format
+ //---------------------
+ if( pDeviceSettingsCombo->AdapterFormat == pOptimalDeviceSettings->AdapterFormat )
+ {
+ fCurRanking += fAdapterFormatWeight;
+ }
+ else
+ {
+ int nBitDepthDelta = abs( ( long )DXUTGetD3D9ColorChannelBits( pDeviceSettingsCombo->AdapterFormat ) -
+ ( long )DXUTGetD3D9ColorChannelBits( pOptimalDeviceSettings->AdapterFormat ) );
+ float fScale = __max( 0.9f - ( float )nBitDepthDelta * 0.2f, 0.0f );
+ fCurRanking += fScale * fAdapterFormatWeight;
+ }
+
+ if( !pDeviceSettingsCombo->Windowed )
+ {
+ // Slightly prefer when it matches the desktop format or is D3DFMT_X8R8G8B8
+ bool bAdapterOptimalMatch;
+ if( DXUTGetD3D9ColorChannelBits( pAdapterDesktopDisplayMode->Format ) >= 8 )
+ bAdapterOptimalMatch = ( pDeviceSettingsCombo->AdapterFormat == pAdapterDesktopDisplayMode->Format );
+ else
+ bAdapterOptimalMatch = ( pDeviceSettingsCombo->AdapterFormat == D3DFMT_X8R8G8B8 );
+
+ if( bAdapterOptimalMatch )
+ fCurRanking += 0.1f;
+ }
+
+ //---------------------
+ // Vertex processing
+ //---------------------
+ if( ( pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) != 0 ||
+ ( pOptimalDeviceSettings->BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING ) != 0 )
+ {
+ if( ( pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) != 0 )
+ fCurRanking += fVertexProcessingWeight;
+ }
+ // Slightly prefer HW T&L
+ if( ( pDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) != 0 )
+ fCurRanking += 0.1f;
+
+ //---------------------
+ // Resolution
+ //---------------------
+ bool bResolutionFound = false;
+ for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ )
+ {
+ D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm );
+ if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
+ continue;
+ if( displayMode.Width == pOptimalDeviceSettings->pp.BackBufferWidth &&
+ displayMode.Height == pOptimalDeviceSettings->pp.BackBufferHeight )
+ bResolutionFound = true;
+ }
+ if( bResolutionFound )
+ fCurRanking += fResolutionWeight;
+
+ //---------------------
+ // Back buffer format
+ //---------------------
+ if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->pp.BackBufferFormat )
+ {
+ fCurRanking += fBackBufferFormatWeight;
+ }
+ else
+ {
+ int nBitDepthDelta = abs( ( long )DXUTGetD3D9ColorChannelBits( pDeviceSettingsCombo->BackBufferFormat ) -
+ ( long )DXUTGetD3D9ColorChannelBits( pOptimalDeviceSettings->pp.BackBufferFormat ) );
+ float fScale = __max( 0.9f - ( float )nBitDepthDelta * 0.2f, 0.0f );
+ fCurRanking += fScale * fBackBufferFormatWeight;
+ }
+
+ // Check if this back buffer format is the same as
+ // the adapter format since this is preferred.
+ bool bAdapterMatchesBB = ( pDeviceSettingsCombo->BackBufferFormat == pDeviceSettingsCombo->AdapterFormat );
+ if( bAdapterMatchesBB )
+ fCurRanking += 0.1f;
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ // No caps for the back buffer count
+
+ //---------------------
+ // Multisample
+ //---------------------
+ bool bMultiSampleFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ )
+ {
+ D3DMULTISAMPLE_TYPE msType = pDeviceSettingsCombo->multiSampleTypeList.GetAt( i );
+ DWORD msQuality = pDeviceSettingsCombo->multiSampleQualityList.GetAt( i );
+
+ if( msType == pOptimalDeviceSettings->pp.MultiSampleType &&
+ msQuality > pOptimalDeviceSettings->pp.MultiSampleQuality )
+ {
+ bMultiSampleFound = true;
+ break;
+ }
+ }
+ if( bMultiSampleFound )
+ fCurRanking += fMultiSampleWeight;
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ // No caps for swap effects
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ if( pDeviceSettingsCombo->depthStencilFormatList.Contains( pOptimalDeviceSettings->pp.AutoDepthStencilFormat ) )
+ fCurRanking += fDepthStencilWeight;
+
+ //---------------------
+ // Present flags
+ //---------------------
+ // No caps for the present flags
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ bool bRefreshFound = false;
+ for( int idm = 0; idm < pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetSize(); idm++ )
+ {
+ D3DDISPLAYMODE displayMode = pDeviceSettingsCombo->pAdapterInfo->displayModeList.GetAt( idm );
+ if( displayMode.Format != pDeviceSettingsCombo->AdapterFormat )
+ continue;
+ if( displayMode.RefreshRate == pOptimalDeviceSettings->pp.FullScreen_RefreshRateInHz )
+ bRefreshFound = true;
+ }
+ if( bRefreshFound )
+ fCurRanking += fRefreshRateWeight;
+
+ //---------------------
+ // Present interval
+ //---------------------
+ // If keep present interval then check that the present interval is supported by this combo
+ if( pDeviceSettingsCombo->presentIntervalList.Contains( pOptimalDeviceSettings->pp.PresentationInterval ) )
+ fCurRanking += fPresentIntervalWeight;
+
+ return fCurRanking;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Builds valid device settings using the match options, the input device settings, and the
+// best device settings combo found.
+//--------------------------------------------------------------------------------------
+void DXUTBuildValidD3D9DeviceSettings( DXUTD3D9DeviceSettings* pValidDeviceSettings,
+ CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ DXUTD3D9DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions )
+{
+ IDirect3D9* pD3D = DXUTGetD3D9Object();
+ D3DDISPLAYMODE adapterDesktopDisplayMode;
+ pD3D->GetAdapterDisplayMode( pBestDeviceSettingsCombo->AdapterOrdinal, &adapterDesktopDisplayMode );
+
+ // For each setting pick the best, taking into account the match options and
+ // what's supported by the device
+
+ //---------------------
+ // Adapter Ordinal
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->AdapterOrdinal
+
+ //---------------------
+ // Device Type
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->DeviceType
+
+ //---------------------
+ // Windowed
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->Windowed
+
+ //---------------------
+ // Adapter Format
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->AdapterFormat
+
+ //---------------------
+ // Vertex processing
+ //---------------------
+ DWORD dwBestBehaviorFlags = 0;
+ if( pMatchOptions->eVertexProcessing == DXUTMT_PRESERVE_INPUT )
+ {
+ dwBestBehaviorFlags = pDeviceSettingsIn->BehaviorFlags;
+ }
+ else if( pMatchOptions->eVertexProcessing == DXUTMT_IGNORE_INPUT )
+ {
+ // The framework defaults to HWVP if available otherwise use SWVP
+ if( ( pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) != 0 )
+ dwBestBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ else
+ dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ }
+ else // if( pMatchOptions->eVertexProcessing == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ // Default to input, and fallback to SWVP if HWVP not available
+ dwBestBehaviorFlags = pDeviceSettingsIn->BehaviorFlags;
+ if( ( pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == 0 &&
+ ( ( dwBestBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) != 0 ||
+ ( dwBestBehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING ) != 0 ) )
+ {
+ dwBestBehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ dwBestBehaviorFlags &= ~D3DCREATE_MIXED_VERTEXPROCESSING;
+ dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ }
+
+ // One of these must be selected
+ if( ( dwBestBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ) == 0 &&
+ ( dwBestBehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING ) == 0 &&
+ ( dwBestBehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING ) == 0 )
+ {
+ if( ( pBestDeviceSettingsCombo->pDeviceInfo->Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) != 0 )
+ dwBestBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ else
+ dwBestBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ }
+ }
+
+ //---------------------
+ // Resolution
+ //---------------------
+ D3DDISPLAYMODE bestDisplayMode;
+ if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT )
+ {
+ bestDisplayMode.Width = pDeviceSettingsIn->pp.BackBufferWidth;
+ bestDisplayMode.Height = pDeviceSettingsIn->pp.BackBufferHeight;
+ }
+ else
+ {
+ D3DDISPLAYMODE displayModeIn;
+ if( pMatchOptions->eResolution == DXUTMT_CLOSEST_TO_INPUT &&
+ pDeviceSettingsIn )
+ {
+ displayModeIn.Width = pDeviceSettingsIn->pp.BackBufferWidth;
+ displayModeIn.Height = pDeviceSettingsIn->pp.BackBufferHeight;
+ }
+ else // if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT )
+ {
+ if( pBestDeviceSettingsCombo->Windowed )
+ {
+ // The framework defaults to 640x480 for windowed
+ displayModeIn.Width = 640;
+ displayModeIn.Height = 480;
+ }
+ else
+ {
+ // The framework defaults to desktop resolution for fullscreen to try to avoid slow mode change
+ displayModeIn.Width = adapterDesktopDisplayMode.Width;
+ displayModeIn.Height = adapterDesktopDisplayMode.Height;
+ }
+ }
+
+ // Call a helper function to find the closest valid display mode to the optimal
+ DXUTFindValidD3D9Resolution( pBestDeviceSettingsCombo, displayModeIn, &bestDisplayMode );
+ }
+
+ //---------------------
+ // Back Buffer Format
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->BackBufferFormat
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ UINT bestBackBufferCount;
+ if( pMatchOptions->eBackBufferCount == DXUTMT_PRESERVE_INPUT )
+ {
+ bestBackBufferCount = pDeviceSettingsIn->pp.BackBufferCount;
+ }
+ else if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT )
+ {
+ // Default to double buffering. Causes less latency than triple buffering
+ bestBackBufferCount = 1;
+ }
+ else // if( pMatchOptions->eBackBufferCount == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ bestBackBufferCount = pDeviceSettingsIn->pp.BackBufferCount;
+ if( bestBackBufferCount > 3 )
+ bestBackBufferCount = 3;
+ if( bestBackBufferCount < 1 )
+ bestBackBufferCount = 1;
+ }
+
+ //---------------------
+ // Multisample
+ //---------------------
+ D3DMULTISAMPLE_TYPE bestMultiSampleType;
+ DWORD bestMultiSampleQuality;
+ if( pDeviceSettingsIn && pDeviceSettingsIn->pp.SwapEffect != D3DSWAPEFFECT_DISCARD )
+ {
+ // Swap effect is not set to discard so multisampling has to off
+ bestMultiSampleType = D3DMULTISAMPLE_NONE;
+ bestMultiSampleQuality = 0;
+ }
+ else
+ {
+ if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT )
+ {
+ bestMultiSampleType = pDeviceSettingsIn->pp.MultiSampleType;
+ bestMultiSampleQuality = pDeviceSettingsIn->pp.MultiSampleQuality;
+ }
+ else if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT )
+ {
+ // Default to no multisampling (always supported)
+ bestMultiSampleType = D3DMULTISAMPLE_NONE;
+ bestMultiSampleQuality = 0;
+ }
+ else if( pMatchOptions->eMultiSample == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ // Default to no multisampling (always supported)
+ bestMultiSampleType = D3DMULTISAMPLE_NONE;
+ bestMultiSampleQuality = 0;
+
+ for( int i = 0; i < pBestDeviceSettingsCombo->multiSampleTypeList.GetSize(); i++ )
+ {
+ D3DMULTISAMPLE_TYPE type = pBestDeviceSettingsCombo->multiSampleTypeList.GetAt( i );
+ DWORD qualityLevels = pBestDeviceSettingsCombo->multiSampleQualityList.GetAt( i );
+
+ // Check whether supported type is closer to the input than our current best
+ if( abs( type - pDeviceSettingsIn->pp.MultiSampleType ) < abs( bestMultiSampleType -
+ pDeviceSettingsIn->pp.MultiSampleType )
+ )
+ {
+ bestMultiSampleType = type;
+ bestMultiSampleQuality = __min( qualityLevels - 1, pDeviceSettingsIn->pp.MultiSampleQuality );
+ }
+ }
+ }
+ else
+ {
+ // Error case
+ bestMultiSampleType = D3DMULTISAMPLE_NONE;
+ bestMultiSampleQuality = 0;
+ }
+ }
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ D3DSWAPEFFECT bestSwapEffect;
+ if( pMatchOptions->eSwapEffect == DXUTMT_PRESERVE_INPUT )
+ {
+ bestSwapEffect = pDeviceSettingsIn->pp.SwapEffect;
+ }
+ else if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT )
+ {
+ bestSwapEffect = D3DSWAPEFFECT_DISCARD;
+ }
+ else // if( pMatchOptions->eSwapEffect == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ bestSwapEffect = pDeviceSettingsIn->pp.SwapEffect;
+
+ // Swap effect has to be one of these 3
+ if( bestSwapEffect != D3DSWAPEFFECT_DISCARD &&
+ bestSwapEffect != D3DSWAPEFFECT_FLIP &&
+ bestSwapEffect != D3DSWAPEFFECT_COPY )
+ {
+ bestSwapEffect = D3DSWAPEFFECT_DISCARD;
+ }
+ }
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ D3DFORMAT bestDepthStencilFormat;
+ bool bestEnableAutoDepthStencil;
+
+ CGrowableArray <int> depthStencilRanking;
+ depthStencilRanking.SetSize( pBestDeviceSettingsCombo->depthStencilFormatList.GetSize() );
+
+ UINT dwBackBufferBitDepth = DXUTGetD3D9ColorChannelBits( pBestDeviceSettingsCombo->BackBufferFormat );
+ UINT dwInputDepthBitDepth = 0;
+ if( pDeviceSettingsIn )
+ dwInputDepthBitDepth = DXUTGetDepthBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
+
+ for( int i = 0; i < pBestDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
+ {
+ D3DFORMAT curDepthStencilFmt = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt( i );
+ DWORD dwCurDepthBitDepth = DXUTGetDepthBits( curDepthStencilFmt );
+ int nRanking;
+
+ if( pMatchOptions->eDepthFormat == DXUTMT_PRESERVE_INPUT )
+ {
+ // Need to match bit depth of input
+ if( dwCurDepthBitDepth == dwInputDepthBitDepth )
+ nRanking = 0;
+ else
+ nRanking = 10000;
+ }
+ else if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT )
+ {
+ // Prefer match of backbuffer bit depth
+ nRanking = abs( ( int )dwCurDepthBitDepth - ( int )dwBackBufferBitDepth * 4 );
+ }
+ else // if( pMatchOptions->eDepthFormat == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ // Prefer match of input depth format bit depth
+ nRanking = abs( ( int )dwCurDepthBitDepth - ( int )dwInputDepthBitDepth );
+ }
+
+ depthStencilRanking.Add( nRanking );
+ }
+
+ UINT dwInputStencilBitDepth = 0;
+ if( pDeviceSettingsIn )
+ dwInputStencilBitDepth = DXUTGetStencilBits( pDeviceSettingsIn->pp.AutoDepthStencilFormat );
+
+ for( int i = 0; i < pBestDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
+ {
+ D3DFORMAT curDepthStencilFmt = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt( i );
+ int nRanking = depthStencilRanking.GetAt( i );
+ DWORD dwCurStencilBitDepth = DXUTGetStencilBits( curDepthStencilFmt );
+
+ if( pMatchOptions->eStencilFormat == DXUTMT_PRESERVE_INPUT )
+ {
+ // Need to match bit depth of input
+ if( dwCurStencilBitDepth == dwInputStencilBitDepth )
+ nRanking += 0;
+ else
+ nRanking += 10000;
+ }
+ else if( pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT )
+ {
+ // Prefer 0 stencil bit depth
+ nRanking += dwCurStencilBitDepth;
+ }
+ else // if( pMatchOptions->eStencilFormat == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ // Prefer match of input stencil format bit depth
+ nRanking += abs( ( int )dwCurStencilBitDepth - ( int )dwInputStencilBitDepth );
+ }
+
+ depthStencilRanking.SetAt( i, nRanking );
+ }
+
+ int nBestRanking = 100000;
+ int nBestIndex = -1;
+ for( int i = 0; i < pBestDeviceSettingsCombo->depthStencilFormatList.GetSize(); i++ )
+ {
+ int nRanking = depthStencilRanking.GetAt( i );
+ if( nRanking < nBestRanking )
+ {
+ nBestRanking = nRanking;
+ nBestIndex = i;
+ }
+ }
+
+ if( nBestIndex >= 0 )
+ {
+ bestDepthStencilFormat = pBestDeviceSettingsCombo->depthStencilFormatList.GetAt( nBestIndex );
+ bestEnableAutoDepthStencil = true;
+ }
+ else
+ {
+ bestDepthStencilFormat = D3DFMT_UNKNOWN;
+ bestEnableAutoDepthStencil = false;
+ }
+
+
+ //---------------------
+ // Present flags
+ //---------------------
+ DWORD dwBestFlags;
+ if( pMatchOptions->ePresentFlags == DXUTMT_PRESERVE_INPUT )
+ {
+ dwBestFlags = pDeviceSettingsIn->pp.Flags;
+ }
+ else if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT )
+ {
+ dwBestFlags = 0;
+ if( bestEnableAutoDepthStencil )
+ dwBestFlags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
+ }
+ else // if( pMatchOptions->ePresentFlags == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ dwBestFlags = pDeviceSettingsIn->pp.Flags;
+ if( bestEnableAutoDepthStencil )
+ dwBestFlags |= D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
+ }
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ if( pBestDeviceSettingsCombo->Windowed )
+ {
+ // Must be 0 for windowed
+ bestDisplayMode.RefreshRate = 0;
+ }
+ else
+ {
+ if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT )
+ {
+ bestDisplayMode.RefreshRate = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz;
+ }
+ else
+ {
+ UINT refreshRateMatch;
+ if( pMatchOptions->eRefreshRate == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ refreshRateMatch = pDeviceSettingsIn->pp.FullScreen_RefreshRateInHz;
+ }
+ else // if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT )
+ {
+ refreshRateMatch = adapterDesktopDisplayMode.RefreshRate;
+ }
+
+ bestDisplayMode.RefreshRate = 0;
+
+ if( refreshRateMatch != 0 )
+ {
+ int nBestRefreshRanking = 100000;
+ CGrowableArray <D3DDISPLAYMODE>* pDisplayModeList =
+ &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList;
+ for( int iDisplayMode = 0; iDisplayMode < pDisplayModeList->GetSize(); iDisplayMode++ )
+ {
+ D3DDISPLAYMODE displayMode = pDisplayModeList->GetAt( iDisplayMode );
+ if( displayMode.Format != pBestDeviceSettingsCombo->AdapterFormat ||
+ displayMode.Height != bestDisplayMode.Height ||
+ displayMode.Width != bestDisplayMode.Width )
+ continue; // Skip display modes that don't match
+
+ // Find the delta between the current refresh rate and the optimal refresh rate
+ int nCurRanking = abs( ( int )displayMode.RefreshRate - ( int )refreshRateMatch );
+
+ if( nCurRanking < nBestRefreshRanking )
+ {
+ bestDisplayMode.RefreshRate = displayMode.RefreshRate;
+ nBestRefreshRanking = nCurRanking;
+
+ // Stop if perfect match found
+ if( nBestRefreshRanking == 0 )
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //---------------------
+ // Present interval
+ //---------------------
+ UINT bestPresentInterval;
+ if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT )
+ {
+ bestPresentInterval = pDeviceSettingsIn->pp.PresentationInterval;
+ }
+ else if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT )
+ {
+ // For windowed and fullscreen, default to D3DPRESENT_INTERVAL_DEFAULT
+ // which will wait for the vertical retrace period to prevent tearing.
+ // For benchmarking, use D3DPRESENT_INTERVAL_DEFAULT which will
+ // will wait not for the vertical retrace period but may introduce tearing.
+ bestPresentInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ else // if( pMatchOptions->ePresentInterval == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ if( pBestDeviceSettingsCombo->presentIntervalList.Contains( pDeviceSettingsIn->pp.PresentationInterval ) )
+ {
+ bestPresentInterval = pDeviceSettingsIn->pp.PresentationInterval;
+ }
+ else
+ {
+ bestPresentInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ }
+
+ // Fill the device settings struct
+ ZeroMemory( pValidDeviceSettings, sizeof( DXUTD3D9DeviceSettings ) );
+ pValidDeviceSettings->AdapterOrdinal = pBestDeviceSettingsCombo->AdapterOrdinal;
+ pValidDeviceSettings->DeviceType = pBestDeviceSettingsCombo->DeviceType;
+ pValidDeviceSettings->AdapterFormat = pBestDeviceSettingsCombo->AdapterFormat;
+ pValidDeviceSettings->BehaviorFlags = dwBestBehaviorFlags;
+ pValidDeviceSettings->pp.BackBufferWidth = bestDisplayMode.Width;
+ pValidDeviceSettings->pp.BackBufferHeight = bestDisplayMode.Height;
+ pValidDeviceSettings->pp.BackBufferFormat = pBestDeviceSettingsCombo->BackBufferFormat;
+ pValidDeviceSettings->pp.BackBufferCount = bestBackBufferCount;
+ pValidDeviceSettings->pp.MultiSampleType = bestMultiSampleType;
+ pValidDeviceSettings->pp.MultiSampleQuality = bestMultiSampleQuality;
+ pValidDeviceSettings->pp.SwapEffect = bestSwapEffect;
+ pValidDeviceSettings->pp.hDeviceWindow = pBestDeviceSettingsCombo->Windowed ? DXUTGetHWNDDeviceWindowed() :
+ DXUTGetHWNDDeviceFullScreen();
+ pValidDeviceSettings->pp.Windowed = pBestDeviceSettingsCombo->Windowed;
+ pValidDeviceSettings->pp.EnableAutoDepthStencil = bestEnableAutoDepthStencil;
+ pValidDeviceSettings->pp.AutoDepthStencilFormat = bestDepthStencilFormat;
+ pValidDeviceSettings->pp.Flags = dwBestFlags;
+ pValidDeviceSettings->pp.FullScreen_RefreshRateInHz = bestDisplayMode.RefreshRate;
+ pValidDeviceSettings->pp.PresentationInterval = bestPresentInterval;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Internal helper function to find the closest allowed display mode to the optimal
+//--------------------------------------------------------------------------------------
+HRESULT DXUTFindValidD3D9Resolution( CD3D9EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ D3DDISPLAYMODE displayModeIn, D3DDISPLAYMODE* pBestDisplayMode )
+{
+ D3DDISPLAYMODE bestDisplayMode;
+ ZeroMemory( &bestDisplayMode, sizeof( D3DDISPLAYMODE ) );
+
+ if( pBestDeviceSettingsCombo->Windowed )
+ {
+ // In windowed mode, all resolutions are valid but restritions still apply
+ // on the size of the window. See DXUTChangeD3D9Device() for details
+ *pBestDisplayMode = displayModeIn;
+ }
+ else
+ {
+ int nBestRanking = 100000;
+ int nCurRanking;
+ CGrowableArray <D3DDISPLAYMODE>* pDisplayModeList = &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList;
+ for( int iDisplayMode = 0; iDisplayMode < pDisplayModeList->GetSize(); iDisplayMode++ )
+ {
+ D3DDISPLAYMODE displayMode = pDisplayModeList->GetAt( iDisplayMode );
+
+ // Skip display modes that don't match the combo's adapter format
+ if( displayMode.Format != pBestDeviceSettingsCombo->AdapterFormat )
+ continue;
+
+ // Find the delta between the current width/height and the optimal width/height
+ nCurRanking = abs( ( int )displayMode.Width - ( int )displayModeIn.Width ) +
+ abs( ( int )displayMode.Height - ( int )displayModeIn.Height );
+
+ if( nCurRanking < nBestRanking )
+ {
+ bestDisplayMode = displayMode;
+ nBestRanking = nCurRanking;
+
+ // Stop if perfect match found
+ if( nBestRanking == 0 )
+ break;
+ }
+ }
+
+ if( bestDisplayMode.Width == 0 )
+ {
+ *pBestDisplayMode = displayModeIn;
+ return E_FAIL; // No valid display modes found
+ }
+
+ *pBestDisplayMode = bestDisplayMode;
+ }
+
+ return S_OK;
+}
+
+
+//======================================================================================
+//======================================================================================
+// Direct3D 10 section
+//======================================================================================
+//======================================================================================
+CD3D10Enumeration* g_pDXUTD3D10Enumeration = NULL;
+
+HRESULT WINAPI DXUTCreateD3D10Enumeration()
+{
+ if( g_pDXUTD3D10Enumeration == NULL )
+ {
+ g_pDXUTD3D10Enumeration = new CD3D10Enumeration();
+ if( NULL == g_pDXUTD3D10Enumeration )
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+}
+
+void WINAPI DXUTDestroyD3D10Enumeration()
+{
+ SAFE_DELETE( g_pDXUTD3D10Enumeration );
+}
+
+class DXUTMemoryHelperD3D10Enum
+{
+public:
+DXUTMemoryHelperD3D10Enum()
+{
+ DXUTCreateD3D10Enumeration();
+}
+~DXUTMemoryHelperD3D10Enum()
+{
+ DXUTDestroyD3D10Enumeration();
+}
+};
+
+
+//--------------------------------------------------------------------------------------
+CD3D10Enumeration* WINAPI DXUTGetD3D10Enumeration( bool bForceEnumerate, bool bEnumerateAllAdapterFormats )
+{
+ // Using an static class with accessor function to allow control of the construction order
+ static DXUTMemoryHelperD3D10Enum d3d10enumMemory;
+
+ if( g_pDXUTD3D10Enumeration && ( !g_pDXUTD3D10Enumeration->HasEnumerated() || bForceEnumerate ) )
+ {
+ g_pDXUTD3D10Enumeration->SetEnumerateAllAdapterFormats( bEnumerateAllAdapterFormats, false );
+ LPDXUTCALLBACKISD3D10DEVICEACCEPTABLE pCallbackIsDeviceAcceptable;
+ void* pUserContext;
+ DXUTGetCallbackD3D10DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext );
+ g_pDXUTD3D10Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext );
+ }
+
+ return g_pDXUTD3D10Enumeration;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10Enumeration::CD3D10Enumeration()
+{
+ m_bHasEnumerated = false;
+ m_IsD3D10DeviceAcceptableFunc = NULL;
+ m_pIsD3D10DeviceAcceptableFuncUserContext = NULL;
+
+ m_nMinWidth = 640;
+ m_nMinHeight = 480;
+ m_nMaxWidth = UINT_MAX;
+ m_nMaxHeight = UINT_MAX;
+ m_bEnumerateAllAdapterFormats = false;
+
+ m_nRefreshMin = 0;
+ m_nRefreshMax = UINT_MAX;
+
+ ResetPossibleDepthStencilFormats();
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10Enumeration::~CD3D10Enumeration()
+{
+ ClearAdapterInfoList();
+}
+
+
+//--------------------------------------------------------------------------------------
+// Enumerate for each adapter all of the supported display modes,
+// device types, adapter formats, back buffer formats, window/full screen support,
+// depth stencil formats, multisampling types/qualities, and presentations intervals.
+//
+// For each combination of device type (HAL/REF), adapter format, back buffer format, and
+// IsWindowed it will call the app's ConfirmDevice callback. This allows the app
+// to reject or allow that combination based on its caps/etc. It also allows the
+// app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP
+// if supported otherwise it will default to SWVP, however the app can change this
+// through the ConfirmDevice callback.
+//--------------------------------------------------------------------------------------
+HRESULT CD3D10Enumeration::Enumerate( LPDXUTCALLBACKISD3D10DEVICEACCEPTABLE IsD3D10DeviceAcceptableFunc,
+ void* pIsD3D10DeviceAcceptableFuncUserContext )
+{
+ CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D10 Enumeration" );
+ HRESULT hr;
+ IDXGIFactory* pFactory = DXUTGetDXGIFactory();
+ if( pFactory == NULL )
+ return E_FAIL;
+
+ m_bHasEnumerated = true;
+ m_IsD3D10DeviceAcceptableFunc = IsD3D10DeviceAcceptableFunc;
+ m_pIsD3D10DeviceAcceptableFuncUserContext = pIsD3D10DeviceAcceptableFuncUserContext;
+
+ ClearAdapterInfoList();
+
+ for( int index = 0; ; ++index )
+ {
+ IDXGIAdapter* pAdapter = NULL;
+ hr = pFactory->EnumAdapters( index, &pAdapter );
+ if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit
+ break;
+
+ CD3D10EnumAdapterInfo* pAdapterInfo = new CD3D10EnumAdapterInfo;
+ if( !pAdapterInfo )
+ {
+ SAFE_RELEASE( pAdapter );
+ return E_OUTOFMEMORY;
+ }
+ ZeroMemory( pAdapterInfo, sizeof( CD3D10EnumAdapterInfo ) );
+ pAdapterInfo->AdapterOrdinal = index;
+ pAdapter->GetDesc( &pAdapterInfo->AdapterDesc );
+ pAdapterInfo->m_pAdapter = pAdapter;
+
+ // Enumerate the device driver types on the adapter.
+ hr = EnumerateDevices( pAdapterInfo );
+ if( FAILED( hr ) )
+ {
+ delete pAdapterInfo;
+ continue;
+ }
+
+ hr = EnumerateOutputs( pAdapterInfo );
+ if( FAILED( hr ) || pAdapterInfo->outputInfoList.GetSize() <= 0 )
+ {
+ delete pAdapterInfo;
+ continue;
+ }
+
+ // Get info for each devicecombo on this device
+ if( FAILED( hr = EnumerateDeviceCombos( pFactory, pAdapterInfo ) ) )
+ {
+ delete pAdapterInfo;
+ continue;
+ }
+
+ hr = m_AdapterInfoList.Add( pAdapterInfo );
+ if( FAILED( hr ) )
+ {
+ delete pAdapterInfo;
+ return hr;
+ }
+ }
+ // If we did not get an adapter then we should still enumerate WARP and Ref.
+ if (m_AdapterInfoList.GetSize() == 0) {
+
+
+ CD3D10EnumAdapterInfo* pAdapterInfo = new CD3D10EnumAdapterInfo;
+ if( !pAdapterInfo )
+ {
+ return E_OUTOFMEMORY;
+ }
+ ZeroMemory( pAdapterInfo, sizeof( CD3D10EnumAdapterInfo ) );
+
+ hr = EnumerateDevices( pAdapterInfo );
+
+ // Get info for each devicecombo on this device
+ if( FAILED( hr = EnumerateDeviceCombosNoAdapter( pAdapterInfo ) ) )
+ {
+ delete pAdapterInfo;
+ }
+
+ if (!FAILED(hr)) hr = m_AdapterInfoList.Add( pAdapterInfo );
+ }
+
+
+
+ //
+ // Check for 2 or more adapters with the same name. Append the name
+ // with some instance number if that's the case to help distinguish
+ // them.
+ //
+ bool bUniqueDesc = true;
+ CD3D10EnumAdapterInfo* pAdapterInfo;
+ for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
+ {
+ CD3D10EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt( i );
+
+ for( int j = i + 1; j < m_AdapterInfoList.GetSize(); j++ )
+ {
+ CD3D10EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt( j );
+ if( wcsncmp( pAdapterInfo1->AdapterDesc.Description,
+ pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 )
+ {
+ bUniqueDesc = false;
+ break;
+ }
+ }
+
+ if( !bUniqueDesc )
+ break;
+ }
+
+ for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
+ {
+ pAdapterInfo = m_AdapterInfoList.GetAt( i );
+
+ wcscpy_s( pAdapterInfo->szUniqueDescription, 100, pAdapterInfo->AdapterDesc.Description );
+ if( !bUniqueDesc )
+ {
+ WCHAR sz[100];
+ swprintf_s( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal );
+ wcscat_s( pAdapterInfo->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz );
+ }
+ }
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CD3D10Enumeration::EnumerateOutputs( CD3D10EnumAdapterInfo* pAdapterInfo )
+{
+ HRESULT hr;
+ IDXGIOutput* pOutput;
+
+ for( int iOutput = 0; ; ++iOutput )
+ {
+ pOutput = NULL;
+ hr = pAdapterInfo->m_pAdapter->EnumOutputs( iOutput, &pOutput );
+ if( DXGI_ERROR_NOT_FOUND == hr )
+ {
+ return S_OK;
+ }
+ else if( FAILED( hr ) )
+ {
+ return hr; //Something bad happened.
+ }
+ else //Success!
+ {
+ CD3D10EnumOutputInfo* pOutputInfo = new CD3D10EnumOutputInfo;
+ if( !pOutputInfo )
+ {
+ SAFE_RELEASE( pOutput );
+ return E_OUTOFMEMORY;
+ }
+ ZeroMemory( pOutputInfo, sizeof( CD3D10EnumOutputInfo ) );
+ pOutput->GetDesc( &pOutputInfo->Desc );
+ pOutputInfo->Output = iOutput;
+ pOutputInfo->m_pOutput = pOutput;
+
+ EnumerateDisplayModes( pOutputInfo );
+ if( pOutputInfo->displayModeList.GetSize() <= 0 )
+ {
+ // If this output has no valid display mode, do not save it.
+ delete pOutputInfo;
+ continue;
+ }
+
+ hr = pAdapterInfo->outputInfoList.Add( pOutputInfo );
+ if( FAILED( hr ) )
+ {
+ delete pOutputInfo;
+ return hr;
+ }
+ }
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CD3D10Enumeration::EnumerateDisplayModes( CD3D10EnumOutputInfo* pOutputInfo )
+{
+ HRESULT hr = S_OK;
+ DXGI_FORMAT allowedAdapterFormatArray[] =
+ {
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
+
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R10G10B10A2_UNORM
+ };
+ int allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof( allowedAdapterFormatArray[0] );
+
+ // Swap perferred modes for apps running in linear space
+ DXGI_FORMAT RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ if( !DXUTIsInGammaCorrectMode() )
+ {
+ allowedAdapterFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
+ allowedAdapterFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM;
+ }
+
+ // The fast path only enumerates R8G8B8A8_UNORM_SRGB modes
+ if( !m_bEnumerateAllAdapterFormats )
+ allowedAdapterFormatArrayCount = 1;
+
+ for( int f = 0; f < allowedAdapterFormatArrayCount; ++f )
+ {
+ // Fast-path: Try to grab at least 512 modes.
+ // This is to avoid calling GetDisplayModeList more times than necessary.
+ // GetDisplayModeList is an expensive call.
+ UINT NumModes = 512;
+ DXGI_MODE_DESC* pDesc = new DXGI_MODE_DESC[ NumModes ];
+ assert( pDesc );
+ if( !pDesc )
+ return E_OUTOFMEMORY;
+
+ hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
+ DXGI_ENUM_MODES_SCALING,
+ &NumModes,
+ pDesc );
+ if( DXGI_ERROR_NOT_FOUND == hr )
+ {
+ SAFE_DELETE_ARRAY( pDesc );
+ NumModes = 0;
+ break;
+ }
+ else if( MAKE_DXGI_HRESULT( 34 ) == hr && RemoteMode == allowedAdapterFormatArray[f] )
+ {
+ // DXGI cannot enumerate display modes over a remote session. Therefore, create a fake display
+ // mode for the current screen resolution for the remote session.
+ if( 0 != GetSystemMetrics( 0x1000 ) ) // SM_REMOTESESSION
+ {
+ DEVMODE DevMode;
+ DevMode.dmSize = sizeof( DEVMODE );
+ if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &DevMode ) )
+ {
+ NumModes = 1;
+ pDesc[0].Width = DevMode.dmPelsWidth;
+ pDesc[0].Height = DevMode.dmPelsHeight;
+ pDesc[0].Format = RemoteMode;
+ pDesc[0].RefreshRate.Numerator = 60;
+ pDesc[0].RefreshRate.Denominator = 1;
+ pDesc[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
+ pDesc[0].Scaling = DXGI_MODE_SCALING_CENTERED;
+ hr = S_OK;
+ }
+ }
+ }
+ else if( DXGI_ERROR_MORE_DATA == hr )
+ {
+ // Slow path. There were more than 512 modes.
+ SAFE_DELETE_ARRAY( pDesc );
+ hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
+ DXGI_ENUM_MODES_SCALING,
+ &NumModes,
+ NULL );
+ if( FAILED( hr ) )
+ {
+ NumModes = 0;
+ break;
+ }
+
+ pDesc = new DXGI_MODE_DESC[ NumModes ];
+ assert( pDesc );
+ if( !pDesc )
+ return E_OUTOFMEMORY;
+
+ hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
+ DXGI_ENUM_MODES_SCALING,
+ &NumModes,
+ pDesc );
+ if( FAILED( hr ) )
+ {
+ SAFE_DELETE_ARRAY( pDesc );
+ NumModes = 0;
+ break;
+ }
+
+ }
+
+ if( 0 == NumModes && 0 == f )
+ {
+ // No R8G8B8A8_UNORM_SRGB modes!
+ // Abort the fast-path if we're on it
+ allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof
+ ( allowedAdapterFormatArray[0] );
+ SAFE_DELETE_ARRAY( pDesc );
+ continue;
+ }
+
+ if( SUCCEEDED( hr ) )
+ {
+ for( UINT m = 0; m < NumModes; m++ )
+ {
+ pOutputInfo->displayModeList.Add( pDesc[m] );
+ }
+ }
+
+ SAFE_DELETE_ARRAY( pDesc );
+ }
+
+ return hr;
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT CD3D10Enumeration::EnumerateDevices( CD3D10EnumAdapterInfo* pAdapterInfo )
+{
+ HRESULT hr;
+
+ const D3D10_DRIVER_TYPE devTypeArray[] =
+ {
+ D3D10_DRIVER_TYPE_HARDWARE,
+ D3D10_DRIVER_TYPE_SOFTWARE,
+ D3D10_DRIVER_TYPE_REFERENCE,
+ };
+ const UINT devTypeArrayCount = sizeof( devTypeArray ) / sizeof( devTypeArray[0] );
+
+ // Enumerate each Direct3D device type
+ for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ )
+ {
+ CD3D10EnumDeviceInfo* pDeviceInfo = new CD3D10EnumDeviceInfo;
+ if( pDeviceInfo == NULL )
+ return E_OUTOFMEMORY;
+
+ // Fill struct w/ AdapterOrdinal and D3DX10_DRIVER_TYPE
+ pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal;
+ pDeviceInfo->DeviceType = devTypeArray[iDeviceType];
+
+ // Call D3D10CreateDevice to ensure that this is a D3D10 device.
+ ID3D10Device* pd3dDevice = NULL;
+ IDXGIAdapter* pAdapter = NULL;
+ if( devTypeArray[iDeviceType] == D3D10_DRIVER_TYPE_HARDWARE )
+ pAdapter = pAdapterInfo->m_pAdapter;
+
+ HMODULE wrp = NULL;
+ if (devTypeArray[iDeviceType] == D3D10_DRIVER_TYPE_SOFTWARE) wrp = LoadLibrary(L"D3D10WARP.dll");
+
+ hr = DXUT_Dynamic_D3D10CreateDevice( pAdapter, devTypeArray[iDeviceType], ( HMODULE )wrp, 0, NULL,
+ D3D10_SDK_VERSION, &pd3dDevice );
+ if( FAILED( hr ) )
+ {
+ delete pDeviceInfo;
+ continue;
+ }
+
+ if( devTypeArray[iDeviceType] != D3D10_DRIVER_TYPE_HARDWARE )
+ {
+ IDXGIDevice* pDXGIDev = NULL;
+ hr = pd3dDevice->QueryInterface( __uuidof( IDXGIDevice ), ( LPVOID* )&pDXGIDev );
+ if( SUCCEEDED( hr ) && pDXGIDev )
+ {
+ SAFE_RELEASE( pAdapterInfo->m_pAdapter );
+ pDXGIDev->GetAdapter( &pAdapterInfo->m_pAdapter );
+ }
+ SAFE_RELEASE( pDXGIDev );
+ }
+
+ SAFE_RELEASE( pd3dDevice );
+ pAdapterInfo->deviceInfoList.Add( pDeviceInfo );
+ }
+
+ return S_OK;
+}
+
+HRESULT CD3D10Enumeration::EnumerateDeviceCombosNoAdapter( CD3D10EnumAdapterInfo* pAdapterInfo )
+{
+ // Iterate through each combination of device driver type, output,
+ // adapter format, and backbuffer format to build the adapter's device combo list.
+ //
+
+ for( int device = 0; device < pAdapterInfo->deviceInfoList.GetSize(); ++device )
+ {
+ CD3D10EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( device );
+
+ DXGI_FORMAT BufferFormatArray[] =
+ {
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
+
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R10G10B10A2_UNORM
+ };
+ const UINT BufferFormatArrayCount = sizeof( BufferFormatArray ) / sizeof
+ ( BufferFormatArray[0] );
+
+ // Swap perferred modes for apps running in linear space
+ if( !DXUTIsInGammaCorrectMode() )
+ {
+ BufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
+ BufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ }
+
+ for( UINT iBufferFormat = 0; iBufferFormat < BufferFormatArrayCount; iBufferFormat++ )
+ {
+ DXGI_FORMAT BufferFormat = BufferFormatArray[iBufferFormat];
+
+
+
+ // determine if there are any modes for this particular format
+
+
+ // If an application callback function has been provided, make sure this device
+ // is acceptable to the app.
+
+ if( m_IsD3D10DeviceAcceptableFunc != NULL )
+ {
+ if( !m_IsD3D10DeviceAcceptableFunc( pAdapterInfo->AdapterOrdinal, 0,
+ pDeviceInfo->DeviceType, BufferFormat,
+ TRUE,
+ m_pIsD3D10DeviceAcceptableFuncUserContext ) )
+ continue;
+ }
+ // At this point, we have an adapter/device/backbufferformat/iswindowed
+ // DeviceCombo that is supported by the system. We still
+ // need to find one or more suitable depth/stencil buffer format,
+ // multisample type, and present interval.
+ CD3D10EnumDeviceSettingsCombo* pDeviceCombo = new CD3D10EnumDeviceSettingsCombo;
+ if( pDeviceCombo == NULL )
+ return E_OUTOFMEMORY;
+
+ pDeviceCombo->AdapterOrdinal = pDeviceInfo->AdapterOrdinal;
+ pDeviceCombo->DeviceType = pDeviceInfo->DeviceType;
+ pDeviceCombo->BackBufferFormat = BufferFormat;
+ pDeviceCombo->Windowed = TRUE;
+ pDeviceCombo->Output = 0;
+ pDeviceCombo->pAdapterInfo = pAdapterInfo;
+ pDeviceCombo->pDeviceInfo = pDeviceInfo;
+ pDeviceCombo->pOutputInfo = NULL;
+
+ BuildMultiSampleQualityList( BufferFormat, pDeviceCombo );
+
+ if( FAILED( pAdapterInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) )
+ delete pDeviceCombo;
+ }
+
+ }
+
+
+ return S_OK;
+}
+//--------------------------------------------------------------------------------------
+HRESULT CD3D10Enumeration::EnumerateDeviceCombos( IDXGIFactory* pFactory, CD3D10EnumAdapterInfo* pAdapterInfo )
+{
+ // Iterate through each combination of device driver type, output,
+ // adapter format, and backbuffer format to build the adapter's device combo list.
+ //
+
+ for( int output = 0; output < pAdapterInfo->outputInfoList.GetSize(); ++output )
+ {
+ CD3D10EnumOutputInfo* pOutputInfo = pAdapterInfo->outputInfoList.GetAt( output );
+
+ for( int device = 0; device < pAdapterInfo->deviceInfoList.GetSize(); ++device )
+ {
+ CD3D10EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( device );
+
+ DXGI_FORMAT backBufferFormatArray[] =
+ {
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
+
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R10G10B10A2_UNORM
+ };
+ const UINT backBufferFormatArrayCount = sizeof( backBufferFormatArray ) / sizeof
+ ( backBufferFormatArray[0] );
+
+ // Swap perferred modes for apps running in linear space
+ if( !DXUTIsInGammaCorrectMode() )
+ {
+ backBufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
+ backBufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ }
+
+ for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ )
+ {
+ DXGI_FORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat];
+
+ for( int nWindowed = 0; nWindowed < 2; nWindowed++ )
+ {
+ if( !nWindowed && pOutputInfo->displayModeList.GetSize() == 0 )
+ continue;
+
+ // determine if there are any modes for this particular format
+ UINT iModes = 0;
+ for( int i = 0; i < pOutputInfo->displayModeList.GetSize(); i++ )
+ {
+ if( backBufferFormat == pOutputInfo->displayModeList.GetAt( i ).Format )
+ iModes ++;
+ }
+ if( 0 == iModes )
+ continue;
+
+ // If an application callback function has been provided, make sure this device
+ // is acceptable to the app.
+ if( m_IsD3D10DeviceAcceptableFunc != NULL )
+ {
+ if( !m_IsD3D10DeviceAcceptableFunc( pAdapterInfo->AdapterOrdinal, output,
+ pDeviceInfo->DeviceType, backBufferFormat,
+ FALSE != nWindowed,
+ m_pIsD3D10DeviceAcceptableFuncUserContext ) )
+ continue;
+ }
+
+ // At this point, we have an adapter/device/backbufferformat/iswindowed
+ // DeviceCombo that is supported by the system. We still
+ // need to find one or more suitable depth/stencil buffer format,
+ // multisample type, and present interval.
+ CD3D10EnumDeviceSettingsCombo* pDeviceCombo = new CD3D10EnumDeviceSettingsCombo;
+ if( pDeviceCombo == NULL )
+ return E_OUTOFMEMORY;
+
+ pDeviceCombo->AdapterOrdinal = pDeviceInfo->AdapterOrdinal;
+ pDeviceCombo->DeviceType = pDeviceInfo->DeviceType;
+ pDeviceCombo->BackBufferFormat = backBufferFormat;
+ pDeviceCombo->Windowed = ( nWindowed != 0 );
+ pDeviceCombo->Output = pOutputInfo->Output;
+ pDeviceCombo->pAdapterInfo = pAdapterInfo;
+ pDeviceCombo->pDeviceInfo = pDeviceInfo;
+ pDeviceCombo->pOutputInfo = pOutputInfo;
+
+ BuildMultiSampleQualityList( backBufferFormat, pDeviceCombo );
+
+ if( FAILED( pAdapterInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) )
+ delete pDeviceCombo;
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Release all the allocated CD3D10EnumAdapterInfo objects and empty the list
+//--------------------------------------------------------------------------------------
+void CD3D10Enumeration::ClearAdapterInfoList()
+{
+ CD3D10EnumAdapterInfo* pAdapterInfo;
+ for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
+ {
+ pAdapterInfo = m_AdapterInfoList.GetAt( i );
+ delete pAdapterInfo;
+ }
+
+ m_AdapterInfoList.RemoveAll();
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D10Enumeration::ResetPossibleDepthStencilFormats()
+{
+ m_DepthStencilPossibleList.RemoveAll();
+ m_DepthStencilPossibleList.Add( DXGI_FORMAT_D32_FLOAT_S8X24_UINT );
+ m_DepthStencilPossibleList.Add( DXGI_FORMAT_D32_FLOAT );
+ m_DepthStencilPossibleList.Add( DXGI_FORMAT_D24_UNORM_S8_UINT );
+ m_DepthStencilPossibleList.Add( DXGI_FORMAT_D16_UNORM );
+}
+
+//--------------------------------------------------------------------------------------
+void CD3D10Enumeration::SetEnumerateAllAdapterFormats( bool bEnumerateAllAdapterFormats, bool bEnumerateNow )
+{
+ m_bEnumerateAllAdapterFormats = bEnumerateAllAdapterFormats;
+
+ if( bEnumerateNow )
+ {
+ LPDXUTCALLBACKISD3D10DEVICEACCEPTABLE pCallbackIsDeviceAcceptable;
+ void* pUserContext;
+ DXUTGetCallbackD3D10DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext );
+ g_pDXUTD3D10Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext );
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+void CD3D10Enumeration::BuildMultiSampleQualityList( DXGI_FORMAT fmt, CD3D10EnumDeviceSettingsCombo* pDeviceCombo )
+{
+ ID3D10Device* pd3dDevice = NULL;
+ IDXGIAdapter* pAdapter = NULL;
+ if( pDeviceCombo->DeviceType == D3D10_DRIVER_TYPE_HARDWARE )
+ DXUTGetDXGIFactory()->EnumAdapters( pDeviceCombo->pAdapterInfo->AdapterOrdinal, &pAdapter );
+
+ if( FAILED( DXUT_Dynamic_D3D10CreateDevice( pAdapter, pDeviceCombo->DeviceType, ( HMODULE )0, 0, NULL,
+ D3D10_SDK_VERSION, &pd3dDevice ) ) )
+ return;
+
+ for( int i = 1; i <= D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT; ++i )
+ {
+ UINT Quality;
+ if( SUCCEEDED( pd3dDevice->CheckMultisampleQualityLevels( fmt, i, &Quality ) ) && Quality > 0 )
+ {
+ pDeviceCombo->multiSampleCountList.Add( i );
+ pDeviceCombo->multiSampleQualityList.Add( Quality );
+ }
+ }
+
+ SAFE_RELEASE( pAdapter );
+ SAFE_RELEASE( pd3dDevice );
+}
+
+
+//--------------------------------------------------------------------------------------
+// Call GetAdapterInfoList() after Enumerate() to get a STL vector of
+// CD3D10EnumAdapterInfo*
+//--------------------------------------------------------------------------------------
+CGrowableArray <CD3D10EnumAdapterInfo*>* CD3D10Enumeration::GetAdapterInfoList()
+{
+ return &m_AdapterInfoList;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10EnumAdapterInfo* CD3D10Enumeration::GetAdapterInfo( UINT AdapterOrdinal )
+{
+ for( int iAdapter = 0; iAdapter < m_AdapterInfoList.GetSize(); iAdapter++ )
+ {
+ CD3D10EnumAdapterInfo* pAdapterInfo = m_AdapterInfoList.GetAt( iAdapter );
+ if( pAdapterInfo->AdapterOrdinal == AdapterOrdinal )
+ return pAdapterInfo;
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10EnumDeviceInfo* CD3D10Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3D10_DRIVER_TYPE DeviceType )
+{
+ CD3D10EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
+ if( pAdapterInfo )
+ {
+ for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ )
+ {
+ CD3D10EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo );
+ if( pDeviceInfo->DeviceType == DeviceType )
+ return pDeviceInfo;
+ }
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10EnumOutputInfo* CD3D10Enumeration::GetOutputInfo( UINT AdapterOrdinal, UINT Output )
+{
+ CD3D10EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
+ if( pAdapterInfo && pAdapterInfo->outputInfoList.GetSize() > int( Output ) )
+ {
+ return pAdapterInfo->outputInfoList.GetAt( Output );
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10EnumDeviceSettingsCombo* CD3D10Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal,
+ D3D10_DRIVER_TYPE DeviceType, UINT Output,
+ DXGI_FORMAT BackBufferFormat, BOOL Windowed )
+{
+ CD3D10EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
+ if( pAdapterInfo )
+ {
+ for( int iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ )
+ {
+ CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList.GetAt(
+ iDeviceCombo );
+ if( pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat &&
+ pDeviceSettingsCombo->Windowed == Windowed )
+ return pDeviceSettingsCombo;
+ }
+ }
+
+ return NULL;
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10EnumOutputInfo::~CD3D10EnumOutputInfo( void )
+{
+ SAFE_RELEASE( m_pOutput );
+ displayModeList.RemoveAll();
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10EnumDeviceInfo::~CD3D10EnumDeviceInfo()
+{
+}
+
+
+//--------------------------------------------------------------------------------------
+CD3D10EnumAdapterInfo::~CD3D10EnumAdapterInfo( void )
+{
+ for( int i = 0; i < outputInfoList.GetSize(); i++ )
+ {
+ CD3D10EnumOutputInfo* pOutputInfo = outputInfoList.GetAt( i );
+ delete pOutputInfo;
+ }
+ outputInfoList.RemoveAll();
+
+ for( int i = 0; i < deviceInfoList.GetSize(); ++i )
+ {
+ CD3D10EnumDeviceInfo* pDeviceInfo = deviceInfoList.GetAt( i );
+ delete pDeviceInfo;
+ }
+ deviceInfoList.RemoveAll();
+
+ for( int i = 0; i < deviceSettingsComboList.GetSize(); ++i )
+ {
+ CD3D10EnumDeviceSettingsCombo* pDeviceCombo = deviceSettingsComboList.GetAt( i );
+ delete pDeviceCombo;
+ }
+ deviceSettingsComboList.RemoveAll();
+
+ SAFE_RELEASE( m_pAdapter );
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns the number of color channel bits in the specified DXGI_FORMAT
+//--------------------------------------------------------------------------------------
+UINT WINAPI DXUTGetDXGIColorChannelBits( DXGI_FORMAT fmt )
+{
+ switch( fmt )
+ {
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return 32;
+
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ return 16;
+
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ return 10;
+
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ return 8;
+
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return 5;
+
+ default:
+ return 0;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+HRESULT DXUTFindValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOut, DXUTD3D10DeviceSettings* pIn,
+ DXUTMatchOptions* pMatchOptions, DXUTD3D10DeviceSettings* pOptimal )
+{
+ // Find the best combination of:
+ // Adapter Ordinal
+ // Device Type
+ // Back Buffer Format
+ // Windowed
+ // given what's available on the system and the match options combined with the device settings input.
+ // This combination of settings is encapsulated by the CD3D10EnumDeviceSettingsCombo class.
+ float fBestRanking = -1.0f;
+ CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo = NULL;
+ DXGI_MODE_DESC adapterDisplayMode;
+
+ CD3D10Enumeration* pd3dEnum = DXUTGetD3D10Enumeration();
+ CGrowableArray <CD3D10EnumAdapterInfo*>* pAdapterList = pd3dEnum->GetAdapterInfoList();
+ for( int iAdapter = 0; iAdapter < pAdapterList->GetSize(); iAdapter++ )
+ {
+ CD3D10EnumAdapterInfo* pAdapterInfo = pAdapterList->GetAt( iAdapter );
+
+ // Get the desktop display mode of adapter
+ DXUTGetD3D10AdapterDisplayMode( pAdapterInfo->AdapterOrdinal, 0, &adapterDisplayMode );
+
+ // Enum all the device settings combinations. A device settings combination is
+ // a unique set of an adapter format, back buffer format, and IsWindowed.
+ for( int iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ )
+ {
+ CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList.GetAt(
+ iDeviceCombo );
+
+ // Skip any combo that doesn't meet the preserve match options
+ if( false == DXUTDoesD3D10DeviceComboMatchPreserveOptions( pDeviceSettingsCombo, pIn, pMatchOptions ) )
+ continue;
+
+ // Get a ranking number that describes how closely this device combo matches the optimal combo
+ float fCurRanking = DXUTRankD3D10DeviceCombo( pDeviceSettingsCombo, pOptimal, &adapterDisplayMode );
+
+ // If this combo better matches the input device settings then save it
+ if( fCurRanking > fBestRanking )
+ {
+ pBestDeviceSettingsCombo = pDeviceSettingsCombo;
+ fBestRanking = fCurRanking;
+ }
+ }
+ }
+
+ // If no best device combination was found then fail
+ if( pBestDeviceSettingsCombo == NULL )
+ return DXUTERR_NOCOMPATIBLEDEVICES;
+
+ // Using the best device settings combo found, build valid device settings taking heed of
+ // the match options and the input device settings
+ DXUTD3D10DeviceSettings validDeviceSettings;
+ DXUTBuildValidD3D10DeviceSettings( &validDeviceSettings, pBestDeviceSettingsCombo, pIn, pMatchOptions );
+ *pOut = validDeviceSettings;
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Internal helper function to build a D3D10 device settings structure based upon the match
+// options. If the match option is set to ignore, then a optimal default value is used.
+// The default value may not exist on the system, but later this will be taken
+// into account.
+//--------------------------------------------------------------------------------------
+void DXUTBuildOptimalD3D10DeviceSettings( DXUTD3D10DeviceSettings* pOptimalDeviceSettings,
+ DXUTD3D10DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions )
+{
+ ZeroMemory( pOptimalDeviceSettings, sizeof( DXUTD3D10DeviceSettings ) );
+
+ // Retrieve the desktop display mode.
+ DXGI_MODE_DESC adapterDesktopDisplayMode = { 640, 480, { 0, 0 }, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB };
+ DXUTGetD3D10AdapterDisplayMode( pOptimalDeviceSettings->AdapterOrdinal, 0, &adapterDesktopDisplayMode );
+
+ //---------------------
+ // Adapter ordinal
+ //---------------------
+ if( pMatchOptions->eAdapterOrdinal == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->AdapterOrdinal = 0;
+ else
+ pOptimalDeviceSettings->AdapterOrdinal = pDeviceSettingsIn->AdapterOrdinal;
+
+ //---------------------
+ // Device type
+ //---------------------
+ if( pMatchOptions->eDeviceType == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->DriverType = D3D10_DRIVER_TYPE_HARDWARE;
+ else
+ pOptimalDeviceSettings->DriverType = pDeviceSettingsIn->DriverType;
+
+ //---------------------
+ // Windowed
+ //---------------------
+ if( pMatchOptions->eWindowed == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->sd.Windowed = TRUE;
+ else
+ pOptimalDeviceSettings->sd.Windowed = pDeviceSettingsIn->sd.Windowed;
+
+ //---------------------
+ // Output #
+ //---------------------
+ if( pMatchOptions->eOutput == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->Output = 0;
+ else
+ pOptimalDeviceSettings->Output = pDeviceSettingsIn->Output;
+
+ //---------------------
+ // Create flags
+ //---------------------
+ pOptimalDeviceSettings->CreateFlags = pDeviceSettingsIn->CreateFlags;
+
+ //---------------------
+ // Resolution
+ //---------------------
+ if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT )
+ {
+ // If windowed, default to 640x480
+ // If fullscreen, default to the desktop res for quick mode change
+ if( pOptimalDeviceSettings->sd.Windowed )
+ {
+ pOptimalDeviceSettings->sd.BufferDesc.Width = 640;
+ pOptimalDeviceSettings->sd.BufferDesc.Height = 480;
+ }
+ else
+ {
+ pOptimalDeviceSettings->sd.BufferDesc.Width = adapterDesktopDisplayMode.Width;
+ pOptimalDeviceSettings->sd.BufferDesc.Height = adapterDesktopDisplayMode.Height;
+ }
+ }
+ else
+ {
+ pOptimalDeviceSettings->sd.BufferDesc.Width = pDeviceSettingsIn->sd.BufferDesc.Width;
+ pOptimalDeviceSettings->sd.BufferDesc.Height = pDeviceSettingsIn->sd.BufferDesc.Height;
+ }
+
+ //---------------------
+ // Back buffer format
+ //---------------------
+ if( pMatchOptions->eBackBufferFormat == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->sd.BufferDesc.Format = adapterDesktopDisplayMode.Format; // Default to match the adapter format
+ else
+ pOptimalDeviceSettings->sd.BufferDesc.Format = pDeviceSettingsIn->sd.BufferDesc.Format;
+
+ //---------------------
+ // Back buffer usage
+ //---------------------
+ pOptimalDeviceSettings->sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->sd.BufferCount = 2; // Default to triple buffering for perf gain
+ else
+ pOptimalDeviceSettings->sd.BufferCount = pDeviceSettingsIn->sd.BufferCount;
+
+ //---------------------
+ // Multisample
+ //---------------------
+ if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT )
+ {
+ // Default to no multisampling
+ pOptimalDeviceSettings->sd.SampleDesc.Count = 0;
+ pOptimalDeviceSettings->sd.SampleDesc.Quality = 0;
+ }
+ else
+ {
+ pOptimalDeviceSettings->sd.SampleDesc.Count = pDeviceSettingsIn->sd.SampleDesc.Count;
+ pOptimalDeviceSettings->sd.SampleDesc.Quality = pDeviceSettingsIn->sd.SampleDesc.Quality;
+ }
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ else
+ pOptimalDeviceSettings->sd.SwapEffect = pDeviceSettingsIn->sd.SwapEffect;
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT &&
+ pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT )
+ {
+ pOptimalDeviceSettings->AutoCreateDepthStencil = TRUE;
+ pOptimalDeviceSettings->AutoDepthStencilFormat = DXGI_FORMAT_D32_FLOAT;
+ }
+ else
+ {
+ pOptimalDeviceSettings->AutoCreateDepthStencil = pDeviceSettingsIn->AutoCreateDepthStencil;
+ pOptimalDeviceSettings->AutoDepthStencilFormat = pDeviceSettingsIn->AutoDepthStencilFormat;
+ }
+
+ //---------------------
+ // Present flags
+ //---------------------
+ if( pMatchOptions->ePresentFlags == DXUTMT_IGNORE_INPUT )
+ pOptimalDeviceSettings->PresentFlags = 0;
+ else
+ pOptimalDeviceSettings->PresentFlags = pDeviceSettingsIn->PresentFlags;
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT )
+ {
+ pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator = 0;
+ pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator = 0;
+ }
+ else
+ pOptimalDeviceSettings->sd.BufferDesc.RefreshRate = pDeviceSettingsIn->sd.BufferDesc.RefreshRate;
+
+ //---------------------
+ // Present interval
+ //---------------------
+ if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT )
+ {
+ // For windowed and fullscreen, default to 1 which will
+ // wait for the vertical retrace period to prevent tearing.
+ // For benchmarking, use 0 which will not wait for the
+ // vertical retrace period but may introduce tearing.
+ pOptimalDeviceSettings->SyncInterval = 1;
+ }
+ else
+ {
+ pOptimalDeviceSettings->SyncInterval = pDeviceSettingsIn->SyncInterval;
+ }
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns false for any CD3D9EnumDeviceSettingsCombo that doesn't meet the preserve
+// match options against the input pDeviceSettingsIn.
+//--------------------------------------------------------------------------------------
+bool DXUTDoesD3D10DeviceComboMatchPreserveOptions( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D10DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions )
+{
+ //---------------------
+ // Adapter ordinal
+ //---------------------
+ if( pMatchOptions->eAdapterOrdinal == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->AdapterOrdinal != pDeviceSettingsIn->AdapterOrdinal ) )
+ return false;
+
+ //---------------------
+ // Device type
+ //---------------------
+ if( pMatchOptions->eDeviceType == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->DeviceType != pDeviceSettingsIn->DriverType ) )
+ return false;
+
+ //---------------------
+ // Windowed
+ //---------------------
+ if( pMatchOptions->eWindowed == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->Windowed != pDeviceSettingsIn->sd.Windowed ) )
+ return false;
+
+ //---------------------
+ // Output
+ //---------------------
+ if( pMatchOptions->eOutput == DXUTMT_PRESERVE_INPUT &&
+ ( pDeviceSettingsCombo->Output != pDeviceSettingsIn->Output ) )
+ return false;
+
+ //---------------------
+ // Resolution
+ //---------------------
+ // If keep resolution then check that width and height supported by this combo
+ if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT )
+ {
+ bool bFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); i++ )
+ {
+ DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( i );
+ if( displayMode.Width == pDeviceSettingsIn->sd.BufferDesc.Width &&
+ displayMode.Height == pDeviceSettingsIn->sd.BufferDesc.Height )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ // If the width and height are not supported by this combo, return false
+ if( !bFound )
+ return false;
+ }
+
+ //---------------------
+ // Back buffer format
+ //---------------------
+ if( pMatchOptions->eBackBufferFormat == DXUTMT_PRESERVE_INPUT &&
+ pDeviceSettingsCombo->BackBufferFormat != pDeviceSettingsIn->sd.BufferDesc.Format )
+ return false;
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ // No caps for the back buffer count
+
+ //---------------------
+ // Multisample
+ //---------------------
+ if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT )
+ {
+ bool bFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->multiSampleCountList.GetSize(); i++ )
+ {
+ UINT Count = pDeviceSettingsCombo->multiSampleCountList.GetAt( i );
+ UINT Quality = pDeviceSettingsCombo->multiSampleQualityList.GetAt( i );
+
+ if( Count == pDeviceSettingsIn->sd.SampleDesc.Count &&
+ Quality > pDeviceSettingsIn->sd.SampleDesc.Quality )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ // If multisample type/quality not supported by this combo, then return false
+ if( !bFound )
+ return false;
+ }
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ // No caps for swap effects
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ // No caps for depth stencil
+
+ //---------------------
+ // Present flags
+ //---------------------
+ // No caps for the present flags
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ // If keep refresh rate then check that the resolution is supported by this combo
+ if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT )
+ {
+ bool bFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); i++ )
+ {
+ DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( i );
+ float fDenom1 = 1;
+ float fDenom2 = 1;
+
+ if( displayMode.RefreshRate.Denominator )
+ fDenom1 = (float)displayMode.RefreshRate.Denominator;
+ if( pDeviceSettingsIn->sd.BufferDesc.RefreshRate.Denominator )
+ fDenom2 = (float)pDeviceSettingsIn->sd.BufferDesc.RefreshRate.Denominator;
+
+ if( fabs( float( displayMode.RefreshRate.Numerator ) / fDenom1 -
+ float( pDeviceSettingsIn->sd.BufferDesc.RefreshRate.Numerator ) / fDenom2 ) < 0.1f )
+ {
+ bFound = true;
+ break;
+ }
+ }
+
+ // If refresh rate not supported by this combo, then return false
+ if( !bFound )
+ return false;
+ }
+
+ //---------------------
+ // Present interval
+ //---------------------
+ // No caps for present interval
+
+ return true;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns a ranking number that describes how closely this device
+// combo matches the optimal combo based on the match options and the optimal device settings
+//--------------------------------------------------------------------------------------
+float DXUTRankD3D10DeviceCombo( CD3D10EnumDeviceSettingsCombo* pDeviceSettingsCombo,
+ DXUTD3D10DeviceSettings* pOptimalDeviceSettings,
+ DXGI_MODE_DESC* pAdapterDisplayMode )
+{
+ float fCurRanking = 0.0f;
+
+ // Arbitrary weights. Gives preference to the ordinal, device type, and windowed
+ const float fAdapterOrdinalWeight = 1000.0f;
+ const float fAdapterOutputWeight = 500.0f;
+ const float fDeviceTypeWeight = 100.0f;
+ const float fWindowWeight = 10.0f;
+ const float fResolutionWeight = 1.0f;
+ const float fBackBufferFormatWeight = 1.0f;
+ const float fMultiSampleWeight = 1.0f;
+ const float fRefreshRateWeight = 1.0f;
+
+ //---------------------
+ // Adapter ordinal
+ //---------------------
+ if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal )
+ fCurRanking += fAdapterOrdinalWeight;
+
+ //---------------------
+ // Adapter ordinal
+ //---------------------
+ if( pDeviceSettingsCombo->Output == pOptimalDeviceSettings->Output )
+ fCurRanking += fAdapterOutputWeight;
+
+ //---------------------
+ // Device type
+ //---------------------
+ if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DriverType )
+ fCurRanking += fDeviceTypeWeight;
+ // Slightly prefer HAL
+ if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL )
+ fCurRanking += 0.1f;
+
+ //---------------------
+ // Windowed
+ //---------------------
+ if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->sd.Windowed )
+ fCurRanking += fWindowWeight;
+
+ //---------------------
+ // Resolution
+ //---------------------
+ bool bResolutionFound = false;
+ if (pDeviceSettingsCombo->pOutputInfo != NULL) {
+ for( int idm = 0; idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); idm++ )
+ {
+ DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm );
+ if( displayMode.Width == pOptimalDeviceSettings->sd.BufferDesc.Width &&
+ displayMode.Height == pOptimalDeviceSettings->sd.BufferDesc.Height )
+ bResolutionFound = true;
+ }
+ }
+ if( bResolutionFound )
+ fCurRanking += fResolutionWeight;
+
+ //---------------------
+ // Back buffer format
+ //---------------------
+ if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->sd.BufferDesc.Format )
+ {
+ fCurRanking += fBackBufferFormatWeight;
+ }
+ else
+ {
+ int nBitDepthDelta = abs( ( long )DXUTGetDXGIColorChannelBits( pDeviceSettingsCombo->BackBufferFormat ) -
+ ( long )DXUTGetDXGIColorChannelBits(
+ pOptimalDeviceSettings->sd.BufferDesc.Format ) );
+ float fScale = __max( 0.9f - ( float )nBitDepthDelta * 0.2f, 0.0f );
+ fCurRanking += fScale * fBackBufferFormatWeight;
+ }
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ // No caps for the back buffer count
+
+ //---------------------
+ // Multisample
+ //---------------------
+ bool bMultiSampleFound = false;
+ for( int i = 0; i < pDeviceSettingsCombo->multiSampleCountList.GetSize(); i++ )
+ {
+ UINT Count = pDeviceSettingsCombo->multiSampleCountList.GetAt( i );
+ UINT Quality = pDeviceSettingsCombo->multiSampleQualityList.GetAt( i );
+
+ if( Count == pOptimalDeviceSettings->sd.SampleDesc.Count &&
+ Quality > pOptimalDeviceSettings->sd.SampleDesc.Quality )
+ {
+ bMultiSampleFound = true;
+ break;
+ }
+ }
+ if( bMultiSampleFound )
+ fCurRanking += fMultiSampleWeight;
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ // No caps for swap effects
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ // No caps for swap effects
+
+ //---------------------
+ // Present flags
+ //---------------------
+ // No caps for the present flags
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ bool bRefreshFound = false;
+ if ( pDeviceSettingsCombo->pOutputInfo != NULL ) {
+ for( int idm = 0; idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); idm++ )
+ {
+ DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm );
+ float fDenom1 = 1;
+ float fDenom2 = 1;
+
+ if( displayMode.RefreshRate.Denominator )
+ fDenom1 = (float)displayMode.RefreshRate.Denominator;
+
+ if( pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator )
+ fDenom2 = (float)pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator;
+
+ if( fabs( float( displayMode.RefreshRate.Numerator ) / fDenom1 -
+ float( pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator ) / fDenom2 ) < 0.1f )
+ bRefreshFound = true;
+ }
+ }
+ if( bRefreshFound )
+ fCurRanking += fRefreshRateWeight;
+
+ //---------------------
+ // Present interval
+ //---------------------
+ // No caps for the present flags
+
+ return fCurRanking;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Builds valid device settings using the match options, the input device settings, and the
+// best device settings combo found.
+//--------------------------------------------------------------------------------------
+void DXUTBuildValidD3D10DeviceSettings( DXUTD3D10DeviceSettings* pValidDeviceSettings,
+ CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ DXUTD3D10DeviceSettings* pDeviceSettingsIn,
+ DXUTMatchOptions* pMatchOptions )
+{
+ DXGI_MODE_DESC adapterDisplayMode;
+ DXUTGetD3D10AdapterDisplayMode( pBestDeviceSettingsCombo->AdapterOrdinal,
+ pBestDeviceSettingsCombo->Output, &adapterDisplayMode );
+
+ // For each setting pick the best, taking into account the match options and
+ // what's supported by the device
+
+ //---------------------
+ // Adapter Ordinal
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->AdapterOrdinal
+
+ //---------------------
+ // Device Type
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->DeviceType
+
+ //---------------------
+ // Windowed
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->Windowed
+
+ //---------------------
+ // Output
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->Output
+
+ //---------------------
+ // Resolution
+ //---------------------
+ DXGI_MODE_DESC bestDisplayMode;
+ if( pMatchOptions->eResolution == DXUTMT_PRESERVE_INPUT )
+ {
+ bestDisplayMode.Width = pDeviceSettingsIn->sd.BufferDesc.Width;
+ bestDisplayMode.Height = pDeviceSettingsIn->sd.BufferDesc.Height;
+ }
+ else
+ {
+ DXGI_MODE_DESC displayModeIn;
+ if( pMatchOptions->eResolution == DXUTMT_CLOSEST_TO_INPUT &&
+ pDeviceSettingsIn )
+ {
+ displayModeIn.Width = pDeviceSettingsIn->sd.BufferDesc.Width;
+ displayModeIn.Height = pDeviceSettingsIn->sd.BufferDesc.Height;
+ }
+ else // if( pMatchOptions->eResolution == DXUTMT_IGNORE_INPUT )
+ {
+ if( pBestDeviceSettingsCombo->Windowed )
+ {
+ // The framework defaults to 640x480 for windowed
+ displayModeIn.Width = 640;
+ displayModeIn.Height = 480;
+ }
+ else
+ {
+ // The framework defaults to desktop resolution for fullscreen to try to avoid slow mode change
+ displayModeIn.Width = adapterDisplayMode.Width;
+ displayModeIn.Height = adapterDisplayMode.Height;
+ }
+ }
+
+ // Call a helper function to find the closest valid display mode to the optimal
+ DXUTFindValidD3D10Resolution( pBestDeviceSettingsCombo, displayModeIn, &bestDisplayMode );
+ }
+
+ //---------------------
+ // Back Buffer Format
+ //---------------------
+ // Just using pBestDeviceSettingsCombo->BackBufferFormat
+
+ //---------------------
+ // Back Buffer usage
+ //---------------------
+ // Just using pDeviceSettingsIn->sd.BackBufferUsage | DXGI_USAGE_RENDERTARGETOUTPUT
+
+ //---------------------
+ // Back buffer count
+ //---------------------
+ UINT bestBackBufferCount;
+ if( pMatchOptions->eBackBufferCount == DXUTMT_PRESERVE_INPUT )
+ {
+ bestBackBufferCount = pDeviceSettingsIn->sd.BufferCount;
+ }
+ else if( pMatchOptions->eBackBufferCount == DXUTMT_IGNORE_INPUT )
+ {
+ // The framework defaults to triple buffering
+ bestBackBufferCount = 2;
+ }
+ else // if( pMatchOptions->eBackBufferCount == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ bestBackBufferCount = pDeviceSettingsIn->sd.BufferCount;
+ if( bestBackBufferCount > 3 )
+ bestBackBufferCount = 3;
+ if( bestBackBufferCount < 1 )
+ bestBackBufferCount = 1;
+ }
+
+ //---------------------
+ // Multisample
+ //---------------------
+ UINT bestMultiSampleCount;
+ UINT bestMultiSampleQuality;
+ if( pDeviceSettingsIn && pDeviceSettingsIn->sd.SwapEffect != DXGI_SWAP_EFFECT_DISCARD )
+ {
+ // Swap effect is not set to discard so multisampling has to off
+ bestMultiSampleCount = 1;
+ bestMultiSampleQuality = 0;
+ }
+ else
+ {
+ if( pMatchOptions->eMultiSample == DXUTMT_PRESERVE_INPUT )
+ {
+ bestMultiSampleCount = pDeviceSettingsIn->sd.SampleDesc.Count;
+ bestMultiSampleQuality = pDeviceSettingsIn->sd.SampleDesc.Quality;
+ }
+ else if( pMatchOptions->eMultiSample == DXUTMT_IGNORE_INPUT )
+ {
+ // Default to no multisampling (always supported)
+ bestMultiSampleCount = 1;
+ bestMultiSampleQuality = 0;
+ }
+ else if( pMatchOptions->eMultiSample == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ // Default to no multisampling (always supported)
+ bestMultiSampleCount = 1;
+ bestMultiSampleQuality = 0;
+
+ for( int i = 0; i < pBestDeviceSettingsCombo->multiSampleCountList.GetSize(); i++ )
+ {
+ UINT Count = pBestDeviceSettingsCombo->multiSampleCountList.GetAt( i );
+ UINT Quality = pBestDeviceSettingsCombo->multiSampleQualityList.GetAt( i );
+
+ // Check whether supported type is closer to the input than our current best
+ if( labs( Count - pDeviceSettingsIn->sd.SampleDesc.Count ) < labs( bestMultiSampleCount -
+ pDeviceSettingsIn->sd.SampleDesc.Count ) )
+ {
+ bestMultiSampleCount = Count;
+ bestMultiSampleQuality = __min( Quality - 1, pDeviceSettingsIn->sd.SampleDesc.Quality );
+ }
+ }
+ }
+ else
+ {
+ // Error case
+ bestMultiSampleCount = 1;
+ bestMultiSampleQuality = 0;
+ }
+ }
+
+ //---------------------
+ // Swap effect
+ //---------------------
+ DXGI_SWAP_EFFECT bestSwapEffect;
+ if( pMatchOptions->eSwapEffect == DXUTMT_PRESERVE_INPUT )
+ {
+ bestSwapEffect = pDeviceSettingsIn->sd.SwapEffect;
+ }
+ else if( pMatchOptions->eSwapEffect == DXUTMT_IGNORE_INPUT )
+ {
+ bestSwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ }
+ else // if( pMatchOptions->eSwapEffect == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ bestSwapEffect = pDeviceSettingsIn->sd.SwapEffect;
+
+ // Swap effect has to be one of these 2
+ if( bestSwapEffect != DXGI_SWAP_EFFECT_DISCARD &&
+ bestSwapEffect != DXGI_SWAP_EFFECT_SEQUENTIAL )
+ {
+ bestSwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+ }
+ }
+
+ //---------------------
+ // Depth stencil
+ //---------------------
+ DXGI_FORMAT bestDepthStencilFormat;
+ bool bestEnableAutoDepthStencil;
+
+ if( pMatchOptions->eDepthFormat == DXUTMT_IGNORE_INPUT &&
+ pMatchOptions->eStencilFormat == DXUTMT_IGNORE_INPUT )
+ {
+ bestEnableAutoDepthStencil = true;
+ bestDepthStencilFormat = DXGI_FORMAT_D32_FLOAT;
+ }
+ else
+ {
+ bestEnableAutoDepthStencil = pDeviceSettingsIn->AutoCreateDepthStencil;
+ bestDepthStencilFormat = pDeviceSettingsIn->AutoDepthStencilFormat;
+ }
+
+ //---------------------
+ // Present flags
+ //---------------------
+
+ //---------------------
+ // Refresh rate
+ //---------------------
+ if( pBestDeviceSettingsCombo->Windowed )
+ {
+ // Must be 0 for windowed
+ bestDisplayMode.RefreshRate.Numerator = 0;
+ bestDisplayMode.RefreshRate.Denominator = 0;
+ }
+ else
+ {
+ if( pMatchOptions->eRefreshRate == DXUTMT_PRESERVE_INPUT )
+ {
+ bestDisplayMode.RefreshRate = pDeviceSettingsIn->sd.BufferDesc.RefreshRate;
+ }
+ else
+ {
+ DXGI_RATIONAL refreshRateMatch;
+ if( pMatchOptions->eRefreshRate == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ refreshRateMatch = pDeviceSettingsIn->sd.BufferDesc.RefreshRate;
+ }
+ else // if( pMatchOptions->eRefreshRate == DXUTMT_IGNORE_INPUT )
+ {
+ refreshRateMatch = adapterDisplayMode.RefreshRate;
+ }
+
+ // Default to 0 in case no matching mode is found.
+ // 0, in this case means that we'll let DXGI choose the best one for us
+ bestDisplayMode.RefreshRate.Numerator = 0;
+ bestDisplayMode.RefreshRate.Denominator = 0;
+
+ // if( refreshRateMatch != 0 )
+ {
+ float fBestRefreshRanking = 100000.0f;
+ CGrowableArray <DXGI_MODE_DESC>* pDisplayModeList =
+ &pBestDeviceSettingsCombo->pOutputInfo->displayModeList;
+ for( int iDisplayMode = 0; iDisplayMode < pDisplayModeList->GetSize(); iDisplayMode++ )
+ {
+ DXGI_MODE_DESC displayMode = pDisplayModeList->GetAt( iDisplayMode );
+ if( displayMode.Height != bestDisplayMode.Height ||
+ displayMode.Width != bestDisplayMode.Width )
+ continue; // Skip display modes that don't match
+
+ // Find the delta between the current refresh rate and the optimal refresh rate
+ float fDenom1 = 1;
+ float fDenom2 = 1;
+ if( displayMode.RefreshRate.Denominator )
+ fDenom1 = (float)displayMode.RefreshRate.Denominator;
+ if( refreshRateMatch.Denominator )
+ fDenom2 = (float)refreshRateMatch.Denominator;
+
+ float fCurRanking = abs( float( displayMode.RefreshRate.Numerator ) / fDenom1 -
+ float( refreshRateMatch.Numerator ) / fDenom2 );
+
+ if( fCurRanking < fBestRefreshRanking )
+ {
+ bestDisplayMode.RefreshRate = displayMode.RefreshRate;
+ fBestRefreshRanking = fCurRanking;
+
+ // Stop if good-enough match found
+ if( fBestRefreshRanking < 0.1f )
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //---------------------
+ // Present interval
+ //---------------------
+ UINT32 bestPresentInterval;
+ if( pMatchOptions->ePresentInterval == DXUTMT_PRESERVE_INPUT )
+ {
+ bestPresentInterval = pDeviceSettingsIn->SyncInterval;
+ }
+ else if( pMatchOptions->ePresentInterval == DXUTMT_IGNORE_INPUT )
+ {
+ // For windowed and fullscreen, default to 1 which will wait for
+ // the vertical retrace period to prevent tearing. For benchmarking,
+ // use 0 which will will wait not for the vertical retrace period
+ // but may introduce tearing.
+
+ // The reference driver does not support v-syncing and will
+ // produce _com_error exceptions when the sync interval is
+ // anything but 0.
+ bestPresentInterval = ( D3D10_DRIVER_TYPE_REFERENCE == pBestDeviceSettingsCombo->DeviceType ) ? 0 : 1;
+ }
+ else // if( pMatchOptions->ePresentInterval == DXUTMT_CLOSEST_TO_INPUT )
+ {
+ bestPresentInterval = pDeviceSettingsIn->SyncInterval;
+ }
+
+ // Fill the device settings struct
+ ZeroMemory( pValidDeviceSettings, sizeof( DXUTD3D10DeviceSettings ) );
+ pValidDeviceSettings->AdapterOrdinal = pBestDeviceSettingsCombo->AdapterOrdinal;
+ pValidDeviceSettings->Output = pBestDeviceSettingsCombo->Output;
+ pValidDeviceSettings->DriverType = pBestDeviceSettingsCombo->DeviceType;
+ pValidDeviceSettings->sd.BufferDesc.Width = bestDisplayMode.Width;
+ pValidDeviceSettings->sd.BufferDesc.Height = bestDisplayMode.Height;
+ pValidDeviceSettings->sd.BufferDesc.Format = pBestDeviceSettingsCombo->BackBufferFormat;
+ pValidDeviceSettings->sd.BufferUsage = pDeviceSettingsIn->sd.BufferUsage | DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ pValidDeviceSettings->sd.BufferCount = bestBackBufferCount;
+ pValidDeviceSettings->sd.SampleDesc.Count = bestMultiSampleCount;
+ pValidDeviceSettings->sd.SampleDesc.Quality = bestMultiSampleQuality;
+ pValidDeviceSettings->sd.SwapEffect = bestSwapEffect;
+ pValidDeviceSettings->sd.OutputWindow = pBestDeviceSettingsCombo->Windowed ? DXUTGetHWNDDeviceWindowed() :
+ DXUTGetHWNDDeviceFullScreen();
+ pValidDeviceSettings->sd.Windowed = pBestDeviceSettingsCombo->Windowed;
+ pValidDeviceSettings->sd.BufferDesc.RefreshRate = bestDisplayMode.RefreshRate;
+ pValidDeviceSettings->sd.Flags = 0;
+ pValidDeviceSettings->SyncInterval = bestPresentInterval;
+ pValidDeviceSettings->AutoCreateDepthStencil = bestEnableAutoDepthStencil;
+ pValidDeviceSettings->AutoDepthStencilFormat = bestDepthStencilFormat;
+ pValidDeviceSettings->CreateFlags = pDeviceSettingsIn->CreateFlags;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Internal helper function to find the closest allowed display mode to the optimal
+//--------------------------------------------------------------------------------------
+HRESULT DXUTFindValidD3D10Resolution( CD3D10EnumDeviceSettingsCombo* pBestDeviceSettingsCombo,
+ DXGI_MODE_DESC displayModeIn, DXGI_MODE_DESC* pBestDisplayMode )
+{
+ DXGI_MODE_DESC bestDisplayMode;
+ ZeroMemory( &bestDisplayMode, sizeof( bestDisplayMode ) );
+
+ if( pBestDeviceSettingsCombo->Windowed )
+ {
+ *pBestDisplayMode = displayModeIn;
+
+ // If our client rect size is smaller than our backbuffer size, use that size.
+ // This would happen when we specify a windowed resolution larger than the screen.
+ MONITORINFO Info;
+ Info.cbSize = sizeof( MONITORINFO );
+ if ( pBestDeviceSettingsCombo->pOutputInfo != NULL ) {
+ GetMonitorInfo( pBestDeviceSettingsCombo->pOutputInfo->Desc.Monitor, &Info );
+
+ UINT Width = Info.rcWork.right - Info.rcWork.left;
+ UINT Height = Info.rcWork.bottom - Info.rcWork.top;
+
+ RECT rcClient = Info.rcWork;
+ AdjustWindowRect( &rcClient, GetWindowLong( DXUTGetHWNDDeviceWindowed(), GWL_STYLE ), FALSE );
+ Width = Width - ( rcClient.right - rcClient.left - Width );
+ Height = Height - ( rcClient.bottom - rcClient.top - Height );
+
+ pBestDisplayMode->Width = __min( pBestDisplayMode->Width, Width );
+ pBestDisplayMode->Height = __min( pBestDisplayMode->Height, Height );
+
+ } else {
+
+ }
+ }
+ else
+ {
+ int nBestRanking = 100000;
+ int nCurRanking;
+ CGrowableArray <DXGI_MODE_DESC>* pDisplayModeList = &pBestDeviceSettingsCombo->pOutputInfo->displayModeList;
+ for( int iDisplayMode = 0; iDisplayMode < pDisplayModeList->GetSize(); iDisplayMode++ )
+ {
+ DXGI_MODE_DESC displayMode = pDisplayModeList->GetAt( iDisplayMode );
+
+ // Find the delta between the current width/height and the optimal width/height
+ nCurRanking = abs( ( int )displayMode.Width - ( int )displayModeIn.Width ) +
+ abs( ( int )displayMode.Height - ( int )displayModeIn.Height );
+
+ if( nCurRanking < nBestRanking )
+ {
+ bestDisplayMode = displayMode;
+ nBestRanking = nCurRanking;
+
+ // Stop if perfect match found
+ if( nBestRanking == 0 )
+ break;
+ }
+ }
+
+ if( bestDisplayMode.Width == 0 )
+ {
+ *pBestDisplayMode = displayModeIn;
+ return E_FAIL; // No valid display modes found
+ }
+
+ *pBestDisplayMode = bestDisplayMode;
+ }
+
+ return S_OK;
+}
+
+
+//--------------------------------------------------------------------------------------
+// Returns the DXGI_MODE_DESC struct for a given adapter and output
+//--------------------------------------------------------------------------------------
+HRESULT WINAPI DXUTGetD3D10AdapterDisplayMode( UINT AdapterOrdinal, UINT nOutput, DXGI_MODE_DESC* pModeDesc )
+{
+ if( !pModeDesc )
+ return E_INVALIDARG;
+
+ CD3D10Enumeration* pD3DEnum = DXUTGetD3D10Enumeration();
+ CD3D10EnumOutputInfo* pOutputInfo = pD3DEnum->GetOutputInfo( AdapterOrdinal, nOutput );
+ if( pOutputInfo )
+ {
+ pModeDesc->Width = 640;
+ pModeDesc->Height = 480;
+ pModeDesc->RefreshRate.Numerator = 0;
+ pModeDesc->RefreshRate.Denominator = 0;
+ pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ pModeDesc->Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ pModeDesc->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+
+ DXGI_OUTPUT_DESC Desc;
+ pOutputInfo->m_pOutput->GetDesc( &Desc );
+ pModeDesc->Width = Desc.DesktopCoordinates.right - Desc.DesktopCoordinates.left;
+ pModeDesc->Height = Desc.DesktopCoordinates.bottom - Desc.DesktopCoordinates.top;
+ }
+
+ // TODO: verify this is needed
+ if( pModeDesc->Format == DXGI_FORMAT_B8G8R8A8_UNORM )
+ pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ return S_OK;
+}