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.
This commit is contained in:
Steve Karolewics
2020-01-30 13:18:07 -05:00
committed by Baldur Karlsson
parent 385121d2ca
commit 2f7b260d39
7 changed files with 112 additions and 81 deletions
+54 -51
View File
@@ -38,7 +38,7 @@ HMODULE d3d11 = NULL;
HMODULE dxgi = NULL;
HMODULE d3dcompiler = NULL;
IDXGIFactoryPtr factory;
IDXGIAdapterPtr adapter;
std::vector<IDXGIAdapterPtr> 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<IDXGIAdapterPtr> &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()
{
{
+2
View File
@@ -50,6 +50,8 @@ struct D3D11GraphicsTest : public GraphicsTest
void Shutdown();
GraphicsWindow *MakeWindow(int width, int height, const char *title);
HRESULT CreateDevice(std::vector<IDXGIAdapterPtr> &adaptersToTry, DXGI_SWAP_CHAIN_DESC *swapDesc,
D3D_FEATURE_LEVEL *features, UINT flags);
void PostDeviceCreate();
enum BufType
+3 -1
View File
@@ -62,11 +62,13 @@ RD_TEST(D3D12_Sharing, D3D12GraphicsTest)
IDXGIAdapterPtr pDXGIAdapter;
HRESULT hr = EnumAdapterByLuid(dev->GetAdapterLuid(), pDXGIAdapter);
std::vector<IDXGIAdapterPtr> 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;
+19 -11
View File
@@ -39,9 +39,9 @@ HMODULE d3d12 = NULL;
HMODULE dxgi = NULL;
HMODULE d3dcompiler = NULL;
IDXGIFactory1Ptr factory;
IDXGIAdapterPtr adapter;
std::vector<IDXGIAdapterPtr> 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<IDXGIAdapterPtr> &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;
}
+2 -1
View File
@@ -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<IDXGIAdapterPtr> &adaptersToTry,
D3D_FEATURE_LEVEL features);
enum BufType
{
+29 -16
View File
@@ -23,7 +23,6 @@
******************************************************************************/
#include "d3d_helpers.h"
#include <vector>
#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<IDXGIAdapterPtr> 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<AdapterInfo> 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<IDXGIAdapterPtr> returnedAdapters;
for(size_t i = 0; i < adapters.size(); ++i)
returnedAdapters.push_back(adapters[i].adapter);
return returnedAdapters;
}
+3 -1
View File
@@ -26,6 +26,7 @@
#include <comdef.h>
#include <string>
#include <vector>
#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<IDXGIAdapterPtr> FindD3DAdapters(IDXGIFactoryPtr factory, int argc, char **argv,
bool &warp);
enum class ResourceType
{