x
Yes
No
Do you want to visit DriveHQ English website?
首页
产品服务
价格
免费试用
下载客户端
关于我们
云文件服务
|
云备份服务
|
FTP服务
|
企业邮箱服务
|
网站托管
|
客户端软件
云文件服务
云备份服务
FTP服务
企业级邮箱服务
网站托管
客户端软件
DXUTenum.cpp - Hosted on DriveHQ Cloud IT Platform
返回上层目录
上传
下载
共享
发布
新建文件夹
新建文件
复制
剪切
删除
粘贴
评论
升级服务
路径: \\game3dprogramming\materials\DarkPuzzle\DXUT\Core\DXUTenum.cpp
旋转
特效
属性
历史版本
//-------------------------------------------------------------------------------------- // File: DXUTEnum.cpp // // Enumerates D3D adapters, devices, modes, etc. // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //#include "DXUT.h" #include "DarkPuzzle.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
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
AdapterIdentifier.Description, pAdapterInfo2->AdapterIdentifier.Description ) == 0 ) { bUniqueDesc = false; break; } } if( !bUniqueDesc ) break; } for( int i=0; i
AdapterIdentifier.Description, -1, pAdapterInfo->szUniqueDescription, 100 ); pAdapterInfo->szUniqueDescription[100] = 0; if( !bUniqueDesc ) { WCHAR sz[100]; StringCchPrintf( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); StringCchCat( pAdapterInfo->szUniqueDescription, 256, sz ); } } return S_OK; } //-------------------------------------------------------------------------------------- // Enumerates D3D devices for a particular adapter. //-------------------------------------------------------------------------------------- HRESULT CD3D9Enumeration::EnumerateDevices( CD3D9EnumAdapterInfo* pAdapterInfo, CGrowableArray
* 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, &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
* 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
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
depthStencilFormatList.GetSize(); iDS++ ) { D3DFORMAT dsFmt = pDeviceCombo->depthStencilFormatList.GetAt(iDS); for( int iMS=0; iMS
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
* CD3D9Enumeration::GetAdapterInfoList() { return &m_AdapterInfoList; } //-------------------------------------------------------------------------------------- CD3D9EnumAdapterInfo* CD3D9Enumeration::GetAdapterInfo( UINT AdapterOrdinal ) { for( int iAdapter=0; iAdapter
AdapterOrdinal == AdapterOrdinal ) return pAdapterInfo; } return NULL; } //-------------------------------------------------------------------------------------- CD3D9EnumDeviceInfo* CD3D9Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3DDEVTYPE DeviceType ) { CD3D9EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal ); if( pAdapterInfo ) { for( int iDeviceInfo=0; iDeviceInfo
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
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
* CD3D9Enumeration::GetPossibleDepthStencilFormatList() { return &m_DepthStencilPossibleList; } //-------------------------------------------------------------------------------------- CGrowableArray
* 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
* 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
* pAdapterList = pd3dEnum->GetAdapterInfoList(); for( int iAdapter=0; iAdapter
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
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
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
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
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
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
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
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
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
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
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
* pDisplayModeList = &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
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
* pDisplayModeList = &pBestDeviceSettingsCombo->pAdapterInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
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; } } // // 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); StringCchCopy( pAdapterInfo->szUniqueDescription, 100, pAdapterInfo->AdapterDesc.Description ); if( !bUniqueDesc ) { WCHAR sz[100]; StringCchPrintf( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); StringCchCat( 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; const DXGI_FORMAT allowedAdapterFormatArray[] = { DXGI_FORMAT_R8G8B8A8_UNORM, //This is DXUT's preferred mode DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, }; int allowedAdapterFormatArrayCount = sizeof(allowedAdapterFormatArray) / sizeof(allowedAdapterFormatArray[0]); // The fast path only enumerates R8G8B8A8_UNORM 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], 0, &NumModes, pDesc ); if( DXGI_ERROR_NOT_FOUND == hr ) { SAFE_DELETE_ARRAY( pDesc ); NumModes = 0; break; } else if( MAKE_DXGI_HRESULT( 34 ) == hr && DXGI_FORMAT_R8G8B8A8_UNORM == 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 = DXGI_FORMAT_R8G8B8A8_UNORM; 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], 0, &NumModes, NULL ); if( FAILED(hr) ) { NumModes = 0; break; } DXGI_MODE_DESC *pDesc = new DXGI_MODE_DESC[ NumModes ]; assert( pDesc ); if( !pDesc ) return E_OUTOFMEMORY; hr = pOutputInfo->m_pOutput->GetDisplayModeList(allowedAdapterFormatArray[f], 0, &NumModes, pDesc ); if( FAILED(hr) ) { SAFE_DELETE_ARRAY( pDesc ); NumModes = 0; break; } } if( 0 == NumModes && 0 == f ) { // No R8G8B8A8_UNORM 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
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_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; hr = DXUT_Dynamic_D3D10CreateDevice( pAdapter, devTypeArray[iDeviceType], (HMODULE)0, 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::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 ); const DXGI_FORMAT backBufferFormatArray[] = { DXGI_FORMAT_R8G8B8A8_UNORM, //This is DXUT's preferred mode DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, }; const UINT backBufferFormatArrayCount = sizeof(backBufferFormatArray) / sizeof(backBufferFormatArray[0]); 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
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
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( pd3dDevice ); } //-------------------------------------------------------------------------------------- // Call GetAdapterInfoList() after Enumerate() to get a STL vector of // CD3D10EnumAdapterInfo* //-------------------------------------------------------------------------------------- CGrowableArray
* 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
* pAdapterList = pd3dEnum->GetAdapterInfoList(); for( int iAdapter=0; iAdapter
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, { 60, 1 }, DXGI_FORMAT_R8G8B8A8_UNORM }; 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 = 60; pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator = 1; } 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
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
pOutputInfo->displayModeList.GetSize(); i++ ) { DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( i ); if( fabs( float(displayMode.RefreshRate.Numerator) / displayMode.RefreshRate.Denominator - float(pDeviceSettingsIn->sd.BufferDesc.RefreshRate.Numerator) / pDeviceSettingsIn->sd.BufferDesc.RefreshRate.Denominator ) < 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; 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
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; for( int idm = 0; idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); idm++ ) { DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm ); if( fabs( float(displayMode.RefreshRate.Numerator)/displayMode.RefreshRate.Denominator - float(pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator)/pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator ) < 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 = 60; bestDisplayMode.RefreshRate.Denominator = 1; } 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 60 in case no matching mode is found bestDisplayMode.RefreshRate.Numerator = 60; bestDisplayMode.RefreshRate.Denominator = 1; // if( refreshRateMatch != 0 ) { float fBestRefreshRanking = 100000.0f; CGrowableArray
* pDisplayModeList = &pBestDeviceSettingsCombo->pOutputInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
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 fCurRanking = abs(float(displayMode.RefreshRate.Numerator)/displayMode.RefreshRate.Denominator - float(refreshRateMatch.Numerator)/refreshRateMatch.Denominator); 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); 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 { int nBestRanking = 100000; int nCurRanking; CGrowableArray
* pDisplayModeList = &pBestDeviceSettingsCombo->pOutputInfo->displayModeList; for( int iDisplayMode=0; iDisplayMode
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 = 60; pModeDesc->RefreshRate.Denominator = 1; pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM; 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; }
DXUTenum.cpp
网页地址
文件地址
上一页
7/10
下一页
下载
( 153 KB )
Comments
Total ratings:
0
Average rating:
无评论
of 10
Would you like to comment?
Join now
, or
Logon
if you are already a member.