diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-30 17:32:14 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-30 17:32:14 -0400 |
| commit | 0f146960444b00f36733f9d6a0878293e24205ff (patch) | |
| tree | ab9a530e9c45c76e7af725af9e267cf5f0855081 /src/core | |
| parent | ca524c9aa883abc4d1c5aeb8aa4d2f9eb0b4225c (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.h | 12 |
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 { |
