From 8476fbfcfe39d12f682c72964228e43167d1599c Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 6 Aug 2026 02:42:53 -0400 Subject: [PATCH] [TEST] Set on fps limiters with adfp --- src/common/adpf.cpp | 37 +++++++++---------- src/common/adpf.h | 4 +- .../service/nvdrv/devices/nvdisp_disp0.cpp | 2 +- src/core/hle/service/vi/conductor.cpp | 29 +++++++++++++-- src/core/hle/service/vi/conductor.h | 1 + 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/common/adpf.cpp b/src/common/adpf.cpp index a627375dd3..8fa2996173 100644 --- a/src/common/adpf.cpp +++ b/src/common/adpf.cpp @@ -101,8 +101,10 @@ struct SessionState { std::mutex g_mutex; std::array g_sessions; +constexpr s64 MAX_REPORTED_TARGETS = 4; + std::atomic g_target_ns{DEFAULT_TARGET.count()}; -thread_local std::chrono::steady_clock::time_point t_work_begin{}; +thread_local std::chrono::steady_clock::time_point t_last_frame{}; SessionState& StateOf(Session session) { return g_sessions[static_cast(session)]; @@ -119,8 +121,6 @@ void CloseLocked(SessionState& state) { } } -// Builds a session for the given thread list without touching any existing one, so a refusal -// costs nothing. AHintSession* CreateSessionFor(Session session, const std::vector& threads) { const Api& api = Resolve(); const s64 target = session == Session::Render ? g_target_ns.load(std::memory_order_relaxed) : 0; @@ -213,8 +213,6 @@ bool AddCurrentThread(Session session) { state.threads.push_back(tid); } if (!SyncLocked(session, state)) { - // The session in use survived the refusal and still holds the list without this thread, - // so only the addition has to be undone. if (added) { std::erase(state.threads, tid); } @@ -252,26 +250,27 @@ void SetTargetWorkDuration(std::chrono::nanoseconds target) { } } -void BeginFrameWork() { - if (!Resolve().usable) { - return; - } - t_work_begin = std::chrono::steady_clock::now(); -} - -void EndFrameWork() { +void ReportFrameInterval() { const Api& api = Resolve(); - if (!api.usable || t_work_begin.time_since_epoch().count() == 0) { + if (!api.usable) { return; } - const auto elapsed = std::chrono::steady_clock::now() - t_work_begin; - t_work_begin = {}; - const s64 actual = std::chrono::duration_cast(elapsed).count(); + const auto now = std::chrono::steady_clock::now(); + const auto previous = t_last_frame; + t_last_frame = now; + if (previous.time_since_epoch().count() == 0) { + return; + } + + s64 actual = std::chrono::duration_cast(now - previous).count(); if (actual <= 0) { return; } + const s64 ceiling = g_target_ns.load(std::memory_order_relaxed) * MAX_REPORTED_TARGETS; + actual = (std::min)(actual, ceiling); + std::scoped_lock lock{g_mutex}; SessionState& state = StateOf(Session::Render); if (state.handle != nullptr) { @@ -309,9 +308,7 @@ void RemoveCurrentThread() {} void SetTargetWorkDuration(std::chrono::nanoseconds) {} -void BeginFrameWork() {} - -void EndFrameWork() {} +void ReportFrameInterval() {} void Shutdown() {} diff --git a/src/common/adpf.h b/src/common/adpf.h index 8a74525e51..6f14a0bee4 100644 --- a/src/common/adpf.h +++ b/src/common/adpf.h @@ -18,8 +18,8 @@ bool AddCurrentThread(Session session); void RemoveCurrentThread(); void SetTargetWorkDuration(std::chrono::nanoseconds target); -void BeginFrameWork(); -void EndFrameWork(); + +void ReportFrameInterval(); void Shutdown(); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 5963902f4c..6e9fe9ec07 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -87,7 +87,7 @@ void nvdisp_disp0::Composite(std::span sorted_layers } system.GPU().RequestComposite(std::move(output_layers), std::move(output_fences)); - Common::ADPF::EndFrameWork(); + Common::ADPF::ReportFrameInterval(); system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs()); system.GetPerfStats().EndSystemFrame(); system.GetPerfStats().BeginSystemFrame(); diff --git a/src/core/hle/service/vi/conductor.cpp b/src/core/hle/service/vi/conductor.cpp index 748d39f27e..fd7233cf93 100644 --- a/src/core/hle/service/vi/conductor.cpp +++ b/src/core/hle/service/vi/conductor.cpp @@ -4,6 +4,8 @@ // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include + #include "common/adpf.h" #include "common/settings.h" #include "common/thread.h" @@ -16,6 +18,8 @@ constexpr auto FrameNs = std::chrono::nanoseconds{1000000000 / 60}; +constexpr s64 UNLOCKED_TARGET_DIVISOR = 4; + namespace Service::VI { Conductor::Conductor(Core::System& system, Container& container, DisplayList& displays) @@ -70,10 +74,8 @@ void Conductor::UnlinkVsyncEvent(u64 display_id, Event* event) { } void Conductor::ProcessVsync() { - Common::ADPF::BeginFrameWork(); - Common::PollThreadPolicies(); - Common::ADPF::SetTargetWorkDuration(std::chrono::nanoseconds{this->GetNextTicks()}); + Common::ADPF::SetTargetWorkDuration(std::chrono::nanoseconds{this->GetFramePeriodNs()}); for (auto& [display_id, manager] : m_vsync_managers) { m_container.ComposeOnDisplay(&m_swap_interval, &m_compose_speed_scale, display_id); @@ -123,4 +125,25 @@ s64 Conductor::GetNextTicks() const { return static_cast(speed_scale * (1000000000.f / effective_fps)); } +s64 Conductor::GetFramePeriodNs() const { + const auto& settings = Settings::values; + f32 speed_scale = 1.f; + bool unlocked = false; + if (settings.use_multi_core.GetValue()) { + if (settings.use_speed_limit.GetValue()) { + speed_scale = 100.f / Settings::SpeedLimit(); + } else { + unlocked = true; + } + } + speed_scale /= m_compose_speed_scale; + + const f32 effective_fps = 60.f / static_cast(m_swap_interval); + s64 period = static_cast(speed_scale * (1000000000.f / effective_fps)); + if (unlocked) { + period /= UNLOCKED_TARGET_DIVISOR; + } + return std::clamp(period, 1'000'000, 100'000'000); +} + } // namespace Service::VI diff --git a/src/core/hle/service/vi/conductor.h b/src/core/hle/service/vi/conductor.h index 59eb2fd022..7c93c230f7 100644 --- a/src/core/hle/service/vi/conductor.h +++ b/src/core/hle/service/vi/conductor.h @@ -44,6 +44,7 @@ private: void ProcessVsync(); void VsyncThread(std::stop_token token); s64 GetNextTicks() const; + s64 GetFramePeriodNs() const; private: Core::System& m_system;