aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 17:32:14 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 17:32:14 -0400
commit0f146960444b00f36733f9d6a0878293e24205ff (patch)
treeab9a530e9c45c76e7af725af9e267cf5f0855081 /src/core
parentca524c9aa883abc4d1c5aeb8aa4d2f9eb0b4225c (diff)
nx2: wait for the presented frame too when the GPU is behind
Present waits for the previous frame's fence so the game prepares the next frame while the GPU thread runs this one. When that fence is not reached yet at present, the GPU is the limit and running ahead gains nothing. It also let Splatoon Raiders get more than a frame ahead of a slow GPU (WSL with a software Vulkan driver): the game rewrote command lists Eden had not read yet (the pushbuffer check counted them changing between submit and execution), Eden then ran the mixed words as commands and crashed 30-50 s into the game on every run with builds 49 and 50. Wait for the presented frame's fence as well in that case; with the GPU keeping up nothing changes. Waiting for the presented frame (EDEN_NX2_FRAMES_AHEAD=0) ran the same session without a changed list or a crash.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/service/nx2_gsv.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/core/hle/service/nx2_gsv.h b/src/core/hle/service/nx2_gsv.h
index 9d00b81368..d787962dca 100644
--- a/src/core/hle/service/nx2_gsv.h
+++ b/src/core/hle/service/nx2_gsv.h
@@ -997,7 +997,19 @@ private:
LOG_DEBUG(Service, "nx2:vi2 present #{} fence ({}, {:#x}), waiting for ({}, {:#x}); now {:#x}",
m_presents, ~w[22], w[24], m_previous_fence_id, m_previous_fence_value,
~w[22] < 192 ? system.Host1x().GetSyncpointManager().GetGuestSyncpointValue(~w[22]) : 0U);
+ // Only run a frame ahead while the GPU keeps up. With the previous frame still on the
+ // GPU here, the GPU is the limit and running ahead gains nothing; and Splatoon Raiders,
+ // which reuses its command memory as if the GPU were at most a frame behind, rewrote
+ // command lists Eden had not read yet (misread commands, then crashes, with a slow
+ // GPU). Wait for this frame too then.
+ const bool gpu_behind =
+ m_previous_fence_id < 192 &&
+ !system.Host1x().GetSyncpointManager().IsReadyGuest(m_previous_fence_id,
+ m_previous_fence_value);
WaitForFrame(m_previous_fence_id, m_previous_fence_value);
+ if (gpu_behind) {
+ WaitForFrame(~w[22], w[24]);
+ }
m_previous_fence_id = ~w[22];
m_previous_fence_value = w[24];
} else {