aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-01 21:39:54 -0500
committerDuck912 <350528965+Duck912@users.noreply.github.com>2026-11-01 21:54:48 -0500
commite7973dae7e2ea44665ff4ec83d7214a5d2daa366 (patch)
tree84c7df0a4a94effb91f1260c2998d70b3f4349b1 /src/core/hle
parent9f22054c6360fcc1bafa673451a5764f5f2ca7d1 (diff)
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>
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/service/nx2_gsv.h9
1 files changed, 8 insertions, 1 deletions
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<std::chrono::nanoseconds>(m_next_vblank - now);
+ static_cast<void>(Kernel::GetCurrentThread(kernel).Sleep(
+ kernel, kernel.HardwareTimer().GetTick() + wait.count() + 2));
}
m_next_vblank += interval;
}