From c59eeb574faef158d11a028340f34b07fa03ab5c Mon Sep 17 00:00:00 2001 From: cdozdil Date: Wed, 24 Jul 2024 19:58:53 +0300 Subject: [PATCH] added reactive mask bias --- OptiScaler/Config.cpp | 4 + OptiScaler/Config.h | 2 + OptiScaler/NVNGX_DLSS_Dx12.cpp | 26 +- OptiScaler/backends/IFeature_Dx11wDx12.cpp | 7 +- OptiScaler/backends/IFeature_Dx11wDx12.h | 2 + OptiScaler/backends/IFeature_Dx12.h | 2 + .../backends/fsr2/FSR2Feature_Dx11On12.cpp | 20 +- OptiScaler/backends/fsr2/FSR2Feature_Dx12.cpp | 21 +- .../fsr2_212/FSR2Feature_Dx11On12_212.cpp | 20 +- .../fsr2_212/FSR2Feature_Dx12_212.cpp | 19 +- .../backends/fsr31/FSR31Feature_Dx11On12.cpp | 22 +- .../backends/fsr31/FSR31Feature_Dx12.cpp | 20 +- OptiScaler/backends/fsr31/FSR31Feature_Dx12.h | 1 - OptiScaler/backends/xess/XeSSFeature_Dx11.cpp | 17 +- OptiScaler/backends/xess/XeSSFeature_Dx12.cpp | 20 +- OptiScaler/bias/Bias_Common.h | 51 ++ OptiScaler/bias/Bias_Dx11.cpp | 468 ++++++++++++++++++ OptiScaler/bias/Bias_Dx11.h | 163 ++++++ OptiScaler/bias/Bias_Dx12.cpp | 434 ++++++++++++++++ OptiScaler/bias/Bias_Dx12.h | 53 ++ OptiScaler/imgui/imgui_common.h | 17 + 21 files changed, 1356 insertions(+), 33 deletions(-) create mode 100644 OptiScaler/bias/Bias_Common.h create mode 100644 OptiScaler/bias/Bias_Dx11.cpp create mode 100644 OptiScaler/bias/Bias_Dx11.h create mode 100644 OptiScaler/bias/Bias_Dx12.cpp create mode 100644 OptiScaler/bias/Bias_Dx12.h diff --git a/OptiScaler/Config.cpp b/OptiScaler/Config.cpp index c9763aec..04495b00 100644 --- a/OptiScaler/Config.cpp +++ b/OptiScaler/Config.cpp @@ -51,6 +51,7 @@ bool Config::Reload(std::filesystem::path iniPath) FsrCameraFar = readFloat("FSR", "CameraFar"); FsrDebugView = readBool("FSR", "DebugView"); Fsr3xIndex = readInt("FSR", "UpscalerIndex"); + FsrUseMaskForTransparency = readBool("FSR", "UseReactiveMaskForTransparency"); } // XeSS @@ -227,6 +228,7 @@ bool Config::Reload(std::filesystem::path iniPath) JitterCancellation = readBool("InitFlags", "JitterCancellation"); DisplayResolution = readBool("InitFlags", "DisplayResolution"); DisableReactiveMask = readBool("InitFlags", "DisableReactiveMask"); + DlssReactiveMaskBias = readFloat("UpscaleRatio", "DlssReactiveMaskBias"); } @@ -452,6 +454,7 @@ bool Config::SaveIni() ini.SetValue("FSR", "CameraFar", GetFloatValue(Instance()->FsrCameraFar).c_str()); ini.SetValue("FSR", "DebugView", GetBoolValue(Instance()->FsrDebugView).c_str()); ini.SetValue("FSR", "UpscalerIndex", GetIntValue(Instance()->Fsr3xIndex).c_str()); + ini.SetValue("FSR", "UseReactiveMaskForTransparency", GetBoolValue(Instance()->FsrUseMaskForTransparency).c_str()); } // XeSS @@ -519,6 +522,7 @@ bool Config::SaveIni() ini.SetValue("InitFlags", "JitterCancellation", GetBoolValue(Instance()->JitterCancellation).c_str()); ini.SetValue("InitFlags", "DisplayResolution", GetBoolValue(Instance()->DisplayResolution).c_str()); ini.SetValue("InitFlags", "DisableReactiveMask", GetBoolValue(Instance()->DisableReactiveMask).c_str()); + ini.SetValue("InitFlags", "DlssReactiveMaskBias", GetFloatValue(Instance()->DlssReactiveMaskBias).c_str()); } // Upscale Ratio Override diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h index 4f43f2fa..6f33d33a 100644 --- a/OptiScaler/Config.h +++ b/OptiScaler/Config.h @@ -25,6 +25,7 @@ public: std::optional JitterCancellation; std::optional DisplayResolution; std::optional DisableReactiveMask; + std::optional DlssReactiveMaskBias; // Logging std::optional LogToFile; @@ -128,6 +129,7 @@ public: std::optional FsrCameraFar; std::optional FsrDebugView; std::optional Fsr3xIndex; + std::optional FsrUseMaskForTransparency; // dx11wdx12 std::optional TextureSyncMethod; diff --git a/OptiScaler/NVNGX_DLSS_Dx12.cpp b/OptiScaler/NVNGX_DLSS_Dx12.cpp index 99c0832b..8880d043 100644 --- a/OptiScaler/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/NVNGX_DLSS_Dx12.cpp @@ -239,7 +239,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext(unsigned long long InApp Config::Instance()->NVNGX_FeatureInfo_Paths.push_back(std::wstring(path)); std::wstring iniPathW(path); - spdlog::debug("NVSDK_NGX_D3D12_Init_Ext PathListInfo[{1}] checking nvngx.ini file in: {0}", wstring_to_string(iniPathW), i); if (Config::Instance()->LoadFromPath(path)) @@ -558,20 +557,23 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsComma upscalerChoice = 3; // if Enabler does not set any upscaler - if (InParameters->Get("DLSSEnabler.Dx12Backend", &upscalerChoice) != NVSDK_NGX_Result_Success && Config::Instance()->Dx12Upscaler.has_value()) + if (InParameters->Get("DLSSEnabler.Dx12Backend", &upscalerChoice) != NVSDK_NGX_Result_Success) { spdlog::info("NVSDK_NGX_D3D12_CreateFeature DLSS Enabler does not set any upscaler using ini: {0}", Config::Instance()->Dx12Upscaler.value()); - if (Config::Instance()->Dx12Upscaler.value() == "xess") - upscalerChoice = 0; - else if (Config::Instance()->Dx12Upscaler.value() == "fsr22") - upscalerChoice = 1; - else if (Config::Instance()->Dx12Upscaler.value() == "fsr21") - upscalerChoice = 2; - else if (Config::Instance()->Dx12Upscaler.value() == "dlss" && Config::Instance()->DLSSEnabled.value_or(true)) - upscalerChoice = 3; - else if (Config::Instance()->Dx12Upscaler.value() == "fsr31") - upscalerChoice = 4; + if (Config::Instance()->Dx12Upscaler.has_value()) + { + if (Config::Instance()->Dx12Upscaler.value() == "xess") + upscalerChoice = 0; + else if (Config::Instance()->Dx12Upscaler.value() == "fsr22") + upscalerChoice = 1; + else if (Config::Instance()->Dx12Upscaler.value() == "fsr21") + upscalerChoice = 2; + else if (Config::Instance()->Dx12Upscaler.value() == "dlss" && Config::Instance()->DLSSEnabled.value_or(true)) + upscalerChoice = 3; + else if (Config::Instance()->Dx12Upscaler.value() == "fsr31") + upscalerChoice = 4; + } spdlog::info("NVSDK_NGX_D3D12_CreateFeature upscalerChoice: {0}", upscalerChoice); } diff --git a/OptiScaler/backends/IFeature_Dx11wDx12.cpp b/OptiScaler/backends/IFeature_Dx11wDx12.cpp index 70ab65c6..bd283d50 100644 --- a/OptiScaler/backends/IFeature_Dx11wDx12.cpp +++ b/OptiScaler/backends/IFeature_Dx11wDx12.cpp @@ -504,11 +504,12 @@ bool IFeature_Dx11wDx12::ProcessDx11Textures(const NVSDK_NGX_Parameter* InParame if (InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, ¶mReactiveMask) != NVSDK_NGX_Result_Success) InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, (void**)¶mReactiveMask); - if (!Config::Instance()->DisableReactiveMask.value_or(true)) + if (!Config::Instance()->DisableReactiveMask.value_or(paramReactiveMask == nullptr)) { if (paramReactiveMask) { - spdlog::debug("IFeature_Dx11wDx12::ProcessDx11Textures Bias mask exist.."); + Config::Instance()->DisableReactiveMask = false; + spdlog::debug("IFeature_Dx11wDx12::ProcessDx11Textures Input Bias mask exist.."); if (CopyTextureFrom11To12(paramReactiveMask, &dx11Reactive, true, Config::Instance()->DontUseNTShared.value_or(false)) == false) return false; @@ -516,7 +517,7 @@ bool IFeature_Dx11wDx12::ProcessDx11Textures(const NVSDK_NGX_Parameter* InParame // This is only needed for XeSS else if (Config::Instance()->Dx11Upscaler.value_or("fsr22") == "xess") { - spdlog::warn("IFeature_Dx11wDx12::ProcessDx11Textures bias mask not exist and its enabled in config, it may cause problems!!"); + spdlog::warn("IFeature_Dx11wDx12::ProcessDx11Textures bias mask not exist and it's enabled in config, it may cause problems!!"); Config::Instance()->DisableReactiveMask = true; Config::Instance()->changeBackend = true; } diff --git a/OptiScaler/backends/IFeature_Dx11wDx12.h b/OptiScaler/backends/IFeature_Dx11wDx12.h index deb116b9..656918b9 100644 --- a/OptiScaler/backends/IFeature_Dx11wDx12.h +++ b/OptiScaler/backends/IFeature_Dx11wDx12.h @@ -2,6 +2,7 @@ #include "IFeature_Dx11.h" #include "../imgui/Imgui_Dx11.h" #include "../rcas/RCAS_Dx12.h" +#include "../bias/Bias_Dx12.h" #include #include @@ -69,6 +70,7 @@ protected: std::unique_ptr OutputScaler = nullptr; std::unique_ptr RCAS = nullptr; + std::unique_ptr Bias = nullptr; HRESULT CreateDx12Device(D3D_FEATURE_LEVEL InFeatureLevel); void GetHardwareAdapter(IDXGIFactory1* InFactory, IDXGIAdapter** InAdapter, D3D_FEATURE_LEVEL InFeatureLevel, bool InRequestHighPerformanceAdapter); diff --git a/OptiScaler/backends/IFeature_Dx12.h b/OptiScaler/backends/IFeature_Dx12.h index bbbe4da6..7b1ed998 100644 --- a/OptiScaler/backends/IFeature_Dx12.h +++ b/OptiScaler/backends/IFeature_Dx12.h @@ -8,6 +8,7 @@ #include "../bicubicscaling/BS_Dx12.h" #include "../rcas/RCAS_Dx12.h" +#include "../bias/Bias_Dx12.h" class IFeature_Dx12 : public virtual IFeature { @@ -16,6 +17,7 @@ protected: static inline std::unique_ptr Imgui = nullptr; std::unique_ptr OutputScaler = nullptr; std::unique_ptr RCAS = nullptr; + std::unique_ptr Bias = nullptr; void ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource, D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState) const; diff --git a/OptiScaler/backends/fsr2/FSR2Feature_Dx11On12.cpp b/OptiScaler/backends/fsr2/FSR2Feature_Dx11On12.cpp index 6db65496..8ec02227 100644 --- a/OptiScaler/backends/fsr2/FSR2Feature_Dx11On12.cpp +++ b/OptiScaler/backends/fsr2/FSR2Feature_Dx11On12.cpp @@ -117,6 +117,7 @@ bool FSR2FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_N OutputScaler = std::make_unique("Output Downsample", Dx12Device, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", Dx12Device); + Bias = std::make_unique("Bias", Dx12Device); } if (!IsInited()) @@ -219,7 +220,24 @@ bool FSR2FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_N params.motionVectors = ffxGetResourceDX12(&_context, dx11Mv.Dx12Resource, L"FSR2_Motion", FFX_RESOURCE_STATE_COMPUTE_READ); params.depth = ffxGetResourceDX12(&_context, dx11Depth.Dx12Resource, L"FSR2_Depth", FFX_RESOURCE_STATE_COMPUTE_READ); params.exposure = ffxGetResourceDX12(&_context, dx11Exp.Dx12Resource, L"FSR2_Exp", FFX_RESOURCE_STATE_COMPUTE_READ); - params.reactive = ffxGetResourceDX12(&_context, dx11Reactive.Dx12Resource, L"FSR2_Reactive", FFX_RESOURCE_STATE_COMPUTE_READ); + + if (dx11Reactive.Dx12Resource != nullptr) + { + if (Config::Instance()->FsrUseMaskForTransparency.value_or(true)) + params.transparencyAndComposition = ffxGetResourceDX12(&_context, dx11Reactive.Dx12Resource, (wchar_t*)L"FSR2_Transparency", FFX_RESOURCE_STATE_COMPUTE_READ); + + if (Bias->IsInit() && Bias->CreateBufferResource(Dx12Device, dx11Reactive.Dx12Resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.45f) > 0.0f && + Bias->Dispatch(Dx12Device, Dx12CommandList, dx11Reactive.Dx12Resource, Config::Instance()->DlssReactiveMaskBias.value_or(0.45f), Bias->Buffer())) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.reactive = ffxGetResourceDX12(&_context, Bias->Buffer(), (wchar_t*)L"FSR2_Reactive", FFX_RESOURCE_STATE_COMPUTE_READ); + } + } + } // OutputScaling if (useSS) diff --git a/OptiScaler/backends/fsr2/FSR2Feature_Dx12.cpp b/OptiScaler/backends/fsr2/FSR2Feature_Dx12.cpp index eb371e47..f790ad89 100644 --- a/OptiScaler/backends/fsr2/FSR2Feature_Dx12.cpp +++ b/OptiScaler/backends/fsr2/FSR2Feature_Dx12.cpp @@ -20,6 +20,7 @@ bool FSR2FeatureDx12::Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* In OutputScaler = std::make_unique("Output Downsample", InDevice, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", InDevice); + Bias = std::make_unique("Bias", InDevice); return true; } @@ -242,16 +243,30 @@ bool FSR2FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_N if (InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, ¶mReactiveMask) != NVSDK_NGX_Result_Success) InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, (void**)¶mReactiveMask); - if (!Config::Instance()->DisableReactiveMask.value_or(true)) + if (!Config::Instance()->DisableReactiveMask.value_or(paramReactiveMask == nullptr)) { if (paramReactiveMask) { - spdlog::debug("FSR2FeatureDx12::Evaluate Bias mask exist.."); + spdlog::debug("FSR2FeatureDx12::Evaluate Input Bias mask exist.."); + Config::Instance()->DisableReactiveMask = false; if (Config::Instance()->MaskResourceBarrier.has_value()) ResourceBarrier(InCommandList, paramReactiveMask, (D3D12_RESOURCE_STATES)Config::Instance()->MaskResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); - params.reactive = ffxGetResourceDX12(&_context, paramReactiveMask, (wchar_t*)L"FSR2_Reactive", FFX_RESOURCE_STATE_COMPUTE_READ); + if (Config::Instance()->FsrUseMaskForTransparency.value_or(true)) + params.transparencyAndComposition = ffxGetResourceDX12(&_context, paramReactiveMask, (wchar_t*)L"FSR2_Transparency", FFX_RESOURCE_STATE_COMPUTE_READ); + + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.45f) > 0.0f && + Bias->IsInit() && Bias->CreateBufferResource(Device, paramReactiveMask, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Bias->Dispatch(Device, InCommandList, paramReactiveMask, Config::Instance()->DlssReactiveMaskBias.value_or(0.45f), Bias->Buffer())) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.reactive = ffxGetResourceDX12(&_context, Bias->Buffer(), (wchar_t*)L"FSR2_Reactive", FFX_RESOURCE_STATE_COMPUTE_READ); + } + } } } diff --git a/OptiScaler/backends/fsr2_212/FSR2Feature_Dx11On12_212.cpp b/OptiScaler/backends/fsr2_212/FSR2Feature_Dx11On12_212.cpp index 4f2fa828..8e6ac9d7 100644 --- a/OptiScaler/backends/fsr2_212/FSR2Feature_Dx11On12_212.cpp +++ b/OptiScaler/backends/fsr2_212/FSR2Feature_Dx11On12_212.cpp @@ -120,6 +120,7 @@ bool FSR2FeatureDx11on12_212::Evaluate(ID3D11DeviceContext* InDeviceContext, NVS OutputScaler = std::make_unique("Output Downsample", Dx12Device, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", Dx12Device); + Bias = std::make_unique("Bias", Dx12Device); } if (!IsInited()) @@ -220,7 +221,24 @@ bool FSR2FeatureDx11on12_212::Evaluate(ID3D11DeviceContext* InDeviceContext, NVS params.motionVectors = Fsr212::ffxGetResourceDX12_212(&_context, dx11Mv.Dx12Resource, (wchar_t*)L"FSR2_Motion", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); params.depth = Fsr212::ffxGetResourceDX12_212(&_context, dx11Depth.Dx12Resource, (wchar_t*)L"FSR2_Depth", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); params.exposure = Fsr212::ffxGetResourceDX12_212(&_context, dx11Exp.Dx12Resource, (wchar_t*)L"FSR2_Exp", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); - params.reactive = Fsr212::ffxGetResourceDX12_212(&_context, dx11Reactive.Dx12Resource, (wchar_t*)L"FSR2_Reactive", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); + + if (dx11Reactive.Dx12Resource != nullptr) + { + if (Config::Instance()->FsrUseMaskForTransparency.value_or(true)) + params.transparencyAndComposition = Fsr212::ffxGetResourceDX12_212(&_context, dx11Reactive.Dx12Resource, (wchar_t*)L"FSR2_Transparency", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); + + if (Bias->IsInit() && Bias->CreateBufferResource(Dx12Device, dx11Reactive.Dx12Resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.45f) > 0.0f && + Bias->Dispatch(Dx12Device, Dx12CommandList, dx11Reactive.Dx12Resource, Config::Instance()->DlssReactiveMaskBias.value_or(0.45f), Bias->Buffer())) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.reactive = Fsr212::ffxGetResourceDX12_212(&_context, Bias->Buffer(), (wchar_t*)L"FSR2_Reactive", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); + } + } + } // OutputScaling if (useSS) diff --git a/OptiScaler/backends/fsr2_212/FSR2Feature_Dx12_212.cpp b/OptiScaler/backends/fsr2_212/FSR2Feature_Dx12_212.cpp index 032d48bb..d56d6331 100644 --- a/OptiScaler/backends/fsr2_212/FSR2Feature_Dx12_212.cpp +++ b/OptiScaler/backends/fsr2_212/FSR2Feature_Dx12_212.cpp @@ -20,6 +20,7 @@ bool FSR2FeatureDx12_212::Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList OutputScaler = std::make_unique("Output Downsample", InDevice, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", InDevice); + Bias = std::make_unique("Bias", InDevice); return true; } @@ -242,16 +243,30 @@ bool FSR2FeatureDx12_212::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVS if (InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, ¶mReactiveMask) != NVSDK_NGX_Result_Success) InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, (void**)¶mReactiveMask); - if (!Config::Instance()->DisableReactiveMask.value_or(true)) + if (!Config::Instance()->DisableReactiveMask.value_or(paramReactiveMask == nullptr)) { if (paramReactiveMask) { spdlog::debug("FSR2FeatureDx12_212::Evaluate Bias mask exist.."); + Config::Instance()->DisableReactiveMask = false; if (Config::Instance()->MaskResourceBarrier.has_value()) ResourceBarrier(InCommandList, paramReactiveMask, (D3D12_RESOURCE_STATES)Config::Instance()->MaskResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); - params.reactive = Fsr212::ffxGetResourceDX12_212(&_context, paramReactiveMask, (wchar_t*)L"FSR2_Reactive", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); + if (Config::Instance()->FsrUseMaskForTransparency.value_or(true)) + params.transparencyAndComposition = Fsr212::ffxGetResourceDX12_212(&_context, paramReactiveMask, (wchar_t*)L"FSR2_Transparency", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); + + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.45f) > 0.0f && + Bias->IsInit() && Bias->CreateBufferResource(Device, paramReactiveMask, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Bias->Dispatch(Device, InCommandList, paramReactiveMask, Config::Instance()->DlssReactiveMaskBias.value_or(0.45f), Bias->Buffer())) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.reactive = Fsr212::ffxGetResourceDX12_212(&_context, Bias->Buffer(), (wchar_t*)L"FSR2_Reactive", Fsr212::FFX_RESOURCE_STATE_COMPUTE_READ); + } + } } } diff --git a/OptiScaler/backends/fsr31/FSR31Feature_Dx11On12.cpp b/OptiScaler/backends/fsr31/FSR31Feature_Dx11On12.cpp index 50b83a63..6090f165 100644 --- a/OptiScaler/backends/fsr31/FSR31Feature_Dx11On12.cpp +++ b/OptiScaler/backends/fsr31/FSR31Feature_Dx11On12.cpp @@ -156,6 +156,7 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ OutputScaler = std::make_unique("Output Downsample", Dx12Device, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", Dx12Device); + Bias = std::make_unique("Bias", Dx12Device); } if (!IsInited()) @@ -260,7 +261,24 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ params.motionVectors = ffxApiGetResourceDX12(dx11Mv.Dx12Resource, FFX_API_RESOURCE_STATE_COMPUTE_READ); params.depth = ffxApiGetResourceDX12(dx11Depth.Dx12Resource, FFX_API_RESOURCE_STATE_COMPUTE_READ); params.exposure = ffxApiGetResourceDX12(dx11Exp.Dx12Resource, FFX_API_RESOURCE_STATE_COMPUTE_READ); - params.reactive = ffxApiGetResourceDX12(dx11Reactive.Dx12Resource, FFX_API_RESOURCE_STATE_COMPUTE_READ); + + if (dx11Reactive.Dx12Resource != nullptr) + { + if (Config::Instance()->FsrUseMaskForTransparency.value_or(true)) + params.transparencyAndComposition = ffxApiGetResourceDX12(dx11Reactive.Dx12Resource, FFX_API_RESOURCE_STATE_COMPUTE_READ); + + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.45f) > 0.0f && + Bias->IsInit() && Bias->CreateBufferResource(Dx12Device, dx11Reactive.Dx12Resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Bias->Dispatch(Dx12Device, Dx12CommandList, dx11Reactive.Dx12Resource, Config::Instance()->DlssReactiveMaskBias.value_or(0.45f), Bias->Buffer())) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.reactive = ffxApiGetResourceDX12(Bias->Buffer(), FFX_API_RESOURCE_STATE_COMPUTE_READ); + } + } + } // Output Scaling if (useSS) @@ -380,7 +398,7 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ (sharpness > 0.0f || (Config::Instance()->MotionSharpnessEnabled.value_or(false) && Config::Instance()->MotionSharpness.value_or(0.4) > 0.0f)) && RCAS->CanRender()) { - spdlog::debug("XeSSFeatureDx11::Evaluate Apply CAS"); + spdlog::debug("FSR31FeatureDx11with12::Evaluate Apply CAS"); if (params.output.resource != RCAS->Buffer()) ResourceBarrier(Dx12CommandList, (ID3D12Resource*)params.output.resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); diff --git a/OptiScaler/backends/fsr31/FSR31Feature_Dx12.cpp b/OptiScaler/backends/fsr31/FSR31Feature_Dx12.cpp index 5d4ea0c1..9337d44d 100644 --- a/OptiScaler/backends/fsr31/FSR31Feature_Dx12.cpp +++ b/OptiScaler/backends/fsr31/FSR31Feature_Dx12.cpp @@ -30,7 +30,7 @@ FSR31FeatureDx12::FSR31FeatureDx12(unsigned int InHandleId, NVSDK_NGX_Parameter* _destroyContext = (PfnFfxDestroyContext)GetProcAddress(_dll, "ffxDestroyContext"); _dispatch = (PfnFfxDispatch)GetProcAddress(_dll, "ffxDispatch"); _query = (PfnFfxQuery)GetProcAddress(_dll, "ffxQuery"); - + _moduleLoaded = _configure != nullptr; } } @@ -57,6 +57,7 @@ bool FSR31FeatureDx12::Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* I OutputScaler = std::make_unique("Output Downsample", InDevice, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", InDevice); + Bias = std::make_unique("Bias", InDevice); return true; } @@ -283,16 +284,29 @@ bool FSR31FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_ if (InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, ¶mReactiveMask) != NVSDK_NGX_Result_Success) InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, (void**)¶mReactiveMask); - if (!Config::Instance()->DisableReactiveMask.value_or(true)) + if (!Config::Instance()->DisableReactiveMask.value_or(paramReactiveMask == nullptr)) { if (paramReactiveMask) { spdlog::debug("FSR31FeatureDx12::Evaluate Bias mask exist.."); + Config::Instance()->DisableReactiveMask = false; if (Config::Instance()->MaskResourceBarrier.has_value()) ResourceBarrier(InCommandList, paramReactiveMask, (D3D12_RESOURCE_STATES)Config::Instance()->MaskResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); - params.reactive = ffxApiGetResourceDX12(paramReactiveMask, FFX_API_RESOURCE_STATE_COMPUTE_READ); + if (Config::Instance()->FsrUseMaskForTransparency.value_or(true)) + params.transparencyAndComposition = ffxApiGetResourceDX12(paramReactiveMask, FFX_API_RESOURCE_STATE_COMPUTE_READ); + + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.45f) > 0.0f && Bias->IsInit() && Bias->CreateBufferResource(Device, paramReactiveMask, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Bias->Dispatch(Device, InCommandList, paramReactiveMask, Config::Instance()->DlssReactiveMaskBias.value_or(0.45f), Bias->Buffer())) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.reactive = ffxApiGetResourceDX12(Bias->Buffer(), FFX_API_RESOURCE_STATE_COMPUTE_READ); + } + } } } diff --git a/OptiScaler/backends/fsr31/FSR31Feature_Dx12.h b/OptiScaler/backends/fsr31/FSR31Feature_Dx12.h index 1c7f7d12..ba08033e 100644 --- a/OptiScaler/backends/fsr31/FSR31Feature_Dx12.h +++ b/OptiScaler/backends/fsr31/FSR31Feature_Dx12.h @@ -4,7 +4,6 @@ #include "dx12/ffx_api_dx12.h" - class FSR31FeatureDx12 : public FSR31Feature, public IFeature_Dx12 { private: diff --git a/OptiScaler/backends/xess/XeSSFeature_Dx11.cpp b/OptiScaler/backends/xess/XeSSFeature_Dx11.cpp index 1890b78d..ac4bca01 100644 --- a/OptiScaler/backends/xess/XeSSFeature_Dx11.cpp +++ b/OptiScaler/backends/xess/XeSSFeature_Dx11.cpp @@ -131,6 +131,7 @@ bool XeSSFeatureDx11::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_NGX_P OutputScaler = std::make_unique("Output Downsample", Dx12Device, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", Dx12Device); + Bias = std::make_unique("Bias", Dx12Device); } if (!IsInited() || !_xessContext || !ModuleLoaded()) @@ -263,7 +264,21 @@ bool XeSSFeatureDx11::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_NGX_P _hasDepth = params.pDepthTexture != nullptr; params.pExposureScaleTexture = dx11Exp.Dx12Resource; _hasExposure = params.pExposureScaleTexture != nullptr; - params.pResponsivePixelMaskTexture = dx11Reactive.Dx12Resource; + + if (dx11Reactive.Dx12Resource != nullptr) + { + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.0f) > 0.0f && + Bias->IsInit() && Bias->CreateBufferResource(Dx12Device, dx11Reactive.Dx12Resource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Bias->Dispatch(Dx12Device, Dx12CommandList, dx11Reactive.Dx12Resource, Config::Instance()->DlssReactiveMaskBias.value_or(0.0f), Bias->Buffer())) + { + Bias->SetBufferState(Dx12CommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.pResponsivePixelMaskTexture = Bias->Buffer(); + } + } + } spdlog::debug("XeSSFeatureDx11::Evaluate Textures -> params complete!"); diff --git a/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp b/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp index 1f94a490..2ae50b4a 100644 --- a/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp +++ b/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp @@ -20,6 +20,7 @@ bool XeSSFeatureDx12::Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* In OutputScaler = std::make_unique("Output Downsample", InDevice, (TargetWidth() < DisplayWidth())); RCAS = std::make_unique("RCAS", InDevice); + Bias = std::make_unique("Bias", InDevice); return true; } @@ -240,16 +241,27 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_N if (InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, ¶mReactiveMask) != NVSDK_NGX_Result_Success) InParameters->Get(NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, (void**)¶mReactiveMask); - if (!Config::Instance()->DisableReactiveMask.value_or(true)) + if (!Config::Instance()->DisableReactiveMask.value_or(paramReactiveMask == nullptr)) { - params.pResponsivePixelMaskTexture = paramReactiveMask; - if (paramReactiveMask) { - spdlog::debug("XeSSFeatureDx12::Evaluate Bias mask exist.."); + spdlog::debug("XeSSFeatureDx12::Evaluate Input Bias mask exist.."); + Config::Instance()->DisableReactiveMask = false; if (Config::Instance()->MaskResourceBarrier.has_value()) ResourceBarrier(InCommandList, params.pResponsivePixelMaskTexture, (D3D12_RESOURCE_STATES)Config::Instance()->MaskResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + if (Config::Instance()->DlssReactiveMaskBias.value_or(0.0f) > 0.0f && + Bias->IsInit() && Bias->CreateBufferResource(Device, paramReactiveMask, D3D12_RESOURCE_STATE_UNORDERED_ACCESS) && Bias->CanRender()) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + if (Bias->Dispatch(Device, InCommandList, paramReactiveMask, Config::Instance()->DlssReactiveMaskBias.value_or(0.0f), Bias->Buffer())) + { + Bias->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + params.pResponsivePixelMaskTexture = Bias->Buffer(); + } + } } else { diff --git a/OptiScaler/bias/Bias_Common.h b/OptiScaler/bias/Bias_Common.h new file mode 100644 index 00000000..31559c2c --- /dev/null +++ b/OptiScaler/bias/Bias_Common.h @@ -0,0 +1,51 @@ +#pragma once + +#include "../pch.h" +#include + +static std::string biasShader = R"( +cbuffer Params : register(b0) +{ + float Bias; +}; + +Texture2D Source : register(t0); +RWTexture2D Dest : register(u0); + +[numthreads(32, 32, 1)] +void CSMain(uint3 DTid : SV_DispatchThreadID) +{ + float3 src = Source.Load(int3(DTid.x, DTid.y, 0)).rgb; + src.r *= Bias; + Dest[DTid.xy] = src; +} +)"; + +static ID3DBlob* BiasCompileShader(const char* shaderCode, const char* entryPoint, const char* target) +{ + ID3DBlob* shaderBlob = nullptr; + ID3DBlob* errorBlob = nullptr; + + HRESULT hr = D3DCompile(shaderCode, strlen(shaderCode), nullptr, nullptr, nullptr, entryPoint, target, D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &shaderBlob, &errorBlob); + + if (FAILED(hr)) + { + spdlog::error("CompileShader error while compiling shader"); + + if (errorBlob) + { + spdlog::error("CompileShader error while compiling shader : {0}", (char*)errorBlob->GetBufferPointer()); + errorBlob->Release(); + } + + if (shaderBlob) + shaderBlob->Release(); + + return nullptr; + } + + if (errorBlob) + errorBlob->Release(); + + return shaderBlob; +} \ No newline at end of file diff --git a/OptiScaler/bias/Bias_Dx11.cpp b/OptiScaler/bias/Bias_Dx11.cpp new file mode 100644 index 00000000..60d83308 --- /dev/null +++ b/OptiScaler/bias/Bias_Dx11.cpp @@ -0,0 +1,468 @@ +#include "Bias_Dx11.h" +#include "../Config.h" + + +static bool CreateComputeShader(ID3D12Device* device, ID3D12RootSignature* rootSignature, ID3D12PipelineState** pipelineState, ID3DBlob* shaderBlob) +{ + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = rootSignature; + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + psoDesc.CS = CD3DX12_SHADER_BYTECODE(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize()); + + HRESULT hr = device->CreateComputePipelineState(&psoDesc, __uuidof(ID3D12PipelineState*), (void**)pipelineState); + + if (FAILED(hr)) + { + spdlog::error("CreateComputeShader CreateComputePipelineState error {0:x}", hr); + return false; + } + + return true; +} + +bool Bias_Dx11::CreateBufferResource(ID3D12Device* InDevice, ID3D12Resource* InSource, D3D12_RESOURCE_STATES InState) +{ + if (InDevice == nullptr || InSource == nullptr) + return false; + + D3D12_RESOURCE_DESC texDesc = InSource->GetDesc(); + + if (_buffer != nullptr) + { + auto bufDesc = _buffer->GetDesc(); + + if (bufDesc.Width != (UINT64)(texDesc.Width) || bufDesc.Height != (UINT)(texDesc.Height) || bufDesc.Format != texDesc.Format) + { + _buffer->Release(); + _buffer = nullptr; + } + else + return true; + } + + spdlog::debug("Bias_Dx11::CreateBufferResource [{0}] Start!", _name); + + D3D12_HEAP_PROPERTIES heapProperties; + D3D12_HEAP_FLAGS heapFlags; + HRESULT hr = InSource->GetHeapProperties(&heapProperties, &heapFlags); + + if (hr != S_OK) + { + spdlog::error("Bias_Dx11::CreateBufferResource [{0}] GetHeapProperties result: {1:x}", _name.c_str(), hr); + return false; + } + + texDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; + texDesc.Width = texDesc.Width; + texDesc.Height = texDesc.Height; + + hr = InDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texDesc, InState, nullptr, IID_PPV_ARGS(&_buffer)); + + if (hr != S_OK) + { + spdlog::error("Bias_Dx11::CreateBufferResource [{0}] CreateCommittedResource result: {1:x}", _name, hr); + return false; + } + + + _buffer->SetName(L"Bias_Buffer"); + _bufferState = InState; + + return true; +} + +bool Bias_Dx11::Dispatch(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* InResource, ID3D12Resource* InMotionVectors, RcasConstants InConstants, ID3D12Resource* OutResource) +{ + if (!_init || InDevice == nullptr || InCmdList == nullptr || InResource == nullptr || OutResource == nullptr) + return false; + + spdlog::debug("Bias_Dx11::Dispatch [{0}] Start!", _name); + + _counter++; + _counter = _counter % 2; + + if (_cpuSrvHandle[_counter].ptr == NULL) + _cpuSrvHandle[_counter] = _srvHeap[_counter]->GetCPUDescriptorHandleForHeapStart(); + + if (_cpuSrvHandle2[_counter].ptr == NULL) + { + _cpuSrvHandle2[_counter] = _cpuSrvHandle[_counter]; + _cpuSrvHandle2[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_cpuUavHandle[_counter].ptr == NULL) + { + _cpuUavHandle[_counter] = _cpuSrvHandle2[_counter]; + _cpuUavHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_cpuCbvHandle[_counter].ptr == NULL) + { + _cpuCbvHandle[_counter] = _cpuUavHandle[_counter]; + _cpuCbvHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_gpuSrvHandle[_counter].ptr == NULL) + _gpuSrvHandle[_counter] = _srvHeap[_counter]->GetGPUDescriptorHandleForHeapStart(); + + if (_gpuSrvHandle2[_counter].ptr == NULL) + { + _gpuSrvHandle2[_counter] = _gpuSrvHandle[_counter]; + _gpuSrvHandle2[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_gpuUavHandle[_counter].ptr == NULL) + { + _gpuUavHandle[_counter] = _gpuSrvHandle2[_counter]; + _gpuUavHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_gpuCbvHandle[_counter].ptr == NULL) + { + _gpuCbvHandle[_counter] = _gpuUavHandle[_counter]; + _gpuCbvHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + auto inDesc = InResource->GetDesc(); + auto mvDesc = InMotionVectors->GetDesc(); + auto outDesc = OutResource->GetDesc(); + + InternalConstants constants{}; + + constants.DisplayHeight = InConstants.DisplayHeight; + constants.DisplayWidth = InConstants.DisplayWidth; + constants.DynamicSharpenEnabled = Config::Instance()->MotionSharpnessEnabled.value_or(false) ? 1 : 0; + constants.MotionSharpness = Config::Instance()->MotionMaxSharpness.value_or(0.8f); + constants.MvScaleX = InConstants.MvScaleX; + constants.MvScaleY = InConstants.MvScaleY; + constants.Sharpness = InConstants.Sharpness; + constants.Debug = Config::Instance()->MotionSharpnessDebug.value_or(false) ? 1 : 0; + constants.Threshold = Config::Instance()->MotionThreshold.value_or(25.0f); + + constants.DisplaySizeMV = mvDesc.Width == inDesc.Width; + constants.MotionTextureScale = (float)mvDesc.Width / (float)inDesc.Width; + + // Create SRV for Input Texture + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = inDesc.Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + + InDevice->CreateShaderResourceView(InResource, &srvDesc, _cpuSrvHandle[_counter]); + + // Create SRV for Motion Texture + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc2 = {}; + srvDesc2.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc2.Format = mvDesc.Format; + srvDesc2.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc2.Texture2D.MipLevels = 1; + + InDevice->CreateShaderResourceView(InMotionVectors, &srvDesc2, _cpuSrvHandle2[_counter]); + + // Create UAV for Output Texture + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.Format = outDesc.Format; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = 0; + + InDevice->CreateUnorderedAccessView(OutResource, nullptr, &uavDesc, _cpuUavHandle[_counter]); + + // Copy the updated constant buffer data to the constant buffer resource + UINT8* pCBDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU + _constantBuffer->Map(0, &readRange, reinterpret_cast(&pCBDataBegin)); + memcpy(pCBDataBegin, &constants, sizeof(constants)); + _constantBuffer->Unmap(0, nullptr); + + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; + cbvDesc.BufferLocation = _constantBuffer->GetGPUVirtualAddress(); + cbvDesc.SizeInBytes = sizeof(constants); + + InDevice->CreateConstantBufferView(&cbvDesc, _cpuCbvHandle[_counter]); + + ID3D12DescriptorHeap* heaps[] = { _srvHeap[_counter] }; + InCmdList->SetDescriptorHeaps(_countof(heaps), heaps); + + InCmdList->SetComputeRootSignature(_rootSignature); + InCmdList->SetPipelineState(_pipelineState); + + InCmdList->SetComputeRootDescriptorTable(0, _gpuSrvHandle[_counter]); + InCmdList->SetComputeRootDescriptorTable(1, _gpuSrvHandle2[_counter]); + InCmdList->SetComputeRootDescriptorTable(2, _gpuUavHandle[_counter]); + InCmdList->SetComputeRootDescriptorTable(3, _gpuCbvHandle[_counter]); + + UINT dispatchWidth = 0; + UINT dispatchHeight = 0; + + dispatchWidth = (inDesc.Width + InNumThreadsX - 1) / InNumThreadsX; + dispatchHeight = (inDesc.Height + InNumThreadsY - 1) / InNumThreadsY; + + InCmdList->Dispatch(dispatchWidth, dispatchHeight, 1); + + return true; +} + +Bias_Dx11::Bias_Dx11(std::string InName, ID3D12Device* InDevice) : _name(InName), _device(InDevice) +{ + if (InDevice == nullptr) + { + spdlog::error("Bias_Dx11::Bias_Dx11 InDevice is nullptr!"); + return; + } + + spdlog::debug("Bias_Dx11::Bias_Dx11 {0} start!", _name); + + // Describe and create the root signature + // --------------------------------------------------- + D3D12_DESCRIPTOR_RANGE descriptorRange[4]; + + // SRV Range (Input Texture) + descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + descriptorRange[0].NumDescriptors = 1; + descriptorRange[0].BaseShaderRegister = 0; // Assuming t0 register in HLSL for SRV + descriptorRange[0].RegisterSpace = 0; + descriptorRange[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // SRV Range (Motion Texture) + descriptorRange[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + descriptorRange[1].NumDescriptors = 1; + descriptorRange[1].BaseShaderRegister = 1; // Assuming t1 register in HLSL for SRV + descriptorRange[1].RegisterSpace = 0; + descriptorRange[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // UAV Range (Output Texture) + descriptorRange[2].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + descriptorRange[2].NumDescriptors = 1; + descriptorRange[2].BaseShaderRegister = 0; // Assuming u0 register in HLSL for UAV + descriptorRange[2].RegisterSpace = 0; + descriptorRange[2].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // CBV Range (Params) + descriptorRange[3].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; + descriptorRange[3].NumDescriptors = 1; + descriptorRange[3].BaseShaderRegister = 0; // Assuming b0 register in HLSL for CBV + descriptorRange[3].RegisterSpace = 0; + descriptorRange[3].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // Define the root parameter (descriptor table) + // --------------------------------------------------- + D3D12_ROOT_PARAMETER rootParameters[4]; + + // Root Parameter for SRV 1 + rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[0].DescriptorTable.NumDescriptorRanges = 1; // One range (SRV) + rootParameters[0].DescriptorTable.pDescriptorRanges = &descriptorRange[0]; // Point to the SRV range + rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[1].DescriptorTable.NumDescriptorRanges = 1; // One range (SRV) + rootParameters[1].DescriptorTable.pDescriptorRanges = &descriptorRange[1]; // Point to the SRV range + rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // Root Parameter for UAV + rootParameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[2].DescriptorTable.NumDescriptorRanges = 1; // One range (UAV) + rootParameters[2].DescriptorTable.pDescriptorRanges = &descriptorRange[2]; // Point to the UAV range + rootParameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // Root Parameter for CBV + rootParameters[3].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[3].DescriptorTable.NumDescriptorRanges = 1; // One range (CBV) + rootParameters[3].DescriptorTable.pDescriptorRanges = &descriptorRange[3]; // Point to the CBV range + rootParameters[3].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // A root signature is an array of root parameters + // --------------------------------------------------- + D3D12_ROOT_SIGNATURE_DESC rootSigDesc; + rootSigDesc.NumParameters = 4; + rootSigDesc.pParameters = rootParameters; + rootSigDesc.NumStaticSamplers = 0; + rootSigDesc.pStaticSamplers = nullptr; + rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + + D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(InternalConstants)); + auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + InDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&_constantBuffer)); + + ID3DBlob* errorBlob; + ID3DBlob* signatureBlob; + + do + { + auto hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signatureBlob, &errorBlob); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] D3D12SerializeRootSignature error {1:x}", _name, hr); + break; + } + + hr = InDevice->CreateRootSignature(0, signatureBlob->GetBufferPointer(), signatureBlob->GetBufferSize(), IID_PPV_ARGS(&_rootSignature)); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] CreateRootSignature error {1:x}", _name, hr); + break; + } + + } while (false); + + if (errorBlob != nullptr) + { + errorBlob->Release(); + errorBlob = nullptr; + } + + if (signatureBlob != nullptr) + { + signatureBlob->Release(); + signatureBlob = nullptr; + } + + if (_rootSignature == nullptr) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] _rootSignature is null!", _name); + return; + } + + // Compile shader blobs + ID3DBlob* _recEncodeShader = CompileShader(rcasCode.c_str(), "CSMain", "cs_5_0"); + + if (_recEncodeShader == nullptr) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] CompileShader error!", _name); + return; + } + + // create pso objects + if (!CreateComputeShader(InDevice, _rootSignature, &_pipelineState, _recEncodeShader)) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] CreateComputeShader error!", _name); + return; + } + + if (_recEncodeShader != nullptr) + { + _recEncodeShader->Release(); + _recEncodeShader = nullptr; + } + + D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; + heapDesc.NumDescriptors = 4; // SRV x 2 + UAV + CBV + heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + + auto hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[0])); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] CreateDescriptorHeap[0] error {1:x}", _name, hr); + return; + } + + hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[1])); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] CreateDescriptorHeap[1] error {1:x}", _name, hr); + return; + } + + hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[2])); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] CreateDescriptorHeap[2] error {1:x}", _name, hr); + return; + } + + hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[3])); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx11::Bias_Dx11 [{0}] CreateDescriptorHeap[3] error {1:x}", _name, hr); + return; + } + + _init = _srvHeap[3] != nullptr; +} + +Bias_Dx11::~Bias_Dx11() +{ + if (!_init) + return; + + ID3D12Fence* d3d12Fence = nullptr; + + do + { + if (_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d12Fence)) != S_OK) + break; + + d3d12Fence->Signal(999); + + HANDLE fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + if (fenceEvent != NULL && d3d12Fence->SetEventOnCompletion(999, fenceEvent) == S_OK) + { + WaitForSingleObject(fenceEvent, INFINITE); + CloseHandle(fenceEvent); + } + + } while (false); + + if (d3d12Fence != nullptr) + { + d3d12Fence->Release(); + d3d12Fence = nullptr; + } + + if (_rootSignature != nullptr) + { + _rootSignature->Release(); + _rootSignature = nullptr; + } + + if (_pipelineState != nullptr) + { + _pipelineState->Release(); + _pipelineState = nullptr; + } + + if (_srvHeap[0] != nullptr) + { + _srvHeap[0]->Release(); + _srvHeap[0] = nullptr; + } + + if (_srvHeap[1] != nullptr) + { + _srvHeap[1]->Release(); + _srvHeap[1] = nullptr; + } + + if (_srvHeap[2] != nullptr) + { + _srvHeap[2]->Release(); + _srvHeap[2] = nullptr; + } + + if (_srvHeap[3] != nullptr) + { + _srvHeap[3]->Release(); + _srvHeap[3] = nullptr; + } + + if (_buffer != nullptr) + { + _buffer->Release(); + _buffer = nullptr; + } + + if (_constantBuffer != nullptr) + { + _constantBuffer->Release(); + _constantBuffer = nullptr; + } +} diff --git a/OptiScaler/bias/Bias_Dx11.h b/OptiScaler/bias/Bias_Dx11.h new file mode 100644 index 00000000..1355f4b7 --- /dev/null +++ b/OptiScaler/bias/Bias_Dx11.h @@ -0,0 +1,163 @@ +#pragma once + +#include "../pch.h" +#include "Bias_Common.h" + +#include + +class Bias_Dx11 +{ +private: + struct alignas(256) InternalConstants + { + float Sharpness; + + // Motion Vector Stuff + int DynamicSharpenEnabled; + int DisplaySizeMV; + int Debug; + + float MotionSharpness; + float MotionTextureScale; + float MvScaleX; + float MvScaleY; + float Threshold; + int DisplayWidth; + int DisplayHeight; + }; + + std::string _name = ""; + bool _init = false; + int _counter = 0; + + //ID3D12RootSignature* _rootSignature = nullptr; + //ID3D12PipelineState* _pipelineState = nullptr; + //ID3D12DescriptorHeap* _srvHeap[4] = { nullptr, nullptr, nullptr, nullptr }; + //D3D12_CPU_DESCRIPTOR_HANDLE _cpuSrvHandle[2]{ { NULL }, { NULL } }; + //D3D12_CPU_DESCRIPTOR_HANDLE _cpuSrvHandle2[2]{ { NULL }, { NULL } }; + //D3D12_CPU_DESCRIPTOR_HANDLE _cpuUavHandle[2]{ { NULL }, { NULL } }; + //D3D12_CPU_DESCRIPTOR_HANDLE _cpuCbvHandle[2]{ { NULL }, { NULL } }; + //D3D12_GPU_DESCRIPTOR_HANDLE _gpuSrvHandle[2]{ { NULL }, { NULL } }; + //D3D12_GPU_DESCRIPTOR_HANDLE _gpuSrvHandle2[2]{ { NULL }, { NULL } }; + //D3D12_GPU_DESCRIPTOR_HANDLE _gpuUavHandle[2]{ { NULL }, { NULL } }; + //D3D12_GPU_DESCRIPTOR_HANDLE _gpuCbvHandle[2]{ { NULL }, { NULL } }; + + ID3D11Device* _device = nullptr; + ID3D11DeviceContext* _deviceContext = nullptr; + ID3D11Resource* _buffer = nullptr; + ID3D11Buffer* _constantBuffer = nullptr; + //D3D12_RESOURCE_STATES _bufferState = D3D12_RESOURCE_STATE_COMMON; + + uint32_t InNumThreadsX = 32; + uint32_t InNumThreadsY = 32; + + inline static std::string rcasCode = R"( +cbuffer Params : register(b0) +{ + float Sharpness; + + // Motion Vector Stuff + int DynamicSharpenEnabled; + int DisplaySizeMV; + int Debug; + + float MotionSharpness; + float MotionTextureScale; + float MvScaleX; + float MvScaleY; + float Threshold; + int DisplayWidth; + int DisplayHeight; +}; + +Texture2D Source : register(t0); +Texture2D Motion : register(t1); +RWTexture2D Dest : register(u0); + +float getBiasLuma(float3 rgb) +{ + return dot(rgb, float3(0.598, 1.174, 0.228)); +} + +[numthreads(32, 32, 1)] +void CSMain(uint3 DTid : SV_DispatchThreadID) +{ + float setSharpness = Sharpness; + + if(DynamicSharpenEnabled > 0 && MotionSharpness > Sharpness) + { + float2 mv; + float mx; + float my; + float factor = MotionSharpness - Sharpness; + float add = 0.0f; + + if(DisplaySizeMV > 0) + mv = Motion.Load(int3(DTid.x, DTid.y, 0)).rg; + else + mv = Motion.Load(int3(DTid.x * MotionTextureScale, DTid.y * MotionTextureScale, 0)).rg; + + mx = abs(mv.r * MvScaleX); + my = abs(mv.g * MvScaleY); + + if(mx > my) + add = (mx / Threshold) * factor; + else + add = (my / Threshold) * factor; + + if(add > factor) + add = factor; + + setSharpness += add; + } + + float3 e = Source.Load(int3(DTid.x, DTid.y, 0)).rgb; + + float3 b = Source.Load(int3(DTid.x, DTid.y - 1, 0)).rgb; + float3 d = Source.Load(int3(DTid.x - 1, DTid.y, 0)).rgb; + float3 f = Source.Load(int3(DTid.x + 1, DTid.y, 0)).rgb; + float3 h = Source.Load(int3(DTid.x, DTid.y + 1, 0)).rgb; + + // Get lumas times 2. Should use luma weights that are twice as large as normal. + float bL = getBiasLuma(b); + float dL = getBiasLuma(d); + float eL = getBiasLuma(e); + float fL = getBiasLuma(f); + float hL = getBiasLuma(h); + + // Min and max of ring. + float3 minRGB = min(min(b, d), min(f, h)); + float3 maxRGB = max(max(b, d), max(f, h)); + + // Immediate constants for peak range. + float2 peakC = float2(1.0, -4.0); + + // Limiters, these need to use high precision reciprocal operations. + // Decided to use standard rcp for now in hopes of optimizing it + float3 hitMin = minRGB * rcp(4.0 * maxRGB); + float3 hitMax = (peakC.xxx - maxRGB) * rcp(4.0 * minRGB + peakC.yyy); + float3 lobeRGB = max(-hitMin, hitMax); + float lobe = max(-0.1875, min(max(lobeRGB.r, max(lobeRGB.g, lobeRGB.b)), 0.0)) * setSharpness; + + // Resolve, which needs medium precision rcp approximation to avoid visible tonality changes. + float rcpL = rcp(4.0 * lobe + 1.0); + float3 output = ((b + d + f + h) * lobe + e) * rcpL; + + if(Debug > 0 && DynamicSharpenEnabled > 0) + output.r *= 1 + (10.0 * (setSharpness - Sharpness)); + + Dest[DTid.xy] = output; +} +)"; + +public: + bool CreateBufferResource(ID3D11Device* InDevice, ID3D11Resource* InSource); + bool Dispatch(ID3D11Device* InDevice, ID3D11DeviceContext* InContext, ID3D11Resource* InResource, ID3D11Resource* InMotionVectors, RcasConstants InConstants, ID3D11Resource* OutResource); + + ID3D11Resource* Buffer() { return _buffer; } + bool IsInit() const { return _init; } + + Bias_Dx11(std::string InName, ID3D11Device* InDevice); + + ~Bias_Dx11(); +}; \ No newline at end of file diff --git a/OptiScaler/bias/Bias_Dx12.cpp b/OptiScaler/bias/Bias_Dx12.cpp new file mode 100644 index 00000000..fcc3d3de --- /dev/null +++ b/OptiScaler/bias/Bias_Dx12.cpp @@ -0,0 +1,434 @@ +#include "Bias_Dx12.h" +#include "../Config.h" + +bool Bias_Dx12::CreateComputeShader(ID3D12Device* device, ID3D12RootSignature* rootSignature, ID3D12PipelineState** pipelineState, ID3DBlob* shaderBlob) +{ + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = rootSignature; + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + psoDesc.CS = CD3DX12_SHADER_BYTECODE(shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize()); + + HRESULT hr = device->CreateComputePipelineState(&psoDesc, __uuidof(ID3D12PipelineState*), (void**)pipelineState); + + if (FAILED(hr)) + { + spdlog::error("CreateComputeShader CreateComputePipelineState error {0:x}", hr); + return false; + } + + return true; +} + +bool Bias_Dx12::CreateBufferResource(ID3D12Device* InDevice, ID3D12Resource* InSource, D3D12_RESOURCE_STATES InState) +{ + if (InDevice == nullptr || InSource == nullptr) + return false; + + D3D12_RESOURCE_DESC texDesc = InSource->GetDesc(); + + if (_buffer != nullptr) + { + auto bufDesc = _buffer->GetDesc(); + + if (bufDesc.Width != (UINT64)(texDesc.Width) || bufDesc.Height != (UINT)(texDesc.Height) || bufDesc.Format != texDesc.Format) + { + _buffer->Release(); + _buffer = nullptr; + } + else + return true; + } + + spdlog::debug("Bias_Dx12::CreateBufferResource [{0}] Start!", _name); + + D3D12_HEAP_PROPERTIES heapProperties; + D3D12_HEAP_FLAGS heapFlags; + HRESULT hr = InSource->GetHeapProperties(&heapProperties, &heapFlags); + + if (hr != S_OK) + { + spdlog::error("Bias_Dx12::CreateBufferResource [{0}] GetHeapProperties result: {1:x}", _name.c_str(), hr); + return false; + } + + texDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; + texDesc.Width = texDesc.Width; + texDesc.Height = texDesc.Height; + + hr = InDevice->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &texDesc, InState, nullptr, IID_PPV_ARGS(&_buffer)); + + if (hr != S_OK) + { + spdlog::error("Bias_Dx12::CreateBufferResource [{0}] CreateCommittedResource result: {1:x}", _name, hr); + return false; + } + + + _buffer->SetName(L"Bias_Buffer"); + _bufferState = InState; + + return true; +} + +void Bias_Dx12::SetBufferState(ID3D12GraphicsCommandList* InCommandList, D3D12_RESOURCE_STATES InState) +{ + if (_bufferState == InState) + return; + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Transition.pResource = _buffer; + barrier.Transition.StateBefore = _bufferState; + barrier.Transition.StateAfter = InState; + barrier.Transition.Subresource = 0; + InCommandList->ResourceBarrier(1, &barrier); + + _bufferState = InState; +} + +bool Bias_Dx12::Dispatch(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* InResource, float InBias, ID3D12Resource* OutResource) +{ + if (!_init || InDevice == nullptr || InCmdList == nullptr || InResource == nullptr || OutResource == nullptr) + return false; + + spdlog::debug("Bias_Dx12::Dispatch [{0}] Start!", _name); + + _counter++; + _counter = _counter % 2; + + if (_cpuSrvHandle[_counter].ptr == NULL) + _cpuSrvHandle[_counter] = _srvHeap[_counter]->GetCPUDescriptorHandleForHeapStart(); + + if (_cpuUavHandle[_counter].ptr == NULL) + { + _cpuUavHandle[_counter] = _cpuSrvHandle[_counter]; + _cpuUavHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_cpuCbvHandle[_counter].ptr == NULL) + { + _cpuCbvHandle[_counter] = _cpuUavHandle[_counter]; + _cpuCbvHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_gpuSrvHandle[_counter].ptr == NULL) + _gpuSrvHandle[_counter] = _srvHeap[_counter]->GetGPUDescriptorHandleForHeapStart(); + + if (_gpuUavHandle[_counter].ptr == NULL) + { + _gpuUavHandle[_counter] = _gpuSrvHandle[_counter]; + _gpuUavHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + if (_gpuCbvHandle[_counter].ptr == NULL) + { + _gpuCbvHandle[_counter] = _gpuUavHandle[_counter]; + _gpuCbvHandle[_counter].ptr += InDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + } + + auto inDesc = InResource->GetDesc(); + auto outDesc = OutResource->GetDesc(); + + // Create SRV for Input Texture + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = inDesc.Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + + InDevice->CreateShaderResourceView(InResource, &srvDesc, _cpuSrvHandle[_counter]); + + // Create UAV for Output Texture + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.Format = outDesc.Format; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = 0; + + InDevice->CreateUnorderedAccessView(OutResource, nullptr, &uavDesc, _cpuUavHandle[_counter]); + + InternalConstants constants{}; + + if (InBias < 0.0f) + constants.Bias = 0.0f; + else if (InBias > 0.9f) + constants.Bias = 0.9f; + else + constants.Bias = InBias; + + // Copy the updated constant buffer data to the constant buffer resource + BYTE* pCBDataBegin; + CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU + auto result = _constantBuffer->Map(0, &readRange, reinterpret_cast(&pCBDataBegin)); + + if (result != S_OK) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] _constantBuffer->Map error {1:x}", _name, (unsigned int)result); + return false; + } + + if (pCBDataBegin == nullptr) + { + _constantBuffer->Unmap(0, nullptr); + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] pCBDataBegin is null!", _name); + return false; + } + + memcpy(pCBDataBegin, &constants, sizeof(constants)); + _constantBuffer->Unmap(0, nullptr); + + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; + cbvDesc.BufferLocation = _constantBuffer->GetGPUVirtualAddress(); + cbvDesc.SizeInBytes = sizeof(constants); + InDevice->CreateConstantBufferView(&cbvDesc, _cpuCbvHandle[_counter]); + + ID3D12DescriptorHeap* heaps[] = { _srvHeap[_counter] }; + InCmdList->SetDescriptorHeaps(_countof(heaps), heaps); + + InCmdList->SetComputeRootSignature(_rootSignature); + InCmdList->SetPipelineState(_pipelineState); + + InCmdList->SetComputeRootDescriptorTable(0, _gpuSrvHandle[_counter]); + InCmdList->SetComputeRootDescriptorTable(1, _gpuUavHandle[_counter]); + InCmdList->SetComputeRootDescriptorTable(2, _gpuCbvHandle[_counter]); + + UINT dispatchWidth = 0; + UINT dispatchHeight = 0; + + dispatchWidth = (inDesc.Width + InNumThreadsX - 1) / InNumThreadsX; + dispatchHeight = (inDesc.Height + InNumThreadsY - 1) / InNumThreadsY; + + InCmdList->Dispatch(dispatchWidth, dispatchHeight, 1); + + return true; +} + +Bias_Dx12::Bias_Dx12(std::string InName, ID3D12Device* InDevice) : _name(InName), _device(InDevice) +{ + if (InDevice == nullptr) + { + spdlog::error("Bias_Dx12::Bias_Dx12 InDevice is nullptr!"); + return; + } + + spdlog::debug("Bias_Dx12::Bias_Dx12 {0} start!", _name); + + // Describe and create the root signature + // --------------------------------------------------- + D3D12_DESCRIPTOR_RANGE descriptorRange[3]; + + // SRV Range (Input Texture) + descriptorRange[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + descriptorRange[0].NumDescriptors = 1; + descriptorRange[0].BaseShaderRegister = 0; // Assuming t0 register in HLSL for SRV + descriptorRange[0].RegisterSpace = 0; + descriptorRange[0].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // UAV Range (Output Texture) + descriptorRange[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + descriptorRange[1].NumDescriptors = 1; + descriptorRange[1].BaseShaderRegister = 0; // Assuming u0 register in HLSL for UAV + descriptorRange[1].RegisterSpace = 0; + descriptorRange[1].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // CBV Range (Params) + descriptorRange[2].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; + descriptorRange[2].NumDescriptors = 1; + descriptorRange[2].BaseShaderRegister = 0; // Assuming b0 register in HLSL for CBV + descriptorRange[2].RegisterSpace = 0; + descriptorRange[2].OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; + + // Define the root parameter (descriptor table) + // --------------------------------------------------- + D3D12_ROOT_PARAMETER rootParameters[3]; + + // Root Parameter for SRV 1 + rootParameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[0].DescriptorTable.NumDescriptorRanges = 1; // One range (SRV) + rootParameters[0].DescriptorTable.pDescriptorRanges = &descriptorRange[0]; // Point to the SRV range + rootParameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // Root Parameter for UAV + rootParameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[1].DescriptorTable.NumDescriptorRanges = 1; // One range (UAV) + rootParameters[1].DescriptorTable.pDescriptorRanges = &descriptorRange[1]; // Point to the UAV range + rootParameters[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // Root Parameter for CBV + rootParameters[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + rootParameters[2].DescriptorTable.NumDescriptorRanges = 1; // One range (CBV) + rootParameters[2].DescriptorTable.pDescriptorRanges = &descriptorRange[2]; // Point to the CBV range + rootParameters[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // A root signature is an array of root parameters + // --------------------------------------------------- + D3D12_ROOT_SIGNATURE_DESC rootSigDesc; + rootSigDesc.NumParameters = 3; + rootSigDesc.pParameters = rootParameters; + rootSigDesc.NumStaticSamplers = 0; + rootSigDesc.pStaticSamplers = nullptr; + rootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + + D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(InternalConstants)); + auto heapProps = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + + auto result = InDevice->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&_constantBuffer)); + + if (result != S_OK) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] CreateCommittedResource error {1:x}", _name, (unsigned int)result); + return; + } + + ID3DBlob* errorBlob; + ID3DBlob* signatureBlob; + + do + { + auto hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signatureBlob, &errorBlob); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] D3D12SerializeRootSignature error {1:x}", _name, (unsigned int)hr); + break; + } + + hr = InDevice->CreateRootSignature(0, signatureBlob->GetBufferPointer(), signatureBlob->GetBufferSize(), IID_PPV_ARGS(&_rootSignature)); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] CreateRootSignature error {1:x}", _name, (unsigned int)hr); + break; + } + + } while (false); + + if (errorBlob != nullptr) + { + errorBlob->Release(); + errorBlob = nullptr; + } + + if (signatureBlob != nullptr) + { + signatureBlob->Release(); + signatureBlob = nullptr; + } + + if (_rootSignature == nullptr) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] _rootSignature is null!", _name); + return; + } + + // Compile shader blobs + ID3DBlob* _recEncodeShader = BiasCompileShader(biasShader.c_str(), "CSMain", "cs_5_0"); + + if (_recEncodeShader == nullptr) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] CompileShader error!", _name); + return; + } + + // create pso objects + if (!CreateComputeShader(InDevice, _rootSignature, &_pipelineState, _recEncodeShader)) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] CreateComputeShader error!", _name); + return; + } + + if (_recEncodeShader != nullptr) + { + _recEncodeShader->Release(); + _recEncodeShader = nullptr; + } + + D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {}; + heapDesc.NumDescriptors = 3; // SRV + UAV + CBV + heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + + auto hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[0])); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] CreateDescriptorHeap[0] error {1:x}", _name, (unsigned int)hr); + return; + } + + hr = InDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_srvHeap[1])); + + if (FAILED(hr)) + { + spdlog::error("Bias_Dx12::Bias_Dx12 [{0}] CreateDescriptorHeap[1] error {1:x}", _name, (unsigned int)hr); + return; + } + + _init = _srvHeap[1] != nullptr; +} + +Bias_Dx12::~Bias_Dx12() +{ + if (!_init) + return; + + ID3D12Fence* d3d12Fence = nullptr; + + do + { + if (_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d12Fence)) != S_OK) + break; + + d3d12Fence->Signal(999); + + HANDLE fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + + if (fenceEvent != NULL && d3d12Fence->SetEventOnCompletion(999, fenceEvent) == S_OK) + { + WaitForSingleObject(fenceEvent, INFINITE); + CloseHandle(fenceEvent); + } + + } while (false); + + if (d3d12Fence != nullptr) + { + d3d12Fence->Release(); + d3d12Fence = nullptr; + } + + if (_rootSignature != nullptr) + { + _rootSignature->Release(); + _rootSignature = nullptr; + } + + if (_pipelineState != nullptr) + { + _pipelineState->Release(); + _pipelineState = nullptr; + } + + if (_srvHeap[0] != nullptr) + { + _srvHeap[0]->Release(); + _srvHeap[0] = nullptr; + } + + if (_srvHeap[1] != nullptr) + { + _srvHeap[1]->Release(); + _srvHeap[1] = nullptr; + } + + if (_buffer != nullptr) + { + _buffer->Release(); + _buffer = nullptr; + } + + if (_constantBuffer != nullptr) + { + _constantBuffer->Release(); + _constantBuffer = nullptr; + } +} diff --git a/OptiScaler/bias/Bias_Dx12.h b/OptiScaler/bias/Bias_Dx12.h new file mode 100644 index 00000000..a376d882 --- /dev/null +++ b/OptiScaler/bias/Bias_Dx12.h @@ -0,0 +1,53 @@ +#pragma once + +#include "../pch.h" +#include "Bias_Common.h" + +#include +#include "../d3dx/d3dx12.h" + +class Bias_Dx12 +{ +private: + struct alignas(256) InternalConstants + { + float Bias; + }; + + std::string _name = ""; + bool _init = false; + int _counter = 0; + + ID3D12RootSignature* _rootSignature = nullptr; + ID3D12PipelineState* _pipelineState = nullptr; + ID3D12DescriptorHeap* _srvHeap[2] = { nullptr, nullptr }; + D3D12_CPU_DESCRIPTOR_HANDLE _cpuSrvHandle[2]{ { NULL }, { NULL } }; + D3D12_CPU_DESCRIPTOR_HANDLE _cpuUavHandle[2]{ { NULL }, { NULL } }; + D3D12_CPU_DESCRIPTOR_HANDLE _cpuCbvHandle[2]{ { NULL }, { NULL } }; + D3D12_GPU_DESCRIPTOR_HANDLE _gpuSrvHandle[2]{ { NULL }, { NULL } }; + D3D12_GPU_DESCRIPTOR_HANDLE _gpuUavHandle[2]{ { NULL }, { NULL } }; + D3D12_GPU_DESCRIPTOR_HANDLE _gpuCbvHandle[2]{ { NULL }, { NULL } }; + + inline static bool CreateComputeShader(ID3D12Device* device, ID3D12RootSignature* rootSignature, ID3D12PipelineState** pipelineState, ID3DBlob* shaderBlob); + + ID3D12Device* _device = nullptr; + ID3D12Resource* _buffer = nullptr; + ID3D12Resource* _constantBuffer = nullptr; + D3D12_RESOURCE_STATES _bufferState = D3D12_RESOURCE_STATE_COMMON; + + UINT InNumThreadsX = 32; + UINT InNumThreadsY = 32; + +public: + bool CreateBufferResource(ID3D12Device* InDevice, ID3D12Resource* InSource, D3D12_RESOURCE_STATES InState); + void SetBufferState(ID3D12GraphicsCommandList* InCommandList, D3D12_RESOURCE_STATES InState); + bool Dispatch(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCmdList, ID3D12Resource* InResource, float InBias, ID3D12Resource* OutResource); + + ID3D12Resource* Buffer() { return _buffer; } + bool IsInit() const { return _init; } + bool CanRender() const { return _init && _buffer != nullptr; } + + Bias_Dx12(std::string InName, ID3D12Device* InDevice); + + ~Bias_Dx12(); +}; \ No newline at end of file diff --git a/OptiScaler/imgui/imgui_common.h b/OptiScaler/imgui/imgui_common.h index 056e4e51..149a5275 100644 --- a/OptiScaler/imgui/imgui_common.h +++ b/OptiScaler/imgui/imgui_common.h @@ -906,7 +906,16 @@ public: if (Config::Instance()->CurrentFeature->Name() != "DLSSD") { if (ImGui::Button("Apply") && Config::Instance()->newBackend != "" && Config::Instance()->newBackend != currentBackend) + { + if (Config::Instance()->newBackend == "xess") + { + // Reseting them for xess + Config::Instance()->DisableReactiveMask.reset(); + Config::Instance()->DlssReactiveMaskBias.reset(); + } + Config::Instance()->changeBackend = true; + } ImGui::SameLine(0.0f, 6.0f); @@ -1132,6 +1141,10 @@ public: ShowHelpMarker("Might help achieve better image quality\n" "And potentially less ghosting"); } + + auto useAsTransparency = Config::Instance()->FsrUseMaskForTransparency.value_or(true); + if (ImGui::Checkbox("Use Reactive Mask as Transparency Mask", &useAsTransparency)) + Config::Instance()->FsrUseMaskForTransparency = useAsTransparency; } // DLSS ----------------- @@ -1652,6 +1665,10 @@ public: } ImGui::EndTable(); + + auto bias = Config::Instance()->DlssReactiveMaskBias.value_or(0.45f); + if (Config::Instance()->AdvancedSettings.value_or(false) && ImGui::SliderFloat("Reactive Mask Bias", &bias, 0.0f, 0.9f, "%.2f", ImGuiSliderFlags_NoRoundToFormat)) + Config::Instance()->DlssReactiveMaskBias = bias; } // LOGGING -----------------------------