From 3a86ab7b3fa373de1990f2e6bfa751e4a55d91b4 Mon Sep 17 00:00:00 2001 From: cdozdil Date: Mon, 3 Jun 2024 00:02:50 +0300 Subject: [PATCH] implementation fiddleing --- OptiScaler/backends/IFeature.h | 5 + OptiScaler/backends/IFeature_Dx12.cpp | 276 ++++++++++++++++++ OptiScaler/backends/IFeature_Dx12.h | 7 +- OptiScaler/backends/xess/XeSSFeature_Dx12.cpp | 96 +++++- OptiScaler/backends/xess/XeSSFeature_Dx12.h | 2 + 5 files changed, 383 insertions(+), 3 deletions(-) diff --git a/OptiScaler/backends/IFeature.h b/OptiScaler/backends/IFeature.h index 377b6b9a..c7f94071 100644 --- a/OptiScaler/backends/IFeature.h +++ b/OptiScaler/backends/IFeature.h @@ -1,4 +1,8 @@ #pragma once +#include "IFeatureCreateParams.h" +#include "IFeatureEvaluateParams.h" + + #include #include @@ -16,6 +20,7 @@ private: protected: NVSDK_NGX_Handle* _handle = nullptr; + IFeatureCreateParams _createParams = {}; float _sharpness = 0; bool _hasColor = false; diff --git a/OptiScaler/backends/IFeature_Dx12.cpp b/OptiScaler/backends/IFeature_Dx12.cpp index 73de8541..b71a6e62 100644 --- a/OptiScaler/backends/IFeature_Dx12.cpp +++ b/OptiScaler/backends/IFeature_Dx12.cpp @@ -2,6 +2,7 @@ #include "IFeature_Dx12.h" #include "../pch.h" + void IFeature_Dx12::ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource, D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState) const { D3D12_RESOURCE_BARRIER barrier = {}; @@ -13,6 +14,281 @@ void IFeature_Dx12::ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID InCommandList->ResourceBarrier(1, &barrier); } +bool IFeature_Dx12::BeforeEvaluate(ID3D12GraphicsCommandList* InCommandList, const IFeatureEvaluateParams* InParams, ID3D12Resource* OutputTexture) +{ + auto useOutputScaling = Config::Instance()->OutputScalingEnabled.value_or(false) && !Config::Instance()->DisplayResolution.value_or(_createParams.DisplayResolutionMV()); + auto outputScalingMultiplier = Config::Instance()->OutputScalingMultiplier.value_or(1.5f); + + auto paramColor = (ID3D12Resource*)InParams->InputColor(); + auto paramMotion = (ID3D12Resource*)InParams->InputMotion(); + auto paramOutput = (ID3D12Resource*)InParams->OutputColor(); + auto paramDepth = (ID3D12Resource*)InParams->InputDepth(); + auto paramExposure = (ID3D12Resource*)InParams->InputExposure(); + auto paramMask = (ID3D12Resource*)InParams->InputMask(); + + // Color + if (paramColor) + { + spdlog::debug("IFeature_Dx12::BeforeEvaluate Color exist.."); + paramColor->SetName(L"paramColor"); + + if (Config::Instance()->ColorResourceBarrier.has_value()) + { + ResourceBarrier(InCommandList, paramColor, (D3D12_RESOURCE_STATES)Config::Instance()->ColorResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + else if (Config::Instance()->NVNGX_Engine == NVSDK_NGX_ENGINE_TYPE_UNREAL) + { + Config::Instance()->ColorResourceBarrier = (int)D3D12_RESOURCE_STATE_RENDER_TARGET; + ResourceBarrier(InCommandList, paramColor, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + } + else + { + spdlog::error("IFeature_Dx12::BeforeEvaluate Color not exist!!"); + return false; + } + + // Motion + if (paramMotion) + { + spdlog::debug("IFeature_Dx12::BeforeEvaluate MotionVectors exist.."); + paramMotion->SetName(L"paramMotion"); + + if (Config::Instance()->MVResourceBarrier.has_value()) + { + ResourceBarrier(InCommandList, paramMotion, (D3D12_RESOURCE_STATES)Config::Instance()->MVResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + else if (Config::Instance()->NVNGX_Engine == NVSDK_NGX_ENGINE_TYPE_UNREAL) + { + Config::Instance()->MVResourceBarrier = (int)D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + ResourceBarrier(InCommandList, paramMotion, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + } + else + { + spdlog::error("IFeature_Dx12::BeforeEvaluate MotionVectors not exist!!"); + return false; + } + + // Output + if (paramOutput) + { + spdlog::debug("IFeature_Dx12::BeforeEvaluate Output exist.."); + paramOutput->SetName(L"paramOutput"); + + if (Config::Instance()->OutputResourceBarrier.has_value()) + { + ResourceBarrier(InCommandList, paramOutput, (D3D12_RESOURCE_STATES)Config::Instance()->OutputResourceBarrier.value(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + } + + if (useOutputScaling) + { + if (OutputScaler->CreateBufferResource(Device, paramOutput, TargetWidth(), TargetHeight(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS)) + { + OutputScaler->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + OutputTexture = OutputScaler->Buffer(); + } + else + OutputTexture = paramOutput; + } + else + OutputTexture = paramOutput; + + if (Config::Instance()->RcasEnabled.value_or(true) && + (InParams->Sharpness() > 0.0f || (Config::Instance()->MotionSharpnessEnabled.value_or(false) && Config::Instance()->MotionSharpness.value_or(0.4) > 0.0f)) && + RCAS->IsInit() && RCAS->CreateBufferResource(Device, OutputTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)) + { + RCAS->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + OutputTexture = RCAS->Buffer(); + } + } + else + { + spdlog::error("IFeature_Dx12::BeforeEvaluate Output not exist!!"); + return false; + } + + // Depth + if (paramDepth) + { + spdlog::debug("IFeature_Dx12::BeforeEvaluate Depth exist.."); + paramDepth->SetName(L"params.pDepthTexture"); + + if (Config::Instance()->DepthResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramDepth, (D3D12_RESOURCE_STATES)Config::Instance()->DepthResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + else + { + if (!Config::Instance()->DisplayResolution.value_or(false)) + spdlog::error("IFeature_Dx12::BeforeEvaluate Depth not exist!!"); + else + spdlog::info("IFeature_Dx12::BeforeEvaluate Using high res motion vectors, depth is not needed!!"); + } + + // Exposure + if (!Config::Instance()->AutoExposure.value_or(false)) + { + + if (paramExposure) + { + spdlog::debug("IFeature_Dx12::BeforeEvaluate ExposureTexture exist.."); + + if (Config::Instance()->ExposureResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramExposure, (D3D12_RESOURCE_STATES)Config::Instance()->ExposureResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + else + { + spdlog::warn("IFeature_Dx12::BeforeEvaluate AutoExposure disabled but ExposureTexture is not exist, it may cause problems!!"); + Config::Instance()->AutoExposure = true; + Config::Instance()->changeBackend = true; + return true; + } + } + else + spdlog::debug("IFeature_Dx12::BeforeEvaluate AutoExposure enabled!"); + + // Mask + if (!Config::Instance()->DisableReactiveMask.value_or(true)) + { + if (paramMask) + { + spdlog::debug("IFeature_Dx12::BeforeEvaluate Bias mask exist.."); + + if (Config::Instance()->MaskResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramMask, (D3D12_RESOURCE_STATES)Config::Instance()->MaskResourceBarrier.value(), D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + } + else + { + spdlog::warn("IFeature_Dx12::BeforeEvaluate Bias mask not exist and its enabled in config, it may cause problems!!"); + Config::Instance()->DisableReactiveMask = true; + Config::Instance()->changeBackend = true; + return true; + } + } + + _hasColor = paramColor != nullptr; + _hasMV = paramMotion != nullptr; + _hasOutput = paramOutput != nullptr; + _hasDepth = paramDepth != nullptr; + _hasExposure = paramExposure != nullptr; + _hasTM = paramMask != nullptr; + + return true; +} + +void IFeature_Dx12::AfterEvaluate(ID3D12GraphicsCommandList* InCommandList, const IFeatureEvaluateParams* InParams, ID3D12Resource* OutputTexture) +{ + auto useOutputScaling = Config::Instance()->OutputScalingEnabled.value_or(false) && !Config::Instance()->DisplayResolution.value_or(_createParams.DisplayResolutionMV()); + + auto paramColor = (ID3D12Resource*)InParams->InputColor(); + auto paramMotion = (ID3D12Resource*)InParams->InputMotion(); + auto paramOutput = (ID3D12Resource*)InParams->OutputColor(); + auto paramDepth = (ID3D12Resource*)InParams->InputDepth(); + auto paramExposure = (ID3D12Resource*)InParams->InputExposure(); + auto paramMask = (ID3D12Resource*)InParams->InputMask(); + + // apply rcas + if (Config::Instance()->RcasEnabled.value_or(true) && + (InParams->Sharpness() > 0.0f || (Config::Instance()->MotionSharpnessEnabled.value_or(false) && Config::Instance()->MotionSharpness.value_or(0.4) > 0.0f)) && + RCAS->CanRender()) + { + if (OutputTexture != RCAS->Buffer()) + ResourceBarrier(InCommandList, OutputTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + RCAS->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + RcasConstants rcasConstants{}; + rcasConstants.Sharpness = InParams->Sharpness(); + rcasConstants.DisplayWidth = TargetWidth(); + rcasConstants.DisplayHeight = TargetHeight(); + rcasConstants.MvScaleX = InParams->MvScaleX(); + rcasConstants.MvScaleY = InParams->MvScaleY(); + rcasConstants.DisplaySizeMV = _createParams.DisplayResolutionMV(); + rcasConstants.RenderHeight = RenderHeight(); + rcasConstants.RenderWidth = RenderWidth(); + + if (useOutputScaling) + { + if (!RCAS->Dispatch(Device, InCommandList, OutputTexture, paramMotion, rcasConstants, OutputScaler->Buffer())) + { + Config::Instance()->RcasEnabled = false; + return; + } + } + else + { + if (!RCAS->Dispatch(Device, InCommandList, OutputTexture, paramMotion, rcasConstants, paramOutput)) + { + Config::Instance()->RcasEnabled = false; + return; + } + } + } + + if (useOutputScaling) + { + spdlog::debug("IFeature_Dx12::AfterEvaluate output scaling output..."); + OutputScaler->SetBufferState(InCommandList, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE); + + if (!OutputScaler->Dispatch(Device, InCommandList, OutputScaler->Buffer(), paramOutput)) + { + Config::Instance()->OutputScalingEnabled = false; + Config::Instance()->changeBackend = true; + return; + } + } + + // Imgui + if (!Config::Instance()->OverlayMenu.value_or(true) && _frameCount > 30) + { + if (Imgui != nullptr && Imgui.get() != nullptr) + { + if (Imgui->IsHandleDifferent()) + { + Imgui.reset(); + } + else + Imgui->Render(InCommandList, paramOutput); + } + else + { + if (Imgui == nullptr || Imgui.get() == nullptr) + Imgui = std::make_unique(GetForegroundWindow(), Device); + } + } + + // Restore resource states + if (paramColor && Config::Instance()->ColorResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramColor, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + (D3D12_RESOURCE_STATES)Config::Instance()->ColorResourceBarrier.value()); + + if (paramMotion && Config::Instance()->MVResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramMotion, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + (D3D12_RESOURCE_STATES)Config::Instance()->MVResourceBarrier.value()); + + if (paramOutput && Config::Instance()->OutputResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramOutput, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + (D3D12_RESOURCE_STATES)Config::Instance()->OutputResourceBarrier.value()); + + if (paramDepth && Config::Instance()->DepthResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramDepth, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + (D3D12_RESOURCE_STATES)Config::Instance()->DepthResourceBarrier.value()); + + if (paramExposure && Config::Instance()->ExposureResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramExposure, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + (D3D12_RESOURCE_STATES)Config::Instance()->ExposureResourceBarrier.value()); + + if (paramMask && Config::Instance()->MaskResourceBarrier.has_value()) + ResourceBarrier(InCommandList, paramMask, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + (D3D12_RESOURCE_STATES)Config::Instance()->MaskResourceBarrier.value()); +} + IFeature_Dx12::IFeature_Dx12(unsigned int InHandleId, const NVSDK_NGX_Parameter* InParameters) { } diff --git a/OptiScaler/backends/IFeature_Dx12.h b/OptiScaler/backends/IFeature_Dx12.h index df143bcd..c08874b6 100644 --- a/OptiScaler/backends/IFeature_Dx12.h +++ b/OptiScaler/backends/IFeature_Dx12.h @@ -13,16 +13,21 @@ class IFeature_Dx12 : public virtual IFeature { protected: ID3D12Device* Device = nullptr; + static inline std::unique_ptr Imgui = nullptr; std::unique_ptr OutputScaler = nullptr; - std::unique_ptr RCAS = nullptr; void ResourceBarrier(ID3D12GraphicsCommandList* InCommandList, ID3D12Resource* InResource, D3D12_RESOURCE_STATES InBeforeState, D3D12_RESOURCE_STATES InAfterState) const; public: virtual bool Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCommandList, const NVSDK_NGX_Parameter* InParameters) = 0; + virtual bool Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCommandList, const IFeatureCreateParams InParams) = 0; virtual bool Evaluate(ID3D12GraphicsCommandList* InCommandList, const NVSDK_NGX_Parameter* InParameters) = 0; + virtual bool Evaluate(ID3D12GraphicsCommandList* InCommandList, const IFeatureEvaluateParams* InParams) = 0; + + bool BeforeEvaluate(ID3D12GraphicsCommandList* InCommandList, const IFeatureEvaluateParams* InParams, ID3D12Resource* OutputTexture); + void AfterEvaluate(ID3D12GraphicsCommandList* InCommandList, const IFeatureEvaluateParams* InParams, ID3D12Resource* OutputTexture); IFeature_Dx12(unsigned int InHandleId, const NVSDK_NGX_Parameter* InParameters); diff --git a/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp b/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp index e2d5f410..1ca4599c 100644 --- a/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp +++ b/OptiScaler/backends/xess/XeSSFeature_Dx12.cpp @@ -178,7 +178,7 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const N else params.pOutputTexture = paramOutput; - if (Config::Instance()->RcasEnabled.value_or(true) && + if (Config::Instance()->RcasEnabled.value_or(true) && (sharpness > 0.0f || (Config::Instance()->MotionSharpnessEnabled.value_or(false) && Config::Instance()->MotionSharpness.value_or(0.4) > 0.0f)) && RCAS->IsInit() && RCAS->CreateBufferResource(Device, params.pOutputTexture, D3D12_RESOURCE_STATE_UNORDERED_ACCESS)) { @@ -291,7 +291,7 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const N } // apply rcas - if (Config::Instance()->RcasEnabled.value_or(true) && + if (Config::Instance()->RcasEnabled.value_or(true) && (sharpness > 0.0f || (Config::Instance()->MotionSharpnessEnabled.value_or(false) && Config::Instance()->MotionSharpness.value_or(0.4) > 0.0f)) && RCAS->CanRender()) { @@ -397,6 +397,98 @@ bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const N return true; } +bool XeSSFeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, const IFeatureEvaluateParams* InParams) +{ + spdlog::debug("XeSSFeatureDx12::Evaluate"); + + if (!IsInited() || !_xessContext || !ModuleLoaded()) + { + spdlog::error("XeSSFeatureDx12::Evaluate Not inited!"); + return false; + } + + if (!RCAS->IsInit()) + Config::Instance()->RcasEnabled = false; + + if (!OutputScaler->IsInit()) + Config::Instance()->OutputScalingEnabled = false; + + if (Config::Instance()->xessDebug) + { + spdlog::error("XeSSFeatureDx12::Evaluate xessDebug"); + + xess_dump_parameters_t dumpParams{}; + dumpParams.frame_count = Config::Instance()->xessDebugFrames; + dumpParams.frame_idx = dumpCount; + dumpParams.path = "."; + dumpParams.dump_elements_mask = XESS_DUMP_INPUT_COLOR | XESS_DUMP_INPUT_VELOCITY | XESS_DUMP_INPUT_DEPTH | XESS_DUMP_OUTPUT | XESS_DUMP_EXECUTION_PARAMETERS | XESS_DUMP_HISTORY; + + if (!Config::Instance()->DisableReactiveMask.value_or(true)) + dumpParams.dump_elements_mask |= XESS_DUMP_INPUT_RESPONSIVE_PIXEL_MASK; + + StartDump()(_xessContext, &dumpParams); + Config::Instance()->xessDebug = false; + dumpCount += Config::Instance()->xessDebugFrames; + } + + xess_result_t xessResult; + xess_d3d12_execute_params_t params{}; + + params.jitterOffsetX = InParams->JitterOffsetX(); + params.jitterOffsetY = InParams->JitterOffsetY(); + params.exposureScale = InParams->ExposureScale(); + params.resetHistory = InParams->Reset() ? 1 : 0; + + if (InParams->RenderWidth() > 0) + params.inputWidth = InParams->RenderWidth(); + else + params.inputWidth = RenderWidth(); + + if (InParams->RenderHeight() > 0) + params.inputHeight = InParams->RenderHeight(); + else + params.inputHeight = RenderHeight(); + + spdlog::debug("XeSSFeatureDx12::Evaluate Input Resolution: {0}x{1}", params.inputWidth, params.inputHeight); + + auto sharpness = InParams->Sharpness(); + + auto beforeResult = BeforeEvaluate(InCommandList, InParams, params.pOutputTexture); + + // Autoexposure Reset + if (Config::Instance()->changeBackend) + return true; + + params.pColorTexture = (ID3D12Resource*)InParams->InputColor(); + params.pDepthTexture = (ID3D12Resource*)InParams->InputDepth(); + params.pExposureScaleTexture = (ID3D12Resource*)InParams->InputExposure(); + params.pVelocityTexture = (ID3D12Resource*)InParams->InputMotion(); + params.pResponsivePixelMaskTexture = (ID3D12Resource*)InParams->InputMask(); + + xessResult = SetVelocityScale()(_xessContext, InParams->MvScaleX(), InParams->MvScaleY()); + + if (xessResult != XESS_RESULT_SUCCESS) + { + spdlog::error("XeSSFeatureDx12::Evaluate xessSetVelocityScale: {0}", ResultToString(xessResult)); + return false; + } + + spdlog::debug("XeSSFeatureDx12::Evaluate Executing!!"); + xessResult = D3D12Execute()(_xessContext, InCommandList, ¶ms); + + if (xessResult != XESS_RESULT_SUCCESS) + { + spdlog::error("XeSSFeatureDx12::Evaluate xessD3D12Execute error: {0}", ResultToString(xessResult)); + return false; + } + + AfterEvaluate(InCommandList, InParams, params.pOutputTexture); + + _frameCount++; + + return true; +} + XeSSFeatureDx12::~XeSSFeatureDx12() { if (RCAS != nullptr && RCAS.get() != nullptr) diff --git a/OptiScaler/backends/xess/XeSSFeature_Dx12.h b/OptiScaler/backends/xess/XeSSFeature_Dx12.h index bb525a7c..6034bc6f 100644 --- a/OptiScaler/backends/xess/XeSSFeature_Dx12.h +++ b/OptiScaler/backends/xess/XeSSFeature_Dx12.h @@ -1,5 +1,6 @@ #pragma once #include "../IFeature_Dx12.h" +#include "../IFeatureCreateParams.h" #include "XeSSFeature.h" #include @@ -16,6 +17,7 @@ public: bool Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCommandList, const NVSDK_NGX_Parameter* InParameters) override; bool Evaluate(ID3D12GraphicsCommandList* InCommandList, const NVSDK_NGX_Parameter* InParameters) override; + bool Evaluate(ID3D12GraphicsCommandList* InCommandList, const IFeatureEvaluateParams* InParams) override; ~XeSSFeatureDx12(); }; \ No newline at end of file