diff options
| author | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-01 03:20:42 +0100 |
|---|---|---|
| committer | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-02 00:11:25 +0100 |
| commit | cce6d44af23f08a7287a66d745fec34e38c9eb25 (patch) | |
| tree | 6d26989c997978d71a2ea771be4dba28155b0845 /src/video_core/dma_pusher.cpp | |
| parent | 803ece5f90bbdc5ef9751f559cbe8b2ecbdb2aac (diff) | |
nx2: execute command lists as submitted
With the present waiting for the previous frame's fence, the game
refills command memory it already submitted while the GPU thread is
still running that frame, so some frames rendered into the wrong image.
Copy each entry's words at submit and execute the copy. Resumed entries
and ranges the GPU has newer words for still read memory.
EDEN_NX2_PB_SNAPSHOT=0 executes from memory.
Ported from Wael3rd/Eglantine-MKW (bd3119a86f).
Assisted-by: Claude Sonnet 5.5 (porting the fix)
(cherry picked from commit 408bb84d06ae0729697ef9bed2c2ba76ce6dff42)
Diffstat (limited to 'src/video_core/dma_pusher.cpp')
| -rw-r--r-- | src/video_core/dma_pusher.cpp | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 8c142b36db..cbbc7f26eb 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -155,7 +155,21 @@ bool DmaPusher::Step() { // (the split only starts with unsafe reads; the settings can change mid-game). const bool use_safe = !VideoCommon::GpuSplit::Get().Active() && (Settings::IsDMALevelDefault() ? Settings::IsGPULevelHigh() : Settings::IsDMALevelSafe()); - if (use_safe) { + // The words as submitted, unless this is a resumed entry or the GPU has newer ones the + // safe read below would flush (with the split, the front can't tell: it reads memory + // unflushed anyway). + const bool submitted = command_resume_offset == 0 && + dma_pushbuffer_subindex < command_list.submitted_offsets.size() && + !(use_safe && memory_manager.IsMemoryDirty(dma_state.dma_get, + header.size * sizeof(u32))); + if (submitted) { + const std::span<const CommandHeader> commands{ + command_list.submitted_words.data() + + command_list.submitted_offsets[dma_pushbuffer_subindex], + header.size}; + RecordParsedEntry(header, commands); + command_resume_offset += ProcessCommands(commands, 0); + } else if (use_safe) { Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader, Tegra::Memory::GuestMemoryFlags::SafeRead>headers(memory_manager, dma_state.dma_get, header.size, &command_headers); const std::span<const CommandHeader> commands{headers.data(), headers.size()}; RecordParsedEntry(header, commands); |
