From b9f5ecaaa8cd75347a5914f1ade717cda1f22413 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 11 Dec 2018 15:04:45 +0000 Subject: [PATCH] Add GPU selection on command line to VK/D3D11/D3D12 tests --- util/test/demos/d3d11/d3d11_helpers.h | 3 + util/test/demos/d3d11/d3d11_test.cpp | 122 +++++++++++++++++++++-- util/test/demos/d3d12/d3d12_helpers.h | 1 + util/test/demos/d3d12/d3d12_test.cpp | 99 ++++++++++++++++-- util/test/demos/vk/vk_test.cpp | 49 ++++++++- util/test/demos/win32/win32_platform.cpp | 48 +++++++++ util/test/demos/win32/win32_platform.h | 5 + 7 files changed, 311 insertions(+), 16 deletions(-) diff --git a/util/test/demos/d3d11/d3d11_helpers.h b/util/test/demos/d3d11/d3d11_helpers.h index 879d192b1..64b825d63 100644 --- a/util/test/demos/d3d11/d3d11_helpers.h +++ b/util/test/demos/d3d11/d3d11_helpers.h @@ -36,6 +36,9 @@ COM_SMARTPTR(ID3DBlob); COM_SMARTPTR(IDXGISwapChain); +COM_SMARTPTR(IDXGIFactory); +COM_SMARTPTR(IDXGIDevice); +COM_SMARTPTR(IDXGIAdapter); COM_SMARTPTR(ID3D11Device); COM_SMARTPTR(ID3D11Device1); diff --git a/util/test/demos/d3d11/d3d11_test.cpp b/util/test/demos/d3d11/d3d11_test.cpp index 1dea09f31..a2bafe867 100644 --- a/util/test/demos/d3d11/d3d11_test.cpp +++ b/util/test/demos/d3d11/d3d11_test.cpp @@ -30,6 +30,8 @@ #include "../renderdoc_app.h" #include "../win32/win32_window.h" +typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID, void **); + bool D3D11GraphicsTest::Init(int argc, char **argv) { // parse parameters here to override parameters @@ -39,6 +41,7 @@ bool D3D11GraphicsTest::Init(int argc, char **argv) // ... HMODULE d3d11 = LoadLibraryA("d3d11.dll"); + HMODULE dxgi = LoadLibraryA("dxgi.dll"); HMODULE d3dcompiler = LoadLibraryA("d3dcompiler_47.dll"); if(!d3dcompiler) d3dcompiler = LoadLibraryA("d3dcompiler_46.dll"); @@ -49,12 +52,15 @@ bool D3D11GraphicsTest::Init(int argc, char **argv) if(!d3dcompiler) d3dcompiler = LoadLibraryA("d3dcompiler_43.dll"); - if(!d3d11 || !d3dcompiler) + if(!d3d11 || !dxgi || !d3dcompiler) { TEST_ERROR("Couldn't load D3D11"); return false; } + PFN_CREATE_DXGI_FACTORY createFactory = + (PFN_CREATE_DXGI_FACTORY)GetProcAddress(dxgi, "CreateDXGIFactory"); + dyn_D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3d11, "D3D11CreateDevice"); dyn_D3D11CreateDeviceAndSwapChain = (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress( d3d11, "D3D11CreateDeviceAndSwapChain"); @@ -71,16 +77,91 @@ bool D3D11GraphicsTest::Init(int argc, char **argv) HRESULT hr = S_OK; + IDXGIFactoryPtr factory = NULL; + + hr = createFactory(__uuidof(IDXGIFactory), (void **)&factory); + + if(factory.GetInterfacePtr() == NULL || FAILED(hr)) + { + TEST_ERROR("CreateDXGIFactory failed: %x", hr); + return false; + } + + struct AdapterInfo + { + IDXGIAdapterPtr adapter; + DXGI_ADAPTER_DESC desc; + }; + + std::vector adapters; + + for(UINT i = 0; i < 10; i++) + { + IDXGIAdapterPtr a; + hr = factory->EnumAdapters(i, &a); + if(hr == S_OK && a) + { + DXGI_ADAPTER_DESC desc; + a->GetDesc(&desc); + adapters.push_back({a, desc}); + } + else + { + break; + } + } + + IDXGIAdapterPtr adapter = NULL; + + for(int i = 0; i < argc; i++) + { + if(!strcmp(argv[i], "--warp")) + { + driver = D3D_DRIVER_TYPE_WARP; + break; + } + if(!strcmp(argv[i], "--gpu") && i + 1 < argc) + { + std::string needle = strlower(argv[i + 1]); + + if(needle == "warp") + { + driver = D3D_DRIVER_TYPE_WARP; + break; + } + + const bool nv = (needle == "nv" || needle == "nvidia"); + const bool amd = (needle == "amd"); + const bool intel = (needle == "intel"); + + for(size_t a = 0; a < adapters.size(); a++) + { + std::string haystack = strlower(Wide2UTF8(adapters[a].desc.Description)); + + if(haystack.find(needle) != std::string::npos || (nv && adapters[a].desc.VendorId == 0x10DE) || + (amd && adapters[a].desc.VendorId == 0x1002) || + (intel && adapters[a].desc.VendorId == 0x8086)) + { + driver = D3D_DRIVER_TYPE_UNKNOWN; + adapter = adapters[a].adapter; + break; + } + } + + break; + } + } + if(headless) { - hr = dyn_D3D11CreateDevice(NULL, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, + hr = dyn_D3D11CreateDevice(adapter, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, 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(NULL, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, + hr = dyn_D3D11CreateDevice(adapter, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, features, 1, D3D11_SDK_VERSION, &dev, NULL, &ctx); } @@ -88,7 +169,7 @@ bool D3D11GraphicsTest::Init(int argc, char **argv) if(FAILED(hr) && features[0] != D3D_FEATURE_LEVEL_11_0) { driver = D3D_DRIVER_TYPE_REFERENCE; - hr = dyn_D3D11CreateDevice(NULL, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, + hr = dyn_D3D11CreateDevice(adapter, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, features, 1, D3D11_SDK_VERSION, &dev, NULL, &ctx); } @@ -121,7 +202,7 @@ bool D3D11GraphicsTest::Init(int argc, char **argv) swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapDesc.Flags = 0; - hr = dyn_D3D11CreateDeviceAndSwapChain(NULL, driver, NULL, + hr = dyn_D3D11CreateDeviceAndSwapChain(adapter, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, features, 1, D3D11_SDK_VERSION, &swapDesc, &swap, &dev, NULL, &ctx); @@ -129,7 +210,7 @@ bool D3D11GraphicsTest::Init(int argc, char **argv) if(FAILED(hr)) { driver = D3D_DRIVER_TYPE_WARP; - hr = dyn_D3D11CreateDeviceAndSwapChain(NULL, driver, NULL, + hr = dyn_D3D11CreateDeviceAndSwapChain(adapter, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, features, 1, D3D11_SDK_VERSION, &swapDesc, &swap, &dev, NULL, &ctx); } @@ -138,7 +219,7 @@ bool D3D11GraphicsTest::Init(int argc, char **argv) if(FAILED(hr)) { driver = D3D_DRIVER_TYPE_REFERENCE; - hr = dyn_D3D11CreateDeviceAndSwapChain(NULL, driver, NULL, + hr = dyn_D3D11CreateDeviceAndSwapChain(adapter, driver, NULL, debugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0, features, 1, D3D11_SDK_VERSION, &swapDesc, &swap, &dev, NULL, &ctx); } @@ -211,6 +292,33 @@ bool D3D11GraphicsTest::IsSupported() void D3D11GraphicsTest::PostDeviceCreate() { + { + IDXGIDevicePtr pDXGIDevice; + HRESULT hr = dev->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice); + + if(FAILED(hr) || !pDXGIDevice) + { + TEST_ERROR("Couldn't get DXGI Device"); + } + else + { + IDXGIAdapterPtr pDXGIAdapter; + hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter); + + if(FAILED(hr) || !pDXGIAdapter) + { + TEST_ERROR("Couldn't get DXGI Adapter"); + } + else + { + DXGI_ADAPTER_DESC desc = {}; + pDXGIAdapter->GetDesc(&desc); + + TEST_LOG("Running D3D11 test on %ls", desc.Description); + } + } + } + // if(d3d11_1) { dev->QueryInterface(__uuidof(ID3D11Device1), (void **)&dev1); diff --git a/util/test/demos/d3d12/d3d12_helpers.h b/util/test/demos/d3d12/d3d12_helpers.h index cfc331462..beab65263 100644 --- a/util/test/demos/d3d12/d3d12_helpers.h +++ b/util/test/demos/d3d12/d3d12_helpers.h @@ -35,6 +35,7 @@ COM_SMARTPTR(ID3DBlob); COM_SMARTPTR(IDXGISwapChain); COM_SMARTPTR(IDXGISwapChain1); COM_SMARTPTR(IDXGIFactory4); +COM_SMARTPTR(IDXGIAdapter); COM_SMARTPTR(ID3D12Debug); COM_SMARTPTR(ID3D12Debug1); diff --git a/util/test/demos/d3d12/d3d12_test.cpp b/util/test/demos/d3d12/d3d12_test.cpp index 3202176b8..ebfb7d857 100644 --- a/util/test/demos/d3d12/d3d12_test.cpp +++ b/util/test/demos/d3d12/d3d12_test.cpp @@ -52,7 +52,7 @@ bool D3D12GraphicsTest::Init(int argc, char **argv) if(!d3dcompiler) d3dcompiler = LoadLibraryA("d3dcompiler_43.dll"); - if(!d3d12 || !d3dcompiler) + if(!d3d12 || !dxgi || !d3dcompiler) { TEST_ERROR("Couldn't load D3D12"); return false; @@ -114,20 +114,84 @@ bool D3D12GraphicsTest::Init(int argc, char **argv) return false; } - hr = dyn_D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void **)&dev); + struct AdapterInfo + { + IDXGIAdapterPtr adapter; + DXGI_ADAPTER_DESC desc; + }; + + std::vector adapters; + + for(UINT i = 0; i < 10; i++) + { + IDXGIAdapterPtr a; + hr = m_Factory->EnumAdapters(i, &a); + if(hr == S_OK && a) + { + DXGI_ADAPTER_DESC desc; + a->GetDesc(&desc); + adapters.push_back({a, desc}); + } + else + { + break; + } + } + + IDXGIAdapterPtr warp = NULL; + m_Factory->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&warp); + + IDXGIAdapterPtr adapter = NULL; + + for(int i = 0; i < argc; i++) + { + if(!strcmp(argv[i], "--warp")) + { + adapter = warp; + break; + } + if(!strcmp(argv[i], "--gpu") && i + 1 < argc) + { + std::string needle = strlower(argv[i + 1]); + + if(needle == "warp") + { + adapter = warp; + break; + } + + const bool nv = (needle == "nv" || needle == "nvidia"); + const bool amd = (needle == "amd"); + const bool intel = (needle == "intel"); + + for(size_t a = 0; a < adapters.size(); a++) + { + std::string haystack = strlower(Wide2UTF8(adapters[a].desc.Description)); + + if(haystack.find(needle) != std::string::npos || + (nv && adapters[a].desc.VendorId == 0x10DE) || + (amd && adapters[a].desc.VendorId == 0x1002) || + (intel && adapters[a].desc.VendorId == 0x8086)) + { + adapter = adapters[a].adapter; + break; + } + } + + break; + } + } + + hr = dyn_D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), + (void **)&dev); // if it failed, try again on warp if(FAILED(hr)) { - IDXGIAdapter *adapter = NULL; - m_Factory->EnumWarpAdapter(__uuidof(IDXGIAdapter), (void **)&adapter); - + adapter = warp; if(adapter) - { hr = dyn_D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void **)&dev); - adapter->Release(); - } } if(FAILED(hr)) @@ -137,6 +201,25 @@ bool D3D12GraphicsTest::Init(int argc, char **argv) } } + { + LUID luid = dev->GetAdapterLuid(); + + IDXGIAdapterPtr pDXGIAdapter; + HRESULT hr = m_Factory->EnumAdapterByLuid(luid, __uuidof(IDXGIAdapter), (void **)&pDXGIAdapter); + + if(FAILED(hr)) + { + TEST_ERROR("Couldn't get DXGI adapter by LUID from D3D device"); + } + else + { + DXGI_ADAPTER_DESC desc = {}; + pDXGIAdapter->GetDesc(&desc); + + TEST_LOG("Running D3D12 test on %ls", desc.Description); + } + } + { D3D12_COMMAND_QUEUE_DESC desc = {}; desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; diff --git a/util/test/demos/vk/vk_test.cpp b/util/test/demos/vk/vk_test.cpp index fe0830b70..e57f67a70 100644 --- a/util/test/demos/vk/vk_test.cpp +++ b/util/test/demos/vk/vk_test.cpp @@ -173,7 +173,54 @@ bool VulkanGraphicsTest::Init(int argc, char **argv) return false; } - phys = physDevices[0]; + std::vector physProps; + for(VkPhysicalDevice p : physDevices) + { + VkPhysicalDeviceProperties props; + vkGetPhysicalDeviceProperties(p, &props); + physProps.push_back(props); + } + + // default to the first discrete card + for(size_t i = 0; i < physDevices.size(); i++) + { + if(physProps[i].deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + { + phys = physDevices[i]; + break; + } + } + + // if none found, default to first + if(phys == VK_NULL_HANDLE) + phys = physDevices[0]; + + // allow command line override + for(int i = 0; i < argc; i++) + { + if(!strcmp(argv[i], "--gpu") && i + 1 < argc) + { + std::string needle = strlower(argv[i + 1]); + + const bool nv = (needle == "nv" || needle == "nvidia"); + const bool amd = (needle == "amd"); + const bool intel = (needle == "intel"); + + for(size_t p = 0; p < physDevices.size(); p++) + { + std::string haystack = strlower(physProps[p].deviceName); + + if(haystack.find(needle) != std::string::npos || (nv && physProps[p].vendorID == 0x10DE) || + (amd && physProps[p].vendorID == 0x1002) || (intel && physProps[p].vendorID == 0x8086)) + { + phys = physDevices[p]; + break; + } + } + + break; + } + } std::vector queueProps; vkh::getQueueFamilyProperties(queueProps, phys); diff --git a/util/test/demos/win32/win32_platform.cpp b/util/test/demos/win32/win32_platform.cpp index bffc122be..4142ca787 100644 --- a/util/test/demos/win32/win32_platform.cpp +++ b/util/test/demos/win32/win32_platform.cpp @@ -40,3 +40,51 @@ std::string GetCWD() return cwdstr; } + +std::string Wide2UTF8(const std::wstring &s) +{ + int bytes_required = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, NULL, 0, NULL, NULL); + + if(bytes_required == 0) + return ""; + + std::string ret; + ret.resize(bytes_required); + + int res = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, &ret[0], bytes_required, NULL, NULL); + + if(ret.back() == 0) + ret.pop_back(); + + if(res == 0) + { + TEST_WARN("Failed to convert wstring '%ls'", s.c_str()); + return ""; + } + + return ret; +} + +std::wstring UTF82Wide(const std::string &s) +{ + int chars_required = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); + + if(chars_required == 0) + return L""; + + std::wstring ret; + ret.resize(chars_required); + + int res = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, &ret[0], chars_required); + + if(ret.back() == 0) + ret.pop_back(); + + if(res == 0) + { + TEST_WARN("Failed to convert utf-8 string '%s'", s.c_str()); + return L""; + } + + return ret; +} diff --git a/util/test/demos/win32/win32_platform.h b/util/test/demos/win32/win32_platform.h index 7dcaad344..0989cd95c 100644 --- a/util/test/demos/win32/win32_platform.h +++ b/util/test/demos/win32/win32_platform.h @@ -29,6 +29,11 @@ #define NOMINMAX #include +#include + +std::string Wide2UTF8(const std::wstring &s); +std::wstring UTF82Wide(const std::string &s); + #define DEBUG_BREAK() \ do \ { \