diff --git a/OptiScaler/State.h b/OptiScaler/State.h index 921fbb0e..1f662a79 100644 --- a/OptiScaler/State.h +++ b/OptiScaler/State.h @@ -21,7 +21,8 @@ typedef enum GameQuirk Cyberpunk, FMF2, RDR1, - Banishers + Banishers, + SplitFiction } GameQuirk; typedef enum FGType : uint32_t diff --git a/OptiScaler/dllmain.cpp b/OptiScaler/dllmain.cpp index 54d2efe9..bbb564b4 100644 --- a/OptiScaler/dllmain.cpp +++ b/OptiScaler/dllmain.cpp @@ -2398,6 +2398,11 @@ static void CheckQuirks() { LOG_INFO("Enabling a quirk for Banishers (Disable FSR2 Inputs)"); } } + else if (exePathFilename == "SplitFiction.exe") + { + State::Instance().gameQuirk = SplitFiction; + LOG_INFO("Enabling a quirk for Split Fiction (Quick upscaler reinit)"); + } } bool isNvidia() diff --git a/OptiScaler/inputs/FfxApi_Dx12.cpp b/OptiScaler/inputs/FfxApi_Dx12.cpp index f7b01ff5..27b7b338 100644 --- a/OptiScaler/inputs/FfxApi_Dx12.cpp +++ b/OptiScaler/inputs/FfxApi_Dx12.cpp @@ -51,10 +51,14 @@ static bool CreateDLSSContext(ffxContext handle, const ffxDispatchDescUpscale* p params->Set(NVSDK_NGX_Parameter_Height, pExecParams->renderSize.height); params->Set(NVSDK_NGX_Parameter_OutWidth, initParams->maxUpscaleSize.width); params->Set(NVSDK_NGX_Parameter_OutHeight, initParams->maxUpscaleSize.height); + params->Set("FSR.upscaleSize.width", pExecParams->upscaleSize.width); + params->Set("FSR.upscaleSize.height", pExecParams->upscaleSize.height); - auto ratio = (float)initParams->maxUpscaleSize.width / (float)pExecParams->renderSize.width; + auto width = pExecParams->upscaleSize.width > 0 ? pExecParams->upscaleSize.width : initParams->maxUpscaleSize.width; - LOG_INFO("renderWidth: {}, maxWidth: {}, ratio: {}", pExecParams->renderSize.width, initParams->maxUpscaleSize.width, ratio); + auto ratio = (float)width / (float)pExecParams->renderSize.width; + + LOG_INFO("renderWidth: {}, maxWidth: {}, ratio: {}", pExecParams->renderSize.width, width, ratio); if (ratio <= 3.0) params->Set(NVSDK_NGX_Parameter_PerfQualityValue, NVSDK_NGX_PerfQuality_Value_UltraPerformance); diff --git a/OptiScaler/inputs/FfxApi_Vk.cpp b/OptiScaler/inputs/FfxApi_Vk.cpp index 89afa374..7164b786 100644 --- a/OptiScaler/inputs/FfxApi_Vk.cpp +++ b/OptiScaler/inputs/FfxApi_Vk.cpp @@ -183,10 +183,14 @@ static bool CreateDLSSContext(ffxContext handle, const ffxDispatchDescUpscale* p params->Set(NVSDK_NGX_Parameter_Height, pExecParams->renderSize.height); params->Set(NVSDK_NGX_Parameter_OutWidth, initParams->maxUpscaleSize.width); params->Set(NVSDK_NGX_Parameter_OutHeight, initParams->maxUpscaleSize.height); + params->Set("FSR.upscaleSize.width", pExecParams->upscaleSize.width); + params->Set("FSR.upscaleSize.height", pExecParams->upscaleSize.height); - auto ratio = (float)initParams->maxUpscaleSize.width / (float)pExecParams->renderSize.width; + auto width = pExecParams->upscaleSize.width > 0 ? pExecParams->upscaleSize.width : initParams->maxUpscaleSize.width; - LOG_INFO("renderWidth: {}, maxWidth: {}, ratio: {}", pExecParams->renderSize.width, initParams->maxUpscaleSize.width, ratio); + auto ratio = (float)width / (float)pExecParams->renderSize.width; + + LOG_INFO("renderWidth: {}, maxWidth: {}, ratio: {}", pExecParams->renderSize.width, width, ratio); if (ratio <= 3.0) params->Set(NVSDK_NGX_Parameter_PerfQualityValue, NVSDK_NGX_PerfQuality_Value_UltraPerformance); diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp index a5dfcddf..718ae5d5 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp @@ -1159,6 +1159,14 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom IFeature_Dx12* deviceContext = nullptr; + if (Dx12Contexts[handleId].feature) { + auto* feature = Dx12Contexts[handleId].feature.get(); + + // FSR 3.1 supports upscaleSize that doesn't need reinit to change output resolution + if (!std::string(feature->Name()).starts_with("FSR 3.1") && feature->Name() != "FSR3 w/Dx12" && feature->UpdateOutputResolution(InParameters)) + State::Instance().changeBackend[handleId] = true; + } + // Change backend if (State::Instance().changeBackend[handleId]) { @@ -1198,8 +1206,15 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom dc = nullptr; - LOG_DEBUG("sleeping before reset of current feature for 1000ms"); - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + if (State::Instance().gameQuirk = SplitFiction) { + LOG_DEBUG("sleeping before reset of current feature for 100ms (Split Fiction)"); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + else + { + LOG_DEBUG("sleeping before reset of current feature for 1000ms"); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } Dx12Contexts[handleId].feature.reset(); Dx12Contexts[handleId].feature = nullptr; @@ -1344,7 +1359,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom State::Instance().currentFeature = Dx12Contexts[handleId].feature.get(); FrameGen_Dx12::fgTarget = 20; - return NVSDK_NGX_Result_Success; + //return NVSDK_NGX_Result_Success; } deviceContext = Dx12Contexts[handleId].feature.get(); diff --git a/OptiScaler/upscalers/IFeature.cpp b/OptiScaler/upscalers/IFeature.cpp index 4c7ce875..61fedebb 100644 --- a/OptiScaler/upscalers/IFeature.cpp +++ b/OptiScaler/upscalers/IFeature.cpp @@ -24,6 +24,8 @@ bool IFeature::SetInitParameters(NVSDK_NGX_Parameter* InParameters) InParameters->Get(NVSDK_NGX_Parameter_OutHeight, &outHeight) == NVSDK_NGX_Result_Success && InParameters->Get(NVSDK_NGX_Parameter_PerfQualityValue, &pqValue) == NVSDK_NGX_Result_Success) { + GetDynamicOutputResolution(InParameters, &outWidth, &outHeight); + // Thanks to Crytek added these checks if (width > 16384 || width < 20) width = 0; @@ -154,3 +156,65 @@ float IFeature::GetSharpness(const NVSDK_NGX_Parameter* InParameters) return sharpness; } + +bool IFeature::UpdateOutputResolution(const NVSDK_NGX_Parameter* InParameters) +{ + // Check for FSR's dynamic resolution output + auto fsrDynamicOutputWidth = 0; + auto fsrDynamicOutputHeight = 0; + + InParameters->Get("FSR.upscaleSize.width", &fsrDynamicOutputWidth); + InParameters->Get("FSR.upscaleSize.height", &fsrDynamicOutputHeight); + + if (Config::Instance()->OutputScalingEnabled.value_or_default()) { + if (_targetWidth == fsrDynamicOutputWidth || _targetHeight == fsrDynamicOutputHeight) + return false; + + if (fsrDynamicOutputWidth > 0 && fsrDynamicOutputHeight > 0 && + ((unsigned int)(fsrDynamicOutputWidth * Config::Instance()->OutputScalingMultiplier.value_or_default()) != _targetWidth || fsrDynamicOutputWidth != _displayWidth || (unsigned int)(fsrDynamicOutputHeight * Config::Instance()->OutputScalingMultiplier.value_or_default()) != _targetHeight || fsrDynamicOutputHeight != _displayHeight)) { + _targetWidth = fsrDynamicOutputWidth * Config::Instance()->OutputScalingMultiplier.value_or_default(); + _displayWidth = fsrDynamicOutputWidth; + _targetHeight = fsrDynamicOutputHeight * Config::Instance()->OutputScalingMultiplier.value_or_default(); + _displayHeight = fsrDynamicOutputHeight; + + return true; + } + } + else + { + if (fsrDynamicOutputWidth > 0 && fsrDynamicOutputHeight > 0 && + (fsrDynamicOutputWidth != _targetWidth || fsrDynamicOutputWidth != _displayWidth || fsrDynamicOutputHeight != _targetHeight || fsrDynamicOutputHeight != _displayHeight)) { + _targetWidth = fsrDynamicOutputWidth; + _displayWidth = fsrDynamicOutputWidth; + _targetHeight = fsrDynamicOutputHeight; + _displayHeight = fsrDynamicOutputHeight; + + return true; + } + } + + return false; +} + +void IFeature::GetDynamicOutputResolution(NVSDK_NGX_Parameter* InParameters, unsigned int* width, unsigned int* height) +{ + // FSR 3.1 uses upscaleSize for this, max size should stay the same + int supportsUpscaleSize = 0; + InParameters->Get("OptiScaler.SupportsUpscaleSize", &supportsUpscaleSize); + if (supportsUpscaleSize) { + InParameters->Set("OptiScaler.SupportsUpscaleSize", 0); + return; + } + + // Check for FSR's dynamic resolution output + auto fsrDynamicOutputWidth = 0; + auto fsrDynamicOutputHeight = 0; + + InParameters->Get("FSR.upscaleSize.width", &fsrDynamicOutputWidth); + InParameters->Get("FSR.upscaleSize.height", &fsrDynamicOutputHeight); + + if (fsrDynamicOutputWidth > 0 && fsrDynamicOutputHeight > 0) { + *width = fsrDynamicOutputWidth; + *height = fsrDynamicOutputHeight; + } +} diff --git a/OptiScaler/upscalers/IFeature.h b/OptiScaler/upscalers/IFeature.h index 9c356612..749381e2 100644 --- a/OptiScaler/upscalers/IFeature.h +++ b/OptiScaler/upscalers/IFeature.h @@ -39,6 +39,7 @@ protected: void SetHandle(unsigned int InHandleId); bool SetInitParameters(NVSDK_NGX_Parameter* InParameters); void GetRenderResolution(NVSDK_NGX_Parameter* InParameters, unsigned int* OutWidth, unsigned int* OutHeight); + void GetDynamicOutputResolution(NVSDK_NGX_Parameter* InParameters, unsigned int* width, unsigned int* height); float GetSharpness(const NVSDK_NGX_Parameter* InParameters); virtual void SetInit(bool InValue) { _isInited = InValue; } @@ -49,6 +50,7 @@ public: int GetFeatureFlags() const { return _featureFlags; } + bool UpdateOutputResolution(const NVSDK_NGX_Parameter* InParameters); unsigned int DisplayWidth() const { return _displayWidth; }; unsigned int DisplayHeight() const { return _displayHeight; }; unsigned int TargetWidth() const { return _targetWidth; }; diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp index 2b2f741c..87ff5d42 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp @@ -449,8 +449,11 @@ bool FSR31FeatureDx11::Evaluate(ID3D11DeviceContext* DeviceContext, NVSDK_NGX_Pa LOG_WARN("Velocity configure result: {}", (UINT)result); } - InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width); - InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height); + if (InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.width *= Config::Instance()->OutputScalingMultiplier.value_or_default(); + + if (InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.height *= Config::Instance()->OutputScalingMultiplier.value_or_default(); LOG_DEBUG("Dispatch!!"); auto result = ffxFsr3ContextDispatchUpscale(&_upscalerContext, ¶ms); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp index 0d2651dd..ef9a3859 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp @@ -6,7 +6,12 @@ #include "FSR31Feature_Dx11On12.h" -FSR31FeatureDx11on12::FSR31FeatureDx11on12(unsigned int InHandleId, NVSDK_NGX_Parameter* InParameters) : FSR31Feature(InHandleId, InParameters), IFeature_Dx11wDx12(InHandleId, InParameters), IFeature_Dx11(InHandleId, InParameters), IFeature(InHandleId, InParameters) +NVSDK_NGX_Parameter* FSR31FeatureDx11on12::SetParameters(NVSDK_NGX_Parameter* InParameters) { + InParameters->Set("OptiScaler.SupportsUpscaleSize", true); + return InParameters; +} + +FSR31FeatureDx11on12::FSR31FeatureDx11on12(unsigned int InHandleId, NVSDK_NGX_Parameter* InParameters) : FSR31Feature(InHandleId, InParameters), IFeature_Dx11wDx12(InHandleId, InParameters), IFeature_Dx11(InHandleId, InParameters), IFeature(InHandleId, SetParameters(InParameters)) { _moduleLoaded = FfxApiProxy::InitFfxDx12(); @@ -344,8 +349,11 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ LOG_WARN("Velocity configure result: {}", (UINT)result); } - InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width); - InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height); + if (InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.width *= Config::Instance()->OutputScalingMultiplier.value_or_default(); + + if (InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.height *= Config::Instance()->OutputScalingMultiplier.value_or_default(); LOG_DEBUG("Dispatch!!"); auto ffxresult = FfxApiProxy::D3D12_Dispatch()(&_context, ¶ms.header); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.h b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.h index 778c541c..72a1e3aa 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.h +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.h @@ -10,6 +10,7 @@ class FSR31FeatureDx11on12 : public FSR31Feature, public IFeature_Dx11wDx12 { private: bool _baseInit = false; + NVSDK_NGX_Parameter* SetParameters(NVSDK_NGX_Parameter* InParameters); protected: bool InitFSR3(const NVSDK_NGX_Parameter* InParameters); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp index 46a20e7b..fff3a12a 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp @@ -6,7 +6,12 @@ #include "FSR31Feature_Dx12.h" -FSR31FeatureDx12::FSR31FeatureDx12(unsigned int InHandleId, NVSDK_NGX_Parameter* InParameters) : FSR31Feature(InHandleId, InParameters), IFeature_Dx12(InHandleId, InParameters), IFeature(InHandleId, InParameters) +NVSDK_NGX_Parameter* FSR31FeatureDx12::SetParameters(NVSDK_NGX_Parameter* InParameters) { + InParameters->Set("OptiScaler.SupportsUpscaleSize", true); + return InParameters; +} + +FSR31FeatureDx12::FSR31FeatureDx12(unsigned int InHandleId, NVSDK_NGX_Parameter* InParameters) : FSR31Feature(InHandleId, InParameters), IFeature_Dx12(InHandleId, InParameters), IFeature(InHandleId, SetParameters(InParameters)) { _moduleLoaded = FfxApiProxy::InitFfxDx12(); @@ -395,8 +400,11 @@ bool FSR31FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_ LOG_WARN("Velocity configure result: {}", (UINT)result); } - InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width); - InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height); + if (InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.width *= Config::Instance()->OutputScalingMultiplier.value_or_default(); + + if (InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.height *= Config::Instance()->OutputScalingMultiplier.value_or_default(); LOG_DEBUG("Dispatch!!"); auto result = FfxApiProxy::D3D12_Dispatch()(&_context, ¶ms.header); @@ -404,6 +412,12 @@ bool FSR31FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_ if (result != FFX_API_RETURN_OK) { LOG_ERROR("_dispatch error: {0}", FfxApiProxy::ReturnCodeToString(result)); + + if (result == FFX_API_RETURN_ERROR_RUNTIME_ERROR) { + LOG_WARN("Trying to recover by recreating the feature"); + State::Instance().changeBackend[Handle()->Id] = true; + } + return false; } diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.h b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.h index 23d3e9dd..9d12b57b 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.h +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.h @@ -8,6 +8,7 @@ class FSR31FeatureDx12 : public FSR31Feature, public IFeature_Dx12 { private: + NVSDK_NGX_Parameter* SetParameters(NVSDK_NGX_Parameter* InParameters); protected: bool InitFSR3(const NVSDK_NGX_Parameter* InParameters); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp index 6b6fee15..7d079636 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp @@ -553,8 +553,11 @@ bool FSR31FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* LOG_WARN("Velocity configure result: {}", (UINT)result); } - InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width); - InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height); + if (InParameters->Get("FSR.upscaleSize.width", ¶ms.upscaleSize.width) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.width *= Config::Instance()->OutputScalingMultiplier.value_or_default(); + + if (InParameters->Get("FSR.upscaleSize.height", ¶ms.upscaleSize.height) == NVSDK_NGX_Result_Success && Config::Instance()->OutputScalingEnabled.value_or_default()) + params.upscaleSize.height *= Config::Instance()->OutputScalingMultiplier.value_or_default(); LOG_DEBUG("Dispatch!!"); auto result = FfxApiProxy::VULKAN_Dispatch()(&_context, ¶ms.header);