From 29f43dc304c011c7f99ca89e6edc68bd2228f736 Mon Sep 17 00:00:00 2001 From: cdozdil Date: Wed, 29 Oct 2025 16:07:39 +0300 Subject: [PATCH] Integrated format transfer shader to FSR-FG for hudless and UI resources --- OptiScaler/framegen/ffx/FSRFG_Dx12.cpp | 127 ++++++++++++++++++++++--- OptiScaler/framegen/ffx/FSRFG_Dx12.h | 9 ++ 2 files changed, 122 insertions(+), 14 deletions(-) diff --git a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp index dfb75382..9dea4e06 100644 --- a/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp +++ b/OptiScaler/framegen/ffx/FSRFG_Dx12.cpp @@ -8,6 +8,91 @@ #include +static inline void ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource, + D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState) +{ + if (InBeforeState == InAfterState) + return; + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = InResource; + barrier.Transition.StateBefore = InBeforeState; + barrier.Transition.StateAfter = InAfterState; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + InCommandList->ResourceBarrier(1, &barrier); +} + +bool FSRFG_Dx12::HudlessFormatTransfer(int index, ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, + DXGI_FORMAT targetFormat, Dx12Resource* resource) +{ + if (_hudlessTransfer[index].get() == nullptr || !_hudlessTransfer[index].get()->IsFormatCompatible(targetFormat)) + { + LOG_DEBUG("Format change, recreate the FormatTransfer"); + + if (_hudlessTransfer[index].get() != nullptr) + _hudlessTransfer[index].reset(); + + _hudlessTransfer[index] = std::make_unique("FormatTransfer", device, targetFormat); + + return false; + } + + if (_hudlessTransfer[index].get() != nullptr && + _hudlessTransfer[index].get()->CreateBufferResource(device, resource->GetResource(), + D3D12_RESOURCE_STATE_UNORDERED_ACCESS)) + { + ResourceBarrier(cmdList, resource->GetResource(), resource->state, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + _hudlessTransfer[index].get()->Dispatch(device, cmdList, resource->GetResource(), + _hudlessTransfer[index].get()->Buffer()); + + ResourceBarrier(cmdList, resource->GetResource(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + resource->state); + + resource->copy = _hudlessTransfer[index].get()->Buffer(); + return true; + } + + return false; +} + +bool FSRFG_Dx12::UIFormatTransfer(int index, ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, + DXGI_FORMAT targetFormat, Dx12Resource* resource) +{ + if (_uiTransfer[index].get() == nullptr || !_uiTransfer[index].get()->IsFormatCompatible(targetFormat)) + { + LOG_DEBUG("Format change, recreate the FormatTransfer"); + + if (_uiTransfer[index].get() != nullptr) + _uiTransfer[index].reset(); + + _uiTransfer[index] = std::make_unique("FormatTransfer", device, targetFormat); + + return false; + } + + if (_uiTransfer[index].get() != nullptr && + _uiTransfer[index].get()->CreateBufferResource(device, resource->GetResource(), + D3D12_RESOURCE_STATE_UNORDERED_ACCESS)) + { + ResourceBarrier(cmdList, resource->GetResource(), resource->state, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + _uiTransfer[index].get()->Dispatch(device, cmdList, resource->GetResource(), + _uiTransfer[index].get()->Buffer()); + + ResourceBarrier(cmdList, resource->GetResource(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + resource->state); + + resource->copy = _uiTransfer[index].get()->Buffer(); + return true; + } + + return false; +} + int GetFormatPrecisionGroup(FfxApiSurfaceFormat format) { switch (format) @@ -935,19 +1020,26 @@ void FSRFG_Dx12::SetResource(Dx12Resource* inputResource) if (type == FG_ResourceType::UIColor) { + auto format = State::Instance().currentSwapchainDesc.BufferDesc.Format; + auto uiFormatGroup = GetFormatPrecisionGroup( (FfxApiSurfaceFormat) ffxApiGetSurfaceFormatDX12(fResource->GetResource()->GetDesc().Format)); - auto scFormatGroup = GetFormatPrecisionGroup( - (FfxApiSurfaceFormat) ffxApiGetSurfaceFormatDX12(State::Instance().currentSwapchainDesc.BufferDesc.Format)); + auto scFormatGroup = GetFormatPrecisionGroup((FfxApiSurfaceFormat) ffxApiGetSurfaceFormatDX12(format)); if (uiFormatGroup == -1 || scFormatGroup == -1 || uiFormatGroup != scFormatGroup) { - LOG_WARN("Skipping UI resource due to format mismatch! UI: {}, swapchain: {}", uiFormatGroup, - scFormatGroup); + if (!UIFormatTransfer(fIndex, _device, GetUICommandList(fIndex), format, fResource)) + { + LOG_WARN("Skipping UI resource due to format mismatch! UI: {}, swapchain: {}", uiFormatGroup, + scFormatGroup); - _frameResources[fIndex][type] = {}; - - return; + _frameResources[fIndex][type] = {}; + return; + } + else + { + fResource->validity = FG_ResourceValidity::UntilPresent; + } } _noUi[fIndex] = false; @@ -956,19 +1048,26 @@ void FSRFG_Dx12::SetResource(Dx12Resource* inputResource) _noDistortionField[fIndex] = false; else if (type == FG_ResourceType::HudlessColor) { + auto format = State::Instance().currentSwapchainDesc.BufferDesc.Format; + auto hudlessFormatGroup = GetFormatPrecisionGroup( (FfxApiSurfaceFormat) ffxApiGetSurfaceFormatDX12(fResource->GetResource()->GetDesc().Format)); - auto scFormatGroup = GetFormatPrecisionGroup( - (FfxApiSurfaceFormat) ffxApiGetSurfaceFormatDX12(State::Instance().currentSwapchainDesc.BufferDesc.Format)); + auto scFormatGroup = GetFormatPrecisionGroup((FfxApiSurfaceFormat) ffxApiGetSurfaceFormatDX12(format)); if (hudlessFormatGroup == -1 || scFormatGroup == -1 || hudlessFormatGroup != scFormatGroup) { - LOG_WARN("Skipping hudless resource due to format mismatch! hudless: {}, swapchain: {}", hudlessFormatGroup, - scFormatGroup); + if (!HudlessFormatTransfer(fIndex, _device, GetUICommandList(fIndex), format, fResource)) + { + LOG_WARN("Skipping hudless resource due to format mismatch! hudless: {}, swapchain: {}", + hudlessFormatGroup, scFormatGroup); - _frameResources[fIndex][type] = {}; - - return; + _frameResources[fIndex][type] = {}; + return; + } + else + { + fResource->validity = FG_ResourceValidity::UntilPresent; + } } _noHudless[fIndex] = false; diff --git a/OptiScaler/framegen/ffx/FSRFG_Dx12.h b/OptiScaler/framegen/ffx/FSRFG_Dx12.h index 230c7ce5..7823e27c 100644 --- a/OptiScaler/framegen/ffx/FSRFG_Dx12.h +++ b/OptiScaler/framegen/ffx/FSRFG_Dx12.h @@ -4,6 +4,8 @@ #include +#include + #include #include @@ -18,6 +20,9 @@ class FSRFG_Dx12 : public virtual IFGFeature_Dx12 uint32_t _maxRenderWidth = 0; uint32_t _maxRenderHeight = 0; + std::unique_ptr _hudlessTransfer[BUFFER_COUNT]; + std::unique_ptr _uiTransfer[BUFFER_COUNT]; + ID3D12GraphicsCommandList* _fgCommandList[BUFFER_COUNT] {}; ID3D12CommandAllocator* _fgCommandAllocator[BUFFER_COUNT] {}; @@ -53,6 +58,10 @@ class FSRFG_Dx12 : public virtual IFGFeature_Dx12 bool ExecuteCommandList(int index); bool Dispatch(); void ConfigureFramePaceTuning(); + bool HudlessFormatTransfer(int index, ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, + DXGI_FORMAT targetFormat, Dx12Resource* resource); + bool UIFormatTransfer(int index, ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, DXGI_FORMAT targetFormat, + Dx12Resource* resource); protected: void ReleaseObjects() override final;