зеркало из https://github.com/microsoft/DXUT.git
1271 строка
49 KiB
C++
1271 строка
49 KiB
C++
//--------------------------------------------------------------------------------------
|
|
// File: DXUTDevice11.cpp
|
|
//
|
|
// Enumerates D3D adapters, devices, modes, etc.
|
|
//
|
|
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
//
|
|
// http://go.microsoft.com/fwlink/?LinkId=320437
|
|
//--------------------------------------------------------------------------------------
|
|
#include "DXUT.h"
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Forward declarations
|
|
//--------------------------------------------------------------------------------------
|
|
extern void DXUTGetCallbackD3D11DeviceAcceptable( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable, void** ppUserContext );
|
|
|
|
CD3D11Enumeration* g_pDXUTD3D11Enumeration = nullptr;
|
|
|
|
HRESULT WINAPI DXUTCreateD3D11Enumeration()
|
|
{
|
|
if( !g_pDXUTD3D11Enumeration )
|
|
{
|
|
g_pDXUTD3D11Enumeration = new (std::nothrow) CD3D11Enumeration();
|
|
if( !g_pDXUTD3D11Enumeration )
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
void WINAPI DXUTDestroyD3D11Enumeration()
|
|
{
|
|
SAFE_DELETE( g_pDXUTD3D11Enumeration );
|
|
}
|
|
|
|
class DXUTMemoryHelperD3D11Enum
|
|
{
|
|
public:
|
|
DXUTMemoryHelperD3D11Enum() noexcept { DXUTCreateD3D11Enumeration(); }
|
|
~DXUTMemoryHelperD3D11Enum() { DXUTDestroyD3D11Enumeration(); }
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
CD3D11Enumeration* WINAPI DXUTGetD3D11Enumeration( bool bForceEnumerate, bool bEnumerateAllAdapterFormats, D3D_FEATURE_LEVEL forceFL )
|
|
{
|
|
// Using an static class with accessor function to allow control of the construction order
|
|
static DXUTMemoryHelperD3D11Enum d3d11enumMemory;
|
|
if( g_pDXUTD3D11Enumeration && ( !g_pDXUTD3D11Enumeration->HasEnumerated() || bForceEnumerate ) )
|
|
{
|
|
g_pDXUTD3D11Enumeration->SetEnumerateAllAdapterFormats( bEnumerateAllAdapterFormats );
|
|
LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE pCallbackIsDeviceAcceptable;
|
|
void* pUserContext;
|
|
DXUTGetCallbackD3D11DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext );
|
|
g_pDXUTD3D11Enumeration->SetForceFeatureLevel(forceFL);
|
|
|
|
g_pDXUTD3D11Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext );
|
|
}
|
|
|
|
return g_pDXUTD3D11Enumeration;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CD3D11Enumeration::CD3D11Enumeration() noexcept :
|
|
m_bHasEnumerated(false),
|
|
m_IsD3D11DeviceAcceptableFunc(nullptr),
|
|
m_pIsD3D11DeviceAcceptableFuncUserContext(nullptr),
|
|
m_bEnumerateAllAdapterFormats(false),
|
|
m_forceFL(D3D_FEATURE_LEVEL(0)),
|
|
m_warpFL(D3D_FEATURE_LEVEL_10_1),
|
|
m_refFL(D3D_FEATURE_LEVEL_11_0)
|
|
{
|
|
ResetPossibleDepthStencilFormats();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CD3D11Enumeration::~CD3D11Enumeration()
|
|
{
|
|
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.
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CD3D11Enumeration::Enumerate( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE IsD3D11DeviceAcceptableFunc,
|
|
void* pIsD3D11DeviceAcceptableFuncUserContext )
|
|
{
|
|
CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D11 Enumeration" );
|
|
HRESULT hr;
|
|
auto pFactory = DXUTGetDXGIFactory();
|
|
if( !pFactory )
|
|
return E_FAIL;
|
|
|
|
m_bHasEnumerated = true;
|
|
m_IsD3D11DeviceAcceptableFunc = IsD3D11DeviceAcceptableFunc;
|
|
m_pIsD3D11DeviceAcceptableFuncUserContext = pIsD3D11DeviceAcceptableFuncUserContext;
|
|
|
|
ClearAdapterInfoList();
|
|
|
|
for( int index = 0; ; ++index )
|
|
{
|
|
IDXGIAdapter* pAdapter = nullptr;
|
|
hr = pFactory->EnumAdapters( index, &pAdapter );
|
|
if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit
|
|
break;
|
|
|
|
IDXGIAdapter2* pAdapter2 = nullptr;
|
|
if ( SUCCEEDED( pAdapter->QueryInterface( __uuidof(IDXGIAdapter2), ( LPVOID* )&pAdapter2 ) ) )
|
|
{
|
|
// Succeeds on DirectX 11.1 Runtime systems
|
|
DXGI_ADAPTER_DESC2 desc;
|
|
hr = pAdapter2->GetDesc2( &desc );
|
|
pAdapter2->Release();
|
|
|
|
if ( SUCCEEDED(hr) && ( desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE ) )
|
|
{
|
|
// Skip "always there" Microsoft Basics Display Driver
|
|
pAdapter->Release();
|
|
continue;
|
|
}
|
|
}
|
|
|
|
auto pAdapterInfo = new (std::nothrow) CD3D11EnumAdapterInfo;
|
|
if( !pAdapterInfo )
|
|
{
|
|
SAFE_RELEASE( pAdapter );
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
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.empty() )
|
|
{
|
|
delete pAdapterInfo;
|
|
continue;
|
|
}
|
|
|
|
// Get info for each devicecombo on this device
|
|
if( FAILED( hr = EnumerateDeviceCombos( pAdapterInfo ) ) )
|
|
{
|
|
delete pAdapterInfo;
|
|
continue;
|
|
}
|
|
|
|
m_AdapterInfoList.push_back( pAdapterInfo );
|
|
}
|
|
|
|
// If we did not get an adapter then we should still enumerate WARP and Ref.
|
|
if (m_AdapterInfoList.size() == 0)
|
|
{
|
|
auto pAdapterInfo = new (std::nothrow) CD3D11EnumAdapterInfo;
|
|
if( !pAdapterInfo )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
pAdapterInfo->bAdapterUnavailable = true;
|
|
|
|
hr = EnumerateDevices( pAdapterInfo );
|
|
|
|
// Get info for each devicecombo on this device
|
|
if( FAILED( hr = EnumerateDeviceCombosNoAdapter( pAdapterInfo ) ) )
|
|
{
|
|
delete pAdapterInfo;
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) m_AdapterInfoList.push_back( 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;
|
|
for( size_t i = 0; i < m_AdapterInfoList.size(); i++ )
|
|
{
|
|
auto pAdapterInfo1 = m_AdapterInfoList[ i ];
|
|
|
|
for( size_t j = i + 1; j < m_AdapterInfoList.size(); j++ )
|
|
{
|
|
auto pAdapterInfo2 = m_AdapterInfoList[ j ];
|
|
if( wcsncmp( pAdapterInfo1->AdapterDesc.Description,
|
|
pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 )
|
|
{
|
|
bUniqueDesc = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !bUniqueDesc )
|
|
break;
|
|
}
|
|
|
|
for( auto it = m_AdapterInfoList.begin(); it != m_AdapterInfoList.end(); ++it )
|
|
{
|
|
wcscpy_s((*it)->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, (*it)->AdapterDesc.Description);
|
|
if( !bUniqueDesc )
|
|
{
|
|
WCHAR sz[32];
|
|
swprintf_s( sz, 32, L" (#%u)", (*it)->AdapterOrdinal );
|
|
wcscat_s( (*it)->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz );
|
|
}
|
|
}
|
|
|
|
// Check WARP max feature level
|
|
{
|
|
static const D3D_FEATURE_LEVEL fLvlWarp[] =
|
|
{
|
|
#if defined(USE_DIRECT3D11_3) || defined(USE_DIRECT3D11_4)
|
|
D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0,
|
|
#endif
|
|
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1
|
|
};
|
|
|
|
ID3D11Device* pDevice = nullptr;
|
|
hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, fLvlWarp, _countof(fLvlWarp),
|
|
D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr );
|
|
if ( hr == E_INVALIDARG )
|
|
{
|
|
#if defined(USE_DIRECT3D11_3) || defined(USE_DIRECT3D11_4)
|
|
// DirectX 11.1 runtime will not recognize FL 12.x, so try without it
|
|
hr = DXUT_Dynamic_D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, &fLvlWarp[2], _countof(fLvlWarp) - 2,
|
|
D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr);
|
|
if (hr == E_INVALIDARG)
|
|
{
|
|
// DirectX 11.0 runtime will not recognize FL 11.1+, so try without it
|
|
hr = DXUT_Dynamic_D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, &fLvlWarp[3], _countof(fLvlWarp) - 3,
|
|
D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr);
|
|
}
|
|
#else
|
|
// DirectX 11.0 runtime will not recognize FL 11.1, so try without it
|
|
hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, &fLvlWarp[1], _countof(fLvlWarp) - 1,
|
|
D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr );
|
|
#endif
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
pDevice->Release();
|
|
}
|
|
else
|
|
m_warpFL = D3D_FEATURE_LEVEL_10_1;
|
|
}
|
|
|
|
// Check REF max feature level
|
|
{
|
|
static const D3D_FEATURE_LEVEL fLvlRef[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
|
|
|
|
ID3D11Device* pDevice = nullptr;
|
|
hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_REFERENCE, 0, 0, fLvlRef, _countof(fLvlRef),
|
|
D3D11_SDK_VERSION, &pDevice, &m_refFL, nullptr );
|
|
if ( hr == E_INVALIDARG )
|
|
{
|
|
// DirectX 11.0 runtime will not recognize FL 11.1, so try without it
|
|
hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_REFERENCE, 0, 0, &fLvlRef[1], _countof(fLvlRef) - 1,
|
|
D3D11_SDK_VERSION, &pDevice, &m_refFL, nullptr );
|
|
}
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
pDevice->Release();
|
|
}
|
|
else
|
|
m_refFL = D3D_FEATURE_LEVEL_11_0;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT CD3D11Enumeration::EnumerateOutputs( _In_ CD3D11EnumAdapterInfo* pAdapterInfo )
|
|
{
|
|
HRESULT hr;
|
|
IDXGIOutput* pOutput;
|
|
|
|
for( int iOutput = 0; ; ++iOutput )
|
|
{
|
|
pOutput = nullptr;
|
|
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!
|
|
{
|
|
auto pOutputInfo = new (std::nothrow) CD3D11EnumOutputInfo;
|
|
if( !pOutputInfo )
|
|
{
|
|
SAFE_RELEASE( pOutput );
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
pOutputInfo->Output = iOutput;
|
|
pOutputInfo->m_pOutput = pOutput;
|
|
pOutput->GetDesc( &pOutputInfo->Desc );
|
|
|
|
EnumerateDisplayModes( pOutputInfo );
|
|
if( pOutputInfo->displayModeList.empty() )
|
|
{
|
|
// If this output has no valid display mode, do not save it.
|
|
delete pOutputInfo;
|
|
continue;
|
|
}
|
|
|
|
pAdapterInfo->outputInfoList.push_back( pOutputInfo );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT CD3D11Enumeration::EnumerateDisplayModes( _In_ CD3D11EnumOutputInfo* pOutputInfo )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DXGI_FORMAT allowedAdapterFormatArray[] =
|
|
{
|
|
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
|
|
|
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
|
DXGI_FORMAT_R10G10B10A2_UNORM
|
|
};
|
|
int allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof( allowedAdapterFormatArray[0] );
|
|
|
|
// Swap perferred modes for apps running in linear space
|
|
DXGI_FORMAT RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
if( !DXUTIsInGammaCorrectMode() )
|
|
{
|
|
allowedAdapterFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
allowedAdapterFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
}
|
|
|
|
// The fast path only enumerates R8G8B8A8_UNORM_SRGB modes
|
|
if( !m_bEnumerateAllAdapterFormats )
|
|
allowedAdapterFormatArrayCount = 1;
|
|
|
|
for( int f = 0; f < allowedAdapterFormatArrayCount; ++f )
|
|
{
|
|
// Fast-path: Try to grab at least 512 modes.
|
|
// This is to avoid calling GetDisplayModeList more times than necessary.
|
|
// GetDisplayModeList is an expensive call.
|
|
UINT NumModes = 512;
|
|
auto pDesc = new (std::nothrow) DXGI_MODE_DESC[ NumModes ];
|
|
assert( pDesc );
|
|
if( !pDesc )
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
|
|
DXGI_ENUM_MODES_SCALING,
|
|
&NumModes,
|
|
pDesc );
|
|
if( DXGI_ERROR_NOT_FOUND == hr )
|
|
{
|
|
SAFE_DELETE_ARRAY( pDesc );
|
|
NumModes = 0;
|
|
break;
|
|
}
|
|
else if( MAKE_DXGI_HRESULT( 34 ) == hr && RemoteMode == allowedAdapterFormatArray[f] )
|
|
{
|
|
// DXGI cannot enumerate display modes over a remote session. Therefore, create a fake display
|
|
// mode for the current screen resolution for the remote session.
|
|
if( 0 != GetSystemMetrics( 0x1000 ) ) // SM_REMOTESESSION
|
|
{
|
|
DEVMODE DevMode;
|
|
DevMode.dmSize = sizeof( DEVMODE );
|
|
if( EnumDisplaySettings( nullptr, 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 = 0;
|
|
pDesc[0].RefreshRate.Denominator = 0;
|
|
pDesc[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
|
|
pDesc[0].Scaling = DXGI_MODE_SCALING_CENTERED;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
else if( DXGI_ERROR_MORE_DATA == hr )
|
|
{
|
|
// Slow path. There were more than 512 modes.
|
|
SAFE_DELETE_ARRAY( pDesc );
|
|
hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
|
|
DXGI_ENUM_MODES_SCALING,
|
|
&NumModes,
|
|
nullptr );
|
|
if( FAILED( hr ) )
|
|
{
|
|
NumModes = 0;
|
|
break;
|
|
}
|
|
|
|
pDesc = new (std::nothrow) DXGI_MODE_DESC[ NumModes ];
|
|
assert( pDesc );
|
|
if( !pDesc )
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
|
|
DXGI_ENUM_MODES_SCALING,
|
|
&NumModes,
|
|
pDesc );
|
|
if( FAILED( hr ) )
|
|
{
|
|
SAFE_DELETE_ARRAY( pDesc );
|
|
NumModes = 0;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if( 0 == NumModes && 0 == f )
|
|
{
|
|
// No R8G8B8A8_UNORM_SRGB modes!
|
|
// Abort the fast-path if we're on it
|
|
allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof
|
|
( allowedAdapterFormatArray[0] );
|
|
SAFE_DELETE_ARRAY( pDesc );
|
|
continue;
|
|
}
|
|
|
|
if( SUCCEEDED( hr ) )
|
|
{
|
|
for( UINT m = 0; m < NumModes; m++ )
|
|
{
|
|
#pragma warning ( suppress : 6385 )
|
|
pOutputInfo->displayModeList.push_back( pDesc[m] );
|
|
}
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY( pDesc );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
HRESULT CD3D11Enumeration::EnumerateDevices( _In_ CD3D11EnumAdapterInfo* pAdapterInfo )
|
|
{
|
|
HRESULT hr;
|
|
auto deviceSettings = DXUTGetDeviceSettings();
|
|
const D3D_DRIVER_TYPE devTypeArray[] =
|
|
{
|
|
D3D_DRIVER_TYPE_HARDWARE,
|
|
D3D_DRIVER_TYPE_WARP,
|
|
D3D_DRIVER_TYPE_REFERENCE
|
|
};
|
|
const UINT devTypeArrayCount = sizeof( devTypeArray ) / sizeof( devTypeArray[0] );
|
|
|
|
// Enumerate each Direct3D device type
|
|
for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ )
|
|
{
|
|
auto pDeviceInfo = new (std::nothrow) CD3D11EnumDeviceInfo;
|
|
if( !pDeviceInfo )
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Fill struct w/ AdapterOrdinal and D3D_DRIVER_TYPE
|
|
pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal;
|
|
pDeviceInfo->DeviceType = devTypeArray[iDeviceType];
|
|
|
|
static const D3D_FEATURE_LEVEL FeatureLevels[] =
|
|
{
|
|
#if defined(USE_DIRECT3D11_3) || defined(USE_DIRECT3D11_4)
|
|
D3D_FEATURE_LEVEL_12_1,
|
|
D3D_FEATURE_LEVEL_12_0,
|
|
#endif
|
|
D3D_FEATURE_LEVEL_11_1,
|
|
D3D_FEATURE_LEVEL_11_0,
|
|
D3D_FEATURE_LEVEL_10_1,
|
|
D3D_FEATURE_LEVEL_10_0,
|
|
D3D_FEATURE_LEVEL_9_3,
|
|
D3D_FEATURE_LEVEL_9_2,
|
|
D3D_FEATURE_LEVEL_9_1
|
|
};
|
|
UINT NumFeatureLevels = ARRAYSIZE( FeatureLevels );
|
|
|
|
// Call D3D11CreateDevice to ensure that this is a D3D11 device.
|
|
ID3D11Device* pd3dDevice = nullptr;
|
|
ID3D11DeviceContext* pd3dDeviceContext = nullptr;
|
|
hr = DXUT_Dynamic_D3D11CreateDevice( (devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? pAdapterInfo->m_pAdapter : nullptr,
|
|
(devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? D3D_DRIVER_TYPE_UNKNOWN : devTypeArray[iDeviceType],
|
|
( HMODULE )0,
|
|
0,
|
|
FeatureLevels,
|
|
NumFeatureLevels,
|
|
D3D11_SDK_VERSION,
|
|
&pd3dDevice,
|
|
&pDeviceInfo->MaxLevel,
|
|
&pd3dDeviceContext );
|
|
|
|
if ( hr == E_INVALIDARG )
|
|
{
|
|
#if defined(USE_DIRECT3D11_3) || defined(USE_DIRECT3D11_4)
|
|
// DirectX 11.1 runtime will not recognize FL 12.x, so try without it
|
|
hr = DXUT_Dynamic_D3D11CreateDevice((devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? pAdapterInfo->m_pAdapter : nullptr,
|
|
(devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? D3D_DRIVER_TYPE_UNKNOWN : devTypeArray[iDeviceType],
|
|
(HMODULE)0, 0,
|
|
&FeatureLevels[2], NumFeatureLevels - 2,
|
|
D3D11_SDK_VERSION, &pd3dDevice, &pDeviceInfo->MaxLevel,
|
|
&pd3dDeviceContext);
|
|
|
|
if (hr == E_INVALIDARG)
|
|
{
|
|
// DirectX 11.0 runtime will not recognize FL 11.1, so try without it
|
|
hr = DXUT_Dynamic_D3D11CreateDevice((devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? pAdapterInfo->m_pAdapter : nullptr,
|
|
(devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? D3D_DRIVER_TYPE_UNKNOWN : devTypeArray[iDeviceType],
|
|
(HMODULE)0, 0,
|
|
&FeatureLevels[3], NumFeatureLevels - 3,
|
|
D3D11_SDK_VERSION, &pd3dDevice, &pDeviceInfo->MaxLevel,
|
|
&pd3dDeviceContext);
|
|
}
|
|
#else
|
|
// DirectX 11.0 runtime will not recognize FL 11.1, so try without it
|
|
hr = DXUT_Dynamic_D3D11CreateDevice( (devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? pAdapterInfo->m_pAdapter : nullptr,
|
|
(devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? D3D_DRIVER_TYPE_UNKNOWN : devTypeArray[iDeviceType],
|
|
( HMODULE )0, 0,
|
|
&FeatureLevels[1], NumFeatureLevels - 1,
|
|
D3D11_SDK_VERSION, &pd3dDevice, &pDeviceInfo->MaxLevel,
|
|
&pd3dDeviceContext );
|
|
#endif
|
|
}
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
delete pDeviceInfo;
|
|
continue;
|
|
}
|
|
else if ( pDeviceInfo->MaxLevel < deviceSettings.MinimumFeatureLevel )
|
|
{
|
|
delete pDeviceInfo;
|
|
SAFE_RELEASE( pd3dDevice );
|
|
SAFE_RELEASE( pd3dDeviceContext );
|
|
continue;
|
|
}
|
|
|
|
if (m_forceFL == 0 || m_forceFL == pDeviceInfo->MaxLevel)
|
|
{
|
|
pDeviceInfo->SelectedLevel = pDeviceInfo->MaxLevel;
|
|
}
|
|
else if (m_forceFL > pDeviceInfo->MaxLevel)
|
|
{
|
|
delete pDeviceInfo;
|
|
SAFE_RELEASE( pd3dDevice );
|
|
SAFE_RELEASE( pd3dDeviceContext );
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// A device was created with a higher feature level that the user-specified feature level.
|
|
SAFE_RELEASE( pd3dDevice );
|
|
SAFE_RELEASE( pd3dDeviceContext );
|
|
D3D_FEATURE_LEVEL rtFL;
|
|
hr = DXUT_Dynamic_D3D11CreateDevice( (devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? pAdapterInfo->m_pAdapter : nullptr,
|
|
(devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE) ? D3D_DRIVER_TYPE_UNKNOWN : devTypeArray[iDeviceType],
|
|
( HMODULE )0,
|
|
0,
|
|
&m_forceFL,
|
|
1,
|
|
D3D11_SDK_VERSION,
|
|
&pd3dDevice,
|
|
&rtFL,
|
|
&pd3dDeviceContext );
|
|
|
|
if( SUCCEEDED( hr ) && rtFL == m_forceFL )
|
|
{
|
|
pDeviceInfo->SelectedLevel = m_forceFL;
|
|
}
|
|
else
|
|
{
|
|
delete pDeviceInfo;
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
SAFE_RELEASE( pd3dDevice );
|
|
SAFE_RELEASE( pd3dDeviceContext );
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS ho;
|
|
hr = pd3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &ho, sizeof(ho));
|
|
if ( FAILED(hr) )
|
|
memset( &ho, 0, sizeof(ho) );
|
|
|
|
pDeviceInfo->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = ho.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x;
|
|
SAFE_RELEASE( pd3dDeviceContext );
|
|
SAFE_RELEASE( pd3dDevice );
|
|
pAdapterInfo->deviceInfoList.push_back( pDeviceInfo );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CD3D11Enumeration::EnumerateDeviceCombosNoAdapter( _In_ CD3D11EnumAdapterInfo* pAdapterInfo )
|
|
{
|
|
// Iterate through each combination of device driver type, output,
|
|
// adapter format, and backbuffer format to build the adapter's device combo list.
|
|
//
|
|
|
|
for( auto dit = pAdapterInfo->deviceInfoList.cbegin(); dit != pAdapterInfo->deviceInfoList.cend(); ++dit )
|
|
{
|
|
DXGI_FORMAT BufferFormatArray[] =
|
|
{
|
|
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
|
|
|
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
|
DXGI_FORMAT_R10G10B10A2_UNORM
|
|
};
|
|
|
|
// Swap perferred modes for apps running in linear space
|
|
if( !DXUTIsInGammaCorrectMode() )
|
|
{
|
|
BufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
BufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
}
|
|
|
|
for( UINT iBufferFormat = 0; iBufferFormat < _countof( BufferFormatArray ); iBufferFormat++ )
|
|
{
|
|
DXGI_FORMAT BufferFormat = BufferFormatArray[iBufferFormat];
|
|
|
|
// determine if there are any modes for this particular format
|
|
|
|
// If an application callback function has been provided, make sure this device
|
|
// is acceptable to the app.
|
|
if( m_IsD3D11DeviceAcceptableFunc )
|
|
{
|
|
if( !m_IsD3D11DeviceAcceptableFunc( pAdapterInfo,
|
|
0,
|
|
*dit,
|
|
BufferFormat,
|
|
TRUE,
|
|
m_pIsD3D11DeviceAcceptableFuncUserContext ) )
|
|
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.
|
|
CD3D11EnumDeviceSettingsCombo* pDeviceCombo = new (std::nothrow) CD3D11EnumDeviceSettingsCombo;
|
|
if( !pDeviceCombo )
|
|
return E_OUTOFMEMORY;
|
|
|
|
pDeviceCombo->AdapterOrdinal = (*dit)->AdapterOrdinal;
|
|
pDeviceCombo->DeviceType = (*dit)->DeviceType;
|
|
pDeviceCombo->BackBufferFormat = BufferFormat;
|
|
pDeviceCombo->Windowed = TRUE;
|
|
pDeviceCombo->Output = 0;
|
|
pDeviceCombo->pAdapterInfo = pAdapterInfo;
|
|
pDeviceCombo->pDeviceInfo = (*dit);
|
|
pDeviceCombo->pOutputInfo = nullptr;
|
|
|
|
BuildMultiSampleQualityList( BufferFormat, pDeviceCombo );
|
|
|
|
pAdapterInfo->deviceSettingsComboList.push_back( pDeviceCombo );
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
HRESULT CD3D11Enumeration::EnumerateDeviceCombos( CD3D11EnumAdapterInfo* pAdapterInfo )
|
|
{
|
|
// Iterate through each combination of device driver type, output,
|
|
// adapter format, and backbuffer format to build the adapter's device combo list.
|
|
//
|
|
for( size_t output = 0; output < pAdapterInfo->outputInfoList.size(); ++output )
|
|
{
|
|
auto pOutputInfo = pAdapterInfo->outputInfoList[ output ];
|
|
|
|
for( size_t device = 0; device < pAdapterInfo->deviceInfoList.size(); ++device )
|
|
{
|
|
auto pDeviceInfo = pAdapterInfo->deviceInfoList[ device ];
|
|
|
|
DXGI_FORMAT backBufferFormatArray[] =
|
|
{
|
|
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
|
|
|
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
|
DXGI_FORMAT_R10G10B10A2_UNORM
|
|
};
|
|
|
|
// Swap perferred modes for apps running in linear space
|
|
if( !DXUTIsInGammaCorrectMode() )
|
|
{
|
|
backBufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
backBufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
}
|
|
|
|
for( UINT iBackBufferFormat = 0; iBackBufferFormat < _countof( backBufferFormatArray ); iBackBufferFormat++ )
|
|
{
|
|
DXGI_FORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat];
|
|
|
|
for( int nWindowed = 0; nWindowed < 2; nWindowed++ )
|
|
{
|
|
if( !nWindowed && pOutputInfo->displayModeList.size() == 0 )
|
|
continue;
|
|
|
|
// determine if there are any modes for this particular format
|
|
size_t iModes = 0;
|
|
for( size_t i = 0; i < pOutputInfo->displayModeList.size(); i++ )
|
|
{
|
|
if( backBufferFormat == pOutputInfo->displayModeList[ i ].Format )
|
|
++iModes;
|
|
}
|
|
if( !iModes )
|
|
continue;
|
|
|
|
// If an application callback function has been provided, make sure this device
|
|
// is acceptable to the app.
|
|
if( m_IsD3D11DeviceAcceptableFunc )
|
|
{
|
|
if( !m_IsD3D11DeviceAcceptableFunc( pAdapterInfo, static_cast<UINT>( output ),
|
|
pDeviceInfo, backBufferFormat,
|
|
FALSE != nWindowed,
|
|
m_pIsD3D11DeviceAcceptableFuncUserContext ) )
|
|
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.
|
|
auto pDeviceCombo = new (std::nothrow) CD3D11EnumDeviceSettingsCombo;
|
|
if( !pDeviceCombo )
|
|
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 );
|
|
|
|
pAdapterInfo->deviceSettingsComboList.push_back( pDeviceCombo );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Release all the allocated CD3D11EnumAdapterInfo objects and empty the list
|
|
//--------------------------------------------------------------------------------------
|
|
void CD3D11Enumeration::ClearAdapterInfoList()
|
|
{
|
|
for( auto it = m_AdapterInfoList.begin(); it != m_AdapterInfoList.end(); ++it )
|
|
{
|
|
auto pAdapterInfo = *it;
|
|
delete pAdapterInfo;
|
|
}
|
|
m_AdapterInfoList.clear();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
void CD3D11Enumeration::ResetPossibleDepthStencilFormats()
|
|
{
|
|
m_DepthStencilPossibleList.clear();
|
|
m_DepthStencilPossibleList.push_back( DXGI_FORMAT_D32_FLOAT_S8X24_UINT );
|
|
m_DepthStencilPossibleList.push_back( DXGI_FORMAT_D32_FLOAT );
|
|
m_DepthStencilPossibleList.push_back( DXGI_FORMAT_D24_UNORM_S8_UINT );
|
|
m_DepthStencilPossibleList.push_back( DXGI_FORMAT_D16_UNORM );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
void CD3D11Enumeration::SetEnumerateAllAdapterFormats( _In_ bool bEnumerateAllAdapterFormats )
|
|
{
|
|
m_bEnumerateAllAdapterFormats = bEnumerateAllAdapterFormats;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
void CD3D11Enumeration::BuildMultiSampleQualityList( DXGI_FORMAT fmt, CD3D11EnumDeviceSettingsCombo* pDeviceCombo )
|
|
{
|
|
ID3D11Device* pd3dDevice = nullptr;
|
|
ID3D11DeviceContext* pd3dDeviceContext = nullptr;
|
|
IDXGIAdapter* pAdapter = nullptr;
|
|
|
|
D3D_FEATURE_LEVEL *FeatureLevels = &(pDeviceCombo->pDeviceInfo->SelectedLevel);
|
|
D3D_FEATURE_LEVEL returnedFeatureLevel;
|
|
|
|
UINT NumFeatureLevels = 1;
|
|
|
|
HRESULT hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter,
|
|
pDeviceCombo->DeviceType,
|
|
( HMODULE )0,
|
|
0,
|
|
FeatureLevels,
|
|
NumFeatureLevels,
|
|
D3D11_SDK_VERSION,
|
|
&pd3dDevice,
|
|
&returnedFeatureLevel,
|
|
&pd3dDeviceContext ) ;
|
|
|
|
if( FAILED( hr)) return;
|
|
|
|
if (returnedFeatureLevel != pDeviceCombo->pDeviceInfo->SelectedLevel) return;
|
|
|
|
for( int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++i )
|
|
{
|
|
UINT Quality;
|
|
if( SUCCEEDED( pd3dDevice->CheckMultisampleQualityLevels( fmt, i, &Quality ) ) && Quality > 0 )
|
|
{
|
|
//From D3D10 docs: When multisampling a texture, the number of quality levels available for an adapter is dependent on the texture
|
|
//format used and the number of samples requested. The maximum sample count is defined by
|
|
//D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT in d3d10.h. If the returned value of pNumQualityLevels is 0,
|
|
//the format and sample count combination is not supported for the installed adapter.
|
|
|
|
if (Quality != 0) {
|
|
pDeviceCombo->multiSampleCountList.push_back( i );
|
|
pDeviceCombo->multiSampleQualityList.push_back( Quality );
|
|
}
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE( pAdapter );
|
|
SAFE_RELEASE( pd3dDevice );
|
|
SAFE_RELEASE (pd3dDeviceContext);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Call GetAdapterInfoList() after Enumerate() to get a STL vector of
|
|
// CD3D11EnumAdapterInfo*
|
|
//--------------------------------------------------------------------------------------
|
|
std::vector <CD3D11EnumAdapterInfo*>* CD3D11Enumeration::GetAdapterInfoList()
|
|
{
|
|
return &m_AdapterInfoList;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CD3D11EnumAdapterInfo* CD3D11Enumeration::GetAdapterInfo( _In_ UINT AdapterOrdinal ) const
|
|
{
|
|
for( auto it = m_AdapterInfoList.cbegin(); it != m_AdapterInfoList.cend(); ++it )
|
|
{
|
|
if( (*it)->AdapterOrdinal == AdapterOrdinal )
|
|
return *it;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
CD3D11EnumDeviceInfo* CD3D11Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3D_DRIVER_TYPE DeviceType ) const
|
|
{
|
|
auto pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
|
|
if( pAdapterInfo )
|
|
{
|
|
for( auto it = pAdapterInfo->deviceInfoList.cbegin(); it != pAdapterInfo->deviceInfoList.cend(); ++it )
|
|
{
|
|
if( (*it)->DeviceType == DeviceType )
|
|
return *it;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
CD3D11EnumOutputInfo* CD3D11Enumeration::GetOutputInfo( UINT AdapterOrdinal, UINT Output ) const
|
|
{
|
|
auto pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
|
|
if( pAdapterInfo && pAdapterInfo->outputInfoList.size() > size_t( Output ) )
|
|
{
|
|
return pAdapterInfo->outputInfoList[ Output ];
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
CD3D11EnumDeviceSettingsCombo* CD3D11Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal,
|
|
DXGI_FORMAT BackBufferFormat, BOOL Windowed ) const
|
|
{
|
|
auto pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
|
|
if( pAdapterInfo )
|
|
{
|
|
for( size_t iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.size(); iDeviceCombo++ )
|
|
{
|
|
auto pDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList[ iDeviceCombo ];
|
|
if( pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat &&
|
|
pDeviceSettingsCombo->Windowed == Windowed )
|
|
return pDeviceSettingsCombo;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CD3D11EnumOutputInfo::~CD3D11EnumOutputInfo()
|
|
{
|
|
SAFE_RELEASE( m_pOutput );
|
|
displayModeList.clear();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CD3D11EnumDeviceInfo::~CD3D11EnumDeviceInfo()
|
|
{
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
CD3D11EnumAdapterInfo::~CD3D11EnumAdapterInfo()
|
|
{
|
|
for( size_t j = 0; j < outputInfoList.size(); ++j )
|
|
{
|
|
auto pOutputInfo = outputInfoList[ j ];
|
|
delete pOutputInfo;
|
|
}
|
|
outputInfoList.clear();
|
|
|
|
for( size_t j = 0; j < deviceInfoList.size(); ++j )
|
|
{
|
|
auto pDeviceInfo = deviceInfoList[ j ];
|
|
delete pDeviceInfo;
|
|
}
|
|
deviceInfoList.clear();
|
|
|
|
for( size_t j = 0; j < deviceSettingsComboList.size(); ++j )
|
|
{
|
|
auto pDeviceCombo = deviceSettingsComboList[ j ];
|
|
delete pDeviceCombo;
|
|
}
|
|
deviceSettingsComboList.clear();
|
|
|
|
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:
|
|
case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
|
|
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:
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
|
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
|
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
|
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
|
|
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
|
return 8;
|
|
|
|
case DXGI_FORMAT_B5G6R5_UNORM:
|
|
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
|
return 5;
|
|
|
|
case DXGI_FORMAT_B4G4R4A4_UNORM:
|
|
return 4;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// 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
|
|
//--------------------------------------------------------------------------------------
|
|
_Use_decl_annotations_
|
|
float DXUTRankD3D11DeviceCombo( CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo,
|
|
DXUTD3D11DeviceSettings* pOptimalDeviceSettings,
|
|
int &bestModeIndex,
|
|
int &bestMSAAIndex
|
|
)
|
|
{
|
|
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 fWARPOverRefWeight = 80.0f;
|
|
|
|
const float fWindowWeight = 10.0f;
|
|
const float fResolutionWeight = 1.0f;
|
|
const float fBackBufferFormatWeight = 1.0f;
|
|
const float fMultiSampleWeight = 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;
|
|
else if (pDeviceSettingsCombo->DeviceType == D3D_DRIVER_TYPE_WARP && pOptimalDeviceSettings->DriverType == D3D_DRIVER_TYPE_HARDWARE) {
|
|
fCurRanking += fWARPOverRefWeight;
|
|
}
|
|
|
|
// Slightly prefer HAL
|
|
if( pDeviceSettingsCombo->DeviceType == D3D_DRIVER_TYPE_HARDWARE )
|
|
fCurRanking += 0.1f;
|
|
|
|
//---------------------
|
|
// Windowed
|
|
//---------------------
|
|
if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->sd.Windowed )
|
|
fCurRanking += fWindowWeight;
|
|
|
|
//---------------------
|
|
// Resolution/Refresh Rate
|
|
//---------------------
|
|
bestModeIndex=0;
|
|
|
|
if( pDeviceSettingsCombo->pOutputInfo )
|
|
{
|
|
bool bResolutionFound = false;
|
|
float best = FLT_MAX;
|
|
|
|
if ( !pDeviceSettingsCombo->Windowed
|
|
&& !pOptimalDeviceSettings->sd.Windowed
|
|
&& ( pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator > 0 || pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator > 0 ) )
|
|
{
|
|
// Match both Resolution & Refresh Rate
|
|
for( size_t idm = 0; idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.size() && !bResolutionFound; idm++ )
|
|
{
|
|
auto const& displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList[ idm ];
|
|
|
|
float refreshDiff = fabsf( ( float( displayMode.RefreshRate.Numerator ) / float( displayMode.RefreshRate.Denominator ) ) -
|
|
( float( pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator ) / float( pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator ) ) );
|
|
|
|
if( displayMode.Width == pOptimalDeviceSettings->sd.BufferDesc.Width
|
|
&& displayMode.Height == pOptimalDeviceSettings->sd.BufferDesc.Height
|
|
&& ( refreshDiff < 0.1f ) )
|
|
{
|
|
bResolutionFound = true;
|
|
bestModeIndex = static_cast<int>( idm );
|
|
break;
|
|
}
|
|
|
|
float current = refreshDiff
|
|
+ fabsf( float( displayMode.Width ) - float ( pOptimalDeviceSettings->sd.BufferDesc.Width ) )
|
|
+ fabsf( float( displayMode.Height ) - float ( pOptimalDeviceSettings->sd.BufferDesc.Height ) );
|
|
|
|
if( current < best )
|
|
{
|
|
best = current;
|
|
bestModeIndex = static_cast<int>( idm );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Match just Resolution
|
|
for( size_t idm = 0; idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.size() && !bResolutionFound; idm++ )
|
|
{
|
|
auto const& displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList[ idm ];
|
|
|
|
if( displayMode.Width == pOptimalDeviceSettings->sd.BufferDesc.Width
|
|
&& displayMode.Height == pOptimalDeviceSettings->sd.BufferDesc.Height )
|
|
{
|
|
bResolutionFound = true;
|
|
bestModeIndex = static_cast<int>( idm );
|
|
break;
|
|
}
|
|
|
|
float current = fabsf( float( displayMode.Width ) - float ( pOptimalDeviceSettings->sd.BufferDesc.Width ) )
|
|
+ fabsf( float( displayMode.Height ) - float ( pOptimalDeviceSettings->sd.BufferDesc.Height ) );
|
|
|
|
if( current < best )
|
|
{
|
|
best = current;
|
|
bestModeIndex = static_cast<int>( idm );
|
|
}
|
|
}
|
|
}
|
|
|
|
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 = std::max<float>( 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;
|
|
bestMSAAIndex = 0;
|
|
for( size_t i = 0; i < pDeviceSettingsCombo->multiSampleCountList.size(); i++ )
|
|
{
|
|
UINT Count = pDeviceSettingsCombo->multiSampleCountList[ i ];
|
|
|
|
if( Count == pOptimalDeviceSettings->sd.SampleDesc.Count )
|
|
{
|
|
bestMSAAIndex = static_cast<int>( i );
|
|
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
|
|
|
|
//---------------------
|
|
// Present interval
|
|
//---------------------
|
|
// No caps for the present flags
|
|
|
|
return fCurRanking;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------------------
|
|
// Returns the DXGI_MODE_DESC struct for a given adapter and output
|
|
//--------------------------------------------------------------------------------------
|
|
#pragma warning ( suppress : 6101 )
|
|
_Use_decl_annotations_
|
|
HRESULT WINAPI DXUTGetD3D11AdapterDisplayMode( UINT AdapterOrdinal, UINT nOutput, DXGI_MODE_DESC* pModeDesc )
|
|
{
|
|
if( !pModeDesc )
|
|
return E_INVALIDARG;
|
|
|
|
auto pD3DEnum = DXUTGetD3D11Enumeration();
|
|
if ( !pD3DEnum )
|
|
return E_POINTER;
|
|
|
|
auto pOutputInfo = pD3DEnum->GetOutputInfo( AdapterOrdinal, nOutput );
|
|
if( pOutputInfo )
|
|
{
|
|
pModeDesc->Width = 800;
|
|
pModeDesc->Height = 600;
|
|
pModeDesc->RefreshRate.Numerator = 0;
|
|
pModeDesc->RefreshRate.Denominator = 0;
|
|
pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
pModeDesc->Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
|
pModeDesc->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
|
|
|
DXGI_OUTPUT_DESC Desc;
|
|
if ( FAILED(pOutputInfo->m_pOutput->GetDesc(&Desc)))
|
|
memset( &Desc, 0, sizeof(Desc) );
|
|
pModeDesc->Width = Desc.DesktopCoordinates.right - Desc.DesktopCoordinates.left;
|
|
pModeDesc->Height = Desc.DesktopCoordinates.bottom - Desc.DesktopCoordinates.top;
|
|
|
|
// This should not be required with DXGI 1.1 support for BGRA...
|
|
if( pModeDesc->Format == DXGI_FORMAT_B8G8R8A8_UNORM )
|
|
pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|