From 78d4e7640cdfd5ad33681264fa961b89cffae7ed Mon Sep 17 00:00:00 2001 From: cdozdil Date: Sun, 19 May 2024 12:49:08 +0300 Subject: [PATCH] more fsr3 fg hook stuff --- OptiScaler/Config.cpp | 4 +- OptiScaler/Config.h | 2 +- OptiScaler/imgui/imgui_overlay_dx12.cpp | 99 ++++++++++++++++++++----- nvngx.ini | 9 ++- 4 files changed, 90 insertions(+), 24 deletions(-) diff --git a/OptiScaler/Config.cpp b/OptiScaler/Config.cpp index 2b5928a8..b1c23d5c 100644 --- a/OptiScaler/Config.cpp +++ b/OptiScaler/Config.cpp @@ -91,7 +91,7 @@ bool Config::Reload() MenuInitDelay = readInt("Menu", "MenuInitDelay"); HookSLDevice = readBool("Menu", "HookSLDevice"); HookSLProxy = readBool("Menu", "HookSLProxy"); - HookUniscalerProxy = readBool("Menu", "HookUniscalerProxy"); + HookFSR3Proxy = readBool("Menu", "HookFSR3Proxy"); // CAS RcasEnabled = readBool("CAS", "Enabled"); @@ -258,7 +258,7 @@ bool Config::SaveIni() ini.SetValue("Menu", "MenuInitDelay", GetIntValue(Instance()->MenuInitDelay).c_str()); ini.SetValue("Menu", "HookSLDevice", GetBoolValue(Instance()->HookSLDevice).c_str()); ini.SetValue("Menu", "HookSLProxy", GetBoolValue(Instance()->HookSLProxy).c_str()); - ini.SetValue("Menu", "HookUniscalerProxy", GetBoolValue(Instance()->HookUniscalerProxy).c_str()); + ini.SetValue("Menu", "HookFSR3Proxy", GetBoolValue(Instance()->HookFSR3Proxy).c_str()); // CAS ini.SetValue("CAS", "Enabled", GetBoolValue(Instance()->RcasEnabled).c_str()); diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h index a2d2eb94..909e58da 100644 --- a/OptiScaler/Config.h +++ b/OptiScaler/Config.h @@ -75,7 +75,7 @@ public: std::optional MenuInitDelay; std::optional HookSLDevice; std::optional HookSLProxy; - std::optional HookUniscalerProxy; + std::optional HookFSR3Proxy; // Upscale Ratio Override std::optional UpscaleRatioOverrideEnabled; diff --git a/OptiScaler/imgui/imgui_overlay_dx12.cpp b/OptiScaler/imgui/imgui_overlay_dx12.cpp index d1b6e96f..db6d104a 100644 --- a/OptiScaler/imgui/imgui_overlay_dx12.cpp +++ b/OptiScaler/imgui/imgui_overlay_dx12.cpp @@ -31,19 +31,25 @@ static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS typedef void(__fastcall* PFN_ExecuteCommandLists)(ID3D12CommandQueue*, UINT, ID3D12CommandList*); typedef HRESULT(__fastcall* PFN_CreateDXGIFactory1)(REFIID riid, void** ppFactory); -typedef IDXGISwapChain4*(__fastcall* PFN_ffxGetDX12SwapchainPtr)(void* ffxSwapChain); +typedef IDXGISwapChain4* (__fastcall* PFN_ffxGetDX12SwapchainPtr)(void* ffxSwapChain); static PFN_Present oPresent_Dx12 = nullptr; -static PFN_Present1 oPresent1_Dx12 = nullptr; +static PFN_Present1 oPresent1_Dx12= nullptr; static PFN_ResizeBuffers oResizeBuffers_Dx12 = nullptr; -static PFN_ResizeBuffers1 oResizeBuffers1_Dx12 = nullptr; +static PFN_ResizeBuffers1 oResizeBuffers1_Dx12= nullptr; + +static PFN_Present oPresent_Dx12_FSR3 = nullptr; +static PFN_Present1 oPresent1_Dx12_FSR3 = nullptr; +static PFN_ResizeBuffers oResizeBuffers_Dx12_FSR3 = nullptr; +static PFN_ResizeBuffers1 oResizeBuffers1_Dx12_FSR3 = nullptr; + static PFN_ExecuteCommandLists oExecuteCommandLists_Dx12 = nullptr; static PFN_CreateSwapChain oCreateSwapChain_Dx12 = nullptr; static PFN_CreateSwapChainForHwnd oCreateSwapChainForHwnd_Dx12 = nullptr; static PFN_CreateSwapChainForComposition oCreateSwapChainForComposition_Dx12 = nullptr; static PFN_CreateSwapChainForCoreWindow oCreateSwapChainForCoreWindow_Dx12 = nullptr; static PFN_ffxGetDX12SwapchainPtr offxGetDX12SwapchainPtr = nullptr; - + static bool _isInited = false; static void RenderImGui_DX12(IDXGISwapChain3* pSwapChain); @@ -96,34 +102,61 @@ static HRESULT WINAPI hkResizeBuffers1_Dx12(IDXGISwapChain3* pSwapChain, UINT Bu return oResizeBuffers1_Dx12(pSwapChain, BufferCount, Width, Height, NewFormat, SwapChainFlags, pCreationNodeMask, ppPresentQueue); } +static HRESULT WINAPI hkPresent_Dx12_FSR3(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags) +{ + RenderImGui_DX12(pSwapChain); + return oPresent_Dx12_FSR3(pSwapChain, SyncInterval, Flags); +} + +static HRESULT WINAPI hkPresent1_Dx12_FSR3(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS* pPresentParameters) +{ + RenderImGui_DX12(pSwapChain); + return oPresent1_Dx12_FSR3(pSwapChain, SyncInterval, PresentFlags, pPresentParameters); +} + +static HRESULT WINAPI hkResizeBuffers_Dx12_FSR3(IDXGISwapChain* pSwapChain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) +{ + CleanupRenderTarget(); + return oResizeBuffers_Dx12_FSR3(pSwapChain, BufferCount, Width, Height, NewFormat, SwapChainFlags); +} + +static HRESULT WINAPI hkResizeBuffers1_Dx12_FSR3(IDXGISwapChain3* pSwapChain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, + UINT SwapChainFlags, const UINT* pCreationNodeMask, IUnknown* const* ppPresentQueue) +{ + CleanupRenderTarget(); + return oResizeBuffers1_Dx12_FSR3(pSwapChain, BufferCount, Width, Height, NewFormat, SwapChainFlags, pCreationNodeMask, ppPresentQueue); +} + static IDXGISwapChain4* WINAPI hkffxGetDX12SwapchainPtr(void* ffxSwapChain) { spdlog::debug("imgui_overlay_dx12::hkffxGetDX12SwapchainPtr!"); IDXGISwapChain4* result = offxGetDX12SwapchainPtr(ffxSwapChain); - if (oPresent_Dx12 == nullptr) + if (oPresent_Dx12_FSR3 == nullptr) { result->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)); void** pVTable = *reinterpret_cast(g_pSwapChain); - oPresent_Dx12 = (PFN_Present)pVTable[8]; - oPresent1_Dx12 = (PFN_Present1)pVTable[22]; - oResizeBuffers_Dx12 = (PFN_ResizeBuffers)pVTable[13]; - oResizeBuffers1_Dx12 = (PFN_ResizeBuffers1)pVTable[39]; + oPresent_Dx12_FSR3 = (PFN_Present)pVTable[8]; + oPresent1_Dx12_FSR3 = (PFN_Present1)pVTable[22]; + oResizeBuffers_Dx12_FSR3 = (PFN_ResizeBuffers)pVTable[13]; + oResizeBuffers1_Dx12_FSR3 = (PFN_ResizeBuffers1)pVTable[39]; // Apply the detour DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); - DetourAttach(&(PVOID&)oPresent_Dx12, hkPresent_Dx12); - DetourAttach(&(PVOID&)oPresent1_Dx12, hkPresent1_Dx12); + DetourAttach(&(PVOID&)oPresent_Dx12_FSR3, hkPresent_Dx12_FSR3); + DetourAttach(&(PVOID&)oPresent1_Dx12_FSR3, hkPresent1_Dx12_FSR3); - DetourAttach(&(PVOID&)oResizeBuffers_Dx12, hkResizeBuffers_Dx12); - DetourAttach(&(PVOID&)oResizeBuffers1_Dx12, hkResizeBuffers1_Dx12); + DetourAttach(&(PVOID&)oResizeBuffers_Dx12_FSR3, hkResizeBuffers_Dx12_FSR3); + DetourAttach(&(PVOID&)oResizeBuffers1_Dx12_FSR3, hkResizeBuffers1_Dx12_FSR3); DetourTransactionCommit(); + + g_pSwapChain->Release(); } return result; @@ -149,8 +182,12 @@ static bool CreateDeviceD3D12(HWND InHWnd, ID3D12Device* InDevice) // Create device D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; + // check for sl.interposer PFN_D3D12_CREATE_DEVICE slCD = (PFN_D3D12_CREATE_DEVICE)DetourFindFunction("sl.interposer.dll", "D3D12CreateDevice"); + if (slCD != nullptr) + spdlog::info("imgui_overlay_dx12::CreateDeviceD3D12 sl.interposer.dll D3D12CreateDevice found"); + if (slCD != nullptr && Config::Instance()->NVNGX_Engine != NVSDK_NGX_ENGINE_TYPE_UNREAL && Config::Instance()->HookSLDevice.value_or(false)) result = slCD(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)); else @@ -176,9 +213,13 @@ static bool CreateDeviceD3D12(HWND InHWnd, ID3D12Device* InDevice) return false; } + // check for sl.interposer PFN_CreateDXGIFactory1 slFactory = (PFN_CreateDXGIFactory1)DetourFindFunction("sl.interposer.dll", "CreateDXGIFactory1"); - IDXGISwapChain1* swapChain1 = NULL; + if(slFactory != nullptr) + spdlog::info("imgui_overlay_dx12::CreateDeviceD3D12 sl.interposer.dll CreateDXGIFactory1 found"); + + IDXGISwapChain1* swapChain1 = nullptr; if (slFactory != nullptr && Config::Instance()->HookSLProxy.value_or(true)) result = slFactory(IID_PPV_ARGS(&g_dxgiFactory)); @@ -191,9 +232,23 @@ static bool CreateDeviceD3D12(HWND InHWnd, ID3D12Device* InDevice) return false; } - offxGetDX12SwapchainPtr = (PFN_ffxGetDX12SwapchainPtr)DetourFindFunction("Uniscaler.asi", "ffxGetDX12SwapchainPtr"); - if (offxGetDX12SwapchainPtr != nullptr && Config::Instance()->HookUniscalerProxy.value_or(true)) + // check for uniscaler + offxGetDX12SwapchainPtr = (PFN_ffxGetDX12SwapchainPtr)DetourFindFunction("Uniscaler.asi", "ffxGetDX12SwapchainPtr"); + bool uniscalerPresent = offxGetDX12SwapchainPtr != nullptr; + + if(uniscalerPresent) + spdlog::info("imgui_overlay_dx12::CreateDeviceD3D12 Uniscaler ffxGetDX12SwapchainPtr found"); + + + // check for native fsr3 + if (offxGetDX12SwapchainPtr == nullptr) + offxGetDX12SwapchainPtr = (PFN_ffxGetDX12SwapchainPtr)DetourFindFunction("ffx_backend_dx12_x64.dll", "ffxGetDX12SwapchainPtr"); + + if(offxGetDX12SwapchainPtr) + spdlog::info("imgui_overlay_dx12::CreateDeviceD3D12 FSR3 ffxGetDX12SwapchainPtr found"); + + if (offxGetDX12SwapchainPtr != nullptr && Config::Instance()->HookFSR3Proxy.value_or(true)) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); @@ -202,7 +257,9 @@ static bool CreateDeviceD3D12(HWND InHWnd, ID3D12Device* InDevice) DetourTransactionCommit(); } - else + + // hook for dxgi proxy too (for dlss-fg + fsr3-fg games) + if(!uniscalerPresent) { result = g_dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, InHWnd, &sd, NULL, NULL, &swapChain1); if (result != S_OK) @@ -610,6 +667,14 @@ void ImGuiOverlayDx12::ShutdownDx12() DetourDetach(&(PVOID&)oResizeBuffers_Dx12, hkResizeBuffers_Dx12); DetourDetach(&(PVOID&)oResizeBuffers1_Dx12, hkResizeBuffers1_Dx12); + DetourDetach(&(PVOID&)oPresent_Dx12_FSR3, hkPresent_Dx12_FSR3); + DetourDetach(&(PVOID&)oPresent1_Dx12_FSR3, hkPresent1_Dx12_FSR3); + + DetourDetach(&(PVOID&)oResizeBuffers_Dx12_FSR3, hkResizeBuffers_Dx12_FSR3); + DetourDetach(&(PVOID&)oResizeBuffers1_Dx12_FSR3, hkResizeBuffers1_Dx12_FSR3); + + DetourDetach(&(PVOID&)offxGetDX12SwapchainPtr, hkffxGetDX12SwapchainPtr); + DetourDetach(&(PVOID&)oExecuteCommandLists_Dx12, hkExecuteCommandLists_Dx12); DetourTransactionCommit(); diff --git a/nvngx.ini b/nvngx.ini index dafb2302..bae421b8 100644 --- a/nvngx.ini +++ b/nvngx.ini @@ -139,23 +139,24 @@ ResetKey=auto ; Integer value - Default (auto) is 90 frames MenuInitDelay=auto -; If sl.interposer is in memory use it's implementation +; If sl.interposer is loaded in memory use it's implementation ; to create D3D12Device, for frame-generation it is ; usually prevent crashed when using menu ; For Unreal engine games this option is force disabled ; true or false - Default (auto) is false HookSLDevice=auto -; If sl.interposer is in memory use it's implementation +; If sl.interposer is loaded in memory use it's implementation ; to create DXGIFactory, for frame-generation it is ; usually prevent crashed when using menu ; true or false - Default (auto) is true HookSLProxy=auto -; If uniscaler.asi is in memory use it's ffx methods +; If FSR3 is loaded in memory use it's implementation ; to receive swapchain ; true or false - Default (auto) is true -HookUniscalerProxy=auto +HookFSR3Proxy=auto +