//-------------------------------------------------------------------------------------- // 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 CD3D11Enumeration::Enumerate( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE IsD3D11DeviceAcceptableFunc, void* pIsD3D11DeviceAcceptableFuncUserContext ) { CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D11 Enumeration" ); HRESULT hr; IDXGIFactory1* pFactory = DXUTGetDXGIFactory(); if( pFactory == NULL ) return E_FAIL; m_bHasEnumerated = true; m_IsD3D11DeviceAcceptableFunc = IsD3D11DeviceAcceptableFunc; m_pIsD3D11DeviceAcceptableFuncUserContext = pIsD3D11DeviceAcceptableFuncUserContext; 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; CD3D11EnumAdapterInfo* pAdapterInfo = new CD3D11EnumAdapterInfo; if( !pAdapterInfo ) { SAFE_RELEASE( pAdapter ); return E_OUTOFMEMORY; } ZeroMemory( pAdapterInfo, sizeof( CD3D11EnumAdapterInfo ) ); pAdapterInfo->AdapterOrdinal = index; pAdapter->GetDesc( &pAdapterInfo->AdapterDesc ); pAdapterInfo->m_pAdapter = pAdapter; // Enumerate the device driver types on the adapter. hr = EnumerateDevices( pAdapterInfo ); if( FAILED( hr ) ) { delete pAdapterInfo; continue; } hr = EnumerateOutputs( pAdapterInfo ); if( FAILED( hr ) || pAdapterInfo->outputInfoList.GetSize() <= 0 ) { delete pAdapterInfo; continue; } // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombos( pFactory, pAdapterInfo ) ) ) { delete pAdapterInfo; continue; } hr = m_AdapterInfoList.Add( pAdapterInfo ); if( FAILED( hr ) ) { delete pAdapterInfo; return hr; } } // If we did not get an adapter then we should still enumerate WARP and Ref. if (m_AdapterInfoList.GetSize() == 0) { CD3D11EnumAdapterInfo* pAdapterInfo = new CD3D11EnumAdapterInfo; if( !pAdapterInfo ) { return E_OUTOFMEMORY; } ZeroMemory( pAdapterInfo, sizeof( CD3D11EnumAdapterInfo ) ); pAdapterInfo->bAdapterUnavailable = true; hr = EnumerateDevices( pAdapterInfo ); // Get info for each devicecombo on this device if( FAILED( hr = EnumerateDeviceCombosNoAdapter( pAdapterInfo ) ) ) { delete pAdapterInfo; } if (!FAILED(hr)) hr = m_AdapterInfoList.Add( pAdapterInfo ); } // // Check for 2 or more adapters with the same name. Append the name // with some instance number if that's the case to help distinguish // them. // bool bUniqueDesc = true; CD3D11EnumAdapterInfo* pAdapterInfo; for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) { CD3D11EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt( i ); for( int j = i + 1; j < m_AdapterInfoList.GetSize(); j++ ) { CD3D11EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt( j ); if( wcsncmp( pAdapterInfo1->AdapterDesc.Description, pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 ) { bUniqueDesc = false; break; } } if( !bUniqueDesc ) break; } for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) { pAdapterInfo = m_AdapterInfoList.GetAt( i ); wcscpy_s( pAdapterInfo->szUniqueDescription, 100, pAdapterInfo->AdapterDesc.Description ); if( !bUniqueDesc ) { WCHAR sz[100]; swprintf_s( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); wcscat_s( pAdapterInfo->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz ); } } return S_OK; }
//-------------------------------------------------------------------------------------- // 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; IDXGIFactory1* 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; } } CD3D11EnumAdapterInfo* 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) { CD3D11EnumAdapterInfo* 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, 100, (*it)->AdapterDesc.Description ); if( !bUniqueDesc ) { WCHAR sz[100]; swprintf_s( sz, 100, L" (#%u)", (*it)->AdapterOrdinal ); wcscat_s( (*it)->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz ); } } D3D_FEATURE_LEVEL fLvl[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 }; // Check WARP max feature level { ID3D11Device* pDevice = nullptr; hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_WARP, 0, 0, fLvl, _countof(fLvl), 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, &fLvl[1], _countof(fLvl) - 1, D3D11_SDK_VERSION, &pDevice, &m_warpFL, nullptr ); } if ( SUCCEEDED(hr) ) { pDevice->Release(); } else m_warpFL = D3D_FEATURE_LEVEL_10_1; } // Check REF max feature level { ID3D11Device* pDevice = nullptr; hr = DXUT_Dynamic_D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_REFERENCE, 0, 0, fLvl, _countof(fLvl), 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, &fLvl[1], _countof(fLvl) - 1, D3D11_SDK_VERSION, &pDevice, &m_refFL, nullptr ); } if ( SUCCEEDED(hr) ) { pDevice->Release(); } else m_refFL = D3D_FEATURE_LEVEL_11_0; } return S_OK; }
//-------------------------------------------------------------------------------------- // Enumerate for each adapter all of the supported display modes, // device types, adapter formats, back buffer formats, window/full screen support, // depth stencil formats, multisampling types/qualities, and presentations intervals. // // For each combination of device type (HAL/REF), adapter format, back buffer format, and // IsWindowed it will call the app's ConfirmDevice callback. This allows the app // to reject or allow that combination based on its caps/etc. It also allows the // app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP // if supported otherwise it will default to SWVP, however the app can change this // through the ConfirmDevice callback. //-------------------------------------------------------------------------------------- HRESULT CD3D9Enumeration::Enumerate( LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE IsD3D9DeviceAcceptableFunc, void* pIsD3D9DeviceAcceptableFuncUserContext ) { CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D9 Enumeration" ); IDirect3D9* pD3D = DXUTGetD3D9Object(); if( pD3D == NULL ) { pD3D = DXUTGetD3D9Object(); if( pD3D == NULL ) return DXUTERR_NODIRECT3D; } m_bHasEnumerated = true; m_pD3D = pD3D; m_IsD3D9DeviceAcceptableFunc = IsD3D9DeviceAcceptableFunc; m_pIsD3D9DeviceAcceptableFuncUserContext = pIsD3D9DeviceAcceptableFuncUserContext; HRESULT hr; ClearAdapterInfoList(); CGrowableArray <D3DFORMAT> adapterFormatList; const D3DFORMAT allowedAdapterFormatArray[] = { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, D3DFMT_A2R10G10B10 }; const UINT allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof ( allowedAdapterFormatArray[0] ); UINT numAdapters = pD3D->GetAdapterCount(); for( UINT adapterOrdinal = 0; adapterOrdinal < numAdapters; adapterOrdinal++ ) { CD3D9EnumAdapterInfo* pAdapterInfo = new CD3D9EnumAdapterInfo; if( pAdapterInfo == NULL ) return E_OUTOFMEMORY; pAdapterInfo->AdapterOrdinal = adapterOrdinal; pD3D->GetAdapterIdentifier( adapterOrdinal, 0, &pAdapterInfo->AdapterIdentifier ); // Get list of all display modes on this adapter. // Also build a temporary list of all display adapter formats. adapterFormatList.RemoveAll(); for( UINT iFormatList = 0; iFormatList < allowedAdapterFormatArrayCount; iFormatList++ ) { D3DFORMAT allowedAdapterFormat = allowedAdapterFormatArray[iFormatList]; UINT numAdapterModes = pD3D->GetAdapterModeCount( adapterOrdinal, allowedAdapterFormat ); for( UINT mode = 0; mode < numAdapterModes; mode++ ) { D3DDISPLAYMODE displayMode; pD3D->EnumAdapterModes( adapterOrdinal, allowedAdapterFormat, mode, &displayMode ); if( displayMode.Width < m_nMinWidth || displayMode.Height < m_nMinHeight || displayMode.Width > m_nMaxWidth || displayMode.Height > m_nMaxHeight || displayMode.RefreshRate < m_nRefreshMin || displayMode.RefreshRate > m_nRefreshMax ) { continue; } pAdapterInfo->displayModeList.Add( displayMode ); if( !adapterFormatList.Contains( displayMode.Format ) ) adapterFormatList.Add( displayMode.Format ); } } D3DDISPLAYMODE displayMode; pD3D->GetAdapterDisplayMode( adapterOrdinal, &displayMode ); if( !adapterFormatList.Contains( displayMode.Format ) ) adapterFormatList.Add( displayMode.Format ); // Sort displaymode list qsort( pAdapterInfo->displayModeList.GetData(), pAdapterInfo->displayModeList.GetSize(), sizeof( D3DDISPLAYMODE ), SortModesCallback ); // Get info for each device on this adapter if( FAILED( EnumerateDevices( pAdapterInfo, &adapterFormatList ) ) ) { delete pAdapterInfo; continue; } // If at least one device on this adapter is available and compatible // with the app, add the adapterInfo to the list if( pAdapterInfo->deviceInfoList.GetSize() > 0 ) { hr = m_AdapterInfoList.Add( pAdapterInfo ); if( FAILED( hr ) ) return hr; } else delete pAdapterInfo; } // // Check for 2 or more adapters with the same name. Append the name // with some instance number if that's the case to help distinguish // them. // bool bUniqueDesc = true; CD3D9EnumAdapterInfo* pAdapterInfo; for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) { CD3D9EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt( i ); for( int j = i + 1; j < m_AdapterInfoList.GetSize(); j++ ) { CD3D9EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt( j ); if( _stricmp( pAdapterInfo1->AdapterIdentifier.Description, pAdapterInfo2->AdapterIdentifier.Description ) == 0 ) { bUniqueDesc = false; break; } } if( !bUniqueDesc ) break; } for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ ) { pAdapterInfo = m_AdapterInfoList.GetAt( i ); MultiByteToWideChar( CP_ACP, 0, pAdapterInfo->AdapterIdentifier.Description, -1, pAdapterInfo->szUniqueDescription, 100 ); pAdapterInfo->szUniqueDescription[100] = 0; if( !bUniqueDesc ) { WCHAR sz[100]; swprintf_s( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal ); wcscat_s( pAdapterInfo->szUniqueDescription, 256, sz ); } } return S_OK; }