diff --git a/OptiScaler.ini b/OptiScaler.ini index cb8b3566..d9ecebce 100644 --- a/OptiScaler.ini +++ b/OptiScaler.ini @@ -378,6 +378,11 @@ HUDFixRelaxedResolutionCheck=auto ; true or false - Default (auto) is false HUDFixImmediate=auto +; New advanced binding tracking system for Hudless resources +; Set false for old Hudfix behavior +; true or false - Default (auto) is true +HUDFixPersistentBindings=auto + ; Resource tracking is always enabled regardless of Hudfix setting ; Might cause performance issues but disabling might cause stability issues ; true or false - Default (auto) is false diff --git a/OptiScaler/Config.cpp b/OptiScaler/Config.cpp index 11e960c5..a025490b 100644 --- a/OptiScaler/Config.cpp +++ b/OptiScaler/Config.cpp @@ -184,6 +184,7 @@ bool Config::Reload(std::filesystem::path iniPath) FGHUDLimit.set_from_config(readInt("OptiFG", "HUDLimit")); FGHUDFixExtended.set_from_config(readBool("OptiFG", "HUDFixExtended")); FGImmediateCapture.set_from_config(readBool("OptiFG", "HUDFixImmediate")); + FGHudfixPersistentBindings.set_from_config(readBool("OptiFG", "HUDFixPersistentBindings")); FGUseShards.set_from_config(readBool("OptiFG", "UseShards")); FGAlwaysTrackHeaps.set_from_config(readBool("OptiFG", "AlwaysTrackHeaps")); FGResourceBlocking.set_from_config(readBool("OptiFG", "ResourceBlocking")); @@ -1026,6 +1027,8 @@ bool Config::SaveIni() ini.SetValue("OptiFG", "HUDFixExtended", GetBoolValue(Instance()->FGHUDFixExtended.value_for_config()).c_str()); ini.SetValue("OptiFG", "HUDFixImmediate", GetBoolValue(Instance()->FGImmediateCapture.value_for_config()).c_str()); + ini.SetValue("OptiFG", "HUDFixPersistentBindings", + GetBoolValue(Instance()->FGHudfixPersistentBindings.value_for_config()).c_str()); ini.SetValue("OptiFG", "UseShards", GetBoolValue(Instance()->FGUseShards.value_for_config()).c_str()); ini.SetValue("OptiFG", "AlwaysTrackHeaps", GetBoolValue(Instance()->FGAlwaysTrackHeaps.value_for_config()).c_str()); diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h index 8eee1a8a..74e32d61 100644 --- a/OptiScaler/Config.h +++ b/OptiScaler/Config.h @@ -550,6 +550,7 @@ class Config CustomOptional FGHUDLimit { 1 }; CustomOptional FGHUDFixExtended { false }; CustomOptional FGImmediateCapture { false }; + CustomOptional FGHudfixPersistentBindings { true }; CustomOptional FGDontUseSwapchainBuffers { false }; CustomOptional FGRelaxedResolutionCheck { false }; CustomOptional FGHudfixDisableRTV { false }; diff --git a/OptiScaler/hooks/D3D12_Hooks.cpp b/OptiScaler/hooks/D3D12_Hooks.cpp index c1e13b1b..d65c81fc 100644 --- a/OptiScaler/hooks/D3D12_Hooks.cpp +++ b/OptiScaler/hooks/D3D12_Hooks.cpp @@ -394,9 +394,12 @@ static void hkSetDescriptorHeaps(ID3D12GraphicsCommandList* commandList, UINT Nu { if (!lateInProgressSetDescriptorHeaps && !isUpscalerActive && commandList != nullptr) { - ResTrack_Dx12::OnSetDescriptorHeaps(commandList, NumDescriptorHeaps, ppDescriptorHeaps); + auto config = Config::Instance(); - if (Config::Instance()->ExtendedStateRestore.value_or_default() && ppDescriptorHeaps != nullptr) + if (config->FGHudfixPersistentBindings.value_or_default()) + ResTrack_Dx12::OnSetDescriptorHeaps(commandList, NumDescriptorHeaps, ppDescriptorHeaps); + + if (config->ExtendedStateRestore.value_or_default() && ppDescriptorHeaps != nullptr) { std::unique_lock lock(descriptorHeapsMutex); @@ -426,9 +429,12 @@ static void hkSetComputeRootSignature(ID3D12GraphicsCommandList* commandList, ID { if (!lateInProgressSetComputeRootSignature && !isUpscalerActive && commandList != nullptr) { - ResTrack_Dx12::OnSetComputeRootSignature(commandList, pRootSignature); + auto config = Config::Instance(); - if (Config::Instance()->RestoreComputeSignature.value_or_default() && pRootSignature != nullptr) + if (config->FGHudfixPersistentBindings.value_or_default()) + ResTrack_Dx12::OnSetComputeRootSignature(commandList, pRootSignature); + + if (config->RestoreComputeSignature.value_or_default() && pRootSignature != nullptr) { { auto paramCount = GetRootParameterCount(pRootSignature); @@ -573,9 +579,12 @@ static void hkSetGraphicsRootSignature(ID3D12GraphicsCommandList* commandList, I { if (!lateInProgressSetGraphicsRootSignature && !isUpscalerActive && commandList != nullptr) { - ResTrack_Dx12::OnSetGraphicsRootSignature(commandList, pRootSignature); + auto config = Config::Instance(); - if (Config::Instance()->RestoreGraphicSignature.value_or_default() && pRootSignature != nullptr) + if (config->FGHudfixPersistentBindings.value_or_default()) + ResTrack_Dx12::OnSetGraphicsRootSignature(commandList, pRootSignature); + + if (config->RestoreGraphicSignature.value_or_default() && pRootSignature != nullptr) { std::unique_lock lock(rootSignatureMutex); @@ -734,9 +743,12 @@ static void hkSetDescriptorHeapsLate(ID3D12GraphicsCommandList* commandList, UIN if (!isUpscalerActive && commandList != nullptr) { - ResTrack_Dx12::OnSetDescriptorHeaps(commandList, NumDescriptorHeaps, ppDescriptorHeaps); + auto config = Config::Instance(); - if (Config::Instance()->ExtendedStateRestore.value_or_default() && ppDescriptorHeaps != nullptr) + if (config->FGHudfixPersistentBindings.value_or_default()) + ResTrack_Dx12::OnSetDescriptorHeaps(commandList, NumDescriptorHeaps, ppDescriptorHeaps); + + if (config->ExtendedStateRestore.value_or_default() && ppDescriptorHeaps != nullptr) { std::unique_lock lock(descriptorHeapsMutex); @@ -762,9 +774,12 @@ static void hkSetComputeRootSignatureLate(ID3D12GraphicsCommandList* commandList if (!isUpscalerActive && commandList != nullptr) { - ResTrack_Dx12::OnSetComputeRootSignature(commandList, pRootSignature); + auto config = Config::Instance(); - if (Config::Instance()->RestoreComputeSignature.value_or_default() && pRootSignature != nullptr) + if (config->FGHudfixPersistentBindings.value_or_default()) + ResTrack_Dx12::OnSetComputeRootSignature(commandList, pRootSignature); + + if (config->RestoreComputeSignature.value_or_default() && pRootSignature != nullptr) { { auto paramCount = GetRootParameterCount(pRootSignature); @@ -935,9 +950,12 @@ static void hkSetGraphicsRootSignatureLate(ID3D12GraphicsCommandList* commandLis if (!isUpscalerActive && commandList != nullptr) { - ResTrack_Dx12::OnSetGraphicsRootSignature(commandList, pRootSignature); + auto config = Config::Instance(); - if (Config::Instance()->RestoreGraphicSignature.value_or_default() && pRootSignature != nullptr) + if (config->FGHudfixPersistentBindings.value_or_default()) + ResTrack_Dx12::OnSetGraphicsRootSignature(commandList, pRootSignature); + + if (config->RestoreGraphicSignature.value_or_default() && pRootSignature != nullptr) { std::unique_lock lock(rootSignatureMutex); signatures.insert_or_assign(commandList, SignatureEntry { SignatureEntryType::Graphics, pRootSignature }); @@ -1103,6 +1121,7 @@ void D3D12Hooks::HookToCommandListLate(ID3D12GraphicsCommandList* commandList) const bool restoreComputeSignature = config->RestoreComputeSignature.value_or_default(); const bool restoreGraphicSignature = config->RestoreGraphicSignature.value_or_default(); const bool extendedRestoreSignature = config->ExtendedStateRestore.value_or_default(); + const bool persistentBindings = config->FGHudfixPersistentBindings.value_or_default(); s_SetPipelineState.o_lateHook = (PFN_SetPipelineState) pVTable[25]; s_SetDescriptorHeaps.o_lateHook = (PFN_SetDescriptorHeaps) pVTable[28]; @@ -1129,7 +1148,7 @@ void D3D12Hooks::HookToCommandListLate(ID3D12GraphicsCommandList* commandList) DetourAttach(&(PVOID&) s_SetPipelineState.o_lateHook, hkSetPipelineStateLate); if (s_SetDescriptorHeaps.o_lateHook != nullptr && - (extendedRestoreSignature || State::Instance().activeFgInput == FGInput::Upscaler)) + (extendedRestoreSignature || (persistentBindings && State::Instance().activeFgInput == FGInput::Upscaler))) { DetourAttach(&(PVOID&) s_SetDescriptorHeaps.o_lateHook, hkSetDescriptorHeapsLate); } @@ -1267,7 +1286,9 @@ static void HookToCommandList(ID3D12Device* InDevice) // Get the vtable pointer PVOID* pVTable = *(PVOID**) commandList; - const bool extendedRestoreSignature = Config::Instance()->ExtendedStateRestore.value_or_default(); + auto config = Config::Instance(); + const bool extendedRestoreSignature = config->ExtendedStateRestore.value_or_default(); + const bool persistentBindings = config->FGHudfixPersistentBindings.value_or_default(); s_SetPipelineState.o_earlyHook = (PFN_SetPipelineState) pVTable[25]; s_SetDescriptorHeaps.o_earlyHook = (PFN_SetDescriptorHeaps) pVTable[28]; @@ -1293,7 +1314,8 @@ static void HookToCommandList(ID3D12Device* InDevice) DetourAttach(&(PVOID&) s_SetPipelineState.o_earlyHook, hkSetPipelineState); if (s_SetDescriptorHeaps.o_earlyHook != nullptr && - (extendedRestoreSignature || State::Instance().activeFgInput == FGInput::Upscaler)) + (extendedRestoreSignature || + (persistentBindings && State::Instance().activeFgInput == FGInput::Upscaler))) { DetourAttach(&(PVOID&) s_SetDescriptorHeaps.o_earlyHook, hkSetDescriptorHeaps); } diff --git a/OptiScaler/resource_tracking/ResTrack_dx12.cpp b/OptiScaler/resource_tracking/ResTrack_dx12.cpp index cc72e508..71896e9c 100644 --- a/OptiScaler/resource_tracking/ResTrack_dx12.cpp +++ b/OptiScaler/resource_tracking/ResTrack_dx12.cpp @@ -1238,7 +1238,8 @@ bool ResTrack_Dx12::ResolveRenderTargetBinding(SIZE_T cpuHandle, ResourceInfo& o bool ResTrack_Dx12::ProcessGraphicsBindings(ID3D12GraphicsCommandList* commandList, UINT captureInfo) { - if (Config::Instance()->FGImmediateCapture.value_or_default()) + if (!_bindingTrackingEnabled.load(std::memory_order_acquire) || + Config::Instance()->FGImmediateCapture.value_or_default()) return false; auto* state = FindBindingState(commandList); @@ -1303,7 +1304,8 @@ bool ResTrack_Dx12::ProcessGraphicsBindings(ID3D12GraphicsCommandList* commandLi bool ResTrack_Dx12::ProcessComputeBindings(ID3D12GraphicsCommandList* commandList, UINT captureInfo) { - if (Config::Instance()->FGImmediateCapture.value_or_default()) + if (!_bindingTrackingEnabled.load(std::memory_order_acquire) || + Config::Instance()->FGImmediateCapture.value_or_default()) return false; auto* state = FindBindingState(commandList); @@ -2092,10 +2094,14 @@ void ResTrack_Dx12::HookCommandList(ID3D12Device* InDevice) // Get the vtable pointer PVOID* pVTable = *(PVOID**) realCL; + const bool persistentBindings = Config::Instance()->FGHudfixPersistentBindings.value_or_default(); // Persistent command-list binding invalidation - o_Reset = (PFN_Reset) pVTable[10]; - o_ClearState = (PFN_ClearState) pVTable[11]; + if (persistentBindings) + { + o_Reset = (PFN_Reset) pVTable[10]; + o_ClearState = (PFN_ClearState) pVTable[11]; + } // hudless shader o_OMSetRenderTargets = (PFN_OMSetRenderTargets) pVTable[46]; @@ -2156,7 +2162,7 @@ void ResTrack_Dx12::HookCommandList(ID3D12Device* InDevice) } else if (State::Instance().activeFgInput == FGInput::Upscaler) { - _bindingTrackingEnabled.store(true, std::memory_order_release); + _bindingTrackingEnabled.store(persistentBindings, std::memory_order_release); } } @@ -2196,17 +2202,20 @@ void ResTrack_Dx12::HookDevice(ID3D12Device* device) _trackedResources.reserve(1024); } - if (!_useShards) + if (Config::Instance()->FGHudfixPersistentBindings.value_or_default()) { - std::lock_guard lock(_bindingStateMutex); - _bindingStates.reserve(256); - } - else - { - for (auto& shard : _bindingShards) + if (!_useShards) { - std::lock_guard lock(shard.mutex); - shard.map.reserve(32); + std::lock_guard lock(_bindingStateMutex); + _bindingStates.reserve(256); + } + else + { + for (auto& shard : _bindingShards) + { + std::lock_guard lock(shard.mutex); + shard.map.reserve(32); + } } } }