From 2f7b260d391c4f6d94ace781b336fe531e314bb9 Mon Sep 17 00:00:00 2001 From: Steve Karolewics Date: Thu, 30 Jan 2020 13:18:07 -0500 Subject: [PATCH] Try creating a device with successive adapters until one succeeds. On laptops with integrated+discrete adapters, adapter 0 may not support D3D12, so a default create device call will fail. Adapters other than the 0th one need to be specified explicitly. --- util/test/demos/d3d11/d3d11_test.cpp | 105 ++++++++++++------------ util/test/demos/d3d11/d3d11_test.h | 2 + util/test/demos/d3d12/d3d12_sharing.cpp | 4 +- util/test/demos/d3d12/d3d12_test.cpp | 30 ++++--- util/test/demos/d3d12/d3d12_test.h | 3 +- util/test/demos/dx/d3d_helpers.cpp | 45 ++++++---- util/test/demos/dx/d3d_helpers.h | 4 +- 7 files changed, 112 insertions(+), 81 deletions(-) diff --git a/util/test/demos/d3d11/d3d11_test.cpp b/util/test/demos/d3d11/d3d11_test.cpp index 18c5b3ebb..d30557474 100644 --- a/util/test/demos/d3d11/d3d11_test.cpp +++ b/util/test/demos/d3d11/d3d11_test.cpp @@ -38,7 +38,7 @@ HMODULE d3d11 = NULL; HMODULE dxgi = NULL; HMODULE d3dcompiler = NULL; IDXGIFactoryPtr factory; -IDXGIAdapterPtr adapter; +std::vector adapters; bool warp = false; pD3DCompile dyn_D3DCompile = NULL; @@ -94,7 +94,7 @@ void D3D11GraphicsTest::Prepare(int argc, char **argv) hr = createFactory(__uuidof(IDXGIFactory), (void **)&factory); if(SUCCEEDED(hr)) - adapter = ChooseD3DAdapter(factory, argc, argv, warp); + adapters = FindD3DAdapters(factory, argc, argv, warp); } if(!d3d11) @@ -111,23 +111,23 @@ void D3D11GraphicsTest::Prepare(int argc, char **argv) if(dyn_D3D11CreateDevice) { - ID3D11DevicePtr tempDev; - D3D_FEATURE_LEVEL features[] = {D3D_FEATURE_LEVEL_11_0}; - hr = dyn_D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, features, 1, - D3D11_SDK_VERSION, &tempDev, NULL, NULL); + hr = CreateDevice(adapters, NULL, features, 0); if(SUCCEEDED(hr)) { - tempDev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &opts, sizeof(opts)); + dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &opts, sizeof(opts)); ID3D11Device1Ptr tempDev1; - tempDev1 = tempDev; + tempDev1 = dev; memset(&opts1, 0, sizeof(opts1)); if(tempDev1) tempDev1->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS1, &opts1, sizeof(opts1)); } + + // This device was only used to get feature support. Set it back to NULL + dev = NULL; } } } @@ -138,41 +138,17 @@ bool D3D11GraphicsTest::Init() return false; D3D_FEATURE_LEVEL features[] = {D3D_FEATURE_LEVEL_11_0}; - D3D_DRIVER_TYPE driver = D3D_DRIVER_TYPE_HARDWARE; if(d3d11_1) features[0] = D3D_FEATURE_LEVEL_11_1; - if(warp) - driver = D3D_DRIVER_TYPE_WARP; - - if(adapter) - driver = D3D_DRIVER_TYPE_UNKNOWN; - HRESULT hr = S_OK; UINT flags = createFlags | (debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0); if(headless) { - hr = dyn_D3D11CreateDevice(adapter, driver, NULL, flags, features, 1, D3D11_SDK_VERSION, &dev, - NULL, &ctx); - - // if it failed but on a high feature level, try again on warp - if(FAILED(hr) && features[0] != D3D_FEATURE_LEVEL_11_0) - { - driver = D3D_DRIVER_TYPE_WARP; - hr = dyn_D3D11CreateDevice(adapter, driver, NULL, flags, features, 1, D3D11_SDK_VERSION, &dev, - NULL, &ctx); - } - - // if it failed again on a high feature level, try last on ref - if(FAILED(hr) && features[0] != D3D_FEATURE_LEVEL_11_0) - { - driver = D3D_DRIVER_TYPE_REFERENCE; - hr = dyn_D3D11CreateDevice(adapter, driver, NULL, flags, features, 1, D3D11_SDK_VERSION, &dev, - NULL, &ctx); - } + hr = CreateDevice(adapters, NULL, features, flags); if(FAILED(hr)) { @@ -203,24 +179,7 @@ bool D3D11GraphicsTest::Init() swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapDesc.Flags = 0; - hr = dyn_D3D11CreateDeviceAndSwapChain(adapter, driver, NULL, flags, features, 1, - D3D11_SDK_VERSION, &swapDesc, &swap, &dev, NULL, &ctx); - - // if it failed but on a high feature level, try again on warp - if(FAILED(hr)) - { - driver = D3D_DRIVER_TYPE_WARP; - hr = dyn_D3D11CreateDeviceAndSwapChain(adapter, driver, NULL, flags, features, 1, - D3D11_SDK_VERSION, &swapDesc, &swap, &dev, NULL, &ctx); - } - - // if it failed again on a high feature level, try last on ref - if(FAILED(hr)) - { - driver = D3D_DRIVER_TYPE_REFERENCE; - hr = dyn_D3D11CreateDeviceAndSwapChain(adapter, driver, NULL, flags, features, 1, - D3D11_SDK_VERSION, &swapDesc, &swap, &dev, NULL, &ctx); - } + hr = CreateDevice(adapters, &swapDesc, features, flags); if(FAILED(hr)) { @@ -257,6 +216,50 @@ GraphicsWindow *D3D11GraphicsTest::MakeWindow(int width, int height, const char return new Win32Window(width, height, title); } +HRESULT D3D11GraphicsTest::CreateDevice(std::vector &adaptersToTry, + DXGI_SWAP_CHAIN_DESC *swapDesc, D3D_FEATURE_LEVEL *features, + UINT flags) +{ + HRESULT hr = E_FAIL; + for(size_t i = 0; i < adaptersToTry.size(); ++i) + { + if(swapDesc) + hr = dyn_D3D11CreateDeviceAndSwapChain(adaptersToTry[i], D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, + features, 1, D3D11_SDK_VERSION, swapDesc, &swap, &dev, + NULL, &ctx); + else + hr = dyn_D3D11CreateDevice(adaptersToTry[i], D3D_DRIVER_TYPE_UNKNOWN, NULL, flags, features, + 1, D3D11_SDK_VERSION, &dev, NULL, &ctx); + + if(SUCCEEDED(hr)) + break; + } + + // If it failed, try again on warp + if(FAILED(hr)) + { + if(swapDesc) + hr = dyn_D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, flags, features, 1, + D3D11_SDK_VERSION, swapDesc, &swap, &dev, NULL, &ctx); + else + hr = dyn_D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, flags, features, 1, + D3D11_SDK_VERSION, &dev, NULL, &ctx); + } + + // If it failed again, try last on ref + if(FAILED(hr)) + { + if(swapDesc) + hr = dyn_D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, features, + 1, D3D11_SDK_VERSION, swapDesc, &swap, &dev, NULL, &ctx); + else + hr = dyn_D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, features, 1, + D3D11_SDK_VERSION, &dev, NULL, &ctx); + } + + return hr; +} + void D3D11GraphicsTest::PostDeviceCreate() { { diff --git a/util/test/demos/d3d11/d3d11_test.h b/util/test/demos/d3d11/d3d11_test.h index d57c2abcc..cbcac811a 100644 --- a/util/test/demos/d3d11/d3d11_test.h +++ b/util/test/demos/d3d11/d3d11_test.h @@ -50,6 +50,8 @@ struct D3D11GraphicsTest : public GraphicsTest void Shutdown(); GraphicsWindow *MakeWindow(int width, int height, const char *title); + HRESULT CreateDevice(std::vector &adaptersToTry, DXGI_SWAP_CHAIN_DESC *swapDesc, + D3D_FEATURE_LEVEL *features, UINT flags); void PostDeviceCreate(); enum BufType diff --git a/util/test/demos/d3d12/d3d12_sharing.cpp b/util/test/demos/d3d12/d3d12_sharing.cpp index 3b6d0f0af..6921944ab 100644 --- a/util/test/demos/d3d12/d3d12_sharing.cpp +++ b/util/test/demos/d3d12/d3d12_sharing.cpp @@ -62,11 +62,13 @@ RD_TEST(D3D12_Sharing, D3D12GraphicsTest) IDXGIAdapterPtr pDXGIAdapter; HRESULT hr = EnumAdapterByLuid(dev->GetAdapterLuid(), pDXGIAdapter); + std::vector adapters; + adapters.push_back(pDXGIAdapter); if(FAILED(hr)) return 2; - dev2 = CreateDevice(pDXGIAdapter); + dev2 = CreateDevice(adapters, D3D_FEATURE_LEVEL_11_0); if(!dev2) return 2; diff --git a/util/test/demos/d3d12/d3d12_test.cpp b/util/test/demos/d3d12/d3d12_test.cpp index c3dc8542b..109b0f9b9 100644 --- a/util/test/demos/d3d12/d3d12_test.cpp +++ b/util/test/demos/d3d12/d3d12_test.cpp @@ -39,9 +39,9 @@ HMODULE d3d12 = NULL; HMODULE dxgi = NULL; HMODULE d3dcompiler = NULL; IDXGIFactory1Ptr factory; -IDXGIAdapterPtr adapter; +std::vector adapters; bool d3d12on7 = false; -}; +}; // namespace void D3D12GraphicsTest::Prepare(int argc, char **argv) { @@ -90,13 +90,18 @@ void D3D12GraphicsTest::Prepare(int argc, char **argv) { bool warp = false; - adapter = ChooseD3DAdapter(factory, argc, argv, warp); + adapters = FindD3DAdapters(factory, argc, argv, warp); if(warp && !d3d12on7) { IDXGIFactory4Ptr factory4 = factory; + IDXGIAdapterPtr warpAdapter; if(factory4) - factory4->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&adapter); + { + hr = factory4->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&warpAdapter); + if(SUCCEEDED(hr)) + adapters.push_back(warpAdapter); + } } } } @@ -182,7 +187,7 @@ bool D3D12GraphicsTest::Init() } } - dev = CreateDevice(adapter); + dev = CreateDevice(adapters, D3D_FEATURE_LEVEL_11_0); if(!dev) return false; @@ -420,17 +425,20 @@ HRESULT D3D12GraphicsTest::EnumAdapterByLuid(LUID luid, IDXGIAdapterPtr &pAdapte return E_FAIL; } -ID3D12DevicePtr D3D12GraphicsTest::CreateDevice(IDXGIAdapterPtr a) +ID3D12DevicePtr D3D12GraphicsTest::CreateDevice(std::vector &adaptersToTry, + D3D_FEATURE_LEVEL features) { HRESULT hr = S_OK; - ID3D12DevicePtr ret; + for(size_t i = 0; i < adaptersToTry.size(); ++i) + { + hr = dyn_D3D12CreateDevice(adaptersToTry[i], features, __uuidof(ID3D12Device), (void **)&ret); - hr = dyn_D3D12CreateDevice(a, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void **)&ret); - - if(FAILED(hr)) - TEST_ERROR("D3D12CreateDevice failed: %x", hr); + if(SUCCEEDED(hr)) + return ret; + } + TEST_ERROR("D3D12CreateDevice failed: %x", hr); return ret; } diff --git a/util/test/demos/d3d12/d3d12_test.h b/util/test/demos/d3d12/d3d12_test.h index 1853dcb39..d90fc7186 100644 --- a/util/test/demos/d3d12/d3d12_test.h +++ b/util/test/demos/d3d12/d3d12_test.h @@ -52,7 +52,8 @@ struct D3D12GraphicsTest : public GraphicsTest GraphicsWindow *MakeWindow(int width, int height, const char *title); HRESULT EnumAdapterByLuid(LUID luid, IDXGIAdapterPtr &pAdapter); - ID3D12DevicePtr CreateDevice(IDXGIAdapterPtr adapter); + ID3D12DevicePtr CreateDevice(std::vector &adaptersToTry, + D3D_FEATURE_LEVEL features); enum BufType { diff --git a/util/test/demos/dx/d3d_helpers.cpp b/util/test/demos/dx/d3d_helpers.cpp index 57bfc3f42..e7a4f2447 100644 --- a/util/test/demos/dx/d3d_helpers.cpp +++ b/util/test/demos/dx/d3d_helpers.cpp @@ -23,7 +23,6 @@ ******************************************************************************/ #include "d3d_helpers.h" -#include #include "../test_common.h" std::string D3DFullscreenQuadVertex = R"EOSHADER( @@ -87,7 +86,8 @@ float4 main(v2f IN) : SV_Target0 )EOSHADER"; -IDXGIAdapterPtr ChooseD3DAdapter(IDXGIFactoryPtr factory, int argc, char **argv, bool &warp) +std::vector FindD3DAdapters(IDXGIFactoryPtr factory, int argc, char **argv, + bool &warp) { struct AdapterInfo { @@ -98,31 +98,30 @@ IDXGIAdapterPtr ChooseD3DAdapter(IDXGIFactoryPtr factory, int argc, char **argv, std::vector adapters; HRESULT hr = S_OK; - - for(UINT i = 0; i < 10; i++) { - IDXGIAdapterPtr a; - hr = factory->EnumAdapters(i, &a); - if(hr == S_OK && a) + UINT i = 0; + while(true) { + IDXGIAdapterPtr a; + hr = factory->EnumAdapters(i, &a); + if(hr != S_OK || !a) + break; + DXGI_ADAPTER_DESC desc; a->GetDesc(&desc); adapters.push_back({a, desc}); - } - else - { - break; + i++; } } - IDXGIAdapterPtr adapter = NULL; + IDXGIAdapterPtr specifiedAdapter = NULL; for(int i = 0; i < argc; i++) { if(!strcmp(argv[i], "--warp")) { warp = true; - adapter = NULL; + specifiedAdapter = NULL; break; } if(!strcmp(argv[i], "--gpu") && i + 1 < argc) @@ -132,7 +131,7 @@ IDXGIAdapterPtr ChooseD3DAdapter(IDXGIFactoryPtr factory, int argc, char **argv, if(needle == "warp") { warp = true; - adapter = NULL; + specifiedAdapter = NULL; break; } @@ -149,7 +148,7 @@ IDXGIAdapterPtr ChooseD3DAdapter(IDXGIFactoryPtr factory, int argc, char **argv, (amd && adapters[a].desc.VendorId == PCI_VENDOR_AMD) || (intel && adapters[a].desc.VendorId == PCI_VENDOR_INTEL)) { - adapter = adapters[a].adapter; + specifiedAdapter = adapters[a].adapter; break; } } @@ -158,5 +157,19 @@ IDXGIAdapterPtr ChooseD3DAdapter(IDXGIFactoryPtr factory, int argc, char **argv, } } - return adapter; + // Return the adapters that we want to consider: + // With an adapter specified by command line, only return that one + // With warp specified, return an empty adapter list - fallback will occur + // Otherwise, return all adapters, to be attempted in order + if(specifiedAdapter) + return {specifiedAdapter}; + + if(warp) + return {}; + + std::vector returnedAdapters; + for(size_t i = 0; i < adapters.size(); ++i) + returnedAdapters.push_back(adapters[i].adapter); + + return returnedAdapters; } diff --git a/util/test/demos/dx/d3d_helpers.h b/util/test/demos/dx/d3d_helpers.h index 79ffc3159..33b62ba2c 100644 --- a/util/test/demos/dx/d3d_helpers.h +++ b/util/test/demos/dx/d3d_helpers.h @@ -26,6 +26,7 @@ #include #include +#include #include "dx/official/dxgi1_4.h" extern std::string D3DFullscreenQuadVertex; @@ -43,7 +44,8 @@ COM_SMARTPTR(IDXGIAdapter); COM_SMARTPTR(IDXGISurface); COM_SMARTPTR(IDXGIResource); -IDXGIAdapterPtr ChooseD3DAdapter(IDXGIFactoryPtr factory, int argc, char **argv, bool &warp); +std::vector FindD3DAdapters(IDXGIFactoryPtr factory, int argc, char **argv, + bool &warp); enum class ResourceType {