From 092c16d6f39b395e7b3e105a42963733bf9de045 Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Fri, 30 Oct 2026 00:54:19 -0400 Subject: gpu_split: reset the ring when the split stops GpuSplit is a static instance and outlives the emulation session. Stop() joined the back thread but kept the ring positions and engine pointers, so the next session's back thread started reading at 0 of a new, empty ring while `published` still held the old session's position: each empty entry reads as a wrap, the back thread skipped ahead a ring at a time and never landed on the old position. The front then spun in Drain(), the next game's first GPU work never ran, and it waited on its first syncpoint forever (Mario Kart World loaded after another Switch 2 game: syncpoint 2 stuck at 0, waiting for 2). The back thread also held the previous session's freed engines. Stop() now drops the ring and resets the positions, the engines and the front macro mode, so MaybeStart() begins a clean ring. --- src/video_core/gpu_split.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/video_core/gpu_split.cpp') diff --git a/src/video_core/gpu_split.cpp b/src/video_core/gpu_split.cpp index 07fda589ff..f913ca82ce 100644 --- a/src/video_core/gpu_split.cpp +++ b/src/video_core/gpu_split.cpp @@ -122,6 +122,21 @@ void GpuSplit::Stop() { wake.notify_one(); back_thread.join(); active = false; + // The split is static and outlives the emulation session. The next session's back thread + // starts reading at 0: with the old positions kept it skipped through the new, empty ring a + // wrap at a time and never reached the old write position (the next game's first GPU work + // never ran, it waited on its syncpoint forever), and the engines it held were freed. + ring.reset(); + write_position = 0; + published_local = 0; + consumed_cache = 0; + publish_every = PublishEvery; + front_engine = nullptr; + back_engine = nullptr; + front_macros = false; + published.store(0, std::memory_order_relaxed); + consumed.store(0, std::memory_order_relaxed); + back_waiting.store(false, std::memory_order_relaxed); } u64* GpuSplit::ReserveSlow(size_t words) { -- cgit v1.2.3