diff --git a/OptiScaler.ini b/OptiScaler.ini index 2af8903b..0ef2d91f 100644 --- a/OptiScaler.ini +++ b/OptiScaler.ini @@ -259,6 +259,21 @@ ForceBorderless=auto ; true or false - Default (auto) is 1 InterpolationCount=auto +; Default (auto) is true +UseGamesReflexMarkers=auto + +; For overriding game's value sent to SL, could be Nvngx FG, could be noFG when someone uses real DLSSG +; Default (auto) is no override +OverrideInterpolationCount=auto + +; Try to force Dynamic MFG. Requires Nvidia Blackwell or any AMD/Intel +; Default (auto) is false +OverrideForceDMFG=auto + +; Sets the FPS target for dynamic multi frame generation +; When non-zero, you won't be able to manually adjust the FG multiplier +; Default (auto) is 0 (disabled) +FramerateTargetDMFG=auto ; ------------------------------------------------------- @@ -934,9 +949,6 @@ LatencyFlexMode=auto ; Default (auto) is 0 ForceReflex=auto -; When using FG via Nvngx, sets the FPS target for dynamic multi frame generation -; Default (auto) is 0 -FramerateTargetDMFG=auto ; ------------------------------------------------------- diff --git a/OptiScaler/Config.cpp b/OptiScaler/Config.cpp index 81260a11..4f0c4507 100644 --- a/OptiScaler/Config.cpp +++ b/OptiScaler/Config.cpp @@ -219,6 +219,13 @@ bool Config::Reload(std::filesystem::path iniPath) if (FGDLSSGOverrideInterpolationCount.has_value() && (FGDLSSGOverrideInterpolationCount.value() < 1 || FGDLSSGOverrideInterpolationCount.value() > 6)) FGDLSSGOverrideInterpolationCount.reset(); + + FGDLSSGFramerateTargetDMFG.set_from_config(readInt("DLSSG", "FramerateTargetDMFG")); + FGDLSSGOverrideForceDMFG.set_from_config(readBool("DLSSG", "OverrideForceDMFG")); + + // DMFG target can currently only be set on launch, inform using the ForceDMFG + if (FGDLSSGFramerateTargetDMFG.has_value() && FGDLSSGFramerateTargetDMFG.value() > 0) + FGDLSSGOverrideForceDMFG.set_volatile_value(true); } // FSR FG Inputs @@ -649,10 +656,8 @@ bool Config::Reload(std::filesystem::path iniPath) else FN_ForceReflex.reset(); - FramerateTargetDMFG.set_from_config(readInt("fakenvapi", "FramerateTargetDMFG")); - // DMFG is a mess with our reflex implementations, disable by default - if (FramerateTargetDMFG.value_or_default() != 0 && !FN_ForceReflex.has_value()) + if (FGDLSSGOverrideForceDMFG.value_or_default() && !FN_ForceReflex.has_value()) FN_ForceReflex.set_volatile_value(ForceReflex::ForceDisable); } @@ -920,6 +925,10 @@ bool Config::SaveIni() GetBoolValue(Instance()->FGDLSSGUseGamesReflexMarkers.value_for_config()).c_str()); ini.SetValue("DLSSG", "OverrideInterpolationCount", GetIntValue(Instance()->FGDLSSGOverrideInterpolationCount.value_for_config()).c_str()); + ini.SetValue("DLSSG", "FramerateTargetDMFG", + GetIntValue(Instance()->FGDLSSGFramerateTargetDMFG.value_for_config()).c_str()); + ini.SetValue("DLSSG", "OverrideForceDMFG", + GetBoolValue(Instance()->FGDLSSGOverrideForceDMFG.value_for_config()).c_str()); } // OptiFG @@ -1363,8 +1372,6 @@ bool Config::SaveIni() ini.SetValue("fakenvapi", "LatencyFlexMode", GetIntValue(Instance()->FN_LatencyFlexMode.value_for_config()).c_str()); ini.SetValue("fakenvapi", "ForceReflex", GetIntValue(Instance()->FN_ForceReflex.value_for_config()).c_str()); - ini.SetValue("fakenvapi", "FramerateTargetDMFG", - GetIntValue(Instance()->FramerateTargetDMFG.value_for_config()).c_str()); } // inputs diff --git a/OptiScaler/Config.h b/OptiScaler/Config.h index 1c917e69..b534cf8c 100644 --- a/OptiScaler/Config.h +++ b/OptiScaler/Config.h @@ -519,9 +519,13 @@ class Config CustomOptional FGXeFGForceBorderless { false }; // DLSSG - CustomOptional FGDLSSGInterpolationCount { 1 }; + CustomOptional FGDLSSGInterpolationCount { 1 }; // For Opti's own SL instance CustomOptional FGDLSSGUseGamesReflexMarkers { true }; - CustomOptional FGDLSSGOverrideInterpolationCount; + CustomOptional + FGDLSSGOverrideInterpolationCount; // For overriding game's value sent to SL, could be Nvngx FG, could be noFG + // but someone just uses real DLSSG + CustomOptional FGDLSSGOverrideForceDMFG { false }; // Overrides game's DLSSG mode to Dynamic + CustomOptional FGDLSSGFramerateTargetDMFG { 0 }; // Applies on launch // fakenvapi CustomOptional UseFakenvapi { true }; @@ -529,7 +533,6 @@ class Config CustomOptional FN_ForceLatencyFlex { false }; CustomOptional FN_LatencyFlexMode { LFXMode::Conservative }; CustomOptional FN_ForceReflex { ForceReflex::InGame }; - CustomOptional FramerateTargetDMFG { 0 }; // Inputs CustomOptional EnableDlssInputs { true }; diff --git a/OptiScaler/State.h b/OptiScaler/State.h index 89bdc833..ec0704e2 100644 --- a/OptiScaler/State.h +++ b/OptiScaler/State.h @@ -9,6 +9,7 @@ #include #include #include +#include enum class FGPreset : uint32_t { @@ -157,6 +158,7 @@ class State feature_version streamlineVersion = { 0, 0, 0 }; + // Has value when Opti was able to hook sl and the game set DLSSG options std::optional dlssgMfgMax = std::nullopt; API api = API::NotSelected; @@ -182,6 +184,9 @@ class State int xefgMaxInterpolationCount = 1; int dlssgMaxInterpolationCount = 1; + bool dlssgDMFGSupported = false; + sl::DLSSGMode dlssgLastSetMode = sl::DLSSGMode::eOff; + int dlssgDetectedInterpolationCount = 0; // DLSS bool dlssPresetsOverriddenExternally = false; diff --git a/OptiScaler/framegen/nvngx/Nvngx_FG.cpp b/OptiScaler/framegen/nvngx/Nvngx_FG.cpp index 40a64ea9..c206cf42 100644 --- a/OptiScaler/framegen/nvngx/Nvngx_FG.cpp +++ b/OptiScaler/framegen/nvngx/Nvngx_FG.cpp @@ -419,13 +419,6 @@ NVSDK_NGX_Result Nvngx_FG::D3D12_EvaluateFeature(ID3D12GraphicsCommandList* InCm } } - if (Config::Instance()->FramerateTargetDMFG.value_or_default() != 0 && fakenvapi::isUsingAsMainNvapi()) - { - int frameCount = 0; - InParameters->Get("DLSSG.MultiFrameCount", &frameCount); - Config::Instance()->FGDLSSGOverrideInterpolationCount.set_volatile_value(frameCount); - } - NVSDK_NGX_Handle TempHandle = { .Id = InFeatureHandle->Id - DLSSG_MOD_ID_OFFSET }; return _DLSSG_D3D12_EvaluateFeature(InCmdList, &TempHandle, InParameters, InCallback); } diff --git a/OptiScaler/hooks/Reflex_Hooks.cpp b/OptiScaler/hooks/Reflex_Hooks.cpp index db68ae24..6d07e276 100644 --- a/OptiScaler/hooks/Reflex_Hooks.cpp +++ b/OptiScaler/hooks/Reflex_Hooks.cpp @@ -642,8 +642,18 @@ void ReflexHooks::update(bool fgActive, bool isVulkan) if (lastFgNumFramesToGenerate != _FgNumFramesToGenerate) { + // Don't reload when using Dynamic MFG if (fakenvapi::isUsingAsMainNvapi()) - State::Instance().fakenvapiReloadLowLatency = true; + { + if (State::Instance().dlssgLastSetMode != (sl::DLSSGMode) 3) + State::Instance().fakenvapiReloadLowLatency = true; + + if (Config::Instance()->FN_ForceReflex.value_or_default() != ForceReflex::ForceEnable && + (State::Instance().dlssgLastSetMode != (sl::DLSSGMode) 3 || _FgNumFramesToGenerate > 1)) + { + Config::Instance()->FN_ForceReflex.set_volatile_value(ForceReflex::ForceDisable); + } + } lastFgNumFramesToGenerate = _FgNumFramesToGenerate; setFPSLimit(currentFps); diff --git a/OptiScaler/hooks/Streamline_Hooks.cpp b/OptiScaler/hooks/Streamline_Hooks.cpp index f2c8ab1b..7fcdea6b 100644 --- a/OptiScaler/hooks/Streamline_Hooks.cpp +++ b/OptiScaler/hooks/Streamline_Hooks.cpp @@ -748,16 +748,29 @@ sl::Result StreamlineHooks::hkslDLSSGSetOptions(const sl::ViewportHandle& viewpo lastDlssgViewport = viewport; lastDlssgOptions = options; - // Make DLSSG auto always mean On sl::DLSSGOptions newOptions = options; - newOptions.mode = newOptions.mode == sl::DLSSGMode::eOff ? sl::DLSSGMode::eOff : sl::DLSSGMode::eOn; + + // Make DLSSG auto always mean On + // if (newOptions.mode == sl::DLSSGMode::eAuto) + // newOptions.mode = sl::DLSSGMode::eOn; auto& state = State::Instance(); + const auto dlssgPotentiallyActive = newOptions.mode == sl::DLSSGMode::eOn || + newOptions.mode == sl::DLSSGMode::eAuto || newOptions.mode == (sl::DLSSGMode) 3; + + bool enableDynamicMode = Config::Instance()->FGDLSSGOverrideForceDMFG.value_or_default() && + state.dlssgDMFGSupported && dlssgPotentiallyActive; + + if (enableDynamicMode) + { + newOptions.mode = (sl::DLSSGMode) 3; + } + if (state.swapchainApi == API::Vulkan) { // Only matters for Vulkan, DX doesn't use this delay - if (options.mode != sl::DLSSGMode::eOff && !MenuOverlayBase::IsVisible()) + if (dlssgPotentiallyActive && !MenuOverlayBase::IsVisible()) state.delayMenuRenderBy = 10; if (MenuOverlayBase::IsVisible()) @@ -770,8 +783,9 @@ sl::Result StreamlineHooks::hkslDLSSGSetOptions(const sl::ViewportHandle& viewpo LOG_TRACE("DLSSG Modified Mode: {}", magic_enum::enum_name(newOptions.mode)); - if (options.mode != sl::DLSSGMode::eOff && state.streamlineVersion >= feature_version { 2, 7, 2 }) + if (dlssgPotentiallyActive && state.streamlineVersion >= feature_version { 2, 7, 1 }) { + // Populate dlssgMfgMax once if (!state.dlssgMfgMax.has_value()) { sl::DLSSGState localState {}; @@ -790,28 +804,84 @@ sl::Result StreamlineHooks::hkslDLSSGSetOptions(const sl::ViewportHandle& viewpo } } + // Won't take effect with Dynamic if (Config::Instance()->FGDLSSGOverrideInterpolationCount.has_value()) { - newOptions.numFramesToGenerate = Config::Instance()->FGDLSSGOverrideInterpolationCount.value(); + auto overrideCount = Config::Instance()->FGDLSSGOverrideInterpolationCount.value(); + if (overrideCount != 0) + newOptions.numFramesToGenerate = overrideCount; + else if (!enableDynamicMode) + newOptions.mode = sl::DLSSGMode::eOff; } } - if (newOptions.mode == sl::DLSSGMode::eOff) - ReflexHooks::setDlssgFrameCount(0); - else - ReflexHooks::setDlssgFrameCount(newOptions.numFramesToGenerate); + state.dlssgLastSetMode = newOptions.mode; return o_slDLSSGSetOptions(viewport, newOptions); } +// TODO: update once sl::DLSSGState becomes v4 +struct DLSSGState4 : sl::DLSSGState +{ + sl::Boolean bIsDynamicMFGSupportAvailable = sl::eInvalid; +}; + sl::Result StreamlineHooks::hkslDLSSGGetState(const sl::ViewportHandle& viewport, sl::DLSSGState& state, const sl::DLSSGOptions* options) { - auto result = o_slDLSSGGetState(viewport, state, options); + sl::Result result {}; + + { + static sl::DLSSGState s; + assert(s.structVersion == 3); + } + + const auto originalStructVersion = state.structVersion; + if (originalStructVersion < 4) + { + DLSSGState4 newState {}; + newState.structVersion = 4; + + // We might be feeding a newer struct to an older SL but that seems to work just fine for this Get function + result = o_slDLSSGGetState(viewport, dynamic_cast(newState), options); + + // Copy back data to game's struct + memcpy(&state, &newState, 56); // struct ver 1 size + state.structVersion = originalStructVersion; + + if (originalStructVersion >= 2) + { + state.numFramesToGenerateMax = newState.numFramesToGenerateMax; + state.bReserved4 = newState.bReserved4; + state.bIsVsyncSupportAvailable = newState.bIsVsyncSupportAvailable; + } + + if (originalStructVersion >= 3) + { + state.inputsProcessingCompletionFence = newState.inputsProcessingCompletionFence; + state.lastPresentInputsProcessingCompletionFenceValue = + newState.lastPresentInputsProcessingCompletionFenceValue; + } + + State::Instance().dlssgDMFGSupported = newState.bIsDynamicMFGSupportAvailable == sl::eTrue; + } + else + { + result = o_slDLSSGGetState(viewport, state, options); + + auto ver4struct = reinterpret_cast(state); + State::Instance().dlssgDMFGSupported = ver4struct.bIsDynamicMFGSupportAvailable == sl::eTrue; + } + + if (!State::Instance().dlssgDMFGSupported) + { + Config::Instance()->FGDLSSGOverrideForceDMFG.set_volatile_value(false); + Config::Instance()->FGDLSSGFramerateTargetDMFG.set_volatile_value(0); + } auto& optiState = State::Instance(); - if (optiState.streamlineVersion >= feature_version { 2, 7, 2 }) + if (optiState.streamlineVersion >= feature_version { 2, 7, 1 }) { if (!optiState.dlssgMfgMax.has_value()) { diff --git a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp index 963e6778..f6a95718 100644 --- a/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp +++ b/OptiScaler/inputs/NVNGX_DLSS_Dx12.cpp @@ -25,6 +25,7 @@ #include static ankerl::unordered_dense::map> Dx12Contexts; +static std::unordered_map HandleToFeature; static ID3D12Device* D3D12Device = nullptr; static int evalCounter = 0; @@ -666,7 +667,10 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsComma NVSDK_NGX_Result res = Nvngx_FG::D3D12_CreateFeature(InCmdList, InFeatureID, InParameters, OutHandle); if (*OutHandle) + { LOG_INFO("Created modded DLSSG feature with HandleId: {}", (*OutHandle)->Id); + HandleToFeature[(*OutHandle)->Id] = InFeatureID; + } return res; } @@ -682,9 +686,14 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsComma NVSDK_NGX_Result res = NVNGXProxy::D3D12_CreateFeature()(InCmdList, InFeatureID, InParameters, OutHandle); if (*OutHandle) + { LOG_INFO("Native CreateFeature success, HandleId: {}", (*OutHandle)->Id); + HandleToFeature[(*OutHandle)->Id] = InFeatureID; + } else + { LOG_INFO("Native CreateFeature failed: {:#x}", (uint32_t) res); + } return res; } @@ -694,7 +703,12 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsComma } // OptiScaler internal handling (SuperSampling or RayReconstruction) - return TryCreateOptiFeature(InCmdList, InFeatureID, InParameters, OutHandle); + auto tryResult = TryCreateOptiFeature(InCmdList, InFeatureID, InParameters, OutHandle); + + if (tryResult == NVSDK_NGX_Result_Success) + HandleToFeature[(*OutHandle)->Id] = InFeatureID; + + return tryResult; } NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle* InHandle) @@ -990,6 +1004,32 @@ NVSDK_NGX_API NVSDK_NGX_Result NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCom const State& state = State::Instance(); const Config& cfg = *Config::Instance(); + auto feature = HandleToFeature[handleId]; + static size_t evalWithoutFG = 0; + bool fgCreated = std::any_of(HandleToFeature.begin(), HandleToFeature.end(), + [](const auto& pair) { return pair.second == NVSDK_NGX_Feature_FrameGeneration; }); + + if (feature == NVSDK_NGX_Feature_FrameGeneration) + { + evalWithoutFG = 0; + + int frameCount = 0; + InParameters->Get("DLSSG.MultiFrameCount", &frameCount); + State::Instance().dlssgDetectedInterpolationCount = frameCount; + ReflexHooks::setDlssgFrameCount(frameCount); + } + else if (fgCreated) + { + evalWithoutFG++; + + if (evalWithoutFG == 6) + { + // Report FG as disabled + State::Instance().dlssgDetectedInterpolationCount = 0; + ReflexHooks::setDlssgFrameCount(0); + } + } + // Native DLSS passthrough if (handleId < DLSS_MOD_ID_OFFSET) { diff --git a/OptiScaler/menu/menu_common.cpp b/OptiScaler/menu/menu_common.cpp index e13bc55a..de8f6d66 100644 --- a/OptiScaler/menu/menu_common.cpp +++ b/OptiScaler/menu/menu_common.cpp @@ -3101,32 +3101,45 @@ bool MenuCommon::RenderMenu() ImGui::Spacing(); } - if (state.dlssgMfgMax.has_value() && state.dlssgMfgMax.value() > 1) + ImGui::BeginDisabled(state.dlssgDMFGSupported && + config->FGDLSSGOverrideForceDMFG.value_or_default()); + if (state.dlssgMfgMax.has_value() && state.dlssgMfgMax.value() >= 1) { auto maxInterpolationCount = state.dlssgMfgMax.value(); if (maxInterpolationCount > 1) { - const char* intModes[] = { "Off", "2X", "3X", "4X", "5X", "6X" }; - auto currentSet = config->FGDLSSGOverrideInterpolationCount.value_or(0); - auto currentIntCount = intModes[currentSet]; + const char* intModes[] = { "Default", "Off", "2X", "3X", "4X", "5X", "6X" }; + + // Map config value to UI index + int currentSet = 0; + if (config->FGDLSSGOverrideInterpolationCount.has_value()) + { + currentSet = config->FGDLSSGOverrideInterpolationCount.value() + 1; + } + + const char* currentIntCount = intModes[currentSet]; ImGui::PushItemWidth(95.0f * menuResScale); if (ImGui::BeginCombo("Override DLSSG", currentIntCount)) { - for (int i = 0; i <= maxInterpolationCount; i++) + for (int i = 0; i <= maxInterpolationCount + 1; i++) { if (ImGui::Selectable(intModes[i], (currentSet == i))) { if (i == 0) { + // Default, no override config->FGDLSSGOverrideInterpolationCount.reset(); } else { - LOG_DEBUG("DLSSG Interpolation Count set to: {}", i); - config->FGDLSSGOverrideInterpolationCount = i; + // UI index, store value + int framesToGenerate = i - 1; + + LOG_DEBUG("DLSSG Interpolation Count set to: {}", framesToGenerate); + config->FGDLSSGOverrideInterpolationCount = framesToGenerate; } StreamlineHooks::updateDlssgOptions(); @@ -3137,11 +3150,38 @@ bool MenuCommon::RenderMenu() } ImGui::PopItemWidth(); - - ShowHelpMarker("Overrides DLSSG interpolation count"); } } + ImGui::EndDisabled(); + + if (state.dlssgDMFGSupported) + { + ImGui::SameLine(0.0f, 16.0f); + + ImGui::BeginDisabled(config->FGDLSSGFramerateTargetDMFG.value_or_default()); + + if (bool dynamicMFG = config->FGDLSSGOverrideForceDMFG.value_or_default(); + ImGui::Checkbox("Force Dynamic MFG", &dynamicMFG)) + { + config->FGDLSSGOverrideForceDMFG = dynamicMFG; + StreamlineHooks::updateDlssgOptions(); + } + + if (config->FGDLSSGFramerateTargetDMFG.value_or_default()) + { + ShowHelpMarker("You have set a custom FPS target in the config\n" + "You cannot disable DMFG while the game is running"); + } + else + { + ShowHelpMarker("Currently targets your monitors refresh rate\n" + "For custom targets set FramerateTargetDMFG in the config and restart"); + } + + ImGui::EndDisabled(); + } + auto fgOutput = reinterpret_cast(state.currentFG); if (((state.activeFgOutput == FGOutput::FSRFG || state.activeFgOutput == FGOutput::XeFG || state.activeFgOutput == FGOutput::DLSSG || @@ -4170,12 +4210,14 @@ bool MenuCommon::RenderMenu() ImGui::Text("Using Nukem's via the MFG mod from dlss-enabler-headless.asi"); } + bool dmfgActive = state.dlssgDMFGSupported && config->FGDLSSGOverrideForceDMFG.value_or_default(); + if (!ReflexHooks::isReflexHooked()) { ImGui::TextColored(ImVec4(1.f, 0.f, 0.f, 1.f), "Reflex not hooked"); ImGui::Text("If you are using an AMD/Intel GPU, then make sure you have Fakenvapi"); } - else if (ReflexHooks::dlssgFrameCountToGenerate() == 0) + else if (ReflexHooks::dlssgFrameCountToGenerate() == 0 && !dmfgActive) { ImGui::Text("Please select DLSS Frame Generation in the game options\n" "You might need to select DLSS first"); @@ -4185,7 +4227,7 @@ bool MenuCommon::RenderMenu() { ImGui::Text("Current DLSSG state:"); ImGui::SameLine(); - if (auto count = ReflexHooks::dlssgFrameCountToGenerate(); count > 0) + if (auto count = state.dlssgDetectedInterpolationCount; count > 0) { ImGui::TextColored(ImVec4(0.f, 1.f, 0.25f, 1.f), std::format("ON {}x", count + 1).c_str()); } diff --git a/OptiScaler/nvapi/NvApiHooks.cpp b/OptiScaler/nvapi/NvApiHooks.cpp index 86e24aa0..e9811ba0 100644 --- a/OptiScaler/nvapi/NvApiHooks.cpp +++ b/OptiScaler/nvapi/NvApiHooks.cpp @@ -59,6 +59,43 @@ NvAPI_Status __stdcall NvApiHooks::hkNvAPI_DRS_GetSetting(NvDRSSessionHandle hSe auto result = o_NvAPI_DRS_GetSetting(hSession, hProfile, settingId, pSetting); if (pSetting && result == NVAPI_OK) { + const auto dmfgFpsTarget = Config::Instance()->FGDLSSGFramerateTargetDMFG.value_or_default(); + if (settingId == NGX_DLSSG_MODE_ID && dmfgFpsTarget != 0) + { + pSetting->settingId = settingId; + // constexpr auto name = L"NGX_DLSSG_MODE_ID"; + // memcpy_s(pSetting->settingName, sizeof(pSetting->settingName), name, sizeof(*name) * wcslen(name)); + pSetting->settingType = NVDRS_DWORD_TYPE; + pSetting->isCurrentPredefined = 0; + pSetting->u32CurrentValue = NGX_DLSSG_MODE_DEFAULT; + + LOG_DEBUG("Set NGX_DLSSG_MODE_ID to {}", pSetting->u32CurrentValue); + } + + if (settingId == NGX_DLSSG_DYNAMIC_TARGET_FRAME_RATE_ID && dmfgFpsTarget != 0) + { + pSetting->settingId = settingId; + // constexpr auto name = L"NGX_DLSSG_DYNAMIC_TARGET_FRAME_RATE_ID"; + // memcpy_s(pSetting->settingName, sizeof(pSetting->settingName), name, sizeof(*name) * wcslen(name)); + pSetting->settingType = NVDRS_DWORD_TYPE; + pSetting->isCurrentPredefined = 0; + pSetting->u32CurrentValue = dmfgFpsTarget; + + LOG_DEBUG("Set NGX_DLSSG_DYNAMIC_TARGET_FRAME_RATE_ID to {}", pSetting->u32CurrentValue); + } + + if (settingId == NGX_DLSSG_DYNAMIC_MULTI_FRAME_COUNT_MAX_ID && dmfgFpsTarget != 0) + { + pSetting->settingId = settingId; + // constexpr auto name = L"NGX_DLSSG_DYNAMIC_MULTI_FRAME_COUNT_MAX_ID"; + // memcpy_s(pSetting->settingName, sizeof(pSetting->settingName), name, sizeof(*name) * wcslen(name)); + pSetting->settingType = NVDRS_DWORD_TYPE; + pSetting->isCurrentPredefined = 0; + pSetting->u32CurrentValue = NGX_DLSSG_DYNAMIC_MULTI_FRAME_COUNT_MAX_DEFAULT; + + LOG_DEBUG("Set NGX_DLSSG_DYNAMIC_MULTI_FRAME_COUNT_MAX_ID to {}", pSetting->u32CurrentValue); + } + if (settingId == NGX_DLSS_SR_OVERRIDE_RENDER_PRESET_SELECTION_ID) { if (Config::Instance()->RenderPresetOverride.value_or_default()) diff --git a/OptiScaler/nvapi/fakenvapi/low_latency_d3d.cpp b/OptiScaler/nvapi/fakenvapi/low_latency_d3d.cpp index 47722bed..1f532c09 100644 --- a/OptiScaler/nvapi/fakenvapi/low_latency_d3d.cpp +++ b/OptiScaler/nvapi/fakenvapi/low_latency_d3d.cpp @@ -42,9 +42,10 @@ bool LowLatency::update_low_latency_tech(IUnknown* pDevice) delete currently_active_tech; } + // Don't use AL2 and XeLL when using DMFG or MFG if (!Config::Instance()->FN_ForceLatencyFlex.value_or_default() && - (!Nvngx_FG::isMFG() || ReflexHooks::dlssgFrameCountToGenerate() <= 1) && - Config::Instance()->FramerateTargetDMFG.value_or_default() == 0) + State::Instance().dlssgDetectedInterpolationCount <= 1 && + State::Instance().dlssgLastSetMode != (sl::DLSSGMode) 3) { currently_active_tech = new AntiLag2(); if (currently_active_tech->init(pDevice)) @@ -83,7 +84,7 @@ bool LowLatency::update_low_latency_tech(IUnknown* pDevice) bool change_detected = last_force_latencyflex != force_latencyflex; last_force_latencyflex = force_latencyflex; - if (State::Instance().fakenvapiReloadLowLatency && Config::Instance()->FramerateTargetDMFG.value_or_default() == 0) + if (State::Instance().fakenvapiReloadLowLatency) { change_detected = true; State::Instance().fakenvapiReloadLowLatency = false; diff --git a/OptiScaler/nvapi/fakenvapi/low_latency_tech/ll_antilag2.cpp b/OptiScaler/nvapi/fakenvapi/low_latency_tech/ll_antilag2.cpp index aafeca09..2c23c032 100644 --- a/OptiScaler/nvapi/fakenvapi/low_latency_tech/ll_antilag2.cpp +++ b/OptiScaler/nvapi/fakenvapi/low_latency_tech/ll_antilag2.cpp @@ -143,8 +143,14 @@ void AntiLag2::deinit() amdxc64_load_times = 0; } - if (dx12_ctx.m_pAntiLagAPI && !AMD::AntiLag2DX12::DeInitialize(&dx12_ctx)) - LOG_INFO("FSR Latency Reduction 2.0 DX12 deinitialized"); + if (dx12_ctx.m_pAntiLagAPI) + { + // WAR for AL2 not deiniting properly when it's enabled + AMD::AntiLag2DX12::Update(&dx12_ctx, false, 0); + + if (!AMD::AntiLag2DX12::DeInitialize(&dx12_ctx)) + LOG_INFO("FSR Latency Reduction 2.0 DX12 deinitialized"); + } if (dx11_ctx.m_pAntiLagAPI && !AMD::AntiLag2DX11::DeInitialize(&dx11_ctx)) LOG_INFO("FSR Latency Reduction 2.0 DX11 deinitialized"); diff --git a/OptiScaler/nvapi/fakenvapi/low_latency_vk.cpp b/OptiScaler/nvapi/fakenvapi/low_latency_vk.cpp index 305e6f22..0772c258 100644 --- a/OptiScaler/nvapi/fakenvapi/low_latency_vk.cpp +++ b/OptiScaler/nvapi/fakenvapi/low_latency_vk.cpp @@ -43,7 +43,7 @@ bool LowLatency::update_low_latency_tech(HANDLE vkDevice) bool change_detected = last_force_latencyflex != force_latencyflex; last_force_latencyflex = force_latencyflex; - if (State::Instance().fakenvapiReloadLowLatency && Config::Instance()->FramerateTargetDMFG.value_or_default() == 0) + if (State::Instance().fakenvapiReloadLowLatency) { change_detected = true; State::Instance().fakenvapiReloadLowLatency = false; diff --git a/OptiScaler/nvapi/fakenvapi/nvapi_calls.cpp b/OptiScaler/nvapi/fakenvapi/nvapi_calls.cpp index 993ed77b..a1ff11f3 100644 --- a/OptiScaler/nvapi/fakenvapi/nvapi_calls.cpp +++ b/OptiScaler/nvapi/fakenvapi/nvapi_calls.cpp @@ -724,35 +724,6 @@ NvAPI_Status __cdecl NvAPI_DRS_GetBaseProfile(NvDRSSessionHandle session, NvDRSP NvAPI_Status __cdecl NvAPI_DRS_GetSetting(NvDRSSessionHandle hSession, NvDRSProfileHandle hProfile, NvU32 settingId, NVDRS_SETTING* pSetting) { - auto setting = (ESetting) settingId; - - auto dmfgFpsTarget = Config::Instance()->FramerateTargetDMFG.value_or_default(); - if (setting == NGX_DLSSG_MODE_ID && dmfgFpsTarget != 0) - { - pSetting->settingId = settingId; - constexpr auto name = L"NGX_DLSSG_MODE_ID"; - memcpy_s(pSetting->settingName, sizeof(pSetting->settingName), name, sizeof(*name) * wcslen(name)); - pSetting->settingType = NVDRS_DWORD_TYPE; - pSetting->u32CurrentValue = NGX_DLSSG_MODE_DYNAMIC; - - LOG_DEBUG("Set NGX_DLSSG_MODE_ID"); - - return OK(); - } - - if (setting == NGX_DLSSG_DYNAMIC_TARGET_FRAME_RATE_ID && dmfgFpsTarget != 0) - { - pSetting->settingId = settingId; - constexpr auto name = L"NGX_DLSSG_DYNAMIC_TARGET_FRAME_RATE_ID"; - memcpy_s(pSetting->settingName, sizeof(pSetting->settingName), name, sizeof(*name) * wcslen(name)); - pSetting->settingType = NVDRS_DWORD_TYPE; - pSetting->u32CurrentValue = dmfgFpsTarget; - - LOG_DEBUG("Set NGX_DLSSG_DYNAMIC_TARGET_FRAME_RATE_ID to {}", pSetting->u32CurrentValue); - - return OK(); - } - LOG_DEBUG("Missing get setting: {:X}", settingId); return OK(); }