From f8b5c42100329efe3f7dd995094d96c1405f4f86 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 2 May 2024 16:41:08 +0100 Subject: [PATCH] Add a command line argument to the demos project to load a DLL * We also automatically check for a DLL under /D3D12/ next to the executable --- util/test/demos/d3d12/d3d12_helpers.h | 5 + util/test/demos/d3d12/d3d12_sharing.cpp | 10 +- util/test/demos/d3d12/d3d12_test.cpp | 212 ++++++++++++++++++++---- util/test/demos/d3d12/d3d12_test.h | 5 + 4 files changed, 198 insertions(+), 34 deletions(-) diff --git a/util/test/demos/d3d12/d3d12_helpers.h b/util/test/demos/d3d12/d3d12_helpers.h index 721ef6719..480f40477 100644 --- a/util/test/demos/d3d12/d3d12_helpers.h +++ b/util/test/demos/d3d12/d3d12_helpers.h @@ -34,6 +34,11 @@ COM_SMARTPTR(ID3DBlob); COM_SMARTPTR(ID3D12Debug); COM_SMARTPTR(ID3D12Debug1); +COM_SMARTPTR(ID3D12SDKConfiguration); +COM_SMARTPTR(ID3D12SDKConfiguration1); +COM_SMARTPTR(ID3D12DeviceFactory); +COM_SMARTPTR(ID3D12DeviceConfiguration); + COM_SMARTPTR(ID3D12Device); COM_SMARTPTR(ID3D12Device1); COM_SMARTPTR(ID3D12Device2); diff --git a/util/test/demos/d3d12/d3d12_sharing.cpp b/util/test/demos/d3d12/d3d12_sharing.cpp index 2e8fd43be..bb256b8eb 100644 --- a/util/test/demos/d3d12/d3d12_sharing.cpp +++ b/util/test/demos/d3d12/d3d12_sharing.cpp @@ -87,14 +87,16 @@ RD_TEST(D3D12_Sharing, D3D12GraphicsTest) ID3D12RootSignaturePtr sig = MakeSig({}); // swap dev with devB, to force pso to be created on the 'second' device (should be identical to - // the first). This may be completely redundant as we might have two identical pointers, but - // that's not guaranteed. - std::swap(dev, devB); + // the first if not using dynamic DLLs). This may be completely redundant as we might have two + // identical pointers, but that's not guaranteed. + if(!devFactory) + std::swap(dev, devB); ID3D12PipelineStatePtr pso = MakePSO().RootSig(sig).InputLayout().VS(vsblob).PS(psblob); // set them back - std::swap(dev, devB); + if(!devFactory) + std::swap(dev, devB); ResourceBarrier(d3d12vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); diff --git a/util/test/demos/d3d12/d3d12_test.cpp b/util/test/demos/d3d12/d3d12_test.cpp index 9c0574c43..8e203b8cd 100644 --- a/util/test/demos/d3d12/d3d12_test.cpp +++ b/util/test/demos/d3d12/d3d12_test.cpp @@ -57,6 +57,149 @@ PFN_D3D12_CREATE_DEVICE dyn_D3D12CreateDevice = NULL; PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE dyn_serializeRootSig; PFN_D3D12_SERIALIZE_ROOT_SIGNATURE dyn_serializeRootSigOld; + +struct DevicePointers +{ + ID3D12DebugPtr debug; + ID3D12DeviceFactoryPtr factory; + ID3D12DeviceConfigurationPtr config; +}; + +DevicePointers PrepareCreateDeviceFromDLL(const std::string &d3d12path, bool debug, bool gpuValidation) +{ + DevicePointers ret; + + HRESULT hr = S_OK; + + ID3D12DeviceFactoryPtr devfactory = NULL; + if(!d3d12path.empty()) + { +#ifdef WIN64 +#define BITNESS_SUFFIX "/x64" +#else +#define BITNESS_SUFFIX "/win32" +#endif + + PFN_D3D12_GET_INTERFACE getD3D12Interface = + (PFN_D3D12_GET_INTERFACE)GetProcAddress(d3d12, "D3D12GetInterface"); + + ID3D12SDKConfigurationPtr config = NULL; + hr = getD3D12Interface(CLSID_D3D12SDKConfiguration, __uuidof(ID3D12SDKConfiguration), + (void **)&config); + + ID3D12SDKConfiguration1Ptr config1 = NULL; + if(config) + config1 = config; + + if(config1) + { + std::string path = d3d12path; + + // try to load d3d12core.dll - starting with if the argument is directly to the dll, otherwise + // try increasing suffixes + HMODULE mod = NULL; + mod = LoadLibraryA(path.c_str()); + + if(mod) + { + size_t trim = path.find_last_of("/\\"); + path[trim] = '\0'; + } + else + { + mod = LoadLibraryA((path + "/d3d12core.dll").c_str()); + if(mod) + { + // path is the folder as needed + } + else + { + path = d3d12path + BITNESS_SUFFIX; + mod = LoadLibraryA((path + "/d3d12core.dll").c_str()); + if(mod) + { + } + else + { + path = d3d12path + "/bin" BITNESS_SUFFIX; + mod = LoadLibraryA((path + "/d3d12core.dll").c_str()); + + if(!mod) + { + TEST_LOG("Couldn't find D3D12 dll under path %s", d3d12path.c_str()); + } + } + } + } + + if(mod) + { + DWORD *version = (DWORD *)GetProcAddress(mod, "D3D12SDKVersion"); + + if(version) + { + hr = config1->CreateDeviceFactory(*version, path.c_str(), __uuidof(ID3D12DeviceFactory), + (void **)&devfactory); + + if(FAILED(hr)) + devfactory = NULL; + } + } + } + + if(!devfactory) + { + TEST_LOG("Tried to enable dynamic D3D12 SDK, but failed to get interface"); + } + + ret.factory = devfactory; + ret.config = devfactory; + } + + if(debug) + { + if(devfactory) + { + hr = devfactory->GetConfigurationInterface(CLSID_D3D12Debug, __uuidof(ID3D12Debug), + (void **)&ret.debug); + + if(FAILED(hr)) + ret.debug = NULL; + } + else + { + PFN_D3D12_GET_DEBUG_INTERFACE getD3D12DebugInterface = + (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(d3d12, "D3D12GetDebugInterface"); + + if(!getD3D12DebugInterface) + { + TEST_ERROR("Couldn't find D3D12GetDebugInterface!"); + return {}; + } + + hr = getD3D12DebugInterface(__uuidof(ID3D12Debug), (void **)&ret.debug); + + if(FAILED(hr)) + ret.debug = NULL; + } + + if(ret.debug) + { + ret.debug->EnableDebugLayer(); + + if(gpuValidation) + { + ID3D12Debug1Ptr debug1 = ret.debug; + + if(debug1) + debug1->SetEnableGPUBasedValidation(true); + } + } + } + + return ret; +} + }; // namespace void D3D12GraphicsTest::Prepare(int argc, char **argv) @@ -166,14 +309,33 @@ void D3D12GraphicsTest::Prepare(int argc, char **argv) { gpuva = true; } + if(i + 1 < argc && + (!strcmp(argv[i], "--d3d12") || !strcmp(argv[i], "--sdk") || !strcmp(argv[i], "--d3d12core"))) + { + d3d12path = argv[i + 1]; + } + } + + if(d3d12path.empty()) + { + d3d12path = GetCWD() + "/D3D12/d3d12core.dll"; + FILE *f = fopen(d3d12path.c_str(), "r"); + if(!f) + d3d12path.clear(); + else + fclose(f); } m_Factory = factory; if(Avail.empty()) { + devFactory = PrepareCreateDeviceFromDLL(d3d12path, debugDevice, gpuva).factory; + ID3D12DevicePtr tmpdev = CreateDevice(adapters, minFeatureLevel); + devFactory = NULL; + if(tmpdev) { tmpdev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &opts, sizeof(opts)); @@ -207,32 +369,11 @@ bool D3D12GraphicsTest::Init() TEST_WARN("Can't get D3D12SerializeVersionedRootSignature - old version of windows?"); } - if(debugDevice) - { - PFN_D3D12_GET_DEBUG_INTERFACE getD3D12DebugInterface = - (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(d3d12, "D3D12GetDebugInterface"); + DevicePointers devPtrs = PrepareCreateDeviceFromDLL(d3d12path, debugDevice, gpuva); - if(!getD3D12DebugInterface) - { - TEST_ERROR("Couldn't find D3D12GetDebugInterface!"); - return false; - } - - HRESULT hr = getD3D12DebugInterface(__uuidof(ID3D12Debug), (void **)&d3d12Debug); - - if(SUCCEEDED(hr) && d3d12Debug) - { - d3d12Debug->EnableDebugLayer(); - - if(gpuva) - { - ID3D12Debug1Ptr debug1 = d3d12Debug; - - if(debug1) - debug1->SetEnableGPUBasedValidation(true); - } - } - } + devFactory = devPtrs.factory; + devConfig = devPtrs.config; + d3d12Debug = devPtrs.debug; dev = CreateDevice(adapters, minFeatureLevel); if(!dev) @@ -534,17 +675,23 @@ ID3D12DevicePtr D3D12GraphicsTest::CreateDevice(const std::vectorCreateDevice(adaptersToTry[i], features, __uuidof(ID3D12Device), + (void **)&device); + else + hr = dyn_D3D12CreateDevice(adaptersToTry[i], features, __uuidof(ID3D12Device), + (void **)&device); if(SUCCEEDED(hr)) - return ret; + return device; } TEST_ERROR("D3D12CreateDevice failed: %x", hr); - return ret; + return NULL; } GraphicsWindow *D3D12GraphicsTest::MakeWindow(int width, int height, const char *title) @@ -580,6 +727,7 @@ void D3D12GraphicsTest::Shutdown() queue = NULL; dev = NULL; + devConfig = NULL; } bool D3D12GraphicsTest::Running() @@ -1495,7 +1643,11 @@ ID3D12RootSignaturePtr D3D12GraphicsTest::MakeSig(const std::vectorSerializeVersionedRootSignature(&verdesc, &blob, &errBlob); + else + hr = dyn_serializeRootSig(&verdesc, &blob, &errBlob); if(FAILED(hr)) { diff --git a/util/test/demos/d3d12/d3d12_test.h b/util/test/demos/d3d12/d3d12_test.h index 92ca48e26..6c0227ed4 100644 --- a/util/test/demos/d3d12/d3d12_test.h +++ b/util/test/demos/d3d12/d3d12_test.h @@ -214,12 +214,17 @@ struct D3D12GraphicsTest : public GraphicsTest D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0; + std::string d3d12path; + bool gpuva = false, m_12On7 = false, m_DXILSupport = false; IDXGIFactory1Ptr m_Factory; ID3D12DebugPtr d3d12Debug; ID3D12InfoQueuePtr infoqueue; + ID3D12DeviceFactoryPtr devFactory; + ID3D12DeviceConfigurationPtr devConfig; + ID3D12DevicePtr dev; ID3D12Device1Ptr dev1; ID3D12Device2Ptr dev2;