From 990ffba23d0b376ebc8c11730a479e668e2ddd2b Mon Sep 17 00:00:00 2001 From: FakeMichau <49685661+FakeMichau@users.noreply.github.com> Date: Tue, 10 Sep 2024 14:26:59 +0200 Subject: [PATCH] Clean up LFX + switch to LFX when FG and an FPS cap are used AL2 doesn't seem to support limiting the framerate when used with FG --- OptiScaler/nvapi/fakenvapi/lowlatency.h | 28 ++++++++++++++----------- OptiScaler/nvapi/fakenvapi/nvapi.cpp | 2 +- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/OptiScaler/nvapi/fakenvapi/lowlatency.h b/OptiScaler/nvapi/fakenvapi/lowlatency.h index 1e6fc2c5..82b32ef1 100644 --- a/OptiScaler/nvapi/fakenvapi/lowlatency.h +++ b/OptiScaler/nvapi/fakenvapi/lowlatency.h @@ -33,7 +33,7 @@ struct LFXStats { uint64_t latency = 0; uint64_t frame_time = 1; uint64_t target = 0; - uint64_t lfx_frame_id = 0; + uint64_t frame_id = 0; bool needs_reset = false; }; @@ -91,25 +91,27 @@ public: inline HRESULT update() { if (!active) return S_FALSE; - if (al_available && !force_lfx) mode = AntiLag2; - else mode = LatencyFlex; + if (al_available && !force_lfx && (min_interval_us == 0 || !fg)) + mode = AntiLag2; + else + mode = LatencyFlex; log(std::format("LowLatency algo: {}", mode == AntiLag2 ? "AntiLag 2" : "LatencyFlex")); log(std::format("FG status: {}", fg ? "enabled" : "disabled")); if (mode == AntiLag2) { #if _MSC_VER && _WIN64 - if (lfx_stats.lfx_frame_id != 1) lfx_stats.needs_reset = true; + if (lfx_stats.frame_id != 1) lfx_stats.needs_reset = true; int max_fps = min_interval_us > 0 ? 1000000 / min_interval_us : 0; if (context_dx12.m_pAntiLagAPI) return AMD::AntiLag2DX12::Update(&context_dx12, true, max_fps); - else + else if (context_dx11.m_pAntiLagAPI) return AMD::AntiLag2DX11::Update(&context_dx11, true, max_fps); #endif } else if (mode == LatencyFlex) { if (lfx_stats.needs_reset) { log("LFX Reset"); - lfx_stats.lfx_frame_id = 1; + lfx_stats.frame_id = 1; lfx_stats.needs_reset = false; lf->Reset(); } @@ -119,12 +121,14 @@ public: // Set FPS Limiter lf->target_frame_time = 1000 * min_interval_us; - lf->EndFrame(lfx_stats.lfx_frame_id, current_timestamp, &lfx_stats.latency, &lfx_stats.frame_time); + lf->EndFrame(lfx_stats.frame_id, current_timestamp, &lfx_stats.latency, &lfx_stats.frame_time); log(std::format("LFX latency: {}, frame_time: {}, current_timestamp: {}", lfx_stats.latency, lfx_stats.frame_time, current_timestamp)); - lfx_stats.lfx_frame_id++; - lfx_stats.target = lf->GetWaitTarget(lfx_stats.lfx_frame_id); + lfx_stats.frame_id++; + lfx_stats.target = lf->GetWaitTarget(lfx_stats.frame_id); if (lfx_stats.target > current_timestamp) { + uint64_t extra_delay = 0; + // uint64_t extra_delay = (lfx_stats.target - current_timestamp) * 0.15; static uint64_t timeout_events = 0; uint64_t timeout_timestamp = current_timestamp + 50000000ULL; if (lfx_stats.target > timeout_timestamp) { @@ -132,15 +136,15 @@ public: timeout_events++; lfx_stats.needs_reset = timeout_events > 5; } else { - timestamp = lfx_stats.target; + timestamp = lfx_stats.target + extra_delay; timeout_events = 0; } - std::this_thread::sleep_for(std::chrono::nanoseconds(lfx_stats.target - current_timestamp)); + std::this_thread::sleep_for(std::chrono::nanoseconds(lfx_stats.target + extra_delay - current_timestamp)); } else { timestamp = current_timestamp; } - lf->BeginFrame(lfx_stats.lfx_frame_id, lfx_stats.target, timestamp); + lf->BeginFrame(lfx_stats.frame_id, lfx_stats.target, timestamp); return S_OK; } return S_FALSE; diff --git a/OptiScaler/nvapi/fakenvapi/nvapi.cpp b/OptiScaler/nvapi/fakenvapi/nvapi.cpp index 958a1814..18cc3821 100755 --- a/OptiScaler/nvapi/fakenvapi/nvapi.cpp +++ b/OptiScaler/nvapi/fakenvapi/nvapi.cpp @@ -529,7 +529,7 @@ namespace nvd { if (lowlatency_ctx.fg && repeat_count == 0) lowlatency_ctx.fg = false; else if (!lowlatency_ctx.fg && repeat_count >= history_size / 2) lowlatency_ctx.fg = true; - if (lowlatency_ctx.fg) lowlatency_ctx.set_fg_type(previous_frame_id != current_frame_id); + if (lowlatency_ctx.fg) lowlatency_ctx.set_fg_type(previous_frame_id == current_frame_id); previous_frame_id = current_frame_id; } log(std::format("Async markerType: {}, frame id: {}", (unsigned int)pSetAsyncFrameMarkerParams->markerType, (unsigned long long)pSetAsyncFrameMarkerParams->frameID));