1 //--------------------------------------------------------------------------------------
\r
2 // File: DXUTDevice11.cpp
\r
4 // Enumerates D3D adapters, devices, modes, etc.
\r
6 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
7 //--------------------------------------------------------------------------------------
\r
9 #undef min // use __min instead
\r
10 #undef max // use __max instead
\r
12 //--------------------------------------------------------------------------------------
\r
13 // Forward declarations
\r
14 //--------------------------------------------------------------------------------------
\r
15 extern void DXUTGetCallbackD3D11DeviceAcceptable( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE* ppCallbackIsDeviceAcceptable, void** ppUserContext );
\r
17 static int __cdecl SortModesCallback( const void* arg1, const void* arg2 );
\r
19 CD3D11Enumeration* g_pDXUTD3D11Enumeration = NULL;
\r
24 HRESULT WINAPI DXUTCreateD3D11Enumeration()
\r
26 if( g_pDXUTD3D11Enumeration == NULL )
\r
28 g_pDXUTD3D11Enumeration = new CD3D11Enumeration();
\r
29 if( NULL == g_pDXUTD3D11Enumeration )
\r
30 return E_OUTOFMEMORY;
\r
35 void WINAPI DXUTDestroyD3D11Enumeration()
\r
37 SAFE_DELETE( g_pDXUTD3D11Enumeration );
\r
40 class DXUTMemoryHelperD3D11Enum
\r
43 DXUTMemoryHelperD3D11Enum()
\r
45 DXUTCreateD3D11Enumeration();
\r
47 ~DXUTMemoryHelperD3D11Enum()
\r
49 DXUTDestroyD3D11Enumeration();
\r
54 //--------------------------------------------------------------------------------------
\r
55 CD3D11Enumeration* WINAPI DXUTGetD3D11Enumeration( bool bForceEnumerate, bool bEnumerateAllAdapterFormats, D3D_FEATURE_LEVEL forceFL )
\r
57 // Using an static class with accessor function to allow control of the construction order
\r
58 static DXUTMemoryHelperD3D11Enum d3d11enumMemory;
\r
59 if( g_pDXUTD3D11Enumeration && ( !g_pDXUTD3D11Enumeration->HasEnumerated() || bForceEnumerate ) )
\r
61 g_pDXUTD3D11Enumeration->SetEnumerateAllAdapterFormats( bEnumerateAllAdapterFormats );
\r
62 LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE pCallbackIsDeviceAcceptable;
\r
64 DXUTGetCallbackD3D11DeviceAcceptable( &pCallbackIsDeviceAcceptable, &pUserContext );
\r
65 g_pDXUTD3D11Enumeration->SetForceFeatureLevel(forceFL);
\r
67 g_pDXUTD3D11Enumeration->Enumerate( pCallbackIsDeviceAcceptable, pUserContext );
\r
70 return g_pDXUTD3D11Enumeration;
\r
74 //--------------------------------------------------------------------------------------
\r
75 CD3D11Enumeration::CD3D11Enumeration()
\r
77 m_bHasEnumerated = false;
\r
78 m_IsD3D11DeviceAcceptableFunc = NULL;
\r
79 m_pIsD3D11DeviceAcceptableFuncUserContext = NULL;
\r
83 m_nMaxWidth = UINT_MAX;
\r
84 m_nMaxHeight = UINT_MAX;
\r
85 m_bEnumerateAllAdapterFormats = false;
\r
88 m_nRefreshMax = UINT_MAX;
\r
90 ResetPossibleDepthStencilFormats();
\r
94 //--------------------------------------------------------------------------------------
\r
95 CD3D11Enumeration::~CD3D11Enumeration()
\r
97 ClearAdapterInfoList();
\r
101 //--------------------------------------------------------------------------------------
\r
102 // Enumerate for each adapter all of the supported display modes,
\r
103 // device types, adapter formats, back buffer formats, window/full screen support,
\r
104 // depth stencil formats, multisampling types/qualities, and presentations intervals.
\r
106 // For each combination of device type (HAL/REF), adapter format, back buffer format, and
\r
107 // IsWindowed it will call the app's ConfirmDevice callback. This allows the app
\r
108 // to reject or allow that combination based on its caps/etc. It also allows the
\r
109 // app to change the BehaviorFlags. The BehaviorFlags defaults non-pure HWVP
\r
110 // if supported otherwise it will default to SWVP, however the app can change this
\r
111 // through the ConfirmDevice callback.
\r
112 //--------------------------------------------------------------------------------------
\r
113 HRESULT CD3D11Enumeration::Enumerate( LPDXUTCALLBACKISD3D11DEVICEACCEPTABLE IsD3D11DeviceAcceptableFunc,
\r
114 void* pIsD3D11DeviceAcceptableFuncUserContext )
\r
116 CDXUTPerfEventGenerator eventGenerator( DXUT_PERFEVENTCOLOR, L"DXUT D3D11 Enumeration" );
\r
118 IDXGIFactory1* pFactory = DXUTGetDXGIFactory();
\r
119 if( pFactory == NULL )
\r
122 m_bHasEnumerated = true;
\r
123 m_IsD3D11DeviceAcceptableFunc = IsD3D11DeviceAcceptableFunc;
\r
124 m_pIsD3D11DeviceAcceptableFuncUserContext = pIsD3D11DeviceAcceptableFuncUserContext;
\r
126 ClearAdapterInfoList();
\r
128 for( int index = 0; ; ++index )
\r
130 IDXGIAdapter* pAdapter = NULL;
\r
131 hr = pFactory->EnumAdapters( index, &pAdapter );
\r
132 if( FAILED( hr ) ) // DXGIERR_NOT_FOUND is expected when the end of the list is hit
\r
135 CD3D11EnumAdapterInfo* pAdapterInfo = new CD3D11EnumAdapterInfo;
\r
136 if( !pAdapterInfo )
\r
138 SAFE_RELEASE( pAdapter );
\r
139 return E_OUTOFMEMORY;
\r
141 ZeroMemory( pAdapterInfo, sizeof( CD3D11EnumAdapterInfo ) );
\r
142 pAdapterInfo->AdapterOrdinal = index;
\r
143 pAdapter->GetDesc( &pAdapterInfo->AdapterDesc );
\r
144 pAdapterInfo->m_pAdapter = pAdapter;
\r
146 // Enumerate the device driver types on the adapter.
\r
147 hr = EnumerateDevices( pAdapterInfo );
\r
150 delete pAdapterInfo;
\r
154 hr = EnumerateOutputs( pAdapterInfo );
\r
155 if( FAILED( hr ) || pAdapterInfo->outputInfoList.GetSize() <= 0 )
\r
157 delete pAdapterInfo;
\r
161 // Get info for each devicecombo on this device
\r
162 if( FAILED( hr = EnumerateDeviceCombos( pFactory, pAdapterInfo ) ) )
\r
164 delete pAdapterInfo;
\r
168 hr = m_AdapterInfoList.Add( pAdapterInfo );
\r
171 delete pAdapterInfo;
\r
177 // If we did not get an adapter then we should still enumerate WARP and Ref.
\r
178 if (m_AdapterInfoList.GetSize() == 0) {
\r
181 CD3D11EnumAdapterInfo* pAdapterInfo = new CD3D11EnumAdapterInfo;
\r
182 if( !pAdapterInfo )
\r
184 return E_OUTOFMEMORY;
\r
186 ZeroMemory( pAdapterInfo, sizeof( CD3D11EnumAdapterInfo ) );
\r
187 pAdapterInfo->bAdapterUnavailable = true;
\r
189 hr = EnumerateDevices( pAdapterInfo );
\r
191 // Get info for each devicecombo on this device
\r
192 if( FAILED( hr = EnumerateDeviceCombosNoAdapter( pAdapterInfo ) ) )
\r
194 delete pAdapterInfo;
\r
197 if (!FAILED(hr)) hr = m_AdapterInfoList.Add( pAdapterInfo );
\r
201 // Check for 2 or more adapters with the same name. Append the name
\r
202 // with some instance number if that's the case to help distinguish
\r
205 bool bUniqueDesc = true;
\r
206 CD3D11EnumAdapterInfo* pAdapterInfo;
\r
207 for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
\r
209 CD3D11EnumAdapterInfo* pAdapterInfo1 = m_AdapterInfoList.GetAt( i );
\r
211 for( int j = i + 1; j < m_AdapterInfoList.GetSize(); j++ )
\r
213 CD3D11EnumAdapterInfo* pAdapterInfo2 = m_AdapterInfoList.GetAt( j );
\r
214 if( wcsncmp( pAdapterInfo1->AdapterDesc.Description,
\r
215 pAdapterInfo2->AdapterDesc.Description, DXGI_MAX_DEVICE_IDENTIFIER_STRING ) == 0 )
\r
217 bUniqueDesc = false;
\r
226 for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
\r
228 pAdapterInfo = m_AdapterInfoList.GetAt( i );
\r
230 wcscpy_s( pAdapterInfo->szUniqueDescription, 100, pAdapterInfo->AdapterDesc.Description );
\r
234 swprintf_s( sz, 100, L" (#%d)", pAdapterInfo->AdapterOrdinal );
\r
235 wcscat_s( pAdapterInfo->szUniqueDescription, DXGI_MAX_DEVICE_IDENTIFIER_STRING, sz );
\r
243 //--------------------------------------------------------------------------------------
\r
244 HRESULT CD3D11Enumeration::EnumerateOutputs( CD3D11EnumAdapterInfo* pAdapterInfo )
\r
247 IDXGIOutput* pOutput;
\r
249 for( int iOutput = 0; ; ++iOutput )
\r
252 hr = pAdapterInfo->m_pAdapter->EnumOutputs( iOutput, &pOutput );
\r
253 if( DXGI_ERROR_NOT_FOUND == hr )
\r
257 else if( FAILED( hr ) )
\r
259 return hr; //Something bad happened.
\r
263 CD3D11EnumOutputInfo* pOutputInfo = new CD3D11EnumOutputInfo;
\r
266 SAFE_RELEASE( pOutput );
\r
267 return E_OUTOFMEMORY;
\r
269 ZeroMemory( pOutputInfo, sizeof( CD3D11EnumOutputInfo ) );
\r
270 pOutput->GetDesc( &pOutputInfo->Desc );
\r
271 pOutputInfo->Output = iOutput;
\r
272 pOutputInfo->m_pOutput = pOutput;
\r
274 EnumerateDisplayModes( pOutputInfo );
\r
275 if( pOutputInfo->displayModeList.GetSize() <= 0 )
\r
277 // If this output has no valid display mode, do not save it.
\r
278 delete pOutputInfo;
\r
282 hr = pAdapterInfo->outputInfoList.Add( pOutputInfo );
\r
285 delete pOutputInfo;
\r
293 //--------------------------------------------------------------------------------------
\r
294 HRESULT CD3D11Enumeration::EnumerateDisplayModes( CD3D11EnumOutputInfo* pOutputInfo )
\r
297 DXGI_FORMAT allowedAdapterFormatArray[] =
\r
299 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
\r
301 DXGI_FORMAT_R8G8B8A8_UNORM,
\r
302 DXGI_FORMAT_R16G16B16A16_FLOAT,
\r
303 DXGI_FORMAT_R10G10B10A2_UNORM
\r
305 int allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof( allowedAdapterFormatArray[0] );
\r
307 // Swap perferred modes for apps running in linear space
\r
308 DXGI_FORMAT RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
\r
309 if( !DXUTIsInGammaCorrectMode() )
\r
311 allowedAdapterFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
\r
312 allowedAdapterFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
\r
313 RemoteMode = DXGI_FORMAT_R8G8B8A8_UNORM;
\r
316 // The fast path only enumerates R8G8B8A8_UNORM_SRGB modes
\r
317 if( !m_bEnumerateAllAdapterFormats )
\r
318 allowedAdapterFormatArrayCount = 1;
\r
320 for( int f = 0; f < allowedAdapterFormatArrayCount; ++f )
\r
322 // Fast-path: Try to grab at least 512 modes.
\r
323 // This is to avoid calling GetDisplayModeList more times than necessary.
\r
324 // GetDisplayModeList is an expensive call.
\r
325 UINT NumModes = 512;
\r
326 DXGI_MODE_DESC* pDesc = new DXGI_MODE_DESC[ NumModes ];
\r
329 return E_OUTOFMEMORY;
\r
331 hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
\r
332 DXGI_ENUM_MODES_SCALING,
\r
335 if( DXGI_ERROR_NOT_FOUND == hr )
\r
337 SAFE_DELETE_ARRAY( pDesc );
\r
341 else if( MAKE_DXGI_HRESULT( 34 ) == hr && RemoteMode == allowedAdapterFormatArray[f] )
\r
343 // DXGI cannot enumerate display modes over a remote session. Therefore, create a fake display
\r
344 // mode for the current screen resolution for the remote session.
\r
345 if( 0 != GetSystemMetrics( 0x1000 ) ) // SM_REMOTESESSION
\r
348 DevMode.dmSize = sizeof( DEVMODE );
\r
349 if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &DevMode ) )
\r
352 pDesc[0].Width = DevMode.dmPelsWidth;
\r
353 pDesc[0].Height = DevMode.dmPelsHeight;
\r
354 pDesc[0].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
\r
355 pDesc[0].RefreshRate.Numerator = 60;
\r
356 pDesc[0].RefreshRate.Denominator = 1;
\r
357 pDesc[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
\r
358 pDesc[0].Scaling = DXGI_MODE_SCALING_CENTERED;
\r
363 else if( DXGI_ERROR_MORE_DATA == hr )
\r
365 // Slow path. There were more than 512 modes.
\r
366 SAFE_DELETE_ARRAY( pDesc );
\r
367 hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
\r
368 DXGI_ENUM_MODES_SCALING,
\r
377 pDesc = new DXGI_MODE_DESC[ NumModes ];
\r
380 return E_OUTOFMEMORY;
\r
382 hr = pOutputInfo->m_pOutput->GetDisplayModeList( allowedAdapterFormatArray[f],
\r
383 DXGI_ENUM_MODES_SCALING,
\r
388 SAFE_DELETE_ARRAY( pDesc );
\r
395 if( 0 == NumModes && 0 == f )
\r
397 // No R8G8B8A8_UNORM_SRGB modes!
\r
398 // Abort the fast-path if we're on it
\r
399 allowedAdapterFormatArrayCount = sizeof( allowedAdapterFormatArray ) / sizeof
\r
400 ( allowedAdapterFormatArray[0] );
\r
401 SAFE_DELETE_ARRAY( pDesc );
\r
405 if( SUCCEEDED( hr ) )
\r
407 for( UINT m = 0; m < NumModes; m++ )
\r
409 pOutputInfo->displayModeList.Add( pDesc[m] );
\r
413 SAFE_DELETE_ARRAY( pDesc );
\r
420 //--------------------------------------------------------------------------------------
\r
421 HRESULT CD3D11Enumeration::EnumerateDevices( CD3D11EnumAdapterInfo* pAdapterInfo )
\r
424 DXUTDeviceSettings deviceSettings = DXUTGetDeviceSettings();
\r
425 const D3D_DRIVER_TYPE devTypeArray[] =
\r
427 D3D_DRIVER_TYPE_HARDWARE,
\r
428 D3D_DRIVER_TYPE_WARP,
\r
429 D3D_DRIVER_TYPE_REFERENCE
\r
431 const UINT devTypeArrayCount = sizeof( devTypeArray ) / sizeof( devTypeArray[0] );
\r
433 // Enumerate each Direct3D device type
\r
434 for( UINT iDeviceType = 0; iDeviceType < devTypeArrayCount; iDeviceType++ )
\r
436 CD3D11EnumDeviceInfo* pDeviceInfo = new CD3D11EnumDeviceInfo;
\r
437 if( pDeviceInfo == NULL )
\r
438 return E_OUTOFMEMORY;
\r
440 // Fill struct w/ AdapterOrdinal and D3DX10_DRIVER_TYPE
\r
441 pDeviceInfo->AdapterOrdinal = pAdapterInfo->AdapterOrdinal;
\r
442 pDeviceInfo->DeviceType = devTypeArray[iDeviceType];
\r
444 D3D_FEATURE_LEVEL FeatureLevels[] =
\r
446 D3D_FEATURE_LEVEL_11_0,
\r
447 D3D_FEATURE_LEVEL_10_1,
\r
448 D3D_FEATURE_LEVEL_10_0,
\r
449 D3D_FEATURE_LEVEL_9_3,
\r
450 D3D_FEATURE_LEVEL_9_2,
\r
451 D3D_FEATURE_LEVEL_9_1
\r
453 UINT NumFeatureLevels = ARRAYSIZE( FeatureLevels );
\r
455 // Call D3D11CreateDevice to ensure that this is a D3D11 device.
\r
456 ID3D11Device* pd3dDevice = NULL;
\r
457 ID3D11DeviceContext* pd3dDeviceContext = NULL;
\r
458 IDXGIAdapter* pAdapter = NULL;
\r
459 //if( devTypeArray[iDeviceType] == D3D_DRIVER_TYPE_HARDWARE )
\r
460 // pAdapter = pAdapterInfo->m_pAdapter;
\r
461 hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter,
\r
462 devTypeArray[iDeviceType],
\r
469 &pDeviceInfo->MaxLevel,
\r
470 &pd3dDeviceContext );
\r
471 if( FAILED( hr ) || pDeviceInfo->MaxLevel < deviceSettings.MinimumFeatureLevel)
\r
473 delete pDeviceInfo;
\r
477 if (g_forceFL == 0 || g_forceFL == pDeviceInfo->MaxLevel) {
\r
478 pDeviceInfo->SelectedLevel = pDeviceInfo->MaxLevel;
\r
480 else if (g_forceFL > pDeviceInfo->MaxLevel) {
\r
481 delete pDeviceInfo;
\r
482 SAFE_RELEASE( pd3dDevice );
\r
483 SAFE_RELEASE( pd3dDeviceContext );
\r
486 // A device was created with a higher feature level that the user-specified feature level.
\r
487 SAFE_RELEASE( pd3dDevice );
\r
488 SAFE_RELEASE( pd3dDeviceContext );
\r
489 D3D_FEATURE_LEVEL rtFL;
\r
490 hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter,
\r
491 devTypeArray[iDeviceType],
\r
499 &pd3dDeviceContext );
\r
501 if( !FAILED( hr ) && rtFL == g_forceFL ) {
\r
503 pDeviceInfo->SelectedLevel = g_forceFL;
\r
505 delete pDeviceInfo;
\r
506 SAFE_RELEASE( pd3dDevice );
\r
507 SAFE_RELEASE( pd3dDeviceContext );
\r
512 IDXGIDevice1* pDXGIDev = NULL;
\r
513 hr = pd3dDevice->QueryInterface( __uuidof( IDXGIDevice1 ), ( LPVOID* )&pDXGIDev );
\r
514 if( SUCCEEDED( hr ) && pDXGIDev )
\r
516 SAFE_RELEASE( pAdapterInfo->m_pAdapter );
\r
517 pDXGIDev->GetAdapter( &pAdapterInfo->m_pAdapter );
\r
519 SAFE_RELEASE( pDXGIDev );
\r
522 D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS ho;
\r
523 pd3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &ho, sizeof(ho));
\r
524 pDeviceInfo->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = ho.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x;
\r
525 SAFE_RELEASE( pd3dDeviceContext );
\r
526 SAFE_RELEASE( pd3dDevice );
\r
527 pAdapterInfo->deviceInfoList.Add( pDeviceInfo );
\r
534 HRESULT CD3D11Enumeration::EnumerateDeviceCombosNoAdapter( CD3D11EnumAdapterInfo* pAdapterInfo )
\r
536 // Iterate through each combination of device driver type, output,
\r
537 // adapter format, and backbuffer format to build the adapter's device combo list.
\r
540 for( int device = 0; device < pAdapterInfo->deviceInfoList.GetSize(); ++device )
\r
542 CD3D11EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( device );
\r
544 DXGI_FORMAT BufferFormatArray[] =
\r
546 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
\r
548 DXGI_FORMAT_R8G8B8A8_UNORM,
\r
549 DXGI_FORMAT_R16G16B16A16_FLOAT,
\r
550 DXGI_FORMAT_R10G10B10A2_UNORM
\r
552 const UINT BufferFormatArrayCount = sizeof( BufferFormatArray ) / sizeof
\r
553 ( BufferFormatArray[0] );
\r
555 // Swap perferred modes for apps running in linear space
\r
556 if( !DXUTIsInGammaCorrectMode() )
\r
558 BufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
\r
559 BufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
\r
562 for( UINT iBufferFormat = 0; iBufferFormat < BufferFormatArrayCount; iBufferFormat++ )
\r
564 DXGI_FORMAT BufferFormat = BufferFormatArray[iBufferFormat];
\r
568 // determine if there are any modes for this particular format
\r
571 // If an application callback function has been provided, make sure this device
\r
572 // is acceptable to the app.
\r
573 if( m_IsD3D11DeviceAcceptableFunc != NULL )
\r
575 if( !m_IsD3D11DeviceAcceptableFunc( pAdapterInfo,
\r
580 m_pIsD3D11DeviceAcceptableFuncUserContext ) )
\r
584 // At this point, we have an adapter/device/backbufferformat/iswindowed
\r
585 // DeviceCombo that is supported by the system. We still
\r
586 // need to find one or more suitable depth/stencil buffer format,
\r
587 // multisample type, and present interval.
\r
588 CD3D11EnumDeviceSettingsCombo* pDeviceCombo = new CD3D11EnumDeviceSettingsCombo;
\r
589 if( pDeviceCombo == NULL )
\r
590 return E_OUTOFMEMORY;
\r
592 pDeviceCombo->AdapterOrdinal = pDeviceInfo->AdapterOrdinal;
\r
593 pDeviceCombo->DeviceType = pDeviceInfo->DeviceType;
\r
594 pDeviceCombo->BackBufferFormat = BufferFormat;
\r
595 pDeviceCombo->Windowed = TRUE;
\r
596 pDeviceCombo->Output = 0;
\r
597 pDeviceCombo->pAdapterInfo = pAdapterInfo;
\r
598 pDeviceCombo->pDeviceInfo = pDeviceInfo;
\r
599 pDeviceCombo->pOutputInfo = NULL;
\r
601 BuildMultiSampleQualityList( BufferFormat, pDeviceCombo );
\r
603 if( FAILED( pAdapterInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) )
\r
604 delete pDeviceCombo;
\r
614 //--------------------------------------------------------------------------------------
\r
615 HRESULT CD3D11Enumeration::EnumerateDeviceCombos( IDXGIFactory1* pFactory, CD3D11EnumAdapterInfo* pAdapterInfo )
\r
617 // Iterate through each combination of device driver type, output,
\r
618 // adapter format, and backbuffer format to build the adapter's device combo list.
\r
621 for( int output = 0; output < pAdapterInfo->outputInfoList.GetSize(); ++output )
\r
623 CD3D11EnumOutputInfo* pOutputInfo = pAdapterInfo->outputInfoList.GetAt( output );
\r
625 for( int device = 0; device < pAdapterInfo->deviceInfoList.GetSize(); ++device )
\r
627 CD3D11EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( device );
\r
629 DXGI_FORMAT backBufferFormatArray[] =
\r
631 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, //This is DXUT's preferred mode
\r
633 DXGI_FORMAT_R8G8B8A8_UNORM,
\r
634 DXGI_FORMAT_R16G16B16A16_FLOAT,
\r
635 DXGI_FORMAT_R10G10B10A2_UNORM
\r
637 const UINT backBufferFormatArrayCount = sizeof( backBufferFormatArray ) / sizeof
\r
638 ( backBufferFormatArray[0] );
\r
640 // Swap perferred modes for apps running in linear space
\r
641 if( !DXUTIsInGammaCorrectMode() )
\r
643 backBufferFormatArray[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
\r
644 backBufferFormatArray[1] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
\r
647 for( UINT iBackBufferFormat = 0; iBackBufferFormat < backBufferFormatArrayCount; iBackBufferFormat++ )
\r
649 DXGI_FORMAT backBufferFormat = backBufferFormatArray[iBackBufferFormat];
\r
651 for( int nWindowed = 0; nWindowed < 2; nWindowed++ )
\r
653 if( !nWindowed && pOutputInfo->displayModeList.GetSize() == 0 )
\r
656 // determine if there are any modes for this particular format
\r
658 for( int i = 0; i < pOutputInfo->displayModeList.GetSize(); i++ )
\r
660 if( backBufferFormat == pOutputInfo->displayModeList.GetAt( i ).Format )
\r
666 // If an application callback function has been provided, make sure this device
\r
667 // is acceptable to the app.
\r
668 if( m_IsD3D11DeviceAcceptableFunc != NULL )
\r
670 if( !m_IsD3D11DeviceAcceptableFunc( pAdapterInfo, output,
\r
671 pDeviceInfo, backBufferFormat,
\r
672 FALSE != nWindowed,
\r
673 m_pIsD3D11DeviceAcceptableFuncUserContext ) )
\r
677 // At this point, we have an adapter/device/backbufferformat/iswindowed
\r
678 // DeviceCombo that is supported by the system. We still
\r
679 // need to find one or more suitable depth/stencil buffer format,
\r
680 // multisample type, and present interval.
\r
681 CD3D11EnumDeviceSettingsCombo* pDeviceCombo = new CD3D11EnumDeviceSettingsCombo;
\r
682 if( pDeviceCombo == NULL )
\r
683 return E_OUTOFMEMORY;
\r
685 pDeviceCombo->AdapterOrdinal = pDeviceInfo->AdapterOrdinal;
\r
686 pDeviceCombo->DeviceType = pDeviceInfo->DeviceType;
\r
687 pDeviceCombo->BackBufferFormat = backBufferFormat;
\r
688 pDeviceCombo->Windowed = ( nWindowed != 0 );
\r
689 pDeviceCombo->Output = pOutputInfo->Output;
\r
690 pDeviceCombo->pAdapterInfo = pAdapterInfo;
\r
691 pDeviceCombo->pDeviceInfo = pDeviceInfo;
\r
692 pDeviceCombo->pOutputInfo = pOutputInfo;
\r
694 BuildMultiSampleQualityList( backBufferFormat, pDeviceCombo );
\r
696 if( FAILED( pAdapterInfo->deviceSettingsComboList.Add( pDeviceCombo ) ) )
\r
697 delete pDeviceCombo;
\r
707 //--------------------------------------------------------------------------------------
\r
708 // Release all the allocated CD3D11EnumAdapterInfo objects and empty the list
\r
709 //--------------------------------------------------------------------------------------
\r
710 void CD3D11Enumeration::ClearAdapterInfoList()
\r
712 CD3D11EnumAdapterInfo* pAdapterInfo;
\r
713 for( int i = 0; i < m_AdapterInfoList.GetSize(); i++ )
\r
715 pAdapterInfo = m_AdapterInfoList.GetAt( i );
\r
716 delete pAdapterInfo;
\r
719 m_AdapterInfoList.RemoveAll();
\r
723 //--------------------------------------------------------------------------------------
\r
724 void CD3D11Enumeration::ResetPossibleDepthStencilFormats()
\r
726 m_DepthStencilPossibleList.RemoveAll();
\r
727 m_DepthStencilPossibleList.Add( DXGI_FORMAT_D32_FLOAT_S8X24_UINT );
\r
728 m_DepthStencilPossibleList.Add( DXGI_FORMAT_D32_FLOAT );
\r
729 m_DepthStencilPossibleList.Add( DXGI_FORMAT_D24_UNORM_S8_UINT );
\r
730 m_DepthStencilPossibleList.Add( DXGI_FORMAT_D16_UNORM );
\r
733 //--------------------------------------------------------------------------------------
\r
734 void CD3D11Enumeration::SetEnumerateAllAdapterFormats( bool bEnumerateAllAdapterFormats )
\r
736 m_bEnumerateAllAdapterFormats = bEnumerateAllAdapterFormats;
\r
740 //--------------------------------------------------------------------------------------
\r
741 void CD3D11Enumeration::BuildMultiSampleQualityList( DXGI_FORMAT fmt, CD3D11EnumDeviceSettingsCombo* pDeviceCombo )
\r
743 ID3D11Device* pd3dDevice = NULL;
\r
744 ID3D11DeviceContext* pd3dDeviceContext = NULL;
\r
745 IDXGIAdapter* pAdapter = NULL;
\r
747 //if( pDeviceCombo->DeviceType == D3D_DRIVER_TYPE_HARDWARE )
\r
748 // DXUTGetDXGIFactory()->EnumAdapters( pDeviceCombo->pAdapterInfo->AdapterOrdinal, &pAdapter );
\r
750 //DXGI_ADAPTER_DESC dad;
\r
751 //pAdapter->GetDesc(&dad);
\r
753 D3D_FEATURE_LEVEL *FeatureLevels = &(pDeviceCombo->pDeviceInfo->SelectedLevel);
\r
754 D3D_FEATURE_LEVEL returnedFeatureLevel;
\r
756 UINT NumFeatureLevels = 1;
\r
758 HRESULT hr = DXUT_Dynamic_D3D11CreateDevice( pAdapter,
\r
759 pDeviceCombo->DeviceType,
\r
766 &returnedFeatureLevel,
\r
767 &pd3dDeviceContext ) ;
\r
769 if( FAILED( hr)) return;
\r
771 if (returnedFeatureLevel != pDeviceCombo->pDeviceInfo->SelectedLevel) return;
\r
773 for( int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; ++i )
\r
776 if( SUCCEEDED( pd3dDevice->CheckMultisampleQualityLevels( fmt, i, &Quality ) ) && Quality > 0 )
\r
778 //From D3D10 docs: When multisampling a texture, the number of quality levels available for an adapter is dependent on the texture
\r
779 //format used and the number of samples requested. The maximum sample count is defined by
\r
780 //D3D10_MAX_MULTISAMPLE_SAMPLE_COUNT in d3d10.h. If the returned value of pNumQualityLevels is 0,
\r
781 //the format and sample count combination is not supported for the installed adapter.
\r
783 if (Quality != 0) {
\r
784 pDeviceCombo->multiSampleCountList.Add( i );
\r
785 pDeviceCombo->multiSampleQualityList.Add( Quality );
\r
790 SAFE_RELEASE( pAdapter );
\r
791 SAFE_RELEASE( pd3dDevice );
\r
792 SAFE_RELEASE (pd3dDeviceContext);
\r
796 //--------------------------------------------------------------------------------------
\r
797 // Call GetAdapterInfoList() after Enumerate() to get a STL vector of
\r
798 // CD3D11EnumAdapterInfo*
\r
799 //--------------------------------------------------------------------------------------
\r
800 CGrowableArray <CD3D11EnumAdapterInfo*>* CD3D11Enumeration::GetAdapterInfoList()
\r
802 return &m_AdapterInfoList;
\r
806 //--------------------------------------------------------------------------------------
\r
807 CD3D11EnumAdapterInfo* CD3D11Enumeration::GetAdapterInfo( UINT AdapterOrdinal )
\r
809 for( int iAdapter = 0; iAdapter < m_AdapterInfoList.GetSize(); iAdapter++ )
\r
811 CD3D11EnumAdapterInfo* pAdapterInfo = m_AdapterInfoList.GetAt( iAdapter );
\r
812 if( pAdapterInfo->AdapterOrdinal == AdapterOrdinal )
\r
813 return pAdapterInfo;
\r
820 //--------------------------------------------------------------------------------------
\r
821 CD3D11EnumDeviceInfo* CD3D11Enumeration::GetDeviceInfo( UINT AdapterOrdinal, D3D_DRIVER_TYPE DeviceType )
\r
823 CD3D11EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
\r
826 for( int iDeviceInfo = 0; iDeviceInfo < pAdapterInfo->deviceInfoList.GetSize(); iDeviceInfo++ )
\r
828 CD3D11EnumDeviceInfo* pDeviceInfo = pAdapterInfo->deviceInfoList.GetAt( iDeviceInfo );
\r
829 if( pDeviceInfo->DeviceType == DeviceType )
\r
830 return pDeviceInfo;
\r
838 //--------------------------------------------------------------------------------------
\r
839 CD3D11EnumOutputInfo* CD3D11Enumeration::GetOutputInfo( UINT AdapterOrdinal, UINT Output )
\r
841 CD3D11EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
\r
842 if( pAdapterInfo && pAdapterInfo->outputInfoList.GetSize() > int( Output ) )
\r
844 return pAdapterInfo->outputInfoList.GetAt( Output );
\r
851 //--------------------------------------------------------------------------------------
\r
852 CD3D11EnumDeviceSettingsCombo* CD3D11Enumeration::GetDeviceSettingsCombo( UINT AdapterOrdinal,
\r
853 D3D_DRIVER_TYPE DeviceType, UINT Output,
\r
854 DXGI_FORMAT BackBufferFormat, BOOL Windowed )
\r
856 CD3D11EnumAdapterInfo* pAdapterInfo = GetAdapterInfo( AdapterOrdinal );
\r
859 for( int iDeviceCombo = 0; iDeviceCombo < pAdapterInfo->deviceSettingsComboList.GetSize(); iDeviceCombo++ )
\r
861 CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo = pAdapterInfo->deviceSettingsComboList.GetAt(
\r
863 if( pDeviceSettingsCombo->BackBufferFormat == BackBufferFormat &&
\r
864 pDeviceSettingsCombo->Windowed == Windowed )
\r
865 return pDeviceSettingsCombo;
\r
873 //--------------------------------------------------------------------------------------
\r
874 CD3D11EnumOutputInfo::~CD3D11EnumOutputInfo( void )
\r
876 SAFE_RELEASE( m_pOutput );
\r
877 displayModeList.RemoveAll();
\r
881 //--------------------------------------------------------------------------------------
\r
882 CD3D11EnumDeviceInfo::~CD3D11EnumDeviceInfo()
\r
887 //--------------------------------------------------------------------------------------
\r
888 CD3D11EnumAdapterInfo::~CD3D11EnumAdapterInfo( void )
\r
890 for( int i = 0; i < outputInfoList.GetSize(); i++ )
\r
892 CD3D11EnumOutputInfo* pOutputInfo = outputInfoList.GetAt( i );
\r
893 delete pOutputInfo;
\r
895 outputInfoList.RemoveAll();
\r
897 for( int i = 0; i < deviceInfoList.GetSize(); ++i )
\r
899 CD3D11EnumDeviceInfo* pDeviceInfo = deviceInfoList.GetAt( i );
\r
900 delete pDeviceInfo;
\r
902 deviceInfoList.RemoveAll();
\r
904 for( int i = 0; i < deviceSettingsComboList.GetSize(); ++i )
\r
906 CD3D11EnumDeviceSettingsCombo* pDeviceCombo = deviceSettingsComboList.GetAt( i );
\r
907 delete pDeviceCombo;
\r
909 deviceSettingsComboList.RemoveAll();
\r
911 SAFE_RELEASE( m_pAdapter );
\r
914 //--------------------------------------------------------------------------------------
\r
915 // Returns the number of color channel bits in the specified DXGI_FORMAT
\r
916 //--------------------------------------------------------------------------------------
\r
917 UINT WINAPI DXUTGetDXGIColorChannelBits( DXGI_FORMAT fmt )
\r
921 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
\r
922 case DXGI_FORMAT_R32G32B32A32_FLOAT:
\r
923 case DXGI_FORMAT_R32G32B32A32_UINT:
\r
924 case DXGI_FORMAT_R32G32B32A32_SINT:
\r
925 case DXGI_FORMAT_R32G32B32_TYPELESS:
\r
926 case DXGI_FORMAT_R32G32B32_FLOAT:
\r
927 case DXGI_FORMAT_R32G32B32_UINT:
\r
928 case DXGI_FORMAT_R32G32B32_SINT:
\r
931 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
\r
932 case DXGI_FORMAT_R16G16B16A16_FLOAT:
\r
933 case DXGI_FORMAT_R16G16B16A16_UNORM:
\r
934 case DXGI_FORMAT_R16G16B16A16_UINT:
\r
935 case DXGI_FORMAT_R16G16B16A16_SNORM:
\r
936 case DXGI_FORMAT_R16G16B16A16_SINT:
\r
939 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
\r
940 case DXGI_FORMAT_R10G10B10A2_UNORM:
\r
941 case DXGI_FORMAT_R10G10B10A2_UINT:
\r
944 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
\r
945 case DXGI_FORMAT_R8G8B8A8_UNORM:
\r
946 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
\r
947 case DXGI_FORMAT_R8G8B8A8_UINT:
\r
948 case DXGI_FORMAT_R8G8B8A8_SNORM:
\r
949 case DXGI_FORMAT_R8G8B8A8_SINT:
\r
952 case DXGI_FORMAT_B5G6R5_UNORM:
\r
953 case DXGI_FORMAT_B5G5R5A1_UNORM:
\r
961 //--------------------------------------------------------------------------------------
\r
962 // Returns a ranking number that describes how closely this device
\r
963 // combo matches the optimal combo based on the match options and the optimal device settings
\r
964 //--------------------------------------------------------------------------------------
\r
965 float DXUTRankD3D11DeviceCombo( CD3D11EnumDeviceSettingsCombo* pDeviceSettingsCombo,
\r
966 DXUTD3D11DeviceSettings* pOptimalDeviceSettings,
\r
967 DXGI_MODE_DESC* pAdapterDisplayMode,
\r
968 int &bestModeIndex,
\r
972 float fCurRanking = 0.0f;
\r
974 // Arbitrary weights. Gives preference to the ordinal, device type, and windowed
\r
975 const float fAdapterOrdinalWeight = 1000.0f;
\r
976 const float fAdapterOutputWeight = 500.0f;
\r
977 const float fDeviceTypeWeight = 100.0f;
\r
978 const float fWARPOverRefWeight = 80.0f;
\r
980 const float fWindowWeight = 10.0f;
\r
981 const float fResolutionWeight = 1.0f;
\r
982 const float fBackBufferFormatWeight = 1.0f;
\r
983 const float fMultiSampleWeight = 1.0f;
\r
984 const float fRefreshRateWeight = 1.0f;
\r
986 //---------------------
\r
988 //---------------------
\r
989 if( pDeviceSettingsCombo->AdapterOrdinal == pOptimalDeviceSettings->AdapterOrdinal )
\r
990 fCurRanking += fAdapterOrdinalWeight;
\r
992 //---------------------
\r
994 //---------------------
\r
995 if( pDeviceSettingsCombo->Output == pOptimalDeviceSettings->Output )
\r
996 fCurRanking += fAdapterOutputWeight;
\r
998 //---------------------
\r
1000 //---------------------
\r
1001 if( pDeviceSettingsCombo->DeviceType == pOptimalDeviceSettings->DriverType )
\r
1002 fCurRanking += fDeviceTypeWeight;
\r
1003 else if (pDeviceSettingsCombo->DeviceType == D3D_DRIVER_TYPE_WARP && pOptimalDeviceSettings->DriverType == D3D_DRIVER_TYPE_HARDWARE) {
\r
1004 fCurRanking += fWARPOverRefWeight;
\r
1007 // Slightly prefer HAL
\r
1008 if( pDeviceSettingsCombo->DeviceType == D3DDEVTYPE_HAL )
\r
1009 fCurRanking += 0.1f;
\r
1011 //---------------------
\r
1013 //---------------------
\r
1014 if( pDeviceSettingsCombo->Windowed == pOptimalDeviceSettings->sd.Windowed )
\r
1015 fCurRanking += fWindowWeight;
\r
1017 //---------------------
\r
1019 //---------------------
\r
1020 bool bResolutionFound = false;
\r
1021 unsigned int best = 0xffffffff;
\r
1023 for( int idm = 0; pDeviceSettingsCombo->pOutputInfo != NULL && idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize() && !bResolutionFound; idm++ )
\r
1025 DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm );
\r
1026 if( displayMode.Width == pOptimalDeviceSettings->sd.BufferDesc.Width &&
\r
1027 displayMode.Height == pOptimalDeviceSettings->sd.BufferDesc.Height )
\r
1028 bResolutionFound = true;
\r
1030 unsigned int current =
\r
1031 (UINT) abs ((int)displayMode.Width - (int)pOptimalDeviceSettings->sd.BufferDesc.Width) +
\r
1032 (UINT) abs ((int)displayMode.Height - (int)pOptimalDeviceSettings->sd.BufferDesc.Height );
\r
1034 if (current < best) {
\r
1036 bestModeIndex= idm;
\r
1041 if( bResolutionFound )
\r
1042 fCurRanking += fResolutionWeight;
\r
1044 //---------------------
\r
1045 // Back buffer format
\r
1046 //---------------------
\r
1047 if( pDeviceSettingsCombo->BackBufferFormat == pOptimalDeviceSettings->sd.BufferDesc.Format )
\r
1049 fCurRanking += fBackBufferFormatWeight;
\r
1053 int nBitDepthDelta = abs( ( long )DXUTGetDXGIColorChannelBits( pDeviceSettingsCombo->BackBufferFormat ) -
\r
1054 ( long )DXUTGetDXGIColorChannelBits(
\r
1055 pOptimalDeviceSettings->sd.BufferDesc.Format ) );
\r
1056 float fScale = __max( 0.9f - ( float )nBitDepthDelta * 0.2f, 0.0f );
\r
1057 fCurRanking += fScale * fBackBufferFormatWeight;
\r
1060 //---------------------
\r
1061 // Back buffer count
\r
1062 //---------------------
\r
1063 // No caps for the back buffer count
\r
1065 //---------------------
\r
1067 //---------------------
\r
1068 bool bMultiSampleFound = false;
\r
1069 bestMSAAIndex = 0;
\r
1070 for( int i = 0; i < pDeviceSettingsCombo->multiSampleCountList.GetSize(); i++ )
\r
1072 UINT Count = pDeviceSettingsCombo->multiSampleCountList.GetAt( i );
\r
1074 if( Count == pOptimalDeviceSettings->sd.SampleDesc.Count )
\r
1076 bestMSAAIndex = i;
\r
1077 bMultiSampleFound = true;
\r
1081 if( bMultiSampleFound )
\r
1082 fCurRanking += fMultiSampleWeight;
\r
1084 //---------------------
\r
1086 //---------------------
\r
1087 // No caps for swap effects
\r
1089 //---------------------
\r
1091 //---------------------
\r
1092 // No caps for swap effects
\r
1094 //---------------------
\r
1096 //---------------------
\r
1097 // No caps for the present flags
\r
1099 //---------------------
\r
1101 //---------------------
\r
1102 bool bRefreshFound = false;
\r
1103 for( int idm = 0; pDeviceSettingsCombo->pOutputInfo != NULL && idm < pDeviceSettingsCombo->pOutputInfo->displayModeList.GetSize(); idm++ )
\r
1105 DXGI_MODE_DESC displayMode = pDeviceSettingsCombo->pOutputInfo->displayModeList.GetAt( idm );
\r
1106 if( fabs( float( displayMode.RefreshRate.Numerator ) / displayMode.RefreshRate.Denominator -
\r
1107 float( pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Numerator ) /
\r
1108 pOptimalDeviceSettings->sd.BufferDesc.RefreshRate.Denominator ) < 0.1f )
\r
1109 bRefreshFound = true;
\r
1111 if( bRefreshFound )
\r
1112 fCurRanking += fRefreshRateWeight;
\r
1114 //---------------------
\r
1115 // Present interval
\r
1116 //---------------------
\r
1117 // No caps for the present flags
\r
1119 return fCurRanking;
\r
1123 //--------------------------------------------------------------------------------------
\r
1124 // Returns the DXGI_MODE_DESC struct for a given adapter and output
\r
1125 //--------------------------------------------------------------------------------------
\r
1126 HRESULT WINAPI DXUTGetD3D11AdapterDisplayMode( UINT AdapterOrdinal, UINT nOutput, DXGI_MODE_DESC* pModeDesc )
\r
1129 return E_INVALIDARG;
\r
1131 CD3D11Enumeration* pD3DEnum = DXUTGetD3D11Enumeration();
\r
1132 CD3D11EnumOutputInfo* pOutputInfo = pD3DEnum->GetOutputInfo( AdapterOrdinal, nOutput );
\r
1135 pModeDesc->Width = 640;
\r
1136 pModeDesc->Height = 480;
\r
1137 pModeDesc->RefreshRate.Numerator = 60;
\r
1138 pModeDesc->RefreshRate.Denominator = 1;
\r
1139 pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
\r
1140 pModeDesc->Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
\r
1141 pModeDesc->ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
\r
1143 DXGI_OUTPUT_DESC Desc;
\r
1144 pOutputInfo->m_pOutput->GetDesc( &Desc );
\r
1145 pModeDesc->Width = Desc.DesktopCoordinates.right - Desc.DesktopCoordinates.left;
\r
1146 pModeDesc->Height = Desc.DesktopCoordinates.bottom - Desc.DesktopCoordinates.top;
\r
1149 // TODO: verify this is needed
\r
1150 if( pModeDesc->Format == DXGI_FORMAT_B8G8R8A8_UNORM )
\r
1151 pModeDesc->Format = DXGI_FORMAT_R8G8B8A8_UNORM;
\r