From 45feb51e841c9454dacaa9e9273243f8d283d451 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Mon, 9 Mar 2026 00:50:09 -0700 Subject: [PATCH] Add DX12 bridge preflight checks and runtime override env --- README.md | 2 + docs/AMD_FSR2_INTEGRATION.md | 2 + src/rendering/amd_fsr3_wrapper_impl.cpp | 64 ++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3d09c7fc..dc29e1a1 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,8 @@ make -j$(nproc) - Wrapper backend mode: - `WOWEE_FSR3_WRAPPER_BACKEND=vulkan_runtime` (default on non-Windows) - `WOWEE_FSR3_WRAPPER_BACKEND=dx12_bridge` (default on Windows; bridge dispatch wiring still in progress) + - DX12 runtime override (for `dx12_bridge`): + - `WOWEE_FSR3_DX12_RUNTIME_LIB=C:\\path\\to\\amd_fidelityfx_framegeneration_dx12.dll` - Path B wrapper libraries must export the clean wrapper ABI (`include/rendering/amd_fsr3_wrapper_abi.h`): - `wowee_fsr3_wrapper_get_abi_version` - `wowee_fsr3_wrapper_initialize` diff --git a/docs/AMD_FSR2_INTEGRATION.md b/docs/AMD_FSR2_INTEGRATION.md index db682777..32122f7f 100644 --- a/docs/AMD_FSR2_INTEGRATION.md +++ b/docs/AMD_FSR2_INTEGRATION.md @@ -55,6 +55,8 @@ Runtime note: - Wrapper backend mode selection: - `WOWEE_FSR3_WRAPPER_BACKEND=vulkan_runtime` - `WOWEE_FSR3_WRAPPER_BACKEND=dx12_bridge` +- DX12 bridge runtime override: + - `WOWEE_FSR3_DX12_RUNTIME_LIB=` - Path B wrapper ABI contract is declared in: - `include/rendering/amd_fsr3_wrapper_abi.h` - Required wrapper exports: diff --git a/src/rendering/amd_fsr3_wrapper_impl.cpp b/src/rendering/amd_fsr3_wrapper_impl.cpp index 4ab3e1cd..3c2844d1 100644 --- a/src/rendering/amd_fsr3_wrapper_impl.cpp +++ b/src/rendering/amd_fsr3_wrapper_impl.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -172,6 +173,7 @@ struct RuntimeFns { }; struct WrapperContext { + WrapperBackend backend = WrapperBackend::VulkanRuntime; void* backendLibHandle = nullptr; RuntimeFns fns{}; void* scratchBuffer = nullptr; @@ -225,6 +227,57 @@ void destroyContext(WrapperContext* ctx) { ctx->backendLibHandle = nullptr; delete ctx; } + +#if defined(_WIN32) +bool runDx12BridgePreflight(std::string& errorMessage) { + std::vector missing; + + HMODULE d3d12 = LoadLibraryA("d3d12.dll"); + if (!d3d12) { + missing.emplace_back("d3d12.dll"); + } else { + FreeLibrary(d3d12); + } + + HMODULE dxgi = LoadLibraryA("dxgi.dll"); + if (!dxgi) { + missing.emplace_back("dxgi.dll"); + } else { + FreeLibrary(dxgi); + } + + std::vector runtimeCandidates; + if (const char* explicitRuntime = std::getenv("WOWEE_FSR3_DX12_RUNTIME_LIB")) { + if (explicitRuntime && *explicitRuntime) runtimeCandidates.emplace_back(explicitRuntime); + } + runtimeCandidates.emplace_back("amd_fidelityfx_framegeneration_dx12.dll"); + runtimeCandidates.emplace_back("ffx_framegeneration_dx12.dll"); + + bool foundRuntime = false; + for (const std::string& candidate : runtimeCandidates) { + HMODULE runtime = LoadLibraryA(candidate.c_str()); + if (runtime) { + FreeLibrary(runtime); + foundRuntime = true; + break; + } + } + if (!foundRuntime) { + missing.emplace_back("amd_fidelityfx_framegeneration_dx12.dll"); + } + + if (missing.empty()) return true; + + std::ostringstream oss; + oss << "dx12_bridge preflight failed, missing: "; + for (size_t i = 0; i < missing.size(); ++i) { + if (i) oss << ", "; + oss << missing[i]; + } + errorMessage = oss.str(); + return false; +} +#endif #endif } // namespace @@ -264,14 +317,20 @@ WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_initialize(const WoweeFsr3W return -1; } - if (selectBackend() == WrapperBackend::Dx12Bridge) { + const WrapperBackend backend = selectBackend(); + if (backend == WrapperBackend::Dx12Bridge) { #if !defined(_WIN32) writeError(outErrorText, outErrorTextCapacity, "dx12_bridge backend is Windows-only in current wrapper build"); return -1; #else + std::string preflightError; + if (!runDx12BridgePreflight(preflightError)) { + writeError(outErrorText, outErrorTextCapacity, preflightError.c_str()); + return -1; + } writeError(outErrorText, outErrorTextCapacity, - "dx12_bridge backend selected but Vulkan<->DX12 interop dispatch is not implemented yet"); + "dx12_bridge preflight passed, but Vulkan<->DX12 interop dispatch is not implemented yet"); return -1; #endif } @@ -299,6 +358,7 @@ WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_initialize(const WoweeFsr3W #endif WrapperContext* ctx = new WrapperContext{}; + ctx->backend = backend; for (const std::string& path : candidates) { ctx->backendLibHandle = openLibrary(path.c_str()); if (ctx->backendLibHandle) break;