From e7973dae7e2ea44665ff4ec83d7214a5d2daa366 Mon Sep 17 00:00:00 2001 From: Duck912 <350528965+Duck912@users.noreply.github.com> Date: Sun, 1 Nov 2026 21:39:54 -0500 Subject: nx2:vi2: sleep in the guest kernel while pacing presents The vi2 session is served by AM's thread on guest core 3, so the host sleep in PaceToVblank held that core for most of every frame. Game threads scheduled there only ran between presents: Fire Emblem: Fortune's Weave's loader got one RomFS read per frame (33 ms apart instead of about 4 ms), which doubled its load times. Assisted-by: Claude Opus 5.5 (debugging, implementation and drafting) Signed-off-by: Duck912 <350528965+Duck912@users.noreply.github.com> --- src/core/hle/service/nx2_gsv.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h index b8268b91a0..397e2aacb8 100644 --- a/src/core/hle/service/nx2_gsv.h +++ b/src/core/hle/service/nx2_gsv.h @@ -46,8 +46,10 @@ #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_session.h" +#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_transfer_memory.h" #include "core/hle/kernel/svc_results.h" #include "core/memory.h" @@ -1589,7 +1591,12 @@ private: // Running slower than the swap interval: show at once and don't bank the lost time. m_next_vblank = now; } else if (now < m_next_vblank) { - std::this_thread::sleep_until(m_next_vblank); + // Sleep this service thread in the guest kernel. It runs on guest core 3, and a host + // sleep held that core for the whole wait: game threads scheduled there ran only + // between presents (Fortune's Weave's loader read one RomFS block per frame). + const auto wait = std::chrono::duration_cast(m_next_vblank - now); + static_cast(Kernel::GetCurrentThread(kernel).Sleep( + kernel, kernel.HardwareTimer().GetTick() + wait.count() + 2)); } m_next_vblank += interval; } -- cgit v1.2.3