From 305f68386a5de6e3e1a06aba509988eb0a4e0445 Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Tue, 3 Feb 2026 03:45:32 -0500 Subject: [PATCH 1/8] Clean up DLSS DX12 inputs - Refactored CreateFeature() and EvaluateFeature() into smaller functions with shared utilities and distinct code paths for internal OptiScaler and passthrough features. - Added documentation to clarify internal implementation details and behavior required by the NGX API. - Added more descriptive error messages. - Fixed a potential memory leak in GetParameters(). Per the DLSS Programming Guide (310.5.0), this deprecated API requires the SDK to manage the lifetime of the returned parameter table, as legacy applications do not free this memory. - Identified a memory management issue: NVNGX_Parameter tables are incorrectly handled in Allocate/Destroy and FeatureProvider. C-style free() is being used on tables allocated with 'new' and on native NGX tables, leading to memory leaks and undefined behavior. Using free() here is actually worse than just willfully leaking memory. This needs fixing. --- OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp | 684 ++++++++++++++++---------- 1 file changed, 420 insertions(+), 264 deletions(-) diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp index 7f308e8d8..e7332073e 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp @@ -82,6 +82,9 @@ static void hkSetGraphicRootSignature(ID3D12GraphicsCommandList* commandList, ID orgSetGraphicRootSignature(commandList, pRootSignature); } +/** + * @brief Attaches hooks to monitor the state of the application's DX12 render pipeline and restore state as needed. + */ static void HookToCommandList(ID3D12GraphicsCommandList* InCmdList) { if (orgSetComputeRootSignature != nullptr || orgSetGraphicRootSignature != nullptr) @@ -109,6 +112,9 @@ static void HookToCommandList(ID3D12GraphicsCommandList* InCmdList) } } +/** + * @brief Uninstalls renderer state monitoring hooks + */ static void UnhookAll() { DetourTransactionBegin(); @@ -133,10 +139,12 @@ static void UnhookAll() #pragma region DLSS Init Calls -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext(unsigned long long InApplicationId, - const wchar_t* InApplicationDataPath, ID3D12Device* InDevice, - NVSDK_NGX_Version InSDKVersion, - const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext( + unsigned long long InApplicationId, + const wchar_t* InApplicationDataPath, + ID3D12Device* InDevice, + NVSDK_NGX_Version InSDKVersion, + const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) { LOG_FUNC(); @@ -217,10 +225,12 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext(unsigned long long InApp return NVSDK_NGX_Result_Success; } -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init(unsigned long long InApplicationId, - const wchar_t* InApplicationDataPath, ID3D12Device* InDevice, - const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo, - NVSDK_NGX_Version InSDKVersion) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init( + unsigned long long InApplicationId, + const wchar_t* InApplicationDataPath, + ID3D12Device* InDevice, + const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo, + NVSDK_NGX_Version InSDKVersion) { LOG_FUNC(); @@ -257,20 +267,23 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init(unsigned long long InApplica // DLSSGMod::InitDLSSGMod_Dx12(); // DLSSGMod::D3D12_Init(InApplicationId, InApplicationDataPath, InDevice, InFeatureInfo, InSDKVersion); // } - + ScopedInit scopedInit {}; auto result = NVSDK_NGX_D3D12_Init_Ext(InApplicationId, InApplicationDataPath, InDevice, InSDKVersion, InFeatureInfo); + LOG_DEBUG("was called NVSDK_NGX_D3D12_Init_Ext"); return result; } -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_ProjectID(const char* InProjectId, - NVSDK_NGX_EngineType InEngineType, - const char* InEngineVersion, - const wchar_t* InApplicationDataPath, - ID3D12Device* InDevice, NVSDK_NGX_Version InSDKVersion, - const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_ProjectID( + const char* InProjectId, + NVSDK_NGX_EngineType InEngineType, + const char* InEngineVersion, + const wchar_t* InApplicationDataPath, + ID3D12Device* InDevice, + NVSDK_NGX_Version InSDKVersion, + const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) { LOG_FUNC(); @@ -417,6 +430,22 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Shutdown1(ID3D12Device* InDevice) #pragma region DLSS Parameter Calls +/** + * @brief Allocates and populates a preexisting NGX param map. + */ +static void GetNGXParameters(std::string InName, NVNGX_Parameters& params) +{ + params.Name = InName; + InitNGXParameters(¶ms); + params.Set("OptiScaler", 1); +} + +/** + * @brief [Deprecated NGX API] Superceeded by NVSDK_NGX_AllocateParameters and NVSDK_NGX_GetCapabilityParameters. + * + * Retrieves a common NVSDK parameter map for providing params to the SDK. The lifetime of this + * map is NOT managed by the application. It is expected to be managed internally by the SDK. + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -424,14 +453,16 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetParameters(NVSDK_NGX_Parameter if (OutParameters == nullptr) return NVSDK_NGX_Result_FAIL_InvalidParameter; + // If DLSS is enabled and the real DLSS module is loaded, get native NGX table if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::D3D12_GetParameters() != nullptr) { - LOG_INFO("calling NVNGXProxy::D3D12_GetParameters"); + LOG_INFO("Calling NVNGXProxy::D3D12_GetParameters"); auto result = NVNGXProxy::D3D12_GetParameters()(OutParameters); - LOG_INFO("calling NVNGXProxy::D3D12_GetParameters result: {0:X}, ptr: {1:X}", (UINT) result, + LOG_INFO("Calling NVNGXProxy::D3D12_GetParameters result: {0:X}, ptr: {1:X}", (UINT) result, (UINT64) *OutParameters); + // Copy OptiScaler config to real NGX param table if (result == NVSDK_NGX_Result_Success) { InitNGXParameters(*OutParameters); @@ -439,11 +470,19 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetParameters(NVSDK_NGX_Parameter } } - *OutParameters = GetNGXParameters("OptiDx12"); + // Get custom parameters if using custom backend + static NVNGX_Parameters oldParams = NVNGX_Parameters(); + GetNGXParameters("OptiDx12", oldParams); + *OutParameters = &oldParams; return NVSDK_NGX_Result_Success; } +/** + * @brief Allocates a new NVSDK parameter map pre-populated with NGX capabilities and information about available features. + * The output parameter map may also be used in the same ways as a parameter map allocated with AllocateParameters(). + * The lifetime of this map is managed by the calling application with DestroyParameters(). + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -451,12 +490,13 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX if (OutParameters == nullptr) return NVSDK_NGX_Result_FAIL_InvalidParameter; + // Get native DLSS params if DLSS is enabled and the module is loaded if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::IsDx12Inited() && NVNGXProxy::D3D12_GetCapabilityParameters() != nullptr) { - LOG_INFO("calling NVNGXProxy::D3D12_GetCapabilityParameters"); + LOG_INFO("Calling NVNGXProxy::D3D12_GetCapabilityParameters"); auto result = NVNGXProxy::D3D12_GetCapabilityParameters()(OutParameters); - LOG_INFO("calling NVNGXProxy::D3D12_GetCapabilityParameters result: {0:X}, ptr: {1:X}", (UINT) result, + LOG_INFO("Calling NVNGXProxy::D3D12_GetCapabilityParameters result: {0:X}, ptr: {1:X}", (UINT) result, (UINT64) *OutParameters); if (result == NVSDK_NGX_Result_Success) @@ -465,12 +505,19 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX return NVSDK_NGX_Result_Success; } } - - *OutParameters = GetNGXParameters("OptiDx12"); + + // Get custom parameters if using custom backend + auto& params = *(new NVNGX_Parameters()); + GetNGXParameters("OptiDx12", params); + *OutParameters = ¶ms; return NVSDK_NGX_Result_Success; } +/** + * @brief Allocates a new parameter map used to provide parameters needed by the DLSS API. The lifetime of this map + * is managed by the calling application with DestroyParameters(). + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_AllocateParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -478,16 +525,16 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_AllocateParameters(NVSDK_NGX_Para if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::D3D12_AllocateParameters() != nullptr) { - LOG_INFO("calling NVNGXProxy::D3D12_AllocateParameters"); + LOG_INFO("Calling NVNGXProxy::D3D12_AllocateParameters"); auto result = NVNGXProxy::D3D12_AllocateParameters()(OutParameters); - LOG_INFO("calling NVNGXProxy::D3D12_AllocateParameters result: {0:X}, ptr: {1:X}", (UINT) result, + LOG_INFO("Calling NVNGXProxy::D3D12_AllocateParameters result: {0:X}, ptr: {1:X}", (UINT) result, (UINT64) *OutParameters); if (result == NVSDK_NGX_Result_Success) return result; } - auto params = new NVNGX_Parameters(); + auto* params = new NVNGX_Parameters(); params->Name = "OptiDx12"; *OutParameters = params; @@ -509,6 +556,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_PopulateParameters_Impl(NVSDK_NGX return NVSDK_NGX_Result_Success; } +/** + * @brief Destroys a given input parameter map created with AllocateParameters or GetCapabilityParameters. + Must not be called on maps returned by GetParameters(). + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_DestroyParameters(NVSDK_NGX_Parameter* InParameters) { LOG_FUNC(); @@ -519,9 +570,9 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_DestroyParameters(NVSDK_NGX_Param if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && NVNGXProxy::D3D12_DestroyParameters() != nullptr) { - LOG_INFO("calling NVNGXProxy::D3D12_DestroyParameters"); + LOG_INFO("Calling NVNGXProxy::D3D12_DestroyParameters"); auto result = NVNGXProxy::D3D12_DestroyParameters()(InParameters); - LOG_INFO("calling NVNGXProxy::D3D12_DestroyParameters result: {0:X}", (UINT) result); + LOG_INFO("Calling NVNGXProxy::D3D12_DestroyParameters result: {0:X}", (UINT) result); UpscalerInputsDx12::Reset(); return NVSDK_NGX_Result_Success; @@ -535,163 +586,238 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_DestroyParameters(NVSDK_NGX_Param #pragma region DLSS Feature Calls -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsCommandList* InCmdList, - NVSDK_NGX_Feature InFeatureID, - NVSDK_NGX_Parameter* InParameters, - NVSDK_NGX_Handle** OutHandle) +static std::string GetUpscalerBackend() { - LOG_FUNC(); + std::string name = "xess"; // Default - if (InCmdList != nullptr) - HookToCommandList(InCmdList); + if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited()) + name = "dlss"; - if (State::Instance().activeFgInput == FGInput::Nukems && DLSSGMod::isDx12Available() && - InFeatureID == NVSDK_NGX_Feature_FrameGeneration) + if (Config::Instance()->Dx12Upscaler.has_value()) + name = Config::Instance()->Dx12Upscaler.value(); + + return name; +} + +static bool EnsureD3D12Device(ID3D12GraphicsCommandList* cmdList) +{ + if (D3D12Device) + return true; + + LOG_DEBUG("Get D3D12 device from InCmdList!"); + + if (FAILED(cmdList->GetDevice(IID_PPV_ARGS(&D3D12Device))) || !D3D12Device) { - auto result = DLSSGMod::D3D12_CreateFeature(InCmdList, InFeatureID, InParameters, OutHandle); - LOG_INFO("Creating new modded DLSSG feature with HandleId: {0}", (*OutHandle)->Id); - return result; + LOG_ERROR("Can't get Dx12Device from InCmdList!"); + return false; } - else if (InFeatureID != NVSDK_NGX_Feature_SuperSampling && InFeatureID != NVSDK_NGX_Feature_RayReconstruction) + + return true; +} + +static void RestoreRootSignatures(ID3D12GraphicsCommandList* cmdList) +{ + const auto& config = *Config::Instance(); + const bool restoreCompute = config.RestoreComputeSignature.value_or_default(); + const bool restoreGraphic = config.RestoreGraphicSignature.value_or_default(); + + if (!restoreCompute && !restoreGraphic) + return; + + if (restoreCompute) { - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::InitDx12(D3D12Device) && - NVNGXProxy::D3D12_CreateFeature() != nullptr) + if (computeSignatures.contains(cmdList)) { - LOG_INFO("calling D3D12_CreateFeature for ({0})", (int) InFeatureID); - auto result = NVNGXProxy::D3D12_CreateFeature()(InCmdList, InFeatureID, InParameters, OutHandle); - - if (result == NVSDK_NGX_Result_Success) - { - LOG_INFO("D3D12_CreateFeature HandleId for ({0}): {1:X}", (int) InFeatureID, (*OutHandle)->Id); - } - else - { - LOG_INFO("D3D12_CreateFeature result for ({0}): {1:X}", (int) InFeatureID, (UINT) result); - } + LOG_TRACE("restore ComputeRootSig: {0:X}", (UINT64) computeSignatures[cmdList]); + orgSetComputeRootSignature(cmdList, computeSignatures[cmdList]); + } + else + { + LOG_TRACE("Can't restore ComputeRootSig"); + } + } - return result; + if (restoreGraphic) + { + if (graphicSignatures.contains(cmdList)) + { + LOG_TRACE("restore GraphicRootSig: {0:X}", (UINT64) graphicSignatures[cmdList]); + orgSetGraphicRootSignature(cmdList, graphicSignatures[cmdList]); } else { - LOG_ERROR("Can't create this feature ({0})!", (int) InFeatureID); - return NVSDK_NGX_Result_FAIL_FeatureNotSupported; + LOG_TRACE("Can't restore GraphicRootSig"); } } +} - // Create feature - State::Instance().api = DX12; - auto handleId = IFeature::GetNextHandleId(); - LOG_INFO("HandleId: {0}", handleId); +static NVSDK_NGX_Result TryCreateOptiFeature( + ID3D12GraphicsCommandList* InCmdList, + NVSDK_NGX_Feature InFeatureID, + NVSDK_NGX_Parameter* InParameters, + NVSDK_NGX_Handle** OutHandle) +{ + State& state = State::Instance(); + const Config& cfg = *Config::Instance(); - // Root signature restore - if (Config::Instance()->RestoreComputeSignature.value_or_default() || - Config::Instance()->RestoreGraphicSignature.value_or_default()) - contextRendering = true; + state.api = DX12; + const uint32_t handleId = IFeature::GetNextHandleId(); + LOG_INFO("Creating OptiScaler feature, HandleId: {}", handleId); + + // Determine backend name + std::string featureName; if (InFeatureID == NVSDK_NGX_Feature_SuperSampling) { - std::string upscalerChoice = "xess"; // Default XeSS - - // If original NVNGX available use DLSS as base upscaler - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited()) - upscalerChoice = "dlss"; + featureName = GetUpscalerBackend(); + LOG_INFO("Creating {} upscaler feature", featureName); + } + else + { + featureName = "dlssd"; + LOG_INFO("Creating DLSSD (Ray Reconstruction) feature"); + } - if (Config::Instance()->Dx12Upscaler.has_value()) - upscalerChoice = Config::Instance()->Dx12Upscaler.value(); + // Root signature restoration setup + const bool restoreCompute = cfg.RestoreComputeSignature.value_or_default(); + const bool restoreGraphic = cfg.RestoreGraphicSignature.value_or_default(); + const bool shouldRestore = restoreCompute || restoreGraphic; - LOG_INFO("Creating new {} upscaler", upscalerChoice); + if (shouldRestore) + contextRendering = true; - Dx12Contexts[handleId] = {}; + // Create context entry + Dx12Contexts[handleId] = {}; - if (!FeatureProvider_Dx12::GetFeature(upscalerChoice, handleId, InParameters, &Dx12Contexts[handleId].feature)) - { - LOG_ERROR("Upscaler can't created"); - return NVSDK_NGX_Result_Fail; - } - } - else if (InFeatureID == NVSDK_NGX_Feature_RayReconstruction) + // Retrieve feature implementation + if (!FeatureProvider_Dx12::GetFeature(featureName, handleId, InParameters, &Dx12Contexts[handleId].feature)) { - LOG_INFO("creating new DLSSD feature"); + LOG_ERROR("Failed to retrieve feature implementation for '{}'", featureName); - Dx12Contexts[handleId] = {}; + if (shouldRestore) + contextRendering = false; - if (!FeatureProvider_Dx12::GetFeature("dlssd", handleId, InParameters, &Dx12Contexts[handleId].feature)) - { - LOG_ERROR("DLSSD can't created"); - return NVSDK_NGX_Result_Fail; - } + Dx12Contexts.erase(handleId); + return NVSDK_NGX_Result_Fail; } - auto deviceContext = Dx12Contexts[handleId].feature.get(); - + // Assign handle if (*OutHandle == nullptr) *OutHandle = new NVSDK_NGX_Handle { handleId }; else (*OutHandle)->Id = handleId; -#pragma region Check for Dx12Device Device - - if (!D3D12Device) + // Ensure D3D12 device + if (!EnsureD3D12Device(InCmdList)) { - LOG_DEBUG("Get D3d12 device from InCmdList!"); - auto deviceResult = InCmdList->GetDevice(IID_PPV_ARGS(&D3D12Device)); + LOG_ERROR("Failed to acquire D3D12 device"); - if (deviceResult != S_OK || !D3D12Device) - { - LOG_ERROR("Can't get Dx12Device from InCmdList!"); - return NVSDK_NGX_Result_Fail; - } + if (shouldRestore) + contextRendering = false; + + // Partial cleanup – handle is allocated but context is incomplete + Dx12Contexts.erase(handleId); + return NVSDK_NGX_Result_Fail; } -#pragma endregion + state.AutoExposure.reset(); - State::Instance().AutoExposure.reset(); + IFeature_Dx12* feature = Dx12Contexts[handleId].feature.get(); - if (deviceContext->Init(D3D12Device, InCmdList, InParameters)) + // Initialize feature + if (feature->Init(D3D12Device, InCmdList, InParameters)) { - State::Instance().currentFeature = deviceContext; + state.currentFeature = feature; evalCounter = 0; - UpscalerInputsDx12::Reset(); } else { - LOG_ERROR("CreateFeature failed, returning to FSR 2.1.2 upscaler"); - State::Instance().newBackend = "fsr21"; - State::Instance().changeBackend[handleId] = true; + LOG_ERROR("Feature '{}' initialization failed falling back to FSR 2.1.2", featureName); + state.newBackend = "fsr21"; + state.changeBackend[handleId] = true; } - if (Config::Instance()->RestoreComputeSignature.value_or_default() || - Config::Instance()->RestoreGraphicSignature.value_or_default()) + // Restore root signatures + if (shouldRestore) { - if (Config::Instance()->RestoreComputeSignature.value_or_default() && computeSignatures.contains(InCmdList)) - { - auto signature = computeSignatures[InCmdList]; - LOG_TRACE("restore ComputeRootSig: {0:X}", (UINT64) signature); - orgSetComputeRootSignature(InCmdList, signature); - } - else if (Config::Instance()->RestoreComputeSignature.value_or_default()) - { - LOG_TRACE("can't restore ComputeRootSig"); - } + RestoreRootSignatures(InCmdList); + contextRendering = false; + } - if (Config::Instance()->RestoreGraphicSignature.value_or_default() && graphicSignatures.contains(InCmdList)) - { - auto signature = graphicSignatures[InCmdList]; - LOG_TRACE("restore GraphicRootSig: {0:X}", (UINT64) signature); - orgSetGraphicRootSignature(InCmdList, signature); - } - else if (Config::Instance()->RestoreGraphicSignature.value_or_default()) + state.FGchanged = true; + + return NVSDK_NGX_Result_Success; +} + +/** + * @brief Instantiates a new feature based on the given unique feature ID and param table and + * provides a handle used to reference the feature elsewhere in the API. Currently supports + * various TSR and Frame Generation algorithms, including a special case for DLSS-RR passthrough. + */ +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature( + ID3D12GraphicsCommandList* InCmdList, + NVSDK_NGX_Feature InFeatureID, + NVSDK_NGX_Parameter* InParameters, + NVSDK_NGX_Handle** OutHandle) +{ + LOG_FUNC(); + + if (!InCmdList) + { + LOG_ERROR("InCmdList is null"); + return NVSDK_NGX_Result_Fail; + } + + if (!OutHandle) + { + LOG_ERROR("OutHandle is null"); + return NVSDK_NGX_Result_Fail; + } + + HookToCommandList(InCmdList); + + const State& state = State::Instance(); + const Config& cfg = *Config::Instance(); + + // Nukem's DLSSG mod passthrough + if (state.activeFgInput == FGInput::Nukems && DLSSGMod::isDx12Available() && + InFeatureID == NVSDK_NGX_Feature_FrameGeneration) + { + LOG_INFO("Passthrough to Nukem's DLSSG CreateFeature for FrameGeneration"); + + NVSDK_NGX_Result res = DLSSGMod::D3D12_CreateFeature(InCmdList, InFeatureID, InParameters, OutHandle); + + if (*OutHandle) + LOG_INFO("Created modded DLSSG feature with HandleId: {}", (*OutHandle)->Id); + + return res; + } + + // Native DLSS passthrough (exclude SuperSampling and RayReconstruction) + if (InFeatureID != NVSDK_NGX_Feature_SuperSampling && InFeatureID != NVSDK_NGX_Feature_RayReconstruction) + { + if (cfg.DLSSEnabled.value_or_default() && NVNGXProxy::InitDx12(D3D12Device) && + NVNGXProxy::D3D12_CreateFeature() != nullptr) { - LOG_TRACE("can't restore GraphicRootSig"); + LOG_INFO("Passthrough to native NGX CreateFeature for feature {}", (int) InFeatureID); + + NVSDK_NGX_Result res = NVNGXProxy::D3D12_CreateFeature()(InCmdList, InFeatureID, InParameters, OutHandle); + + if (*OutHandle) + LOG_INFO("Native CreateFeature success, HandleId: {}", (*OutHandle)->Id); + else + LOG_INFO("Native CreateFeature failed: {:#x}", (uint32_t) res); + + return res; } - contextRendering = false; + LOG_WARN("Native DLSS passthrough not available for feature {}", (int) InFeatureID); + return NVSDK_NGX_Result_FAIL_FeatureNotSupported; } - State::Instance().FGchanged = true; - - return NVSDK_NGX_Result_Success; + // OptiScaler internal handling (SuperSampling or RayReconstruction) + return TryCreateOptiFeature(InCmdList, InFeatureID, InParameters, OutHandle); } NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle* InHandle) @@ -702,8 +828,9 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle* return NVSDK_NGX_Result_Success; auto handleId = InHandle->Id; - State::Instance().FGchanged = true; + + // Clean up framegen if (State::Instance().currentFG != nullptr && State::Instance().activeFgInput == FGInput::Upscaler) { State::Instance().currentFG->DestroyFGContext(); @@ -714,6 +841,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle* if (!shutdown) LOG_INFO("releasing feature with id {0}", handleId); + // OptiScaler handles start after this offset. If it's outside this range, it doesn't belong to OptiScaler. if (handleId < DLSS_MOD_ID_OFFSET) { if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::D3D12_ReleaseFeature() != nullptr) @@ -721,6 +849,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle* if (!shutdown) LOG_INFO("calling D3D12_ReleaseFeature for ({0})", handleId); + // Clean up real DLSS feature auto result = NVNGXProxy::D3D12_ReleaseFeature()(InHandle); if (!shutdown) @@ -736,33 +865,45 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle* return NVSDK_NGX_Result_FAIL_FeatureNotFound; } } + // Clean up OptiScaler feature with framegen else if (State::Instance().activeFgInput == FGInput::Nukems && handleId >= DLSSG_MOD_ID_OFFSET) { LOG_INFO("D3D12_ReleaseFeature modded DLSSG with HandleId: {0}", handleId); return DLSSGMod::D3D12_ReleaseFeature(InHandle); } - if (auto deviceContext = Dx12Contexts[handleId].feature.get(); deviceContext != nullptr) + // Remove feature from context map + if (auto it = Dx12Contexts.find(handleId); it != Dx12Contexts.end()) { - if (deviceContext == State::Instance().currentFeature) - State::Instance().currentFeature = nullptr; + auto& entry = it->second; - Dx12Contexts[handleId].feature.reset(); - auto it = std::find_if(Dx12Contexts.begin(), Dx12Contexts.end(), - [&handleId](const auto& p) { return p.first == handleId; }); - Dx12Contexts.erase(it); - } - else - { - if (!shutdown) - LOG_ERROR("can't release feature with id {0}!", handleId); + if (auto* deviceContext = entry.feature.get()) + { + // Clear global reference if it matches + if (deviceContext == State::Instance().currentFeature) + State::Instance().currentFeature = nullptr; + + // Erase from map (smart pointer reset is implicit on erase) + Dx12Contexts.erase(it); + } } + // Fallback Error Handling + if (!shutdown) + LOG_ERROR("can't release feature with id {0}!", handleId); + return NVSDK_NGX_Result_Success; } +/** + * @brief Used by the client application to check for feature support. + * @param Adapter Device the feature is for. + * @param FeatureDiscoveryInfo Specifies the feature being queried. + * @param OutSupported Used to indicate whether a feature is supported and its requirements. + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetFeatureRequirements( - IDXGIAdapter* Adapter, const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo, + IDXGIAdapter* Adapter, + const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo, NVSDK_NGX_FeatureRequirement* OutSupported) { LOG_DEBUG("for ({0})", (int) FeatureDiscoveryInfo->FeatureID); @@ -776,7 +917,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetFeatureRequirements( Config::Instance()->FGInput == FGInput::DLSSG))) { if (OutSupported == nullptr) - OutSupported = new NVSDK_NGX_FeatureRequirement(); + { + static auto tmp = NVSDK_NGX_FeatureRequirement(); + OutSupported = &tmp; + } OutSupported->FeatureSupported = NVSDK_NGX_FeatureSupportResult_Supported; OutSupported->MinHWArchitecture = 0; @@ -807,184 +951,196 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetFeatureRequirements( return NVSDK_NGX_Result_FAIL_FeatureNotSupported; } -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCmdList, - const NVSDK_NGX_Handle* InFeatureHandle, - NVSDK_NGX_Parameter* InParameters, - PFN_NVSDK_NGX_ProgressCallback InCallback) +static NVSDK_NGX_Result TryEvaluateOptiFeature( + ID3D12GraphicsCommandList* InCmdList, + const NVSDK_NGX_Handle* InFeatureHandle, + NVSDK_NGX_Parameter* InParameters, + PFN_NVSDK_NGX_ProgressCallback InCallback) { - if (InFeatureHandle == nullptr) - { - LOG_DEBUG("InFeatureHandle is null"); - return NVSDK_NGX_Result_FAIL_FeatureNotFound; - } + State& state = State::Instance(); + const Config& cfg = *Config::Instance(); + const uint32_t handleId = InFeatureHandle->Id; - if (InCmdList == nullptr) + auto ctxIt = Dx12Contexts.find(handleId); + if (ctxIt == Dx12Contexts.end()) { - LOG_ERROR("InCmdList is null!!!"); - return NVSDK_NGX_Result_Fail; + LOG_WARN("No context found for handle {}", handleId); + return NVSDK_NGX_Result_FAIL_FeatureNotFound; } - LOG_DEBUG("Handle: {}, CmdList: {:X}", InFeatureHandle->Id, (size_t) InCmdList); - auto handleId = InFeatureHandle->Id; + ContextData& ctxData = ctxIt->second; + IFeature_Dx12* feature = ctxData.feature.get(); - if (handleId < DLSS_MOD_ID_OFFSET) + if (!feature) { - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::D3D12_EvaluateFeature() != nullptr) - { - LOG_DEBUG("D3D12_EvaluateFeature for ({0})", handleId); - auto result = NVNGXProxy::D3D12_EvaluateFeature()(InCmdList, InFeatureHandle, InParameters, InCallback); - LOG_DEBUG("D3D12_EvaluateFeature result for ({0}): {1:X}", handleId, (UINT) result); - return result; - } - else - { - LOG_DEBUG("D3D12_EvaluateFeature not avaliable for ({0})", handleId); - return NVSDK_NGX_Result_FAIL_FeatureNotFound; - } - } - else if (State::Instance().activeFgInput == FGInput::Nukems && handleId >= DLSSG_MOD_ID_OFFSET) - { - return DLSSGMod::D3D12_EvaluateFeature(InCmdList, InFeatureHandle, InParameters, InCallback); - } - - if (!Dx12Contexts.contains(handleId)) + LOG_WARN("Feature pointer is null for handle {}", handleId); return NVSDK_NGX_Result_FAIL_FeatureNotFound; + } - auto deviceContext = &Dx12Contexts[handleId]; - - if (deviceContext->feature == nullptr) // prevent source api name flicker when dlssg is active - State::Instance().setInputApiName = State::Instance().currentInputApiName; + // Prevent API name flicker (e.g., during backend transitions or DLSSG) + if (state.setInputApiName == state.currentInputApiName) + state.setInputApiName.clear(); - if (State::Instance().setInputApiName.length() == 0) - { - if (std::strcmp(State::Instance().currentInputApiName.c_str(), "DLSS") != 0) - State::Instance().currentInputApiName = "DLSS"; - } - else - { - if (std::strcmp(State::Instance().currentInputApiName.c_str(), State::Instance().setInputApiName.c_str()) != 0) - State::Instance().currentInputApiName = State::Instance().setInputApiName; - } + const std::string_view targetApiName = state.setInputApiName.empty() ? "DLSS" : state.setInputApiName; - State::Instance().setInputApiName.clear(); + if (state.currentInputApiName != targetApiName) + state.currentInputApiName = targetApiName; + state.setInputApiName.clear(); evalCounter++; - if (Config::Instance()->SkipFirstFrames.has_value() && evalCounter < Config::Instance()->SkipFirstFrames.value()) + + // Skip evaluation for the first N frames if configured + if (cfg.SkipFirstFrames.has_value() && evalCounter < cfg.SkipFirstFrames.value()) return NVSDK_NGX_Result_Success; if (InCallback) - LOG_INFO("callback exist"); + LOG_INFO("Progress callback provided but unused in synchronous OptiScaler path"); - if (deviceContext->feature) - { - auto* feature = deviceContext->feature.get(); + // Resolution change detection (only for upscalers that may require recreation) + const bool isFSR31OrLater = feature->Name().starts_with("FSR") && feature->Version() >= feature_version { 3, 1, 0 }; - // FSR 3.1 supports upscaleSize that doesn't need reinit to change output resolution - if (!(feature->Name().starts_with("FSR") && feature->Version() >= feature_version { 3, 1, 0 }) && - feature->UpdateOutputResolution(InParameters)) - State::Instance().changeBackend[handleId] = true; - } + if (!isFSR31OrLater && feature->UpdateOutputResolution(InParameters)) + state.changeBackend[handleId] = true; - // Change backend - if (State::Instance().changeBackend[handleId]) + // Backend change or recreation requested + if (state.changeBackend.contains(handleId) && state.changeBackend[handleId]) { + LOG_INFO("Performing backend change/recreation for handle {} to '{}'", handleId, state.newBackend); + UpscalerInputsDx12::Reset(); contextRendering = false; - FeatureProvider_Dx12::ChangeFeature(State::Instance().newBackend, D3D12Device, InCmdList, handleId, - InParameters, deviceContext); + FeatureProvider_Dx12::ChangeFeature(state.newBackend, D3D12Device, InCmdList, handleId, InParameters, &ctxData); + feature = ctxData.feature.get(); - evalCounter = 0; + state.changeBackend.erase(handleId); + + if (!state.newBackend.empty()) + state.newBackend.clear(); + evalCounter = 0; return NVSDK_NGX_Result_Success; } - if (!deviceContext->feature->IsInited() && Config::Instance()->Dx12Upscaler.value_or_default() != "fsr21") + // Fallback to FSR 2.1.2 if feature failed to initialize and user didn't explicitly request it + if (!feature->IsInited() && cfg.Dx12Upscaler.value_or_default() != "fsr21") { - LOG_WARN("InCmdList {0} is not inited, falling back to FSR 2.1.2", deviceContext->feature->Name()); - State::Instance().newBackend = "fsr21"; - State::Instance().changeBackend[handleId] = true; + LOG_WARN("Feature '{}' failed to initialize. Falling back to FSR 2.1.2", feature->Name()); + state.newBackend = "fsr21"; + state.changeBackend[handleId] = true; return NVSDK_NGX_Result_Success; } - State::Instance().currentFeature = deviceContext->feature.get(); + state.currentFeature = feature; - // Root signature restore - if (deviceContext->feature->Name() != "DLSSD" && (Config::Instance()->RestoreComputeSignature.value_or_default() || - Config::Instance()->RestoreGraphicSignature.value_or_default())) - { + // Root signature restoration setup + const bool restoreCompute = cfg.RestoreComputeSignature.value_or_default(); + const bool restoreGraphic = cfg.RestoreGraphicSignature.value_or_default(); + const bool shouldRestore = (feature->Name() != "DLSSD") && (restoreCompute || restoreGraphic); + + if (shouldRestore) contextRendering = true; - } - UpscalerInputsDx12::UpscaleStart(InCmdList, InParameters, deviceContext->feature.get()); - FSR3FG::SetUpscalerInputs(InCmdList, InParameters, deviceContext->feature.get()); + // Prepare upscaling inputs + UpscalerInputsDx12::UpscaleStart(InCmdList, InParameters, feature); + FSR3FG::SetUpscalerInputs(InCmdList, InParameters, feature); - // Record the first timestamp - if (!State::Instance().isWorkingAsNvngx) + if (!state.isWorkingAsNvngx) UpscalerTimeDx12::UpscaleStart(InCmdList); - auto evalResult = false; - - // Run upscaler + // Evaluate the feature + bool evalSuccess = false; { - ScopedSkipHeapCapture skipHeapCapture {}; - evalResult = deviceContext->feature->Evaluate(InCmdList, InParameters); + ScopedSkipHeapCapture skip {}; + evalSuccess = feature->Evaluate(InCmdList, InParameters); } - NVSDK_NGX_Result methodResult = evalResult ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail; - - if (evalResult) + // Cleanup on success + if (evalSuccess) { - // Upscaler time calc - // Record the second timestamp - if (!State::Instance().isWorkingAsNvngx) + if (!state.isWorkingAsNvngx) UpscalerTimeDx12::UpscaleEnd(InCmdList); - // FG Dispatch - UpscalerInputsDx12::UpscaleEnd(InCmdList, InParameters, deviceContext->feature.get()); + UpscalerInputsDx12::UpscaleEnd(InCmdList, InParameters, feature); + } + else + { + LOG_ERROR("Feature evaluation failed for '{}'", feature->Name()); } - // Root signature restore - if (deviceContext->feature->Name() != "DLSSD" && (Config::Instance()->RestoreComputeSignature.value_or_default() || - Config::Instance()->RestoreGraphicSignature.value_or_default())) + // Restore root signatures + if (shouldRestore) { - if (Config::Instance()->RestoreComputeSignature.value_or_default() && computeSignatures.contains(InCmdList)) - { - auto signature = computeSignatures[InCmdList]; - LOG_TRACE("restore orgComputeRootSig: {0:X}", (UINT64) signature); - orgSetComputeRootSignature(InCmdList, signature); - } - else if (Config::Instance()->RestoreComputeSignature.value_or_default()) - { - LOG_WARN("Can't restore ComputeRootSig!"); - } + RestoreRootSignatures(InCmdList); + contextRendering = false; + } - if (Config::Instance()->RestoreGraphicSignature.value_or_default() && graphicSignatures.contains(InCmdList)) - { - auto signature = graphicSignatures[InCmdList]; - LOG_TRACE("restore orgGraphicRootSig: {0:X}", (UINT64) signature); - orgSetGraphicRootSignature(InCmdList, signature); - } - else if (Config::Instance()->RestoreGraphicSignature.value_or_default()) + return evalSuccess ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail; +} + +/** + * @brief Per-frame feature execution. Runs a feature (upscaler, framegen, etc.) on a given command list using a + * preexisting feature instance referenced by a unique handle. + */ +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature( + ID3D12GraphicsCommandList* InCmdList, + const NVSDK_NGX_Handle* InFeatureHandle, + NVSDK_NGX_Parameter* InParameters, + PFN_NVSDK_NGX_ProgressCallback InCallback) +{ + if (!InFeatureHandle) + { + LOG_DEBUG("InFeatureHandle is null"); + return NVSDK_NGX_Result_FAIL_FeatureNotFound; + } + + if (!InCmdList) + { + LOG_ERROR("InCmdList is null"); + return NVSDK_NGX_Result_Fail; + } + + const uint32_t handleId = InFeatureHandle->Id; + LOG_DEBUG("EvaluateFeature - Handle: {}, CmdList: {:p}", handleId, (void*) InCmdList); + + const State& state = State::Instance(); + const Config& cfg = *Config::Instance(); + + // Native DLSS passthrough + if (handleId < DLSS_MOD_ID_OFFSET) + { + if (cfg.DLSSEnabled.value_or_default() && NVNGXProxy::D3D12_EvaluateFeature() != nullptr) { - LOG_WARN("Can't restore GraphicRootSig!"); + LOG_DEBUG("Passthrough to native DLSS EvaluateFeature for handle {}", handleId); + NVSDK_NGX_Result result = + NVNGXProxy::D3D12_EvaluateFeature()(InCmdList, InFeatureHandle, InParameters, InCallback); + LOG_DEBUG("Native DLSS EvaluateFeature result: {:#x}", (uint32_t) result); + return result; } - contextRendering = false; + LOG_DEBUG("Native DLSS EvaluateFeature not available for handle {}", handleId); + return NVSDK_NGX_Result_FAIL_FeatureNotFound; } - LOG_DEBUG("Upscaling done: {}", evalResult); + // Nukem's DLSSG mod passthrough + if (state.activeFgInput == FGInput::Nukems && handleId >= DLSSG_MOD_ID_OFFSET) + { + LOG_DEBUG("Passthrough to Nukem's DLSSG EvaluateFeature for handle {}", handleId); + return DLSSGMod::D3D12_EvaluateFeature(InCmdList, InFeatureHandle, InParameters, InCallback); + } - return methodResult; + // OptiScaler internal handling + return TryEvaluateOptiFeature(InCmdList, InFeatureHandle, InParameters, InCallback); } #pragma endregion #pragma region DLSS Buffer Size Call -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, - const NVSDK_NGX_Parameter* InParameters, - size_t* OutSizeInBytes) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetScratchBufferSize( + NVSDK_NGX_Feature InFeatureId, + const NVSDK_NGX_Parameter* InParameters, + size_t* OutSizeInBytes) { if (OutSizeInBytes == nullptr) return NVSDK_NGX_Result_FAIL_InvalidParameter; From 0b57bf2a1d3cec623d83630276e61538e70b599a Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Tue, 3 Feb 2026 22:27:48 -0500 Subject: [PATCH 2/8] Fix: Correct NGX Parameter table lifetime and deallocation Problem: The previous implementation incorrectly used C-style free() on NVSDK_NGX_Parameter objects within the DLSS feature providers. This was unsafe for several reasons: - Non-trivial types: These structs often contain internal data/tables that free() does not account for, bypassing necessary destructors. - Ambiguous ownership: Tables were inconsistently sourced from internal allocations (OptiScaler), external NGX API calls, or legacy persistent pointers. - Heap/Stack corruption: Using free() on memory managed by the NGX API or on stack-allocated memory from legacy GetParameters() calls. This risked immediate crashes or heap instability. Solution: Introduced a tagging system to explicitly track memory ownership and determine the correct deallocation strategy. When a destruction request is made, the system now checks the table's tag and acts accordingly: 1. InternPersistent: Internal OptiScaler tables for legacy APIs. Lifetime is managed by the SDK; these persist until process exit. 2. InternDynamic: Internal tables explicitly created/destroyed by the client. Now correctly freed using delete with a static_cast to the implementation type. 3. NVPersistent: Native NGX legacy tables. These are ignored as the native SDK manages their lifetime. 4. NVDynamic: Native NGX modern tables. These are now properly forwarded to the native NGX DestroyParameters() function. --- OptiScaler/NVNGX_Parameter.h | 94 ++++++++- OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp | 48 +++-- OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp | 109 +++++----- OptiScaler/inputs/NVNGX_DLSS_Vk.cpp | 54 +++-- OptiScaler/upscalers/FeatureProvider_Dx11.cpp | 78 +++---- OptiScaler/upscalers/FeatureProvider_Dx12.cpp | 192 +++++++++--------- OptiScaler/upscalers/FeatureProvider_Dx12.h | 20 +- OptiScaler/upscalers/FeatureProvider_Vk.cpp | 72 ++++--- 8 files changed, 392 insertions(+), 275 deletions(-) diff --git a/OptiScaler/NVNGX_Parameter.h b/OptiScaler/NVNGX_Parameter.h index 42eb744ed..f67bb2ed2 100644 --- a/OptiScaler/NVNGX_Parameter.h +++ b/OptiScaler/NVNGX_Parameter.h @@ -1,8 +1,6 @@ #pragma once #include "SysUtils.h" - #include "Config.h" - #include // Use real NVNGX params encapsulated in custom one @@ -18,6 +16,24 @@ #define LOG_PARAM(msg, ...) #endif +/** @brief Indicates the lifetime management required by an NGX parameter table. */ +namespace NGX_AllocTypes +{ + // Key used to get/set enum from table + constexpr std::string_view AllocKey = "OptiScaler.ParamAllocType"; + + constexpr uint32_t Unknown = 0; + // Standard behavior in modern DLSS. Created with NGX Allocate(). Freed with Destroy(). + constexpr uint32_t NVDynamic = 1; + // Legacy DLSS. Lifetime managed internally by the SDK. + constexpr uint32_t NVPersistent = 2; + // OptiScaler implementation used internally with new/delete. + constexpr uint32_t InternDynamic = 3; + // OptiScaler implementation for legacy applications. Must maintain a persistent instance + // for the lifetime of the application. + constexpr uint32_t InternPersistent = 4; +} + /// @brief Calculates the resolution scaling ratio override based on the provided quality level and current /// configuration. /// @param input The performance quality value (e.g. Quality, Balanced, Performance). @@ -670,6 +686,17 @@ struct NVNGX_Parameters : public NVSDK_NGX_Parameter { std::string Name; + NVNGX_Parameters(std::string_view name, bool isPersistent) : + Name(name) + { + // Old flag used to indicate custom table. Obsolete? + Set("OptiScaler", 1); + // New tracking flag + Set(NGX_AllocTypes::AllocKey.data(), isPersistent ? + NGX_AllocTypes::InternPersistent : + NGX_AllocTypes::InternDynamic); + } + #ifdef ENABLE_ENCAPSULATED_PARAMS NVSDK_NGX_Parameter* OriginalParam = nullptr; #endif // ENABLE_ENCAPSULATED_PARAMS @@ -981,13 +1008,64 @@ struct NVNGX_Parameters : public NVSDK_NGX_Parameter } }; -/// @brief Allocates and populates a new NGX param map. -inline static NVNGX_Parameters* GetNGXParameters(std::string InName) +/** + * @brief Allocates and populates a new custom NGX param map. The persistence flag indicates + * whether the table should be destroyed when NGX DestroyParameters() is used. + */ +inline static NVNGX_Parameters* GetNGXParameters(std::string_view name, bool isPersistent) { - auto params = new NVNGX_Parameters(); - params->Name = InName; + auto params = new NVNGX_Parameters(name, isPersistent); InitNGXParameters(params); - params->Set("OptiScaler", 1); - return params; } + +/** + * @brief Sets a custom tracking tag to indicate the memory management strategy required by + * the table, indicated by NGX_AllocTypes. + */ +inline static void SetNGXParamAllocType(NVSDK_NGX_Parameter& params, uint32_t allocType) +{ + params.Set(NGX_AllocTypes::AllocKey.data(), allocType); +} + +/** + * @brief Attempts to safely delete an NGX parameter table. Dynamically allocated NGX tables use the NGX API. + * OptiScaler tables use delete. Persistent tables are not freed. + */ +template +static inline bool TryDestroyNGXParameters(NVSDK_NGX_Parameter* InParameters, PFN_DestroyNGXParameters NVFree = nullptr) +{ + if (InParameters == nullptr) + return false; + + uint32_t allocType = NGX_AllocTypes::Unknown; + NVSDK_NGX_Result result = InParameters->Get(NGX_AllocTypes::AllocKey.data(), &allocType); + + // Key not set. Either a bug, or the client application called Reset() on the table before destroying. + // Derived type unknown if this happens. Not safe to delete. Leaking is the best option. + if (result == NVSDK_NGX_Result_Fail) + { + LOG_WARN("Destroy called on NGX table with unset alloc type. Leaking."); + return false; + } + + if (allocType == NGX_AllocTypes::NVDynamic) + { + if (NVFree != nullptr) + { + LOG_INFO("Calling NVFree"); + result = NVFree(InParameters); + LOG_INFO("Calling NVFree result: {0:X}", (UINT) result); + return true; + } + else + return false; + } + else if (allocType == NGX_AllocTypes::InternDynamic) + { + delete static_cast(InParameters); + return true; + } + + return false; +} diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp index f59957bcc..04650c8d5 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp @@ -253,6 +253,12 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_Shutdown1(ID3D11Device* InDevice) #pragma region NVSDK_NGX_D3D11 Parameters +/** + * @brief [Deprecated NGX API] Superceeded by NVSDK_NGX_AllocateParameters and NVSDK_NGX_GetCapabilityParameters. + * + * Retrieves a common NVSDK parameter map for providing params to the SDK. The lifetime of this + * map is NOT managed by the application. It is expected to be managed internally by the SDK. + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_GetParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -272,14 +278,24 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_GetParameters(NVSDK_NGX_Parameter if (result == NVSDK_NGX_Result_Success) { InitNGXParameters(*OutParameters); + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVPersistent); return result; } } - *OutParameters = GetNGXParameters("OptiDx11"); + // Get custom parameters if using custom backend + static NVNGX_Parameters oldParams = NVNGX_Parameters("OptiDx11", true); + *OutParameters = &oldParams; + InitNGXParameters(*OutParameters); + return NVSDK_NGX_Result_Success; } +/** + * @brief Allocates a new NVSDK parameter map pre-populated with NGX capabilities and information about available + * features. The output parameter map may also be used in the same ways as a parameter map allocated with + * AllocateParameters(). The lifetime of this map is managed by the calling application with DestroyParameters(). + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -299,15 +315,21 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_GetCapabilityParameters(NVSDK_NGX if (result == NVSDK_NGX_Result_Success) { InitNGXParameters(*OutParameters); + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVDynamic); return result; } } - *OutParameters = GetNGXParameters("OptiDx11"); + *OutParameters = new NVNGX_Parameters("OptiDx11", false); + InitNGXParameters(*OutParameters); return NVSDK_NGX_Result_Success; } +/** + * @brief Allocates a new parameter map used to provide parameters needed by the DLSS API. The lifetime of this map + * is managed by the calling application with DestroyParameters(). + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_AllocateParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -322,12 +344,14 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_AllocateParameters(NVSDK_NGX_Para LOG_INFO("calling NVNGXProxy::D3D11_AllocateParameters result: {0:X}", (UINT) result); if (result == NVSDK_NGX_Result_Success) + { + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVDynamic); return result; + } } - auto params = new NVNGX_Parameters(); - params->Name = "OptiDx11"; - *OutParameters = params; + *OutParameters = new NVNGX_Parameters("OptiDx11", false); + InitNGXParameters(*OutParameters); return NVSDK_NGX_Result_Success; } @@ -351,19 +375,9 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_DestroyParameters(NVSDK_NGX_Param if (InParameters == nullptr) return NVSDK_NGX_Result_Fail; - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && - NVNGXProxy::D3D11_DestroyParameters() != nullptr) - { - LOG_INFO("calling NVNGXProxy::D3D11_DestroyParameters"); - auto result = NVNGXProxy::D3D11_DestroyParameters()(InParameters); - LOG_INFO("calling NVNGXProxy::D3D11_DestroyParameters result: {0:X}", (UINT) result); - - return result; - } + const bool success = TryDestroyNGXParameters(InParameters, NVNGXProxy::D3D11_DestroyParameters()); - delete InParameters; - - return NVSDK_NGX_Result_Success; + return success ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail; } NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp index e7332073e..d3848b979 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp @@ -58,6 +58,11 @@ static bool contextRendering = false; static std::shared_mutex computeSigatureMutex; static std::shared_mutex graphSigatureMutex; +static bool GetIsDlssModuleInited() +{ + return Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited(); +} + static void hkSetComputeRootSignature(ID3D12GraphicsCommandList* commandList, ID3D12RootSignature* pRootSignature) { if (Config::Instance()->RestoreComputeSignature.value_or_default() && !contextRendering && commandList != nullptr && @@ -430,16 +435,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Shutdown1(ID3D12Device* InDevice) #pragma region DLSS Parameter Calls -/** - * @brief Allocates and populates a preexisting NGX param map. - */ -static void GetNGXParameters(std::string InName, NVNGX_Parameters& params) -{ - params.Name = InName; - InitNGXParameters(¶ms); - params.Set("OptiScaler", 1); -} - /** * @brief [Deprecated NGX API] Superceeded by NVSDK_NGX_AllocateParameters and NVSDK_NGX_GetCapabilityParameters. * @@ -454,8 +449,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetParameters(NVSDK_NGX_Parameter return NVSDK_NGX_Result_FAIL_InvalidParameter; // If DLSS is enabled and the real DLSS module is loaded, get native NGX table - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && - NVNGXProxy::D3D12_GetParameters() != nullptr) + if (GetIsDlssModuleInited() && NVNGXProxy::D3D12_GetParameters() != nullptr) { LOG_INFO("Calling NVNGXProxy::D3D12_GetParameters"); auto result = NVNGXProxy::D3D12_GetParameters()(OutParameters); @@ -466,14 +460,15 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetParameters(NVSDK_NGX_Parameter if (result == NVSDK_NGX_Result_Success) { InitNGXParameters(*OutParameters); + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVPersistent); return NVSDK_NGX_Result_Success; } } // Get custom parameters if using custom backend - static NVNGX_Parameters oldParams = NVNGX_Parameters(); - GetNGXParameters("OptiDx12", oldParams); + static NVNGX_Parameters oldParams = NVNGX_Parameters("OptiDx12", true); *OutParameters = &oldParams; + InitNGXParameters(*OutParameters); return NVSDK_NGX_Result_Success; } @@ -491,8 +486,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX return NVSDK_NGX_Result_FAIL_InvalidParameter; // Get native DLSS params if DLSS is enabled and the module is loaded - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && - NVNGXProxy::IsDx12Inited() && NVNGXProxy::D3D12_GetCapabilityParameters() != nullptr) + if (GetIsDlssModuleInited() && NVNGXProxy::IsDx12Inited() && NVNGXProxy::D3D12_GetCapabilityParameters() != nullptr) { LOG_INFO("Calling NVNGXProxy::D3D12_GetCapabilityParameters"); auto result = NVNGXProxy::D3D12_GetCapabilityParameters()(OutParameters); @@ -501,14 +495,16 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX if (result == NVSDK_NGX_Result_Success) { + // Init external NGX table with current configuration and mark as dynamic+external InitNGXParameters(*OutParameters); + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVDynamic); return NVSDK_NGX_Result_Success; } } // Get custom parameters if using custom backend - auto& params = *(new NVNGX_Parameters()); - GetNGXParameters("OptiDx12", params); + auto& params = *(new NVNGX_Parameters("OptiDx12", false)); + InitNGXParameters(¶ms); *OutParameters = ¶ms; return NVSDK_NGX_Result_Success; @@ -522,20 +518,22 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_AllocateParameters(NVSDK_NGX_Para { LOG_FUNC(); - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && - NVNGXProxy::D3D12_AllocateParameters() != nullptr) + if (GetIsDlssModuleInited() && NVNGXProxy::D3D12_AllocateParameters() != nullptr) { LOG_INFO("Calling NVNGXProxy::D3D12_AllocateParameters"); auto result = NVNGXProxy::D3D12_AllocateParameters()(OutParameters); + LOG_INFO("Calling NVNGXProxy::D3D12_AllocateParameters result: {0:X}, ptr: {1:X}", (UINT) result, (UINT64) *OutParameters); if (result == NVSDK_NGX_Result_Success) + { + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVDynamic); return result; + } } - auto* params = new NVNGX_Parameters(); - params->Name = "OptiDx12"; + auto* params = new NVNGX_Parameters("OptiDx12", false); *OutParameters = params; return NVSDK_NGX_Result_Success; @@ -558,7 +556,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_PopulateParameters_Impl(NVSDK_NGX /** * @brief Destroys a given input parameter map created with AllocateParameters or GetCapabilityParameters. - Must not be called on maps returned by GetParameters(). + Must not be called on maps returned by GetParameters(). Unsupported tables will not be freed. */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_DestroyParameters(NVSDK_NGX_Parameter* InParameters) { @@ -567,28 +565,22 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_DestroyParameters(NVSDK_NGX_Param if (InParameters == nullptr) return NVSDK_NGX_Result_Fail; - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && - NVNGXProxy::D3D12_DestroyParameters() != nullptr) - { - LOG_INFO("Calling NVNGXProxy::D3D12_DestroyParameters"); - auto result = NVNGXProxy::D3D12_DestroyParameters()(InParameters); - LOG_INFO("Calling NVNGXProxy::D3D12_DestroyParameters result: {0:X}", (UINT) result); - UpscalerInputsDx12::Reset(); + const bool isUsingDlss = Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule(); + const bool success = TryDestroyNGXParameters(InParameters, NVNGXProxy::D3D12_DestroyParameters()); - return NVSDK_NGX_Result_Success; - } + if (isUsingDlss) + UpscalerInputsDx12::Reset(); - delete InParameters; - return NVSDK_NGX_Result_Success; + return success ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail; } #pragma endregion #pragma region DLSS Feature Calls -static std::string GetUpscalerBackend() +static std::string_view GetUpscalerBackend() { - std::string name = "xess"; // Default + std::string_view name = "xess"; // Default if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited()) name = "dlss"; @@ -690,7 +682,8 @@ static NVSDK_NGX_Result TryCreateOptiFeature( Dx12Contexts[handleId] = {}; // Retrieve feature implementation - if (!FeatureProvider_Dx12::GetFeature(featureName, handleId, InParameters, &Dx12Contexts[handleId].feature)) + if (!FeatureProvider_Dx12::GetFeature(featureName, handleId, + InParameters, &Dx12Contexts[handleId].feature)) { LOG_ERROR("Failed to retrieve feature implementation for '{}'", featureName); @@ -715,7 +708,7 @@ static NVSDK_NGX_Result TryCreateOptiFeature( if (shouldRestore) contextRendering = false; - // Partial cleanup – handle is allocated but context is incomplete + // Partial cleanup � handle is allocated but context is incomplete Dx12Contexts.erase(handleId); return NVSDK_NGX_Result_Fail; } @@ -962,6 +955,7 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( const uint32_t handleId = InFeatureHandle->Id; auto ctxIt = Dx12Contexts.find(handleId); + if (ctxIt == Dx12Contexts.end()) { LOG_WARN("No context found for handle {}", handleId); @@ -971,17 +965,10 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( ContextData& ctxData = ctxIt->second; IFeature_Dx12* feature = ctxData.feature.get(); - if (!feature) - { - LOG_WARN("Feature pointer is null for handle {}", handleId); - return NVSDK_NGX_Result_FAIL_FeatureNotFound; - } - - // Prevent API name flicker (e.g., during backend transitions or DLSSG) - if (state.setInputApiName == state.currentInputApiName) - state.setInputApiName.clear(); + if (feature == nullptr) // Prevent source api name flicker when dlssg is active + state.setInputApiName = state.currentInputApiName; - const std::string_view targetApiName = state.setInputApiName.empty() ? "DLSS" : state.setInputApiName; + const std::string_view targetApiName = state.setInputApiName.empty() ? "DLSS" : state.setInputApiName.c_str(); if (state.currentInputApiName != targetApiName) state.currentInputApiName = targetApiName; @@ -997,27 +984,25 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( LOG_INFO("Progress callback provided but unused in synchronous OptiScaler path"); // Resolution change detection (only for upscalers that may require recreation) - const bool isFSR31OrLater = feature->Name().starts_with("FSR") && feature->Version() >= feature_version { 3, 1, 0 }; + if (feature != nullptr) + { + const bool isFSR31OrLater = feature->Name().starts_with("FSR") && feature->Version() >= feature_version { 3, 1, 0 }; - if (!isFSR31OrLater && feature->UpdateOutputResolution(InParameters)) - state.changeBackend[handleId] = true; + // FSR 3.1 supports upscaleSize that doesn't need reinit to change output resolution + if (!isFSR31OrLater && feature->UpdateOutputResolution(InParameters)) + state.changeBackend[handleId] = true; + } // Backend change or recreation requested - if (state.changeBackend.contains(handleId) && state.changeBackend[handleId]) + if (state.changeBackend[handleId]) { - LOG_INFO("Performing backend change/recreation for handle {} to '{}'", handleId, state.newBackend); - UpscalerInputsDx12::Reset(); contextRendering = false; - FeatureProvider_Dx12::ChangeFeature(state.newBackend, D3D12Device, InCmdList, handleId, InParameters, &ctxData); + FeatureProvider_Dx12::ChangeFeature(state.newBackend, D3D12Device, + InCmdList, handleId, InParameters, &ctxData); feature = ctxData.feature.get(); - state.changeBackend.erase(handleId); - - if (!state.newBackend.empty()) - state.newBackend.clear(); - evalCounter = 0; return NVSDK_NGX_Result_Success; } @@ -1032,7 +1017,7 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( } state.currentFeature = feature; - + // Root signature restoration setup const bool restoreCompute = cfg.RestoreComputeSignature.value_or_default(); const bool restoreGraphic = cfg.RestoreGraphicSignature.value_or_default(); @@ -1101,7 +1086,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature( } const uint32_t handleId = InFeatureHandle->Id; - LOG_DEBUG("EvaluateFeature - Handle: {}, CmdList: {:p}", handleId, (void*) InCmdList); + LOG_DEBUG("Handle: {}, CmdList: {:p}", handleId, (void*) InCmdList); const State& state = State::Instance(); const Config& cfg = *Config::Instance(); diff --git a/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp b/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp index ac3b28ed8..49c21663a 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Vk.cpp @@ -308,6 +308,12 @@ NVSDK_NGX_VULKAN_Init_ProjectID(const char* InProjectId, NVSDK_NGX_EngineType In InInstance, InPD, InDevice, InGIPA, InGDPA, InSDKVersion, InFeatureInfo); } +/** + * @brief [Deprecated NGX API] Superceeded by NVSDK_NGX_AllocateParameters and NVSDK_NGX_GetCapabilityParameters. + * + * Retrieves a common NVSDK parameter map for providing params to the SDK. The lifetime of this + * map is NOT managed by the application. It is expected to be managed internally by the SDK. + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_GetParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -325,11 +331,16 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_GetParameters(NVSDK_NGX_Paramete if (result == NVSDK_NGX_Result_Success) { InitNGXParameters(*OutParameters); + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVPersistent); return result; } } - *OutParameters = GetNGXParameters("OptiVk"); + // Get custom parameters if using custom backend + static NVNGX_Parameters oldParams = NVNGX_Parameters("OptiVk", true); + *OutParameters = &oldParams; + InitNGXParameters(*OutParameters); + return NVSDK_NGX_Result_Success; } @@ -506,6 +517,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_GetFeatureDeviceExtensionRequire return NVSDK_NGX_Result_Success; } +/** + * @brief Allocates a new parameter map used to provide parameters needed by the DLSS API. The lifetime of this map + * is managed by the calling application with DestroyParameters(). + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_AllocateParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -518,11 +533,13 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_AllocateParameters(NVSDK_NGX_Par LOG_INFO("NVNGXProxy::VULKAN_AllocateParameters result: {0:X}", (UINT) result); if (result == NVSDK_NGX_Result_Success) + { + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVDynamic); return result; + } } - auto params = new NVNGX_Parameters(); - params->Name = "OptiVk"; + auto* params = new NVNGX_Parameters("OptiVk", false); *OutParameters = params; return NVSDK_NGX_Result_Success; @@ -576,6 +593,11 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_GetFeatureRequirements( return NVSDK_NGX_Result_FAIL_FeatureNotSupported; } +/** + * @brief Allocates a new NVSDK parameter map pre-populated with NGX capabilities and information about available + * features. The output parameter map may also be used in the same ways as a parameter map allocated with + * AllocateParameters(). The lifetime of this map is managed by the calling application with DestroyParameters(). + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters) { LOG_FUNC(); @@ -592,12 +614,17 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_GetCapabilityParameters(NVSDK_NG if (result == NVSDK_NGX_Result_Success) { + // Init external NGX table with current configuration and mark as dynamic+external InitNGXParameters(*OutParameters); + SetNGXParamAllocType(*(*OutParameters), NGX_AllocTypes::NVDynamic); return result; } } - *OutParameters = GetNGXParameters("OptiVk"); + // Get custom parameters if using custom backend + auto& params = *(new NVNGX_Parameters("OptiVk", false)); + InitNGXParameters(¶ms); + *OutParameters = ¶ms; return NVSDK_NGX_Result_Success; } @@ -616,6 +643,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_PopulateParameters_Impl(NVSDK_NG return NVSDK_NGX_Result_Success; } +/** + * @brief Destroys a given input parameter map created with AllocateParameters or GetCapabilityParameters. + Must not be called on maps returned by GetParameters(). Unsupported tables will not be freed. + */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_DestroyParameters(NVSDK_NGX_Parameter* InParameters) { LOG_FUNC(); @@ -623,20 +654,9 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_DestroyParameters(NVSDK_NGX_Para if (InParameters == nullptr) return NVSDK_NGX_Result_Fail; - if (Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::NVNGXModule() != nullptr && - NVNGXProxy::VULKAN_DestroyParameters() != nullptr) - { - LOG_INFO("calling NVNGXProxy::VULKAN_DestroyParameters"); - auto result = NVNGXProxy::VULKAN_DestroyParameters()(InParameters); - LOG_INFO("calling NVNGXProxy::VULKAN_DestroyParameters result: {0:X}", (UINT) result); - - return result; - } + const bool success = TryDestroyNGXParameters(InParameters, NVNGXProxy::VULKAN_DestroyParameters()); - delete InParameters; - InParameters = nullptr; - - return NVSDK_NGX_Result_Success; + return success ? NVSDK_NGX_Result_Success : NVSDK_NGX_Result_Fail; } NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_VULKAN_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, diff --git a/OptiScaler/upscalers/FeatureProvider_Dx11.cpp b/OptiScaler/upscalers/FeatureProvider_Dx11.cpp index caa503218..8759f68a9 100644 --- a/OptiScaler/upscalers/FeatureProvider_Dx11.cpp +++ b/OptiScaler/upscalers/FeatureProvider_Dx11.cpp @@ -19,6 +19,9 @@ bool FeatureProvider_Dx11::GetFeature(std::string upscalerName, UINT handleId, NVSDK_NGX_Parameter* parameters, std::unique_ptr* feature) { + State& state = State::Instance(); + Config& cfg = *Config::Instance(); + do { if (upscalerName == "xess") @@ -57,14 +60,14 @@ bool FeatureProvider_Dx11::GetFeature(std::string upscalerName, UINT handleId, N break; } - if (Config::Instance()->DLSSEnabled.value_or_default()) + if (cfg.DLSSEnabled.value_or_default()) { - if (upscalerName == "dlss" && State::Instance().NVNGX_DLSS_Path.has_value()) + if (upscalerName == "dlss" && state.NVNGX_DLSS_Path.has_value()) { *feature = std::make_unique(handleId, parameters); break; } - else if (upscalerName == "dlssd" && State::Instance().NVNGX_DLSSD_Path.has_value()) + else if (upscalerName == "dlssd" && state.NVNGX_DLSSD_Path.has_value()) { *feature = std::make_unique(handleId, parameters); break; @@ -89,7 +92,7 @@ bool FeatureProvider_Dx11::GetFeature(std::string upscalerName, UINT handleId, N } else { - Config::Instance()->Dx11Upscaler = upscalerName; + cfg.Dx11Upscaler = upscalerName; } auto result = (*feature)->ModuleLoaded(); @@ -99,19 +102,25 @@ bool FeatureProvider_Dx11::GetFeature(std::string upscalerName, UINT handleId, N if (upscalerName == "dlssd") upscalerName = "dlss"; - Config::Instance()->Dx11Upscaler = upscalerName; + cfg.Dx11Upscaler = upscalerName; } return result; } -bool FeatureProvider_Dx11::ChangeFeature(std::string upscalerName, ID3D11Device* device, - ID3D11DeviceContext* devContext, UINT handleId, - NVSDK_NGX_Parameter* parameters, ContextData* contextData) +bool FeatureProvider_Dx11::ChangeFeature( + std::string upscalerName, + ID3D11Device* device, + ID3D11DeviceContext* devContext, + UINT handleId, + NVSDK_NGX_Parameter* parameters, + ContextData* contextData) { - if (State::Instance().newBackend == "" || - (!Config::Instance()->DLSSEnabled.value_or_default() && State::Instance().newBackend == "dlss")) - State::Instance().newBackend = Config::Instance()->Dx11Upscaler.value_or_default(); + State& state = State::Instance(); + Config& cfg = *Config::Instance(); + + if (state.newBackend == "" || (!cfg.DLSSEnabled.value_or_default() && state.newBackend == "dlss")) + state.newBackend = cfg.Dx11Upscaler.value_or_default(); contextData->changeBackendCounter++; @@ -120,15 +129,14 @@ bool FeatureProvider_Dx11::ChangeFeature(std::string upscalerName, ID3D11Device* { if (contextData->feature != nullptr) { - LOG_INFO("changing backend to {0}", State::Instance().newBackend); + LOG_INFO("changing backend to {0}", state.newBackend); - auto dc = contextData->feature.get(); - - if (State::Instance().newBackend != "dlssd" && State::Instance().newBackend != "dlss") - contextData->createParams = GetNGXParameters("OptiDx11"); - else - contextData->createParams = parameters; + auto* dc = contextData->feature.get(); + // Use given params if using DLSS passthrough + const std::string_view backend = state.newBackend; + const bool isPassthrough = backend == "dlssd" || backend == "dlss"; + contextData->createParams = isPassthrough ? parameters : GetNGXParameters("OptiDx11", false); contextData->createParams->Set(NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, dc->GetFeatureFlags()); contextData->createParams->Set(NVSDK_NGX_Parameter_Width, dc->RenderWidth()); contextData->createParams->Set(NVSDK_NGX_Parameter_Height, dc->RenderHeight()); @@ -148,12 +156,12 @@ bool FeatureProvider_Dx11::ChangeFeature(std::string upscalerName, ID3D11Device* { LOG_ERROR("can't find handle {0} in Dx11Contexts!", handleId); - State::Instance().newBackend = ""; - State::Instance().changeBackend[handleId] = false; + state.newBackend = ""; + state.changeBackend[handleId] = false; if (contextData->createParams != nullptr) { - free(contextData->createParams); + TryDestroyNGXParameters(contextData->createParams, NVNGXProxy::D3D11_DestroyParameters()); contextData->createParams = nullptr; } @@ -165,11 +173,11 @@ bool FeatureProvider_Dx11::ChangeFeature(std::string upscalerName, ID3D11Device* if (contextData->changeBackendCounter == 2) { - LOG_INFO("Creating new {} upscaler", State::Instance().newBackend); + LOG_INFO("Creating new {} upscaler", state.newBackend); contextData->feature.reset(); - if (!GetFeature(State::Instance().newBackend, handleId, contextData->createParams, &contextData->feature)) + if (!GetFeature(state.newBackend, handleId, contextData->createParams, &contextData->feature)) { LOG_ERROR("Upscaler can't created"); return false; @@ -183,7 +191,7 @@ bool FeatureProvider_Dx11::ChangeFeature(std::string upscalerName, ID3D11Device* // then init and continue auto initResult = contextData->feature->Init(device, devContext, contextData->createParams); - if (Config::Instance()->Dx11DelayedInit.value_or_default()) + if (cfg.Dx11DelayedInit.value_or_default()) { LOG_TRACE("sleeping after new Init of new feature for 1000ms"); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); @@ -193,39 +201,39 @@ bool FeatureProvider_Dx11::ChangeFeature(std::string upscalerName, ID3D11Device* if (!initResult || !contextData->feature->ModuleLoaded()) { - LOG_ERROR("init failed with {0} feature", State::Instance().newBackend); + LOG_ERROR("init failed with {0} feature", state.newBackend); - if (State::Instance().newBackend != "dlssd") + if (state.newBackend != "dlssd") { - State::Instance().newBackend = "fsr22"; - State::Instance().changeBackend[handleId] = true; + state.newBackend = "fsr22"; + state.changeBackend[handleId] = true; } else { - State::Instance().newBackend = ""; - State::Instance().changeBackend[handleId] = false; + state.newBackend = ""; + state.changeBackend[handleId] = false; return false; } } else { - LOG_INFO("init successful for {0}, upscaler changed", State::Instance().newBackend); + LOG_INFO("init successful for {0}, upscaler changed", state.newBackend); - State::Instance().newBackend = ""; - State::Instance().changeBackend[handleId] = false; + state.newBackend = ""; + state.changeBackend[handleId] = false; } // if opti nvparam release it int optiParam = 0; if (contextData->createParams->Get("OptiScaler", &optiParam) == NVSDK_NGX_Result_Success && optiParam == 1) { - free(contextData->createParams); + TryDestroyNGXParameters(contextData->createParams, NVNGXProxy::D3D11_DestroyParameters()); contextData->createParams = nullptr; } } // if initial feature can't be inited - State::Instance().currentFeature = contextData->feature.get(); + state.currentFeature = contextData->feature.get(); return true; } diff --git a/OptiScaler/upscalers/FeatureProvider_Dx12.cpp b/OptiScaler/upscalers/FeatureProvider_Dx12.cpp index 49d651148..c84758e25 100644 --- a/OptiScaler/upscalers/FeatureProvider_Dx12.cpp +++ b/OptiScaler/upscalers/FeatureProvider_Dx12.cpp @@ -1,4 +1,4 @@ -#include +#include "pch.h" #include "FeatureProvider_Dx12.h" #include "Util.h" @@ -14,92 +14,92 @@ #include "upscalers/xess/XeSSFeature_Dx12.h" #include "FeatureProvider_Dx11.h" -bool FeatureProvider_Dx12::GetFeature(std::string upscalerName, UINT handleId, NVSDK_NGX_Parameter* parameters, - std::unique_ptr* feature) +bool FeatureProvider_Dx12::GetFeature( + std::string_view upscalerName, + UINT handleId, + NVSDK_NGX_Parameter* parameters, + std::unique_ptr* feature) { + State& state = State::Instance(); + Config& cfg = *Config::Instance(); ScopedSkipHeapCapture skipHeapCapture {}; + std::string_view config_upscaler(upscalerName); - do + if (upscalerName == "xess") { - if (upscalerName == "xess") - { - *feature = std::make_unique(handleId, parameters); - break; - } - else if (upscalerName == "fsr21") - { - *feature = std::make_unique(handleId, parameters); - break; - } - else if (upscalerName == "fsr22") + *feature = std::make_unique(handleId, parameters); + } + else if (upscalerName == "fsr21") + { + *feature = std::make_unique(handleId, parameters); + } + else if (upscalerName == "fsr22") + { + *feature = std::make_unique(handleId, parameters); + } + else if (upscalerName == "fsr31") + { + *feature = std::make_unique(handleId, parameters); + } + else if (cfg.DLSSEnabled.value_or_default()) + { + if (upscalerName == "dlss" && state.NVNGX_DLSS_Path.has_value()) { - *feature = std::make_unique(handleId, parameters); - break; + *feature = std::make_unique(handleId, parameters); } - else if (upscalerName == "fsr31") + else if (upscalerName == "dlssd" && state.NVNGX_DLSSD_Path.has_value()) { - *feature = std::make_unique(handleId, parameters); - break; - } - - if (Config::Instance()->DLSSEnabled.value_or_default()) - { - if (upscalerName == "dlss" && State::Instance().NVNGX_DLSS_Path.has_value()) - { - *feature = std::make_unique(handleId, parameters); - break; - } - else if (upscalerName == "dlssd" && State::Instance().NVNGX_DLSSD_Path.has_value()) - { - *feature = std::make_unique(handleId, parameters); - break; - } - else - { - *feature = std::make_unique(handleId, parameters); - } + *feature = std::make_unique(handleId, parameters); } else { *feature = std::make_unique(handleId, parameters); + config_upscaler = "fsr21"; } - - } while (false); - - if (!(*feature)->ModuleLoaded()) - { - (*feature).reset(); - *feature = std::make_unique(handleId, parameters); - upscalerName = "fsr21"; } else { - Config::Instance()->Dx12Upscaler = upscalerName; + *feature = std::make_unique(handleId, parameters); + config_upscaler = "fsr21"; } - auto result = (*feature)->ModuleLoaded(); + bool loaded = (*feature)->ModuleLoaded(); - if (result) + if (!loaded) { - if (upscalerName == "dlssd") - upscalerName = "dlss"; - - Config::Instance()->Dx12Upscaler = upscalerName; + *feature = std::make_unique(handleId, parameters); + config_upscaler = "fsr21"; + loaded = true; // Assuming the fallback always loads successfully } - return result; + // Handle display name normalization for DLSSD + if (config_upscaler == "dlssd") + config_upscaler = "dlss"; + + cfg.Dx12Upscaler = std::string(config_upscaler); + + return loaded; } -bool FeatureProvider_Dx12::ChangeFeature(std::string upscalerName, ID3D12Device* device, - ID3D12GraphicsCommandList* cmdList, UINT handleId, - NVSDK_NGX_Parameter* parameters, ContextData* contextData) +bool FeatureProvider_Dx12::ChangeFeature( + std::string_view upscalerName, + ID3D12Device* device, + ID3D12GraphicsCommandList* cmdList, + UINT handleId, + NVSDK_NGX_Parameter* parameters, + ContextData* contextData) { - if (!State::Instance().changeBackend[handleId]) + State& state = State::Instance(); + Config& cfg = *Config::Instance(); + + if (!state.changeBackend[handleId]) return false; - if (State::Instance().newBackend == "" || - (!Config::Instance()->DLSSEnabled.value_or_default() && State::Instance().newBackend == "dlss")) - State::Instance().newBackend = Config::Instance()->Dx12Upscaler.value_or_default(); + const bool isDlssBeingEnabled = !cfg.DLSSEnabled.value_or_default() && state.newBackend == "dlss"; + + // If no name or if dlss is being enabled use the configured upscaler name + if (state.newBackend == "" || isDlssBeingEnabled) + state.newBackend = cfg.Dx12Upscaler.value_or_default(); contextData->changeBackendCounter++; @@ -108,25 +108,24 @@ bool FeatureProvider_Dx12::ChangeFeature(std::string upscalerName, ID3D12Device* // first release everything if (contextData->changeBackendCounter == 1) { - if (State::Instance().currentFG != nullptr && State::Instance().currentFG->IsActive() && - State::Instance().activeFgInput == FGInput::Upscaler) + if (state.currentFG != nullptr && state.currentFG->IsActive() && + state.activeFgInput == FGInput::Upscaler) { - State::Instance().currentFG->DestroyFGContext(); - State::Instance().FGchanged = true; - State::Instance().ClearCapturedHudlesses = true; + state.currentFG->DestroyFGContext(); + state.FGchanged = true; + state.ClearCapturedHudlesses = true; } if (contextData->feature != nullptr) { - LOG_INFO("changing backend to {}", State::Instance().newBackend); - - auto dc = contextData->feature.get(); + LOG_INFO("changing backend to {}", state.newBackend); - if (State::Instance().newBackend != "dlssd" && State::Instance().newBackend != "dlss") - contextData->createParams = GetNGXParameters("OptiDx12"); - else - contextData->createParams = parameters; + auto* dc = contextData->feature.get(); + // Use given params if using DLSS passthrough + const std::string_view backend = state.newBackend; + const bool isPassthrough = backend == "dlssd" || backend == "dlss"; + contextData->createParams = isPassthrough ? parameters : GetNGXParameters("OptiDx12", false); contextData->createParams->Set(NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, dc->GetFeatureFlags()); contextData->createParams->Set(NVSDK_NGX_Parameter_Width, dc->RenderWidth()); contextData->createParams->Set(NVSDK_NGX_Parameter_Height, dc->RenderHeight()); @@ -138,7 +137,7 @@ bool FeatureProvider_Dx12::ChangeFeature(std::string upscalerName, ID3D12Device* State::Instance().currentFeature = nullptr; - if (State::Instance().gameQuirks & GameQuirk::FastFeatureReset) + if (state.gameQuirks & GameQuirk::FastFeatureReset) { LOG_DEBUG("sleeping before reset of current feature for 100ms (Fast Feature Reset)"); std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -152,16 +151,16 @@ bool FeatureProvider_Dx12::ChangeFeature(std::string upscalerName, ID3D12Device* contextData->feature.reset(); contextData->feature = nullptr; } - else + else // Clean up state if no feature is set { LOG_ERROR("can't find handle {0} in Dx12Contexts!", handleId); - State::Instance().newBackend = ""; - State::Instance().changeBackend[handleId] = false; + state.newBackend = ""; + state.changeBackend[handleId] = false; if (contextData->createParams != nullptr) { - free(contextData->createParams); + TryDestroyNGXParameters(contextData->createParams, NVNGXProxy::D3D12_DestroyParameters()); contextData->createParams = nullptr; } @@ -174,11 +173,10 @@ bool FeatureProvider_Dx12::ChangeFeature(std::string upscalerName, ID3D12Device* // create new feature if (contextData->changeBackendCounter == 2) { - LOG_INFO("Creating new {} upscaler", State::Instance().newBackend); - + LOG_INFO("Creating new {} upscaler", state.newBackend); contextData->feature.reset(); - if (!GetFeature(State::Instance().newBackend, handleId, contextData->createParams, &contextData->feature)) + if (!GetFeature(state.newBackend, handleId, contextData->createParams, &contextData->feature)) { LOG_ERROR("Upscaler can't created"); return false; @@ -196,45 +194,47 @@ bool FeatureProvider_Dx12::ChangeFeature(std::string upscalerName, ID3D12Device* if (!initResult) { - LOG_ERROR("init failed with {0} feature", State::Instance().newBackend); + LOG_ERROR("init failed with {0} feature", state.newBackend); - if (State::Instance().newBackend != "dlssd") + if (state.newBackend != "dlssd") { - if (Config::Instance()->Dx12Upscaler == "dlss") - State::Instance().newBackend = "xess"; + if (cfg.Dx12Upscaler == "dlss") + state.newBackend = "xess"; else - State::Instance().newBackend = "fsr21"; + state.newBackend = "fsr21"; } else { // Retry DLSSD - State::Instance().newBackend = "dlssd"; + state.newBackend = "dlssd"; } - State::Instance().changeBackend[handleId] = true; + state.changeBackend[handleId] = true; return NVSDK_NGX_Result_Success; } else { - LOG_INFO("init successful for {0}, upscaler changed", State::Instance().newBackend); + LOG_INFO("init successful for {0}, upscaler changed", state.newBackend); - State::Instance().newBackend = ""; - State::Instance().changeBackend[handleId] = false; + state.newBackend = ""; + state.changeBackend[handleId] = false; } - // if opti nvparam release it + // If this is an OptiScaler fake NVNGX param table, delete it int optiParam = 0; + if (contextData->createParams->Get("OptiScaler", &optiParam) == NVSDK_NGX_Result_Success && optiParam == 1) { - free(contextData->createParams); + TryDestroyNGXParameters(contextData->createParams, NVNGXProxy::D3D12_DestroyParameters()); contextData->createParams = nullptr; } } // if initial feature can't be inited - State::Instance().currentFeature = contextData->feature.get(); - if (State::Instance().currentFG != nullptr && State::Instance().activeFgInput == FGInput::Upscaler) - State::Instance().currentFG->UpdateTarget(); + state.currentFeature = contextData->feature.get(); + + if (state.currentFG != nullptr && state.activeFgInput == FGInput::Upscaler) + state.currentFG->UpdateTarget(); return true; } diff --git a/OptiScaler/upscalers/FeatureProvider_Dx12.h b/OptiScaler/upscalers/FeatureProvider_Dx12.h index 5d410748b..f427de1ba 100644 --- a/OptiScaler/upscalers/FeatureProvider_Dx12.h +++ b/OptiScaler/upscalers/FeatureProvider_Dx12.h @@ -1,17 +1,23 @@ #pragma once - #include "SysUtils.h" - #include "IFeature_Dx12.h" - #include class FeatureProvider_Dx12 { public: - static bool GetFeature(std::string upscalerName, UINT handleId, NVSDK_NGX_Parameter* parameters, - std::unique_ptr* feature); - static bool ChangeFeature(std::string upscalerName, ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, - UINT handleId, NVSDK_NGX_Parameter* parameters, ContextData* contextData); + static bool GetFeature( + std::string_view upscalerName, + UINT handleId, + NVSDK_NGX_Parameter* parameters, + std::unique_ptr* feature); + + static bool ChangeFeature( + std::string_view upscalerName, + ID3D12Device* device, + ID3D12GraphicsCommandList* cmdList, + UINT handleId, + NVSDK_NGX_Parameter* parameters, + ContextData* contextData); }; diff --git a/OptiScaler/upscalers/FeatureProvider_Vk.cpp b/OptiScaler/upscalers/FeatureProvider_Vk.cpp index 44b58aafa..0173a38fa 100644 --- a/OptiScaler/upscalers/FeatureProvider_Vk.cpp +++ b/OptiScaler/upscalers/FeatureProvider_Vk.cpp @@ -18,6 +18,9 @@ bool FeatureProvider_Vk::GetFeature(std::string upscalerName, UINT handleId, NVSDK_NGX_Parameter* parameters, std::unique_ptr* feature) { + State& state = State::Instance(); + Config& cfg = *Config::Instance(); + do { if (upscalerName == "xess") @@ -51,14 +54,14 @@ bool FeatureProvider_Vk::GetFeature(std::string upscalerName, UINT handleId, NVS break; } - if (Config::Instance()->DLSSEnabled.value_or_default()) + if (cfg.DLSSEnabled.value_or_default()) { - if (upscalerName == "dlss" && State::Instance().NVNGX_DLSS_Path.has_value()) + if (upscalerName == "dlss" && state.NVNGX_DLSS_Path.has_value()) { *feature = std::make_unique(handleId, parameters); break; } - else if (upscalerName == "dlssd" && State::Instance().NVNGX_DLSSD_Path.has_value()) + else if (upscalerName == "dlssd" && state.NVNGX_DLSSD_Path.has_value()) { *feature = std::make_unique(handleId, parameters); break; @@ -83,7 +86,7 @@ bool FeatureProvider_Vk::GetFeature(std::string upscalerName, UINT handleId, NVS } else { - Config::Instance()->VulkanUpscaler = upscalerName; + cfg.VulkanUpscaler = upscalerName; } auto result = (*feature)->ModuleLoaded(); @@ -93,7 +96,7 @@ bool FeatureProvider_Vk::GetFeature(std::string upscalerName, UINT handleId, NVS if (upscalerName == "dlssd") upscalerName = "dlss"; - Config::Instance()->VulkanUpscaler = upscalerName; + cfg.VulkanUpscaler = upscalerName; } return result; @@ -104,9 +107,12 @@ bool FeatureProvider_Vk::ChangeFeature(std::string upscalerName, VkInstance inst PFN_vkGetDeviceProcAddr gdpa, UINT handleId, NVSDK_NGX_Parameter* parameters, ContextData* contextData) { - if (State::Instance().newBackend == "" || - (!Config::Instance()->DLSSEnabled.value_or_default() && State::Instance().newBackend == "dlss")) - State::Instance().newBackend = Config::Instance()->VulkanUpscaler.value_or_default(); + State& state = State::Instance(); + Config& cfg = *Config::Instance(); + + if (state.newBackend == "" || + (!cfg.DLSSEnabled.value_or_default() && state.newBackend == "dlss")) + state.newBackend = cfg.VulkanUpscaler.value_or_default(); contextData->changeBackendCounter++; @@ -117,15 +123,14 @@ bool FeatureProvider_Vk::ChangeFeature(std::string upscalerName, VkInstance inst { if (contextData->feature != nullptr) { - LOG_INFO("changing backend to {0}", State::Instance().newBackend); + LOG_INFO("changing backend to {0}", state.newBackend); - auto dc = contextData->feature.get(); - - if (State::Instance().newBackend != "dlssd" && State::Instance().newBackend != "dlss") - contextData->createParams = GetNGXParameters("OptiVk"); - else - contextData->createParams = parameters; + auto* dc = contextData->feature.get(); + // Use given params if using DLSS passthrough + const std::string_view backend = state.newBackend; + const bool isPassthrough = backend == "dlssd" || backend == "dlss"; + contextData->createParams = isPassthrough ? parameters : GetNGXParameters("OptiVk", false); contextData->createParams->Set(NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, dc->GetFeatureFlags()); contextData->createParams->Set(NVSDK_NGX_Parameter_Width, dc->RenderWidth()); contextData->createParams->Set(NVSDK_NGX_Parameter_Height, dc->RenderHeight()); @@ -149,12 +154,12 @@ bool FeatureProvider_Vk::ChangeFeature(std::string upscalerName, VkInstance inst { LOG_ERROR("can't find handle {0} in VkContexts!", handleId); - State::Instance().newBackend = ""; - State::Instance().changeBackend[handleId] = false; + state.newBackend = ""; + state.changeBackend[handleId] = false; if (contextData->createParams != nullptr) { - free(contextData->createParams); + TryDestroyNGXParameters(contextData->createParams, NVNGXProxy::VULKAN_DestroyParameters()); contextData->createParams = nullptr; } @@ -166,11 +171,11 @@ bool FeatureProvider_Vk::ChangeFeature(std::string upscalerName, VkInstance inst if (contextData->changeBackendCounter == 2) { - LOG_INFO("Creating new {} upscaler", State::Instance().newBackend); + LOG_INFO("Creating new {} upscaler", state.newBackend); contextData->feature.reset(); - if (!GetFeature(State::Instance().newBackend, handleId, contextData->createParams, &contextData->feature)) + if (!GetFeature(state.newBackend, handleId, contextData->createParams, &contextData->feature)) { LOG_ERROR("Upscaler can't created"); return false; @@ -193,47 +198,48 @@ bool FeatureProvider_Vk::ChangeFeature(std::string upscalerName, VkInstance inst if (!initResult || !contextData->feature->ModuleLoaded()) { - LOG_ERROR("init failed with {0} feature", State::Instance().newBackend); + LOG_ERROR("init failed with {0} feature", state.newBackend); - if (State::Instance().newBackend != "dlssd") + if (state.newBackend != "dlssd") { - if (Config::Instance()->VulkanUpscaler == "dlss") + if (cfg.VulkanUpscaler == "dlss") { - State::Instance().newBackend = "xess"; + state.newBackend = "xess"; } else { - State::Instance().newBackend = "fsr21"; + state.newBackend = "fsr21"; } } else { // Retry DLSSD - State::Instance().newBackend = "dlssd"; + state.newBackend = "dlssd"; } - State::Instance().changeBackend[handleId] = true; + state.changeBackend[handleId] = true; return NVSDK_NGX_Result_Success; } else { - LOG_INFO("init successful for {0}, upscaler changed", State::Instance().newBackend); + LOG_INFO("init successful for {0}, upscaler changed", state.newBackend); - State::Instance().newBackend = ""; - State::Instance().changeBackend[handleId] = false; + state.newBackend = ""; + state.changeBackend[handleId] = false; } - // if opti nvparam release it + // If this is an OptiScaler fake NVNGX param table, delete it int optiParam = 0; + if (contextData->createParams->Get("OptiScaler", &optiParam) == NVSDK_NGX_Result_Success && optiParam == 1) { - free(contextData->createParams); + TryDestroyNGXParameters(contextData->createParams, NVNGXProxy::VULKAN_DestroyParameters()); contextData->createParams = nullptr; } } // if initial feature can't be inited - State::Instance().currentFeature = contextData->feature.get(); + state.currentFeature = contextData->feature.get(); return true; } From 2d4277472b2dd3eb69efd4b115d8ea5b010188dd Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Tue, 24 Feb 2026 01:17:33 -0500 Subject: [PATCH 3/8] Start gathering unique string literals in header - Started organizing string literals being used as unique identifiers for things like feature selection and parameter lookup into a dedicated header. Less error prone and actually works with intellisense. - The actual usages of these strings have yet to be replaced, but I am using them for new code. --- OptiScaler/Config.h | 6 ++-- OptiScaler/OptiScaler.vcxproj | 1 + OptiScaler/OptiScaler.vcxproj.filters | 3 ++ OptiScaler/OptiTexts.h | 52 +++++++++++++++++++++++++++ OptiScaler/SysUtils.h | 2 ++ 5 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 OptiScaler/OptiTexts.h diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h index 77fb6fd40..056a1078a 100644 --- a/OptiScaler/Config.h +++ b/OptiScaler/Config.h @@ -336,9 +336,9 @@ class Config CustomOptional DontCreateD3D12DeviceForLuma { false }; // Upscalers - CustomOptional Dx11Upscaler { "fsr22" }; - CustomOptional Dx12Upscaler { "xess" }; - CustomOptional VulkanUpscaler { "fsr22" }; + CustomOptional Dx11Upscaler { std::string(OptiKeys::FSR22) }; + CustomOptional Dx12Upscaler { std::string(OptiKeys::XeSS) }; + CustomOptional VulkanUpscaler { std::string(OptiKeys::FSR21) }; // Output Scaling CustomOptional OutputScalingEnabled { false }; diff --git a/OptiScaler/OptiScaler.vcxproj b/OptiScaler/OptiScaler.vcxproj index f58045672..9461b4e87 100644 --- a/OptiScaler/OptiScaler.vcxproj +++ b/OptiScaler/OptiScaler.vcxproj @@ -322,6 +322,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y + diff --git a/OptiScaler/OptiScaler.vcxproj.filters b/OptiScaler/OptiScaler.vcxproj.filters index 5db1dc524..fb14559ff 100644 --- a/OptiScaler/OptiScaler.vcxproj.filters +++ b/OptiScaler/OptiScaler.vcxproj.filters @@ -737,6 +737,9 @@ Header Files + + Header Files + diff --git a/OptiScaler/OptiTexts.h b/OptiScaler/OptiTexts.h new file mode 100644 index 000000000..8722bce30 --- /dev/null +++ b/OptiScaler/OptiTexts.h @@ -0,0 +1,52 @@ +#pragma once + +/** + * @brief Common strings and identifiers used internally by OptiScaler + */ +namespace OptiKeys +{ +using CString = const char[]; + +// Application name provided to upscalers +inline constexpr CString ProjectID = "OptiScaler"; + +// ID code used for the Vulkan input provider +inline constexpr CString VkProvider = "OptiVk"; +// ID code used for the DX11 input provider +inline constexpr CString Dx11Provider = "OptiDx11"; +// ID code used for the DX12 input provider +inline constexpr CString Dx12Provider = "OptiDx12"; + +// ID code used for the XeSS upscaler backend +inline constexpr CString XeSS = "xess"; +// ID code used for the XeSS upscaler backend used with the DirectX 11 on 12 compatibility layer +inline constexpr CString XeSS_11on12 = "xess_12"; +// ID code used for the FSR 2.1.x upscaler backend +inline constexpr CString FSR21 = "fsr21"; +// ID code used for the FSR 2.1.x upscaler backend used with the DirectX 11 on 12 compatibility layer +inline constexpr CString FSR21_11on12 = "fsr21_12"; +// ID code used for the FSR 2.2.x upscaler backend +inline constexpr CString FSR22 = "fsr22"; +// ID code used for the FSR 2.2.x upscaler backend used with the DirectX 11 on 12 compatibility layer +inline constexpr CString FSR22_11on12 = "fsr22_12"; +// ID code used for the FSR 3.1+ upscaler backend +inline constexpr CString FSR31 = "fsr31"; +// ID code used for the FSR 3.1+ upscaler backend used with the DirectX 11 on 12 compatibility layer +inline constexpr CString FSR31_11on12 = "fsr31_12"; +// ID code used for the DLSS upscaler backend +inline constexpr CString DLSS = "dlss"; +// ID code used for the DLSS-D/Ray Reconstruction upscaler+denoiser backend +inline constexpr CString DLSSD = "dlssd"; + +inline constexpr CString FSR_UpscaleWidth = "FSR.upscaleSize.width"; +inline constexpr CString FSR_UpscaleHeight = "FSR.upscaleSize.height"; + +inline constexpr CString FSR_NearPlane = "FSR.cameraNear"; +inline constexpr CString FSR_FarPlane = "FSR.cameraFar"; +inline constexpr CString FSR_CameraFovVertical = "FSR.cameraFovAngleVertical"; +inline constexpr CString FSR_FrameTimeDelta = "FSR.frameTimeDelta"; +inline constexpr CString FSR_ViewSpaceToMetersFactor = "FSR.viewSpaceToMetersFactor"; +inline constexpr CString FSR_TransparencyAndComp = "FSR.transparencyAndComposition"; +inline constexpr CString FSR_Reactive = "FSR.reactive"; + +} // namespace OptiKeys diff --git a/OptiScaler/SysUtils.h b/OptiScaler/SysUtils.h index a284c260d..33a7c89eb 100644 --- a/OptiScaler/SysUtils.h +++ b/OptiScaler/SysUtils.h @@ -181,3 +181,5 @@ inline static void to_lower_in_place(std::string& string) { std::transform(string.begin(), string.end(), string.begin(), ::tolower); } + +#include "OptiTexts.h" \ No newline at end of file From 4d639bbf578348d4ca9fa594daea5924c1420712 Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Tue, 24 Feb 2026 02:30:37 -0500 Subject: [PATCH 4/8] Fix incorrect configurable FOV conversion in FSR - The conversions for manually configured horizontal FOV to vertical FOV used in upscaling have been corrected to use the following formula: vFov = 2 * arctan( tan( hFov / 2 ) * ( h / w ) ) - Added convenience variables for global singletons to Eval functions to help readability - Streamlined ffxResolveTypelessFormat usages. More readable. --- OptiScaler/MathUtils.h | 45 +++++++++++++++++++ OptiScaler/OptiScaler.vcxproj | 3 +- OptiScaler/OptiScaler.vcxproj.filters | 2 +- OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp | 43 +++++++++++------- OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp | 44 ++++++++++-------- OptiScaler/upscalers/IFeature.cpp | 2 +- OptiScaler/upscalers/IFeature.h | 2 +- .../upscalers/fsr2/FSR2Feature_Dx11.cpp | 33 ++++++++------ .../upscalers/fsr2/FSR2Feature_Dx11On12.cpp | 22 +++++---- .../upscalers/fsr2/FSR2Feature_Dx12.cpp | 35 +++++++++------ OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp | 31 +++++++------ .../fsr2_212/FSR2Feature_Dx11On12_212.cpp | 30 ++++++++----- .../fsr2_212/FSR2Feature_Dx12_212.cpp | 41 ++++++++++------- .../upscalers/fsr2_212/FSR2Feature_Vk_212.cpp | 31 +++++++------ OptiScaler/upscalers/fsr31/FSR31Feature.h | 37 +++++++++------ .../upscalers/fsr31/FSR31Feature_Dx11.cpp | 35 +++++++++------ .../upscalers/fsr31/FSR31Feature_Dx11On12.cpp | 44 +++++++++--------- .../upscalers/fsr31/FSR31Feature_Dx12.cpp | 43 ++++++++++-------- .../upscalers/fsr31/FSR31Feature_Vk.cpp | 31 ++++++++----- 19 files changed, 347 insertions(+), 207 deletions(-) create mode 100644 OptiScaler/MathUtils.h diff --git a/OptiScaler/MathUtils.h b/OptiScaler/MathUtils.h new file mode 100644 index 000000000..efebe996f --- /dev/null +++ b/OptiScaler/MathUtils.h @@ -0,0 +1,45 @@ +#pragma once +#include +#include + +namespace OptiMath +{ + // Radians per degree. Used to convert from degrees to radians + inline constexpr float DegToRad = std::numbers::pi_v / 180.0f; + // Degrees per radian. Used to convert from radians to degrees + inline constexpr float RadToDeg = 180.0f / std::numbers::pi_v; + + // Converts from an angle in degrees to radians + [[nodiscard]] inline constexpr float GetRadiansFromDeg(const float deg) { return deg * DegToRad; } + + // Converts from an angle in radians to degrees + [[nodiscard]] inline constexpr float GetDegreesFromRad(const float rad) { return rad * RadToDeg; } + + /** + * @brief Calculates the vertical field of view for a camera from its horizontal FOV and its + * viewport dimensions according to the formula: vFov = 2 * arctan( tan( hFov / 2 ) * ( h / w ) ). + * @param hFovRad: Horizontal field of view + * @param width: Width of the camera viewport + * @param height: Height of the camera viewport + * @return Vertical FOV in radians + */ + [[nodiscard]] inline float GetVerticalFovFromHorizontal(const float hFovRad, const float width, const float height) + { + if (width <= 0.0f) return 0.0f; + return 2.0f * std::atan(std::tan(hFovRad * 0.5f) * (height / width)); + } + + /** + * @brief Calculates the horizontal field of view for a camera from its vertical FOV and its + * viewport dimensions according to the formula: hFov = 2 * arctan( tan( vFov / 2 ) * ( w / h ) ). + * @param vFovRad: Vertical field of view in radians + * @param width: Width of the camera viewport + * @param height: Height of the camera viewport + * @return Horizontal FOV in radians + */ + [[nodiscard]] inline float GetHorizontalFovFromVertical(const float vFovRad, const float width, const float height) + { + if (height <= 0.0f) return 0.0f; + return 2.0f * std::atan(std::tan(vFovRad * 0.5f) * (width / height)); + } +} \ No newline at end of file diff --git a/OptiScaler/OptiScaler.vcxproj b/OptiScaler/OptiScaler.vcxproj index 9461b4e87..fb9dd8647 100644 --- a/OptiScaler/OptiScaler.vcxproj +++ b/OptiScaler/OptiScaler.vcxproj @@ -1,4 +1,4 @@ - + @@ -322,6 +322,7 @@ copy NUL "$(SolutionDir)x64\Release\a\!! EXTRACT ALL FILES TO GAME FOLDER !!" /Y + diff --git a/OptiScaler/OptiScaler.vcxproj.filters b/OptiScaler/OptiScaler.vcxproj.filters index fb14559ff..d308d463c 100644 --- a/OptiScaler/OptiScaler.vcxproj.filters +++ b/OptiScaler/OptiScaler.vcxproj.filters @@ -701,7 +701,7 @@ Header Files - + Header Files diff --git a/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp b/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp index 548057589..6862057e6 100644 --- a/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp +++ b/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp @@ -3,6 +3,7 @@ #include "Config.h" #include "Util.h" +#include "MathUtils.h" #include "resource.h" #include "NVNGX_Parameter.h" @@ -23,6 +24,7 @@ #include "fsr3/ffx_frameinterpolation.h" const UINT fgContext = 0x1337; +using namespace OptiMath; // Swapchain create typedef FFX_API @@ -1252,21 +1254,26 @@ void FSR3FG::SetUpscalerInputs(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_P float tempCameraNear = 0.0f; float tempCameraFar = 0.0f; - InParameters->Get("FSR.cameraNear", &tempCameraNear); - InParameters->Get("FSR.cameraFar", &tempCameraFar); - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || + auto& state = State::Instance(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + + ngxParams.Get(OptiKeys::FSR_NearPlane, &tempCameraNear); + ngxParams.Get(OptiKeys::FSR_FarPlane, &tempCameraFar); + + if (!cfg.FsrUseFsrInputValues.value_or_default() || (tempCameraNear == 0.0f && tempCameraFar == 0.0f)) { if (feature->DepthInverted()) { - cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + cameraFar = cfg.FsrCameraNear.value_or_default(); + cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + cameraFar = cfg.FsrCameraFar.value_or_default(); + cameraNear = cfg.FsrCameraNear.value_or_default(); } } else @@ -1275,20 +1282,22 @@ void FSR3FG::SetUpscalerInputs(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_P cameraFar = tempCameraFar; } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || - InParameters->Get("FSR.cameraFovAngleVertical", &cameraVFov) != NVSDK_NGX_Result_Success) + if (!cfg.FsrUseFsrInputValues.value_or_default() || + ngxParams.Get(OptiKeys::FSR_CameraFovVertical, &cameraVFov) != NVSDK_NGX_Result_Success) { - if (Config::Instance()->FsrVerticalFov.has_value()) - cameraVFov = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - cameraVFov = 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) feature->TargetHeight() * (float) feature->TargetWidth()); + if (cfg.FsrVerticalFov.has_value()) + cameraVFov = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + cameraVFov = GetVerticalFovFromHorizontal(hFovRad, (float) feature->TargetWidth(), (float) feature->TargetHeight()); + } else - cameraVFov = 1.0471975511966f; + cameraVFov = GetRadiansFromDeg(60); } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default()) - InParameters->Get("FSR.viewSpaceToMetersFactor", &meterFactor); + if (!cfg.FsrUseFsrInputValues.value_or_default()) + ngxParams.Get(OptiKeys::FSR_ViewSpaceToMetersFactor, &meterFactor); State::Instance().lastFsrCameraFar = cameraFar; State::Instance().lastFsrCameraNear = cameraNear; diff --git a/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp b/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp index 0b0dc9aaa..74812b94a 100644 --- a/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp +++ b/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp @@ -2,9 +2,10 @@ #include "Upscaler_Inputs_Dx12.h" #include #include - #include "shaders/depth_scale/DS_Dx12.h" +#include "MathUtils.h" +using namespace OptiMath; static DS_Dx12* DepthScale = nullptr; void UpscalerInputsDx12::Init(ID3D12Device* device) @@ -42,21 +43,26 @@ void UpscalerInputsDx12::UpscaleStart(ID3D12GraphicsCommandList* InCmdList, NVSD float tempCameraNear = 0.0f; float tempCameraFar = 0.0f; - InParameters->Get("FSR.cameraNear", &tempCameraNear); - InParameters->Get("FSR.cameraFar", &tempCameraFar); - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || + auto& state = State::Instance(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + + ngxParams.Get(OptiKeys::FSR_NearPlane, &tempCameraNear); + ngxParams.Get(OptiKeys::FSR_FarPlane, &tempCameraFar); + + if (!cfg.FsrUseFsrInputValues.value_or_default() || (tempCameraNear == 0.0f && tempCameraFar == 0.0f)) { if (feature->DepthInverted()) { - cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + cameraFar = cfg.FsrCameraNear.value_or_default(); + cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + cameraFar = cfg.FsrCameraFar.value_or_default(); + cameraNear = cfg.FsrCameraNear.value_or_default(); } } else @@ -65,20 +71,22 @@ void UpscalerInputsDx12::UpscaleStart(ID3D12GraphicsCommandList* InCmdList, NVSD cameraFar = tempCameraFar; } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || - InParameters->Get("FSR.cameraFovAngleVertical", &cameraVFov) != NVSDK_NGX_Result_Success) + if (!cfg.FsrUseFsrInputValues.value_or_default() || + ngxParams.Get(OptiKeys::FSR_CameraFovVertical, &cameraVFov) != NVSDK_NGX_Result_Success) { - if (Config::Instance()->FsrVerticalFov.has_value()) - cameraVFov = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - cameraVFov = 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) feature->TargetHeight() * (float) feature->TargetWidth()); + if (cfg.FsrVerticalFov.has_value()) + cameraVFov = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + cameraVFov = GetVerticalFovFromHorizontal(hFovRad, (float)feature->TargetWidth(), (float) feature->TargetHeight()); + } else - cameraVFov = 1.0471975511966f; + cameraVFov = GetRadiansFromDeg(60); } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default()) - InParameters->Get("FSR.viewSpaceToMetersFactor", &meterFactor); + if (!cfg.FsrUseFsrInputValues.value_or_default()) + ngxParams.Get(OptiKeys::FSR_ViewSpaceToMetersFactor, &meterFactor); State::Instance().lastFsrCameraFar = cameraFar; State::Instance().lastFsrCameraNear = cameraNear; diff --git a/OptiScaler/upscalers/IFeature.cpp b/OptiScaler/upscalers/IFeature.cpp index 5566f9a42..00afde0cc 100644 --- a/OptiScaler/upscalers/IFeature.cpp +++ b/OptiScaler/upscalers/IFeature.cpp @@ -169,7 +169,7 @@ bool IFeature::SetInitParameters(NVSDK_NGX_Parameter* InParameters) return false; } -void IFeature::GetRenderResolution(NVSDK_NGX_Parameter* InParameters, unsigned int* OutWidth, unsigned int* OutHeight) +void IFeature::GetRenderResolution(const NVSDK_NGX_Parameter* InParameters, unsigned int* OutWidth, unsigned int* OutHeight) { if (InParameters->Get(NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width, OutWidth) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/IFeature.h b/OptiScaler/upscalers/IFeature.h index 53affe769..8d59826dc 100644 --- a/OptiScaler/upscalers/IFeature.h +++ b/OptiScaler/upscalers/IFeature.h @@ -78,7 +78,7 @@ class IFeature void SetHandle(unsigned int InHandleId); bool SetInitParameters(NVSDK_NGX_Parameter* InParameters); - void GetRenderResolution(NVSDK_NGX_Parameter* InParameters, unsigned int* OutWidth, unsigned int* OutHeight); + void GetRenderResolution(const 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); diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp index 8be0e3e90..d714e9bf6 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp @@ -1,9 +1,11 @@ #include #include #include - +#include "MathUtils.h" #include "FSR2Feature_Dx11.h" +using namespace OptiMath; + #define ASSIGN_DESC(dest, src) \ dest.Width = src.Width; \ dest.Height = src.Height; \ @@ -244,8 +246,12 @@ bool FSR2FeatureDx11::Evaluate(ID3D11DeviceContext* InContext, NVSDK_NGX_Paramet if (!IsInited()) return false; + auto& state = State::Instance(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) - Config::Instance()->RcasEnabled.set_volatile_value(false); + cfg.RcasEnabled.set_volatile_value(false); ID3D11ShaderResourceView* restoreSRVs[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; ID3D11SamplerState* restoreSamplerStates[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {}; @@ -502,23 +508,24 @@ bool FSR2FeatureDx11::Evaluate(ID3D11DeviceContext* InContext, NVSDK_NGX_Paramet if (DepthInverted()) { - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) DisplayHeight() * (float) DisplayWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); if (InParameters->Get(NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, ¶ms.frameTimeDelta) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp index 492543e29..5ae213bb9 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp @@ -1,8 +1,10 @@ #include #include - +#include "MathUtils.h" #include "FSR2Feature_Dx11On12.h" +using namespace OptiMath; + bool FSR2FeatureDx11on12::Init(ID3D11Device* InDevice, ID3D11DeviceContext* InContext, NVSDK_NGX_Parameter* InParameters) { @@ -22,6 +24,9 @@ bool FSR2FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_N { LOG_FUNC(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!_baseInit) { // to prevent creation dx12 device if we are going to recreate feature @@ -287,14 +292,15 @@ bool FSR2FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_N params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); } - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) TargetHeight() * (float) TargetWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); if (InParameters->Get(NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, ¶ms.frameTimeDelta) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp index dbadc592b..d73338f08 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp @@ -1,7 +1,9 @@ #include #include - #include "FSR2Feature_Dx12.h" +#include "MathUtils.h" + +using namespace OptiMath; bool FSR2FeatureDx12::Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCommandList, NVSDK_NGX_Parameter* InParameters) @@ -35,6 +37,10 @@ bool FSR2FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_N if (!IsInited()) return false; + auto& state = State::Instance(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) Config::Instance()->RcasEnabled.set_volatile_value(false); @@ -339,26 +345,27 @@ bool FSR2FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_N params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || - InParameters->Get("FSR.cameraFar", ¶ms.cameraFar) != NVSDK_NGX_Result_Success) + if (!cfg.FsrUseFsrInputValues.value_or_default() || + ngxParams.Get(OptiKeys::FSR_FarPlane, ¶ms.cameraFar) != NVSDK_NGX_Result_Success) { if (DepthInverted()) - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); else - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || - InParameters->Get("FSR.cameraFovAngleVertical", ¶ms.cameraFovAngleVertical) != NVSDK_NGX_Result_Success) + if (!cfg.FsrUseFsrInputValues.value_or_default() || + ngxParams.Get(OptiKeys::FSR_CameraFovVertical, ¶ms.cameraFovAngleVertical) != NVSDK_NGX_Result_Success) { - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) TargetHeight() * (float) TargetWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); } if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp index b93283048..dd84e96f5 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp @@ -1,9 +1,10 @@ #include #include - #include "FSR2Feature_Vk.h" - #include "nvsdk_ngx_vk.h" +#include "MathUtils.h" + +using namespace OptiMath; bool FSR2FeatureVk::InitFSR2(const NVSDK_NGX_Parameter* InParameters) { @@ -162,6 +163,9 @@ bool FSR2FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* I if (!IsInited()) return false; + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) Config::Instance()->RcasEnabled.set_volatile_value(false); @@ -510,23 +514,24 @@ bool FSR2FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* I if (DepthInverted()) { - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) DisplayHeight() * (float) DisplayWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float) TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); if (InParameters->Get(NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, ¶ms.frameTimeDelta) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp index 61e3ed590..1e2220993 100644 --- a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp +++ b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp @@ -1,7 +1,9 @@ #include #include - #include "FSR2Feature_Dx11On12_212.h" +#include "MathUtils.h" + +using namespace OptiMath; bool FSR2FeatureDx11on12_212::Init(ID3D11Device* InDevice, ID3D11DeviceContext* InContext, NVSDK_NGX_Parameter* InParameters) @@ -22,6 +24,9 @@ bool FSR2FeatureDx11on12_212::Evaluate(ID3D11DeviceContext* InDeviceContext, NVS { LOG_FUNC(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!_baseInit) { // to prevent creation dx12 device if we are going to recreate feature @@ -280,23 +285,24 @@ bool FSR2FeatureDx11on12_212::Evaluate(ID3D11DeviceContext* InDeviceContext, NVS if (DepthInverted()) { - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) TargetHeight() * (float) TargetWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); if (InParameters->Get(NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, ¶ms.frameTimeDelta) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp index 3b184b38e..aaed71747 100644 --- a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp +++ b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp @@ -1,7 +1,9 @@ #include #include - #include "FSR2Feature_Dx12_212.h" +#include "MathUtils.h" + +using namespace OptiMath; bool FSR2FeatureDx12_212::Init(ID3D12Device* InDevice, ID3D12GraphicsCommandList* InCommandList, NVSDK_NGX_Parameter* InParameters) @@ -35,6 +37,10 @@ bool FSR2FeatureDx12_212::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVS if (!IsInited()) return false; + auto& state = State::Instance(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) Config::Instance()->RcasEnabled.set_volatile_value(false); @@ -339,34 +345,35 @@ bool FSR2FeatureDx12_212::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVS LOG_DEBUG("Sharpness: {0}", params.sharpness); - if (Config::Instance()->FsrCameraNear.has_value() || !Config::Instance()->FsrUseFsrInputValues.value_or_default() || - InParameters->Get("FSR.cameraNear", ¶ms.cameraNear) != NVSDK_NGX_Result_Success) + if (cfg.FsrCameraNear.has_value() || !cfg.FsrUseFsrInputValues.value_or_default() || + ngxParams.Get(OptiKeys::FSR_NearPlane, ¶ms.cameraNear) != NVSDK_NGX_Result_Success) { if (DepthInverted()) - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); else - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || - InParameters->Get("FSR.cameraFar", ¶ms.cameraFar) != NVSDK_NGX_Result_Success) + if (!cfg.FsrUseFsrInputValues.value_or_default() || + ngxParams.Get(OptiKeys::FSR_FarPlane, ¶ms.cameraFar) != NVSDK_NGX_Result_Success) { if (DepthInverted()) - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); else - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); } - if (InParameters->Get("FSR.cameraFovAngleVertical", ¶ms.cameraFovAngleVertical) != NVSDK_NGX_Result_Success) + if (ngxParams.Get(OptiKeys::FSR_CameraFovVertical, ¶ms.cameraFovAngleVertical) != NVSDK_NGX_Result_Success) { - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) TargetHeight() * (float) TargetWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); } if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || diff --git a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp index 7cf7b4c9f..d55a27ab9 100644 --- a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp +++ b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp @@ -1,9 +1,10 @@ #include #include - #include "FSR2Feature_Vk_212.h" - #include "nvsdk_ngx_vk.h" +#include "MathUtils.h" + +using namespace OptiMath; bool FSR2FeatureVk212::InitFSR2(const NVSDK_NGX_Parameter* InParameters) { @@ -185,6 +186,9 @@ bool FSR2FeatureVk212::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter if (!IsInited()) return false; + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) Config::Instance()->RcasEnabled.set_volatile_value(false); @@ -533,23 +537,24 @@ bool FSR2FeatureVk212::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter if (DepthInverted()) { - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) DisplayHeight() * (float) DisplayWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); if (InParameters->Get(NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, ¶ms.frameTimeDelta) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature.h b/OptiScaler/upscalers/fsr31/FSR31Feature.h index 809ff8407..eed4d28c8 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature.h +++ b/OptiScaler/upscalers/fsr31/FSR31Feature.h @@ -46,45 +46,56 @@ class FSR31Feature : public virtual IFeature LOG_WARN("can't parse {0}", version_str); } - static inline uint32_t ffxResolveTypelessFormat(uint32_t format) + static inline void ffxResolveTypelessFormat(uint32_t& format) { switch (format) { case FFX_API_SURFACE_FORMAT_R10G10B10A2_TYPELESS: - return FFX_API_SURFACE_FORMAT_R10G10B10A2_UNORM; + format = FFX_API_SURFACE_FORMAT_R10G10B10A2_UNORM; + return; case FFX_API_SURFACE_FORMAT_R32G32B32A32_TYPELESS: - return FFX_API_SURFACE_FORMAT_R32G32B32A32_FLOAT; + format = FFX_API_SURFACE_FORMAT_R32G32B32A32_FLOAT; + return; case FFX_API_SURFACE_FORMAT_R16G16B16A16_TYPELESS: - return FFX_API_SURFACE_FORMAT_R16G16B16A16_FLOAT; + format = FFX_API_SURFACE_FORMAT_R16G16B16A16_FLOAT; + return; case FFX_API_SURFACE_FORMAT_R32G32_TYPELESS: - return FFX_API_SURFACE_FORMAT_R32G32_FLOAT; + format = FFX_API_SURFACE_FORMAT_R32G32_FLOAT; + return; case FFX_API_SURFACE_FORMAT_R8G8B8A8_TYPELESS: - return FFX_API_SURFACE_FORMAT_R8G8B8A8_UNORM; + format = FFX_API_SURFACE_FORMAT_R8G8B8A8_UNORM; + return; case FFX_API_SURFACE_FORMAT_B8G8R8A8_TYPELESS: - return FFX_API_SURFACE_FORMAT_B8G8R8A8_UNORM; + format = FFX_API_SURFACE_FORMAT_B8G8R8A8_UNORM; + return; case FFX_API_SURFACE_FORMAT_R16G16_TYPELESS: - return FFX_API_SURFACE_FORMAT_R16G16_FLOAT; + format = FFX_API_SURFACE_FORMAT_R16G16_FLOAT; + return; case FFX_API_SURFACE_FORMAT_R32_TYPELESS: - return FFX_API_SURFACE_FORMAT_R32_FLOAT; + format = FFX_API_SURFACE_FORMAT_R32_FLOAT; + return; case FFX_API_SURFACE_FORMAT_R8G8_TYPELESS: - return FFX_API_SURFACE_FORMAT_R8G8_UNORM; + format = FFX_API_SURFACE_FORMAT_R8G8_UNORM; + return; case FFX_API_SURFACE_FORMAT_R16_TYPELESS: - return FFX_API_SURFACE_FORMAT_R16_FLOAT; + format = FFX_API_SURFACE_FORMAT_R16_FLOAT; + return; case FFX_API_SURFACE_FORMAT_R8_TYPELESS: - return FFX_API_SURFACE_FORMAT_R8_UNORM; + format = FFX_API_SURFACE_FORMAT_R8_UNORM; + return; default: - return format; // Already typed or unknown + return; // Already typed or unknown } } diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp index 6ab7fd875..71995f1f1 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp @@ -1,8 +1,10 @@ #include #include #include - #include "FSR31Feature_Dx11.h" +#include "MathUtils.h" + +using namespace OptiMath; #define ASSIGN_DESC(dest, src) \ dest.Width = src.Width; \ @@ -142,6 +144,10 @@ bool FSR31FeatureDx11::Evaluate(ID3D11DeviceContext* DeviceContext, NVSDK_NGX_Pa if (!IsInited()) return false; + auto& state = State::Instance(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) Config::Instance()->RcasEnabled.set_volatile_value(false); @@ -420,26 +426,27 @@ bool FSR31FeatureDx11::Evaluate(ID3D11DeviceContext* DeviceContext, NVSDK_NGX_Pa if (DepthInverted()) { - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } - State::Instance().lastFsrCameraFar = params.cameraFar; - State::Instance().lastFsrCameraNear = params.cameraNear; + state.lastFsrCameraFar = params.cameraFar; + state.lastFsrCameraNear = params.cameraNear; - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) DisplayHeight() * (float) DisplayWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); LOG_DEBUG("FsrVerticalFov: {0}", params.cameraFovAngleVertical); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp index a4a570756..1e5fe6738 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp @@ -1,10 +1,11 @@ #include #include #include - #include - #include "FSR31Feature_Dx11On12.h" +#include "MathUtils.h" + +using namespace OptiMath; NVSDK_NGX_Parameter* FSR31FeatureDx11on12::SetParameters(NVSDK_NGX_Parameter* InParameters) { @@ -45,6 +46,9 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ { LOG_FUNC(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!_baseInit) { // to prevent creation dx12 device if we are going to recreate feature @@ -297,13 +301,12 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ // transparencyAndComposition and exposure might be unnecessary here if (Version().major >= 4) { - params.color.description.format = ffxResolveTypelessFormat(params.color.description.format); - params.depth.description.format = ffxResolveTypelessFormat(params.depth.description.format); - params.motionVectors.description.format = ffxResolveTypelessFormat(params.motionVectors.description.format); - params.exposure.description.format = ffxResolveTypelessFormat(params.exposure.description.format); - params.transparencyAndComposition.description.format = - ffxResolveTypelessFormat(params.transparencyAndComposition.description.format); - params.output.description.format = ffxResolveTypelessFormat(params.output.description.format); + ffxResolveTypelessFormat(params.color.description.format); + ffxResolveTypelessFormat(params.depth.description.format); + ffxResolveTypelessFormat(params.motionVectors.description.format); + ffxResolveTypelessFormat(params.exposure.description.format); + ffxResolveTypelessFormat(params.transparencyAndComposition.description.format); + ffxResolveTypelessFormat(params.output.description.format); } float MVScaleX = 1.0f; @@ -325,26 +328,27 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ if (DepthInverted()) { - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } State::Instance().lastFsrCameraFar = params.cameraFar; State::Instance().lastFsrCameraNear = params.cameraNear; - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) TargetHeight() * (float) TargetWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); if (InParameters->Get(NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, ¶ms.frameTimeDelta) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp index 930ed595e..8567ff3bd 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx12.cpp @@ -1,10 +1,11 @@ #include #include #include - #include - #include "FSR31Feature_Dx12.h" +#include "MathUtils.h" + +using namespace OptiMath; NVSDK_NGX_Parameter* FSR31FeatureDx12::SetParameters(NVSDK_NGX_Parameter* InParameters) { @@ -58,6 +59,9 @@ bool FSR31FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_ if (!IsInited()) return false; + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) Config::Instance()->RcasEnabled.set_volatile_value(false); @@ -360,13 +364,12 @@ bool FSR31FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_ // transparencyAndComposition and exposure might be unnecessary here if (Version().major >= 4) { - params.color.description.format = ffxResolveTypelessFormat(params.color.description.format); - params.depth.description.format = ffxResolveTypelessFormat(params.depth.description.format); - params.motionVectors.description.format = ffxResolveTypelessFormat(params.motionVectors.description.format); - params.exposure.description.format = ffxResolveTypelessFormat(params.exposure.description.format); - params.transparencyAndComposition.description.format = - ffxResolveTypelessFormat(params.transparencyAndComposition.description.format); - params.output.description.format = ffxResolveTypelessFormat(params.output.description.format); + ffxResolveTypelessFormat(params.color.description.format); + ffxResolveTypelessFormat(params.depth.description.format); + ffxResolveTypelessFormat(params.motionVectors.description.format); + ffxResolveTypelessFormat(params.exposure.description.format); + ffxResolveTypelessFormat(params.transparencyAndComposition.description.format); + ffxResolveTypelessFormat(params.output.description.format); } float MVScaleX = 1.0f; @@ -401,22 +404,24 @@ bool FSR31FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_ InParameters->Get("FSR.cameraFar", ¶ms.cameraFar) != NVSDK_NGX_Result_Success) { if (DepthInverted()) - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); else - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); } - if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || - InParameters->Get("FSR.cameraFovAngleVertical", ¶ms.cameraFovAngleVertical) != NVSDK_NGX_Result_Success) + if (!cfg.FsrUseFsrInputValues.value_or_default() || + ngxParams.Get(OptiKeys::FSR_CameraFovVertical, ¶ms.cameraFovAngleVertical) != NVSDK_NGX_Result_Success) { - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) TargetHeight() * (float) TargetWidth()); + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); } if (!Config::Instance()->FsrUseFsrInputValues.value_or_default() || diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp index 241aa1cee..c23b4a261 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp @@ -3,8 +3,10 @@ #include #include #include "FSR31Feature_Vk.h" - #include "nvsdk_ngx_vk.h" +#include "MathUtils.h" + +using namespace OptiMath; static inline uint32_t ffxApiGetSurfaceFormatVKLocal(VkFormat fmt) { @@ -320,6 +322,10 @@ bool FSR31FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* if (!IsInited()) return false; + auto& state = State::Instance(); + auto& cfg = *Config::Instance(); + const auto& ngxParams = *InParameters; + if (!RCAS->IsInit()) Config::Instance()->RcasEnabled.set_volatile_value(false); @@ -647,23 +653,24 @@ bool FSR31FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* if (DepthInverted()) { - params.cameraFar = Config::Instance()->FsrCameraNear.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraFar.value_or_default(); + params.cameraFar = cfg.FsrCameraNear.value_or_default(); + params.cameraNear = cfg.FsrCameraFar.value_or_default(); } else { - params.cameraFar = Config::Instance()->FsrCameraFar.value_or_default(); - params.cameraNear = Config::Instance()->FsrCameraNear.value_or_default(); + params.cameraFar = cfg.FsrCameraFar.value_or_default(); + params.cameraNear = cfg.FsrCameraNear.value_or_default(); } - if (Config::Instance()->FsrVerticalFov.has_value()) - params.cameraFovAngleVertical = Config::Instance()->FsrVerticalFov.value() * 0.0174532925199433f; - else if (Config::Instance()->FsrHorizontalFov.value_or_default() > 0.0f) - params.cameraFovAngleVertical = - 2.0f * atan((tan(Config::Instance()->FsrHorizontalFov.value() * 0.0174532925199433f) * 0.5f) / - (float) DisplayHeight() * (float) DisplayWidth()); + if (cfg.FsrVerticalFov.has_value()) + params.cameraFovAngleVertical = GetRadiansFromDeg(cfg.FsrVerticalFov.value()); + else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) + { + const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); + params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + } else - params.cameraFovAngleVertical = 1.0471975511966f; + params.cameraFovAngleVertical = GetRadiansFromDeg(60); if (InParameters->Get(NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, ¶ms.frameTimeDelta) != NVSDK_NGX_Result_Success || From 3305d5e733dc0c527ac954ff0784cd749072b2c7 Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Tue, 24 Feb 2026 02:58:45 -0500 Subject: [PATCH 5/8] Update ffxResolveTypelessFormat usage --- OptiScaler/upscalers/fsr31/FSR31Feature_VkOn12.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_VkOn12.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_VkOn12.cpp index d764a6963..7ce754e3b 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_VkOn12.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_VkOn12.cpp @@ -289,13 +289,12 @@ bool FSR31FeatureVkOn12::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Paramet // For FSR 4 - resolve typeless formats if (Version().major >= 4) { - params.color.description.format = ffxResolveTypelessFormat(params.color.description.format); - params.depth.description.format = ffxResolveTypelessFormat(params.depth.description.format); - params.motionVectors.description.format = ffxResolveTypelessFormat(params.motionVectors.description.format); - params.exposure.description.format = ffxResolveTypelessFormat(params.exposure.description.format); - params.transparencyAndComposition.description.format = - ffxResolveTypelessFormat(params.transparencyAndComposition.description.format); - params.output.description.format = ffxResolveTypelessFormat(params.output.description.format); + ffxResolveTypelessFormat(params.color.description.format); + ffxResolveTypelessFormat(params.depth.description.format); + ffxResolveTypelessFormat(params.motionVectors.description.format); + ffxResolveTypelessFormat(params.exposure.description.format); + ffxResolveTypelessFormat(params.transparencyAndComposition.description.format); + ffxResolveTypelessFormat(params.output.description.format); } float MVScaleX = 1.0f; From 09077b64082f318f97b30ee604c03e9e2daecc5b Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Tue, 24 Feb 2026 03:31:52 -0500 Subject: [PATCH 6/8] Run clang formatting --- OptiScaler/MathUtils.h | 72 ++++++------ OptiScaler/NVNGX_Parameter.h | 40 +++---- OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp | 6 +- OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp | 6 +- OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp | 111 ++++++++---------- OptiScaler/upscalers/FeatureProvider_Dx11.cpp | 12 +- OptiScaler/upscalers/FeatureProvider_Dx12.cpp | 20 +--- OptiScaler/upscalers/FeatureProvider_Dx12.h | 17 +-- OptiScaler/upscalers/FeatureProvider_Vk.cpp | 3 +- OptiScaler/upscalers/IFeature.cpp | 3 +- .../upscalers/fsr2/FSR2Feature_Dx11.cpp | 3 +- .../upscalers/fsr2/FSR2Feature_Dx11On12.cpp | 3 +- .../upscalers/fsr2/FSR2Feature_Dx12.cpp | 3 +- OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp | 3 +- .../fsr2_212/FSR2Feature_Dx11On12_212.cpp | 3 +- .../fsr2_212/FSR2Feature_Dx12_212.cpp | 3 +- .../upscalers/fsr2_212/FSR2Feature_Vk_212.cpp | 3 +- OptiScaler/upscalers/fsr31/FSR31Feature.h | 2 +- .../upscalers/fsr31/FSR31Feature_Dx11.cpp | 3 +- .../upscalers/fsr31/FSR31Feature_Dx11On12.cpp | 3 +- .../upscalers/fsr31/FSR31Feature_Vk.cpp | 3 +- 21 files changed, 148 insertions(+), 174 deletions(-) diff --git a/OptiScaler/MathUtils.h b/OptiScaler/MathUtils.h index efebe996f..df9746fa5 100644 --- a/OptiScaler/MathUtils.h +++ b/OptiScaler/MathUtils.h @@ -4,42 +4,44 @@ namespace OptiMath { - // Radians per degree. Used to convert from degrees to radians - inline constexpr float DegToRad = std::numbers::pi_v / 180.0f; - // Degrees per radian. Used to convert from radians to degrees - inline constexpr float RadToDeg = 180.0f / std::numbers::pi_v; +// Radians per degree. Used to convert from degrees to radians +inline constexpr float DegToRad = std::numbers::pi_v / 180.0f; +// Degrees per radian. Used to convert from radians to degrees +inline constexpr float RadToDeg = 180.0f / std::numbers::pi_v; - // Converts from an angle in degrees to radians - [[nodiscard]] inline constexpr float GetRadiansFromDeg(const float deg) { return deg * DegToRad; } +// Converts from an angle in degrees to radians +[[nodiscard]] inline constexpr float GetRadiansFromDeg(const float deg) { return deg * DegToRad; } - // Converts from an angle in radians to degrees - [[nodiscard]] inline constexpr float GetDegreesFromRad(const float rad) { return rad * RadToDeg; } +// Converts from an angle in radians to degrees +[[nodiscard]] inline constexpr float GetDegreesFromRad(const float rad) { return rad * RadToDeg; } - /** - * @brief Calculates the vertical field of view for a camera from its horizontal FOV and its - * viewport dimensions according to the formula: vFov = 2 * arctan( tan( hFov / 2 ) * ( h / w ) ). - * @param hFovRad: Horizontal field of view - * @param width: Width of the camera viewport - * @param height: Height of the camera viewport - * @return Vertical FOV in radians - */ - [[nodiscard]] inline float GetVerticalFovFromHorizontal(const float hFovRad, const float width, const float height) - { - if (width <= 0.0f) return 0.0f; - return 2.0f * std::atan(std::tan(hFovRad * 0.5f) * (height / width)); - } +/** + * @brief Calculates the vertical field of view for a camera from its horizontal FOV and its + * viewport dimensions according to the formula: vFov = 2 * arctan( tan( hFov / 2 ) * ( h / w ) ). + * @param hFovRad: Horizontal field of view + * @param width: Width of the camera viewport + * @param height: Height of the camera viewport + * @return Vertical FOV in radians + */ +[[nodiscard]] inline float GetVerticalFovFromHorizontal(const float hFovRad, const float width, const float height) +{ + if (width <= 0.0f) + return 0.0f; + return 2.0f * std::atan(std::tan(hFovRad * 0.5f) * (height / width)); +} - /** - * @brief Calculates the horizontal field of view for a camera from its vertical FOV and its - * viewport dimensions according to the formula: hFov = 2 * arctan( tan( vFov / 2 ) * ( w / h ) ). - * @param vFovRad: Vertical field of view in radians - * @param width: Width of the camera viewport - * @param height: Height of the camera viewport - * @return Horizontal FOV in radians - */ - [[nodiscard]] inline float GetHorizontalFovFromVertical(const float vFovRad, const float width, const float height) - { - if (height <= 0.0f) return 0.0f; - return 2.0f * std::atan(std::tan(vFovRad * 0.5f) * (width / height)); - } -} \ No newline at end of file +/** + * @brief Calculates the horizontal field of view for a camera from its vertical FOV and its + * viewport dimensions according to the formula: hFov = 2 * arctan( tan( vFov / 2 ) * ( w / h ) ). + * @param vFovRad: Vertical field of view in radians + * @param width: Width of the camera viewport + * @param height: Height of the camera viewport + * @return Horizontal FOV in radians + */ +[[nodiscard]] inline float GetHorizontalFovFromVertical(const float vFovRad, const float width, const float height) +{ + if (height <= 0.0f) + return 0.0f; + return 2.0f * std::atan(std::tan(vFovRad * 0.5f) * (width / height)); +} +} // namespace OptiMath \ No newline at end of file diff --git a/OptiScaler/NVNGX_Parameter.h b/OptiScaler/NVNGX_Parameter.h index f67bb2ed2..5e3feb75a 100644 --- a/OptiScaler/NVNGX_Parameter.h +++ b/OptiScaler/NVNGX_Parameter.h @@ -19,20 +19,20 @@ /** @brief Indicates the lifetime management required by an NGX parameter table. */ namespace NGX_AllocTypes { - // Key used to get/set enum from table - constexpr std::string_view AllocKey = "OptiScaler.ParamAllocType"; - - constexpr uint32_t Unknown = 0; - // Standard behavior in modern DLSS. Created with NGX Allocate(). Freed with Destroy(). - constexpr uint32_t NVDynamic = 1; - // Legacy DLSS. Lifetime managed internally by the SDK. - constexpr uint32_t NVPersistent = 2; - // OptiScaler implementation used internally with new/delete. - constexpr uint32_t InternDynamic = 3; - // OptiScaler implementation for legacy applications. Must maintain a persistent instance - // for the lifetime of the application. - constexpr uint32_t InternPersistent = 4; -} +// Key used to get/set enum from table +constexpr std::string_view AllocKey = "OptiScaler.ParamAllocType"; + +constexpr uint32_t Unknown = 0; +// Standard behavior in modern DLSS. Created with NGX Allocate(). Freed with Destroy(). +constexpr uint32_t NVDynamic = 1; +// Legacy DLSS. Lifetime managed internally by the SDK. +constexpr uint32_t NVPersistent = 2; +// OptiScaler implementation used internally with new/delete. +constexpr uint32_t InternDynamic = 3; +// OptiScaler implementation for legacy applications. Must maintain a persistent instance +// for the lifetime of the application. +constexpr uint32_t InternPersistent = 4; +} // namespace NGX_AllocTypes /// @brief Calculates the resolution scaling ratio override based on the provided quality level and current /// configuration. @@ -686,15 +686,13 @@ struct NVNGX_Parameters : public NVSDK_NGX_Parameter { std::string Name; - NVNGX_Parameters(std::string_view name, bool isPersistent) : - Name(name) - { + NVNGX_Parameters(std::string_view name, bool isPersistent) : Name(name) + { // Old flag used to indicate custom table. Obsolete? Set("OptiScaler", 1); // New tracking flag - Set(NGX_AllocTypes::AllocKey.data(), isPersistent ? - NGX_AllocTypes::InternPersistent : - NGX_AllocTypes::InternDynamic); + Set(NGX_AllocTypes::AllocKey.data(), + isPersistent ? NGX_AllocTypes::InternPersistent : NGX_AllocTypes::InternDynamic); } #ifdef ENABLE_ENCAPSULATED_PARAMS @@ -1020,7 +1018,7 @@ inline static NVNGX_Parameters* GetNGXParameters(std::string_view name, bool isP } /** - * @brief Sets a custom tracking tag to indicate the memory management strategy required by + * @brief Sets a custom tracking tag to indicate the memory management strategy required by * the table, indicated by NGX_AllocTypes. */ inline static void SetNGXParamAllocType(NVSDK_NGX_Parameter& params, uint32_t allocType) diff --git a/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp b/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp index 6862057e6..fa7c32f46 100644 --- a/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp +++ b/OptiScaler/inputs/FG/FSR3_Dx12_FG.cpp @@ -1262,8 +1262,7 @@ void FSR3FG::SetUpscalerInputs(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_P ngxParams.Get(OptiKeys::FSR_NearPlane, &tempCameraNear); ngxParams.Get(OptiKeys::FSR_FarPlane, &tempCameraFar); - if (!cfg.FsrUseFsrInputValues.value_or_default() || - (tempCameraNear == 0.0f && tempCameraFar == 0.0f)) + if (!cfg.FsrUseFsrInputValues.value_or_default() || (tempCameraNear == 0.0f && tempCameraFar == 0.0f)) { if (feature->DepthInverted()) { @@ -1290,7 +1289,8 @@ void FSR3FG::SetUpscalerInputs(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_P else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - cameraVFov = GetVerticalFovFromHorizontal(hFovRad, (float) feature->TargetWidth(), (float) feature->TargetHeight()); + cameraVFov = + GetVerticalFovFromHorizontal(hFovRad, (float) feature->TargetWidth(), (float) feature->TargetHeight()); } else cameraVFov = GetRadiansFromDeg(60); diff --git a/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp b/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp index 74812b94a..45cd0a2b2 100644 --- a/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp +++ b/OptiScaler/inputs/FG/Upscaler_Inputs_Dx12.cpp @@ -51,8 +51,7 @@ void UpscalerInputsDx12::UpscaleStart(ID3D12GraphicsCommandList* InCmdList, NVSD ngxParams.Get(OptiKeys::FSR_NearPlane, &tempCameraNear); ngxParams.Get(OptiKeys::FSR_FarPlane, &tempCameraFar); - if (!cfg.FsrUseFsrInputValues.value_or_default() || - (tempCameraNear == 0.0f && tempCameraFar == 0.0f)) + if (!cfg.FsrUseFsrInputValues.value_or_default() || (tempCameraNear == 0.0f && tempCameraFar == 0.0f)) { if (feature->DepthInverted()) { @@ -79,7 +78,8 @@ void UpscalerInputsDx12::UpscaleStart(ID3D12GraphicsCommandList* InCmdList, NVSD else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - cameraVFov = GetVerticalFovFromHorizontal(hFovRad, (float)feature->TargetWidth(), (float) feature->TargetHeight()); + cameraVFov = + GetVerticalFovFromHorizontal(hFovRad, (float) feature->TargetWidth(), (float) feature->TargetHeight()); } else cameraVFov = GetRadiansFromDeg(60); diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp index d3848b979..68d360139 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp @@ -59,8 +59,8 @@ static std::shared_mutex computeSigatureMutex; static std::shared_mutex graphSigatureMutex; static bool GetIsDlssModuleInited() -{ - return Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited(); +{ + return Config::Instance()->DLSSEnabled.value_or_default() && NVNGXProxy::IsDx12Inited(); } static void hkSetComputeRootSignature(ID3D12GraphicsCommandList* commandList, ID3D12RootSignature* pRootSignature) @@ -144,12 +144,10 @@ static void UnhookAll() #pragma region DLSS Init Calls -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext( - unsigned long long InApplicationId, - const wchar_t* InApplicationDataPath, - ID3D12Device* InDevice, - NVSDK_NGX_Version InSDKVersion, - const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext(unsigned long long InApplicationId, + const wchar_t* InApplicationDataPath, ID3D12Device* InDevice, + NVSDK_NGX_Version InSDKVersion, + const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) { LOG_FUNC(); @@ -230,12 +228,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_Ext( return NVSDK_NGX_Result_Success; } -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init( - unsigned long long InApplicationId, - const wchar_t* InApplicationDataPath, - ID3D12Device* InDevice, - const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo, - NVSDK_NGX_Version InSDKVersion) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init(unsigned long long InApplicationId, + const wchar_t* InApplicationDataPath, ID3D12Device* InDevice, + const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo, + NVSDK_NGX_Version InSDKVersion) { LOG_FUNC(); @@ -272,7 +268,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init( // DLSSGMod::InitDLSSGMod_Dx12(); // DLSSGMod::D3D12_Init(InApplicationId, InApplicationDataPath, InDevice, InFeatureInfo, InSDKVersion); // } - + ScopedInit scopedInit {}; auto result = NVSDK_NGX_D3D12_Init_Ext(InApplicationId, InApplicationDataPath, InDevice, InSDKVersion, InFeatureInfo); @@ -281,14 +277,12 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init( return result; } -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_ProjectID( - const char* InProjectId, - NVSDK_NGX_EngineType InEngineType, - const char* InEngineVersion, - const wchar_t* InApplicationDataPath, - ID3D12Device* InDevice, - NVSDK_NGX_Version InSDKVersion, - const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_Init_ProjectID(const char* InProjectId, + NVSDK_NGX_EngineType InEngineType, + const char* InEngineVersion, + const wchar_t* InApplicationDataPath, + ID3D12Device* InDevice, NVSDK_NGX_Version InSDKVersion, + const NVSDK_NGX_FeatureCommonInfo* InFeatureInfo) { LOG_FUNC(); @@ -474,9 +468,9 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetParameters(NVSDK_NGX_Parameter } /** - * @brief Allocates a new NVSDK parameter map pre-populated with NGX capabilities and information about available features. - * The output parameter map may also be used in the same ways as a parameter map allocated with AllocateParameters(). - * The lifetime of this map is managed by the calling application with DestroyParameters(). + * @brief Allocates a new NVSDK parameter map pre-populated with NGX capabilities and information about available + * features. The output parameter map may also be used in the same ways as a parameter map allocated with + * AllocateParameters(). The lifetime of this map is managed by the calling application with DestroyParameters(). */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters) { @@ -501,7 +495,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX return NVSDK_NGX_Result_Success; } } - + // Get custom parameters if using custom backend auto& params = *(new NVNGX_Parameters("OptiDx12", false)); InitNGXParameters(¶ms); @@ -511,7 +505,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX } /** - * @brief Allocates a new parameter map used to provide parameters needed by the DLSS API. The lifetime of this map + * @brief Allocates a new parameter map used to provide parameters needed by the DLSS API. The lifetime of this map * is managed by the calling application with DestroyParameters(). */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_AllocateParameters(NVSDK_NGX_Parameter** OutParameters) @@ -555,7 +549,7 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_PopulateParameters_Impl(NVSDK_NGX } /** - * @brief Destroys a given input parameter map created with AllocateParameters or GetCapabilityParameters. + * @brief Destroys a given input parameter map created with AllocateParameters or GetCapabilityParameters. Must not be called on maps returned by GetParameters(). Unsupported tables will not be freed. */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_DestroyParameters(NVSDK_NGX_Parameter* InParameters) @@ -643,11 +637,8 @@ static void RestoreRootSignatures(ID3D12GraphicsCommandList* cmdList) } } -static NVSDK_NGX_Result TryCreateOptiFeature( - ID3D12GraphicsCommandList* InCmdList, - NVSDK_NGX_Feature InFeatureID, - NVSDK_NGX_Parameter* InParameters, - NVSDK_NGX_Handle** OutHandle) +static NVSDK_NGX_Result TryCreateOptiFeature(ID3D12GraphicsCommandList* InCmdList, NVSDK_NGX_Feature InFeatureID, + NVSDK_NGX_Parameter* InParameters, NVSDK_NGX_Handle** OutHandle) { State& state = State::Instance(); const Config& cfg = *Config::Instance(); @@ -682,8 +673,7 @@ static NVSDK_NGX_Result TryCreateOptiFeature( Dx12Contexts[handleId] = {}; // Retrieve feature implementation - if (!FeatureProvider_Dx12::GetFeature(featureName, handleId, - InParameters, &Dx12Contexts[handleId].feature)) + if (!FeatureProvider_Dx12::GetFeature(featureName, handleId, InParameters, &Dx12Contexts[handleId].feature)) { LOG_ERROR("Failed to retrieve feature implementation for '{}'", featureName); @@ -748,11 +738,10 @@ static NVSDK_NGX_Result TryCreateOptiFeature( * provides a handle used to reference the feature elsewhere in the API. Currently supports * various TSR and Frame Generation algorithms, including a special case for DLSS-RR passthrough. */ -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature( - ID3D12GraphicsCommandList* InCmdList, - NVSDK_NGX_Feature InFeatureID, - NVSDK_NGX_Parameter* InParameters, - NVSDK_NGX_Handle** OutHandle) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsCommandList* InCmdList, + NVSDK_NGX_Feature InFeatureID, + NVSDK_NGX_Parameter* InParameters, + NVSDK_NGX_Handle** OutHandle) { LOG_FUNC(); @@ -889,14 +878,13 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle* } /** - * @brief Used by the client application to check for feature support. + * @brief Used by the client application to check for feature support. * @param Adapter Device the feature is for. * @param FeatureDiscoveryInfo Specifies the feature being queried. - * @param OutSupported Used to indicate whether a feature is supported and its requirements. + * @param OutSupported Used to indicate whether a feature is supported and its requirements. */ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetFeatureRequirements( - IDXGIAdapter* Adapter, - const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo, + IDXGIAdapter* Adapter, const NVSDK_NGX_FeatureDiscoveryInfo* FeatureDiscoveryInfo, NVSDK_NGX_FeatureRequirement* OutSupported) { LOG_DEBUG("for ({0})", (int) FeatureDiscoveryInfo->FeatureID); @@ -944,11 +932,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetFeatureRequirements( return NVSDK_NGX_Result_FAIL_FeatureNotSupported; } -static NVSDK_NGX_Result TryEvaluateOptiFeature( - ID3D12GraphicsCommandList* InCmdList, - const NVSDK_NGX_Handle* InFeatureHandle, - NVSDK_NGX_Parameter* InParameters, - PFN_NVSDK_NGX_ProgressCallback InCallback) +static NVSDK_NGX_Result TryEvaluateOptiFeature(ID3D12GraphicsCommandList* InCmdList, + const NVSDK_NGX_Handle* InFeatureHandle, + NVSDK_NGX_Parameter* InParameters, + PFN_NVSDK_NGX_ProgressCallback InCallback) { State& state = State::Instance(); const Config& cfg = *Config::Instance(); @@ -986,7 +973,8 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( // Resolution change detection (only for upscalers that may require recreation) if (feature != nullptr) { - const bool isFSR31OrLater = feature->Name().starts_with("FSR") && feature->Version() >= feature_version { 3, 1, 0 }; + const bool isFSR31OrLater = + feature->Name().starts_with("FSR") && feature->Version() >= feature_version { 3, 1, 0 }; // FSR 3.1 supports upscaleSize that doesn't need reinit to change output resolution if (!isFSR31OrLater && feature->UpdateOutputResolution(InParameters)) @@ -999,8 +987,7 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( UpscalerInputsDx12::Reset(); contextRendering = false; - FeatureProvider_Dx12::ChangeFeature(state.newBackend, D3D12Device, - InCmdList, handleId, InParameters, &ctxData); + FeatureProvider_Dx12::ChangeFeature(state.newBackend, D3D12Device, InCmdList, handleId, InParameters, &ctxData); feature = ctxData.feature.get(); evalCounter = 0; @@ -1017,7 +1004,7 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( } state.currentFeature = feature; - + // Root signature restoration setup const bool restoreCompute = cfg.RestoreComputeSignature.value_or_default(); const bool restoreGraphic = cfg.RestoreGraphicSignature.value_or_default(); @@ -1067,11 +1054,10 @@ static NVSDK_NGX_Result TryEvaluateOptiFeature( * @brief Per-frame feature execution. Runs a feature (upscaler, framegen, etc.) on a given command list using a * preexisting feature instance referenced by a unique handle. */ -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature( - ID3D12GraphicsCommandList* InCmdList, - const NVSDK_NGX_Handle* InFeatureHandle, - NVSDK_NGX_Parameter* InParameters, - PFN_NVSDK_NGX_ProgressCallback InCallback) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCmdList, + const NVSDK_NGX_Handle* InFeatureHandle, + NVSDK_NGX_Parameter* InParameters, + PFN_NVSDK_NGX_ProgressCallback InCallback) { if (!InFeatureHandle) { @@ -1122,10 +1108,9 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature( #pragma region DLSS Buffer Size Call -NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetScratchBufferSize( - NVSDK_NGX_Feature InFeatureId, - const NVSDK_NGX_Parameter* InParameters, - size_t* OutSizeInBytes) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, + const NVSDK_NGX_Parameter* InParameters, + size_t* OutSizeInBytes) { if (OutSizeInBytes == nullptr) return NVSDK_NGX_Result_FAIL_InvalidParameter; diff --git a/OptiScaler/upscalers/FeatureProvider_Dx11.cpp b/OptiScaler/upscalers/FeatureProvider_Dx11.cpp index 8759f68a9..250e867c1 100644 --- a/OptiScaler/upscalers/FeatureProvider_Dx11.cpp +++ b/OptiScaler/upscalers/FeatureProvider_Dx11.cpp @@ -108,18 +108,14 @@ bool FeatureProvider_Dx11::GetFeature(std::string upscalerName, UINT handleId, N return result; } -bool FeatureProvider_Dx11::ChangeFeature( - std::string upscalerName, - ID3D11Device* device, - ID3D11DeviceContext* devContext, - UINT handleId, - NVSDK_NGX_Parameter* parameters, - ContextData* contextData) +bool FeatureProvider_Dx11::ChangeFeature(std::string upscalerName, ID3D11Device* device, + ID3D11DeviceContext* devContext, UINT handleId, + NVSDK_NGX_Parameter* parameters, ContextData* contextData) { State& state = State::Instance(); Config& cfg = *Config::Instance(); - if (state.newBackend == "" || (!cfg.DLSSEnabled.value_or_default() && state.newBackend == "dlss")) + if (state.newBackend == "" || (!cfg.DLSSEnabled.value_or_default() && state.newBackend == "dlss")) state.newBackend = cfg.Dx11Upscaler.value_or_default(); contextData->changeBackendCounter++; diff --git a/OptiScaler/upscalers/FeatureProvider_Dx12.cpp b/OptiScaler/upscalers/FeatureProvider_Dx12.cpp index c84758e25..4a358a968 100644 --- a/OptiScaler/upscalers/FeatureProvider_Dx12.cpp +++ b/OptiScaler/upscalers/FeatureProvider_Dx12.cpp @@ -14,11 +14,8 @@ #include "upscalers/xess/XeSSFeature_Dx12.h" #include "FeatureProvider_Dx11.h" -bool FeatureProvider_Dx12::GetFeature( - std::string_view upscalerName, - UINT handleId, - NVSDK_NGX_Parameter* parameters, - std::unique_ptr* feature) +bool FeatureProvider_Dx12::GetFeature(std::string_view upscalerName, UINT handleId, NVSDK_NGX_Parameter* parameters, + std::unique_ptr* feature) { State& state = State::Instance(); Config& cfg = *Config::Instance(); @@ -81,13 +78,9 @@ bool FeatureProvider_Dx12::GetFeature( return loaded; } -bool FeatureProvider_Dx12::ChangeFeature( - std::string_view upscalerName, - ID3D12Device* device, - ID3D12GraphicsCommandList* cmdList, - UINT handleId, - NVSDK_NGX_Parameter* parameters, - ContextData* contextData) +bool FeatureProvider_Dx12::ChangeFeature(std::string_view upscalerName, ID3D12Device* device, + ID3D12GraphicsCommandList* cmdList, UINT handleId, + NVSDK_NGX_Parameter* parameters, ContextData* contextData) { State& state = State::Instance(); Config& cfg = *Config::Instance(); @@ -108,8 +101,7 @@ bool FeatureProvider_Dx12::ChangeFeature( // first release everything if (contextData->changeBackendCounter == 1) { - if (state.currentFG != nullptr && state.currentFG->IsActive() && - state.activeFgInput == FGInput::Upscaler) + if (state.currentFG != nullptr && state.currentFG->IsActive() && state.activeFgInput == FGInput::Upscaler) { state.currentFG->DestroyFGContext(); state.FGchanged = true; diff --git a/OptiScaler/upscalers/FeatureProvider_Dx12.h b/OptiScaler/upscalers/FeatureProvider_Dx12.h index f427de1ba..57ec46c2d 100644 --- a/OptiScaler/upscalers/FeatureProvider_Dx12.h +++ b/OptiScaler/upscalers/FeatureProvider_Dx12.h @@ -6,18 +6,9 @@ class FeatureProvider_Dx12 { public: + static bool GetFeature(std::string_view upscalerName, UINT handleId, NVSDK_NGX_Parameter* parameters, + std::unique_ptr* feature); - static bool GetFeature( - std::string_view upscalerName, - UINT handleId, - NVSDK_NGX_Parameter* parameters, - std::unique_ptr* feature); - - static bool ChangeFeature( - std::string_view upscalerName, - ID3D12Device* device, - ID3D12GraphicsCommandList* cmdList, - UINT handleId, - NVSDK_NGX_Parameter* parameters, - ContextData* contextData); + static bool ChangeFeature(std::string_view upscalerName, ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, + UINT handleId, NVSDK_NGX_Parameter* parameters, ContextData* contextData); }; diff --git a/OptiScaler/upscalers/FeatureProvider_Vk.cpp b/OptiScaler/upscalers/FeatureProvider_Vk.cpp index 0173a38fa..7af960ccb 100644 --- a/OptiScaler/upscalers/FeatureProvider_Vk.cpp +++ b/OptiScaler/upscalers/FeatureProvider_Vk.cpp @@ -110,8 +110,7 @@ bool FeatureProvider_Vk::ChangeFeature(std::string upscalerName, VkInstance inst State& state = State::Instance(); Config& cfg = *Config::Instance(); - if (state.newBackend == "" || - (!cfg.DLSSEnabled.value_or_default() && state.newBackend == "dlss")) + if (state.newBackend == "" || (!cfg.DLSSEnabled.value_or_default() && state.newBackend == "dlss")) state.newBackend = cfg.VulkanUpscaler.value_or_default(); contextData->changeBackendCounter++; diff --git a/OptiScaler/upscalers/IFeature.cpp b/OptiScaler/upscalers/IFeature.cpp index 00afde0cc..29e5c5153 100644 --- a/OptiScaler/upscalers/IFeature.cpp +++ b/OptiScaler/upscalers/IFeature.cpp @@ -169,7 +169,8 @@ bool IFeature::SetInitParameters(NVSDK_NGX_Parameter* InParameters) return false; } -void IFeature::GetRenderResolution(const NVSDK_NGX_Parameter* InParameters, unsigned int* OutWidth, unsigned int* OutHeight) +void IFeature::GetRenderResolution(const NVSDK_NGX_Parameter* InParameters, unsigned int* OutWidth, + unsigned int* OutHeight) { if (InParameters->Get(NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width, OutWidth) != NVSDK_NGX_Result_Success || diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp index d714e9bf6..f09f8e1d6 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11.cpp @@ -522,7 +522,8 @@ bool FSR2FeatureDx11::Evaluate(ID3D11DeviceContext* InContext, NVSDK_NGX_Paramet else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp index 5ae213bb9..b2cf3ead2 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx11On12.cpp @@ -297,7 +297,8 @@ bool FSR2FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_N else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp index d73338f08..ab8a16344 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Dx12.cpp @@ -362,7 +362,8 @@ bool FSR2FeatureDx12::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVSDK_N else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp b/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp index dd84e96f5..fde1b2f23 100644 --- a/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp +++ b/OptiScaler/upscalers/fsr2/FSR2Feature_Vk.cpp @@ -528,7 +528,8 @@ bool FSR2FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* I else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float) TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp index 1e2220993..f47f14dc8 100644 --- a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp +++ b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx11On12_212.cpp @@ -299,7 +299,8 @@ bool FSR2FeatureDx11on12_212::Evaluate(ID3D11DeviceContext* InDeviceContext, NVS else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp index aaed71747..d1f126b72 100644 --- a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp +++ b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Dx12_212.cpp @@ -370,7 +370,8 @@ bool FSR2FeatureDx12_212::Evaluate(ID3D12GraphicsCommandList* InCommandList, NVS else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp index d55a27ab9..b16898035 100644 --- a/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp +++ b/OptiScaler/upscalers/fsr2_212/FSR2Feature_Vk_212.cpp @@ -551,7 +551,8 @@ bool FSR2FeatureVk212::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature.h b/OptiScaler/upscalers/fsr31/FSR31Feature.h index eed4d28c8..c52d40661 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature.h +++ b/OptiScaler/upscalers/fsr31/FSR31Feature.h @@ -51,7 +51,7 @@ class FSR31Feature : public virtual IFeature switch (format) { case FFX_API_SURFACE_FORMAT_R10G10B10A2_TYPELESS: - format = FFX_API_SURFACE_FORMAT_R10G10B10A2_UNORM; + format = FFX_API_SURFACE_FORMAT_R10G10B10A2_UNORM; return; case FFX_API_SURFACE_FORMAT_R32G32B32A32_TYPELESS: diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp index 71995f1f1..e1fdcca60 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11.cpp @@ -443,7 +443,8 @@ bool FSR31FeatureDx11::Evaluate(ID3D11DeviceContext* DeviceContext, NVSDK_NGX_Pa else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp index 1e5fe6738..6b4be9025 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Dx11On12.cpp @@ -345,7 +345,8 @@ bool FSR31FeatureDx11on12::Evaluate(ID3D11DeviceContext* InDeviceContext, NVSDK_ else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); diff --git a/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp b/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp index c23b4a261..f7ddda95a 100644 --- a/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp +++ b/OptiScaler/upscalers/fsr31/FSR31Feature_Vk.cpp @@ -667,7 +667,8 @@ bool FSR31FeatureVk::Evaluate(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Parameter* else if (cfg.FsrHorizontalFov.value_or_default() > 0.0f) { const float hFovRad = GetRadiansFromDeg(cfg.FsrHorizontalFov.value()); - params.cameraFovAngleVertical = GetVerticalFovFromHorizontal(hFovRad, (float)TargetWidth(), (float)TargetHeight()); + params.cameraFovAngleVertical = + GetVerticalFovFromHorizontal(hFovRad, (float) TargetWidth(), (float) TargetHeight()); } else params.cameraFovAngleVertical = GetRadiansFromDeg(60); From f9875626d74b93ba2383a07230d2fa5f0c46151e Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Wed, 25 Feb 2026 00:11:05 -0500 Subject: [PATCH 7/8] Fix potential NGX handle memory leak if device couldn't be acquired Fixed a preexisting edge case that could cause the NGX handle to be leaked if the D3D12 device could not be acquired. --- OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp index 68d360139..9b3a4a26b 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp @@ -684,12 +684,6 @@ static NVSDK_NGX_Result TryCreateOptiFeature(ID3D12GraphicsCommandList* InCmdLis return NVSDK_NGX_Result_Fail; } - // Assign handle - if (*OutHandle == nullptr) - *OutHandle = new NVSDK_NGX_Handle { handleId }; - else - (*OutHandle)->Id = handleId; - // Ensure D3D12 device if (!EnsureD3D12Device(InCmdList)) { @@ -698,11 +692,17 @@ static NVSDK_NGX_Result TryCreateOptiFeature(ID3D12GraphicsCommandList* InCmdLis if (shouldRestore) contextRendering = false; - // Partial cleanup � handle is allocated but context is incomplete + // Partial cleanup handle is allocated but context is incomplete Dx12Contexts.erase(handleId); return NVSDK_NGX_Result_Fail; } + // Assign handle + if (*OutHandle == nullptr) + *OutHandle = new NVSDK_NGX_Handle { handleId }; + else + (*OutHandle)->Id = handleId; + state.AutoExposure.reset(); IFeature_Dx12* feature = Dx12Contexts[handleId].feature.get(); From 2649058298c57e8cb24636dc3526ac04c8afb066 Mon Sep 17 00:00:00 2001 From: Zach Hembree Date: Wed, 25 Feb 2026 00:01:48 -0500 Subject: [PATCH 8/8] Fix Vulkan upscaler typo and DX11 init error - Vulkan: Correct default upscaler key from FSR 2.1 to FSR 2.2. - DX11: Removed redundant table initialization in DLSS inputs caused by copy-paste error. --- OptiScaler/Config.h | 2 +- OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h index 056a1078a..ed5558aa6 100644 --- a/OptiScaler/Config.h +++ b/OptiScaler/Config.h @@ -338,7 +338,7 @@ class Config // Upscalers CustomOptional Dx11Upscaler { std::string(OptiKeys::FSR22) }; CustomOptional Dx12Upscaler { std::string(OptiKeys::XeSS) }; - CustomOptional VulkanUpscaler { std::string(OptiKeys::FSR21) }; + CustomOptional VulkanUpscaler { std::string(OptiKeys::FSR22) }; // Output Scaling CustomOptional OutputScalingEnabled { false }; diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp index 04650c8d5..89345989e 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx11.cpp @@ -351,7 +351,6 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D11_AllocateParameters(NVSDK_NGX_Para } *OutParameters = new NVNGX_Parameters("OptiDx11", false); - InitNGXParameters(*OutParameters); return NVSDK_NGX_Result_Success; }