diff options
| author | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-02 01:06:48 +0100 |
|---|---|---|
| committer | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-02 01:06:48 +0100 |
| commit | 6612817cb4b6da97c4fc88e232a8efa07a3704db (patch) | |
| tree | b77297449d71ef9b8c006d3d909f4c6afc951768 /src | |
| parent | 51d798ff0373a40098aa77ef13d54307f39e44ac (diff) | |
dma_pusher: restores the trees as the lorax wouldn't be happy without them (add IsGpuWrittenCommands method to check GPU-written entries)
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/dma_pusher.cpp | 25 | ||||
| -rw-r--r-- | src/video_core/dma_pusher.h | 2 |
2 files changed, 17 insertions, 10 deletions
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index cbbc7f26eb..1144488c91 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp @@ -157,9 +157,12 @@ bool DmaPusher::Step() { (Settings::IsDMALevelDefault() ? Settings::IsGPULevelHigh() : Settings::IsDMALevelSafe()); // 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). + // unflushed anyway). Entries on pages the GPU writes (culling) always take the flushing + // read: their words at submit time are an older frame's. const bool submitted = command_resume_offset == 0 && dma_pushbuffer_subindex < command_list.submitted_offsets.size() && + !IsGpuWrittenCommands(dma_state.dma_get, + size_t{header.size} * sizeof(u32)) && !(use_safe && memory_manager.IsMemoryDirty(dma_state.dma_get, header.size * sizeof(u32))); if (submitted) { @@ -460,22 +463,24 @@ void DmaPusher::CallMultiMethod(const u32* base_start, u32 num_methods) { } } -void DmaPusher::FlushGpuWrittenCommands(GPUVAddr address, size_t size) { - // Title 1 runs small command lists its culling dispatches fill in each frame. Accurate GPU - // mode reads every command list through the caches (safe reads); here only the ones on pages - // the GPU has written are, or their draws run with an older frame's words (trees vanish). +bool DmaPusher::IsGpuWrittenCommands(GPUVAddr address, size_t size) { if (!Tegra::g_nx2_ampere.load(std::memory_order_relaxed) || size == 0) { - return; + return false; } - bool written = false; for (GPUVAddr page = address & ~GPUVAddr{0xfff}; page < address + size; page += 0x1000) { if (const auto device = memory_manager.GpuToCpuAddress(page); device && Tegra::Nx2IsGpuWritten(*device)) { - written = true; - break; + return true; } } - if (!written) { + return false; +} + +void DmaPusher::FlushGpuWrittenCommands(GPUVAddr address, size_t size) { + // Title 1 runs small command lists its culling dispatches fill in each frame. Accurate GPU + // mode reads every command list through the caches (safe reads); here only the ones on pages + // the GPU has written are, or their draws run with an older frame's words (trees vanish). + if (!IsGpuWrittenCommands(address, size)) { return; } // The caches belong to the split's back: it first runs what the front queued (the dispatch diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h index d52aef821a..e9dd5e2b6b 100644 --- a/src/video_core/dma_pusher.h +++ b/src/video_core/dma_pusher.h @@ -186,6 +186,8 @@ public: void DumpCurrentEntry(const char* reason); void CheckSubmitHash(const CommandListHeader& header, u64 submit_hash); void RecordParsedEntry(const CommandListHeader& header, std::span<const CommandHeader> commands); + /// Whether the entry lies on device pages the GPU has written (NX2). + bool IsGpuWrittenCommands(GPUVAddr address, size_t size); /// Brings command list words the GPU wrote (still only in host buffers) to guest memory. void FlushGpuWrittenCommands(GPUVAddr address, size_t size); |
