From 833e9717030337a7fd9461eba71ba2ceecc58af1 Mon Sep 17 00:00:00 2001 From: FakeMichau <49685661+FakeMichau@users.noreply.github.com> Date: Tue, 30 Jun 2026 23:18:59 +0200 Subject: [PATCH] Pass the resource lock to the user of GetResource Should fix Witcher 3 crashing during alt tabbing with XeFG --- OptiScaler/framegen/IFGFeature_Dx12.cpp | 11 ++++++----- OptiScaler/framegen/IFGFeature_Dx12.h | 13 ++++++++++++- OptiScaler/framegen/dlssg/DLSSG_Dx12.cpp | 16 ++++++++-------- OptiScaler/framegen/ffx/FSRFG_Dx12.cpp | 14 +++++++------- OptiScaler/framegen/xefg/XeFG_Dx12.cpp | 16 ++++++++-------- OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp | 11 +++++------ OptiScaler/inputs/FG/FfxApi_Dx12_FG.cpp | 6 +++--- 7 files changed, 49 insertions(+), 38 deletions(-) diff --git a/OptiScaler/framegen/IFGFeature_Dx12.cpp b/OptiScaler/framegen/IFGFeature_Dx12.cpp index 812578ad..9c0c6335 100644 --- a/OptiScaler/framegen/IFGFeature_Dx12.cpp +++ b/OptiScaler/framegen/IFGFeature_Dx12.cpp @@ -12,7 +12,7 @@ bool IFGFeature_Dx12::GetResourceCopy(FG_ResourceType type, D3D12_RESOURCE_STATE auto resource = GetResource(type); - if (resource == nullptr || (resource->copy == nullptr && resource->validity == FG_ResourceValidity::ValidNow)) + if (!resource || (resource->copy == nullptr && resource->validity == FG_ResourceValidity::ValidNow)) { LOG_WARN("No resource copy of type {} to use", magic_enum::enum_name(type)); return false; @@ -195,7 +195,7 @@ ID3D12GraphicsCommandList* IFGFeature_Dx12::GetSCCommandList(int index) return _scCommandList[index]; } -Dx12Resource* IFGFeature_Dx12::GetResource(FG_ResourceType type, int index) +LockedDx12Resource IFGFeature_Dx12::GetResource(FG_ResourceType type, int index) { if (index < 0) index = GetIndex(); @@ -204,10 +204,11 @@ Dx12Resource* IFGFeature_Dx12::GetResource(FG_ResourceType type, int index) auto& resources = _frameResources[index]; - if (resources.contains(type)) - return &resources[type]; + auto it = resources.find(type); + if (it != resources.end()) + return { &it->second, std::move(lock) }; - return nullptr; + return { nullptr, std::move(lock) }; } void IFGFeature_Dx12::NewFrame() diff --git a/OptiScaler/framegen/IFGFeature_Dx12.h b/OptiScaler/framegen/IFGFeature_Dx12.h index 4d04880c..172f413a 100644 --- a/OptiScaler/framegen/IFGFeature_Dx12.h +++ b/OptiScaler/framegen/IFGFeature_Dx12.h @@ -31,6 +31,17 @@ struct Dx12Resource ID3D12Resource* GetResource() { return (copy == nullptr) ? resource : copy; } }; +struct LockedDx12Resource +{ + Dx12Resource* resource = nullptr; + std::shared_lock lock; + + Dx12Resource* operator->() { return resource; } + Dx12Resource& operator*() { return *resource; } + + explicit operator bool() const { return resource != nullptr; } +}; + class IFGFeature_Dx12 : public virtual IFGFeature { private: @@ -110,7 +121,7 @@ class IFGFeature_Dx12 : public virtual IFGFeature ID3D12GraphicsCommandList* GetUICommandList(int index = -1); ID3D12GraphicsCommandList* GetSCCommandList(int index = -1); - Dx12Resource* GetResource(FG_ResourceType type, int index = -1); + LockedDx12Resource GetResource(FG_ResourceType type, int index = -1); bool GetResourceCopy(FG_ResourceType type, D3D12_RESOURCE_STATES bufferState, ID3D12Resource* output); ID3D12CommandQueue* GetCommandQueue(); diff --git a/OptiScaler/framegen/dlssg/DLSSG_Dx12.cpp b/OptiScaler/framegen/dlssg/DLSSG_Dx12.cpp index 22c052a9..5bed63e6 100644 --- a/OptiScaler/framegen/dlssg/DLSSG_Dx12.cpp +++ b/OptiScaler/framegen/dlssg/DLSSG_Dx12.cpp @@ -779,9 +779,9 @@ bool DLSSG_Dx12::Present() if (Config::Instance()->FGDrawUIOverFG.value_or_default()) { auto ui = GetResource(FG_ResourceType::UIColor, fIndex); - if (ui != nullptr && (ui->validity == FG_ResourceValidity::UntilPresent || - ui->validity == FG_ResourceValidity::JustTrackCmdlist || - ui->validity == FG_ResourceValidity::UntilPresentFromDispatch)) + if (ui && (ui->validity == FG_ResourceValidity::UntilPresent || + ui->validity == FG_ResourceValidity::JustTrackCmdlist || + ui->validity == FG_ResourceValidity::UntilPresentFromDispatch)) { LOG_DEBUG("UI[{}] resource: {:X}, copy: {}", fIndex, (size_t) ui->resource, (size_t) ui->copy); if (_renderUI.get() == nullptr) @@ -804,7 +804,7 @@ bool DLSSG_Dx12::Present() } } } - else if (ui == nullptr) + else if (!ui) { LOG_WARN("UI resource is nullptr"); } @@ -815,9 +815,9 @@ bool DLSSG_Dx12::Present() if (State::Instance().fgHudlessCompare) { auto hudless = GetResource(FG_ResourceType::HudlessColor, fIndex); - if (hudless != nullptr && (hudless->validity == FG_ResourceValidity::UntilPresent || - hudless->validity == FG_ResourceValidity::JustTrackCmdlist || - hudless->validity == FG_ResourceValidity::UntilPresentFromDispatch)) + if (hudless && (hudless->validity == FG_ResourceValidity::UntilPresent || + hudless->validity == FG_ResourceValidity::JustTrackCmdlist || + hudless->validity == FG_ResourceValidity::UntilPresentFromDispatch)) { LOG_DEBUG("Hudless[{}] resource: {:X}, copy: {}", fIndex, (size_t) hudless->resource, (size_t) hudless->copy); @@ -835,7 +835,7 @@ bool DLSSG_Dx12::Present() } } } - else if (hudless == nullptr) + else if (!hudless) { LOG_WARN("Hudless resource is nullptr"); } diff --git a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp index 87d32c54..ba0c4292 100644 --- a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp +++ b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp @@ -354,7 +354,7 @@ bool FSRFG_Dx12::Dispatch() distortionFieldDesc.header.type = FFX_API_CONFIGURE_DESC_TYPE_FRAMEGENERATION_REGISTERDISTORTIONRESOURCE; auto distortion = GetResource(FG_ResourceType::Distortion, fIndex); - if (distortion != nullptr && IsResourceReady(FG_ResourceType::Distortion, fIndex)) + if (distortion && IsResourceReady(FG_ResourceType::Distortion, fIndex)) { LOG_TRACE("Using Distortion Field: {:X}", (size_t) distortion->GetResource()); @@ -373,7 +373,7 @@ bool FSRFG_Dx12::Dispatch() std::shared_lock lock(_resourceMutex[fIndex]); auto hudless = GetResource(FG_ResourceType::HudlessColor, fIndex); - if (hudless != nullptr && IsResourceReady(FG_ResourceType::HudlessColor, fIndex)) + if (hudless && IsResourceReady(FG_ResourceType::HudlessColor, fIndex)) { LOG_TRACE("Using hudless: {:X}", (size_t) hudless->GetResource()); @@ -527,7 +527,7 @@ bool FSRFG_Dx12::Dispatch() auto velocity = GetResource(FG_ResourceType::Velocity, fIndex); auto depth = GetResource(FG_ResourceType::Depth, fIndex); - if (velocity != nullptr && IsResourceReady(FG_ResourceType::Velocity, fIndex)) + if (velocity && IsResourceReady(FG_ResourceType::Velocity, fIndex)) { LOG_DEBUG("Velocity resource: {:X}", (size_t) velocity->GetResource()); dfgPrepare.motionVectors = ffxApiGetResourceDX12(velocity->GetResource(), GetFfxApiState(velocity->state)); @@ -539,7 +539,7 @@ bool FSRFG_Dx12::Dispatch() return false; } - if (depth != nullptr && IsResourceReady(FG_ResourceType::Depth, fIndex)) + if (depth && IsResourceReady(FG_ResourceType::Depth, fIndex)) { LOG_DEBUG("Depth resource: {:X}", (size_t) depth->GetResource()); dfgPrepare.depth = ffxApiGetResourceDX12(depth->GetResource(), GetFfxApiState(depth->state)); @@ -553,7 +553,7 @@ bool FSRFG_Dx12::Dispatch() if (state.currentFeature && state.activeFgInput == FGInput::Upscaler) dfgPrepare.renderSize = { state.currentFeature->RenderWidth(), state.currentFeature->RenderHeight() }; - else if (depth != nullptr) + else if (depth) dfgPrepare.renderSize = { static_cast(depth->width), depth->height }; else dfgPrepare.renderSize = { dfgPrepare.depth.description.width, dfgPrepare.depth.description.height }; @@ -1685,7 +1685,7 @@ bool FSRFG_Dx12::Present() if (Config::Instance()->FGDrawUIOverFG.value_or_default()) { auto ui = GetResource(FG_ResourceType::UIColor, fIndex); - if (ui != nullptr) + if (ui) { LOG_DEBUG("UI[{}] resource: {:X}, copy: {}", fIndex, (size_t) ui->resource, (size_t) ui->copy); if (_renderUI.get() == nullptr) @@ -1708,7 +1708,7 @@ bool FSRFG_Dx12::Present() } } } - else if (ui == nullptr) + else if (!ui) { LOG_WARN("UI resource is nullptr"); } diff --git a/OptiScaler/framegen/xefg/XeFG_Dx12.cpp b/OptiScaler/framegen/xefg/XeFG_Dx12.cpp index 52467a0d..dca59551 100644 --- a/OptiScaler/framegen/xefg/XeFG_Dx12.cpp +++ b/OptiScaler/framegen/xefg/XeFG_Dx12.cpp @@ -1250,9 +1250,9 @@ bool XeFG_Dx12::Present() if (Config::Instance()->FGDrawUIOverFG.value_or_default()) { auto ui = GetResource(FG_ResourceType::UIColor, fIndex); - if (ui != nullptr && (ui->validity == FG_ResourceValidity::UntilPresent || - ui->validity == FG_ResourceValidity::JustTrackCmdlist || - ui->validity == FG_ResourceValidity::UntilPresentFromDispatch)) + if (ui && (ui->validity == FG_ResourceValidity::UntilPresent || + ui->validity == FG_ResourceValidity::JustTrackCmdlist || + ui->validity == FG_ResourceValidity::UntilPresentFromDispatch)) { LOG_DEBUG("UI[{}] resource: {:X}, copy: {}", fIndex, (size_t) ui->resource, (size_t) ui->copy); if (_renderUI.get() == nullptr) @@ -1275,7 +1275,7 @@ bool XeFG_Dx12::Present() } } } - else if (ui == nullptr) + else if (!ui) { LOG_WARN("UI resource is nullptr"); } @@ -1286,9 +1286,9 @@ bool XeFG_Dx12::Present() if (State::Instance().fgHudlessCompare) { auto hudless = GetResource(FG_ResourceType::HudlessColor, fIndex); - if (hudless != nullptr && (hudless->validity == FG_ResourceValidity::UntilPresent || - hudless->validity == FG_ResourceValidity::JustTrackCmdlist || - hudless->validity == FG_ResourceValidity::UntilPresentFromDispatch)) + if (hudless && (hudless->validity == FG_ResourceValidity::UntilPresent || + hudless->validity == FG_ResourceValidity::JustTrackCmdlist || + hudless->validity == FG_ResourceValidity::UntilPresentFromDispatch)) { LOG_DEBUG("Hudless[{}] resource: {:X}, copy: {}", fIndex, (size_t) hudless->resource, (size_t) hudless->copy); @@ -1306,7 +1306,7 @@ bool XeFG_Dx12::Present() } } } - else if (hudless == nullptr) + else if (!hudless) { LOG_WARN("Hudless resource is nullptr"); } diff --git a/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp b/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp index 3d5136ee..06285943 100644 --- a/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp +++ b/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp @@ -610,8 +610,7 @@ static Fsr3::FfxErrorCode hkffxFrameInterpolationDispatch(FfxFrameInterpolationC fg->SetFrameTimeDelta(params->frameTimeDelta); fg->SetReset(params->reset ? 1 : 0); - if (params->currentBackBuffer_HUDLess.resource != nullptr && - fg->GetResource(FG_ResourceType::HudlessColor) == nullptr) + if (params->currentBackBuffer_HUDLess.resource != nullptr && !fg->GetResource(FG_ResourceType::HudlessColor)) { UINT width = params->interpolationRect.width; UINT height = params->interpolationRect.height; @@ -640,7 +639,7 @@ static Fsr3::FfxErrorCode hkffxFrameInterpolationDispatch(FfxFrameInterpolationC } if (_presentCallback != nullptr && params->currentBackBuffer.resource != nullptr && - fg->GetResource(FG_ResourceType::HudlessColor) == nullptr) + !fg->GetResource(FG_ResourceType::HudlessColor)) { UINT width = params->interpolationRect.width; UINT height = params->interpolationRect.height; @@ -821,7 +820,7 @@ static Fsr3::FfxErrorCode hkffxSetFrameGenerationConfigToSwapchainDX12(Fsr3::Ffx left = 0; } - if (config->HUDLessColor.resource != nullptr && fg->GetResource(FG_ResourceType::HudlessColor) == nullptr) + if (config->HUDLessColor.resource != nullptr && !fg->GetResource(FG_ResourceType::HudlessColor)) { Dx12Resource ui {}; ui.cmdList = nullptr; // Not sure about this @@ -1177,7 +1176,7 @@ void FSR3FG::ffxPresentCallback() if (result == FFX_API_RETURN_OK) { - if (fg->GetResource(FG_ResourceType::HudlessColor, fIndex) == nullptr) + if (!fg->GetResource(FG_ResourceType::HudlessColor, fIndex)) { auto hDesc = _hudless[fIndex]->GetDesc(); Dx12Resource hudless {}; @@ -1271,7 +1270,7 @@ void FSR3FG::ffxPresentCallback() if (result == FFX_API_RETURN_OK) { - if (fg->GetResource(FG_ResourceType::HudlessColor, fIndex) == nullptr) + if (!fg->GetResource(FG_ResourceType::HudlessColor, fIndex)) { auto hDesc = _hudless[fIndex]->GetDesc(); Dx12Resource hudless {}; diff --git a/OptiScaler/inputs/FG/FfxApi_Dx12_FG.cpp b/OptiScaler/inputs/FG/FfxApi_Dx12_FG.cpp index 23b6a0b1..f967c6df 100644 --- a/OptiScaler/inputs/FG/FfxApi_Dx12_FG.cpp +++ b/OptiScaler/inputs/FG/FfxApi_Dx12_FG.cpp @@ -992,7 +992,7 @@ ffxReturnCode_t ffxDispatch_Dx12FG(ffxContext* context, ffxDispatchDescHeader* d if (cdDesc->presentColor.resource != nullptr && !Config::Instance()->FSRFGSkipDispatchForHudless.value_or_default() && - fg->GetResource(FG_ResourceType::HudlessColor) == nullptr) + !fg->GetResource(FG_ResourceType::HudlessColor)) { UINT width = cdDesc->generationRect.width; UINT height = cdDesc->generationRect.height; @@ -1334,7 +1334,7 @@ void ffxPresentCallback() if (result == FFX_API_RETURN_OK) { - if (fg->GetResource(FG_ResourceType::HudlessColor, fIndex) == nullptr) + if (!fg->GetResource(FG_ResourceType::HudlessColor, fIndex)) { auto hDesc = _hudless[fIndex]->GetDesc(); Dx12Resource hudless {}; @@ -1432,7 +1432,7 @@ void ffxPresentCallback() if (result == FFX_API_RETURN_OK) { - if (fg->GetResource(FG_ResourceType::HudlessColor, fIndex) == nullptr) + if (!fg->GetResource(FG_ResourceType::HudlessColor, fIndex)) { auto hDesc = _hudless[fIndex]->GetDesc(); Dx12Resource hudless {};