From 11b0815395d9552856c894aad766c40ba702d06a Mon Sep 17 00:00:00 2001 From: praydog Date: Thu, 18 Jul 2024 15:19:13 -0700 Subject: [PATCH] D3D12: Fix DLSSFG swapchains causing flickering/lag issues --- src/hooks/D3D12Hook.cpp | 48 ++++++++++++++++++++++++++++++++++++++--- src/hooks/D3D12Hook.hpp | 5 +++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/hooks/D3D12Hook.cpp b/src/hooks/D3D12Hook.cpp index bc57e9fe..323bc3a3 100644 --- a/src/hooks/D3D12Hook.cpp +++ b/src/hooks/D3D12Hook.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -225,8 +226,33 @@ bool D3D12Hook::hook() { return false; } + try { + const auto ti = utility::rtti::get_type_info(swap_chain1); + const auto swapchain_classname = ti != nullptr && ti->name() != nullptr ? std::string_view{ti->name()} : "unknown"; + const auto raw_name = ti != nullptr && ti->raw_name() != nullptr ? std::string_view{ti->raw_name()} : "unknown"; + + spdlog::info("Swapchain type info: {}", swapchain_classname); + spdlog::info("Swapchain raw type info: {}", raw_name); + + if (swapchain_classname.contains("interposer::DXGISwapChain")) { // DLSS3 + spdlog::info("Found Streamline (DLSSFG) swapchain during dummy initialization: {:x}", (uintptr_t)swap_chain1); + m_using_frame_generation_swapchain = true; + } + // Need to test this one to see if it actually has the same issues - disabling it for now + /*else if (swapchain_classname.contains("FrameInterpolationSwapChain")) { // FSR3 + spdlog::info("Found FSR3 swapchain during dummy initialization: {:x}", (uintptr_t)swap_chain1); + m_using_frame_generation_swapchain = true; + }*/ + } catch (const std::exception& e) { + spdlog::error("Failed to get type info: {}", e.what()); + } catch (...) { + spdlog::error("Failed to get type info: unknown exception"); + } + spdlog::info("Finding command queue offset"); + m_command_queue_offset = 0; + // Find the command queue offset in the swapchain for (auto i = 0; i < 512 * sizeof(void*); i += sizeof(void*)) { const auto base = (uintptr_t)swap_chain1 + i; @@ -245,9 +271,13 @@ bool D3D12Hook::hook() { } } + auto target_swapchain = swap_chain; + // Scan throughout the swapchain for a valid pointer to scan through // this is usually only necessary for Proton if (m_command_queue_offset == 0) { + bool should_break = false; + for (auto base = 0; base < 512 * sizeof(void*); base += sizeof(void*)) { const auto pre_scan_base = (uintptr_t)swap_chain1 + base; @@ -272,9 +302,21 @@ bool D3D12Hook::hook() { auto data = *(ID3D12CommandQueue**)pre_data; if (data == command_queue) { - m_using_proton_swapchain = true; + // If we hook Streamline's Swapchain, the menu fails to render correctly/flickers + // So we switch out the swapchain with the internal one owned by Streamline + // Side note: Even though we are scanning for Proton here, + // this doubles as an offset scanner for the real swapchain inside Streamline (or FSR3) + if (m_using_frame_generation_swapchain) { + target_swapchain = (IDXGISwapChain3*)scan_base; + } + + if (!m_using_frame_generation_swapchain) { + m_using_proton_swapchain = true; + } + m_command_queue_offset = i; m_proton_swapchain_offset = base; + should_break = true; spdlog::info("Proton potentially detected"); spdlog::info("Found command queue offset: {:x}", i); @@ -282,7 +324,7 @@ bool D3D12Hook::hook() { } } - if (m_using_proton_swapchain) { + if (m_using_proton_swapchain || should_break) { break; } } @@ -301,7 +343,7 @@ bool D3D12Hook::hook() { m_is_phase_1 = true; - auto& present_fn = (*(void***)swap_chain)[8]; // Present + auto& present_fn = (*(void***)target_swapchain)[8]; // Present m_present_hook = std::make_unique(&present_fn, (void*)&D3D12Hook::present); m_hooked = true; }); diff --git a/src/hooks/D3D12Hook.hpp b/src/hooks/D3D12Hook.hpp index 7b51d5de..00e2c26f 100644 --- a/src/hooks/D3D12Hook.hpp +++ b/src/hooks/D3D12Hook.hpp @@ -89,6 +89,10 @@ class D3D12Hook return m_using_proton_swapchain; } + bool is_framegen_swapchain() const { + return m_using_frame_generation_swapchain; + } + void ignore_next_present() { m_ignore_next_present = true; } @@ -114,6 +118,7 @@ class D3D12Hook std::optional m_next_present_interval{}; bool m_using_proton_swapchain{ false }; + bool m_using_frame_generation_swapchain{ false }; bool m_hooked{ false }; bool m_is_phase_1{ true }; bool m_inside_present{false};