diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-29 06:22:54 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-29 20:49:47 -0400 |
| commit | be449da3db512f790c71d60a58e027a5898a0446 (patch) | |
| tree | f6b654821a27b50f248a409ac714b50015dfe327 /src/video_core/gpu.cpp | |
| parent | 8d72c1f92ac12ff5992b92b2e27b84aa31468879 (diff) | |
buffer_cache: no buffer downloads at every fence for Switch 2 titles
Eden copied every GPU-written buffer range back to guest memory at the next fence.
Title 1 signals a fence per compute dispatch, so that was 250-330 MB/s in 13,000-20,000
ranges a second, with the fencing thread holding the buffer cache while it wrote them.
Measured: the native MME's DMA reads never touched those pages (they read query words
written on the CPU side), and with reactive flushing the guest CPU read GPU-written
memory at most 64 times in 200 s. Without them, for Switch 2 titles (native tiling):
fences ~1.1 us instead of ~5, draw setup 6.1 us instead of 6.4-6.7, macro calls 160 ns
instead of 167-170, GPU-thread lock spinning 1.8% (was 5.5%). Regions stay marked GPU
written and are still flushed on demand. EDEN_NX2_BUFFER_DOWNLOADS=0/1 forces either
way. Reactive flushing reads of GPU-written memory are now counted in the log.
Diffstat (limited to 'src/video_core/gpu.cpp')
| -rw-r--r-- | src/video_core/gpu.cpp | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 6441b9511a..53f8f063f7 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -221,6 +221,13 @@ struct GPU::Impl { return raster_area; } raster_area.preemtive = true; + // A guest CPU read of GPU-written memory (reactive flushing): count them, they decide + // whether buffer data must be copied back at every fence (EDEN_NX2_BUFFER_DOWNLOADS). + if (static std::atomic<u64> reads{}; (reads.fetch_add(1, std::memory_order_relaxed) & 63) == 0) { + LOG_INFO(HW_GPU, "CPU read of GPU-written memory [{:#x}, {:#x}) ({} so far)", + raster_area.start_address, raster_area.end_address, + reads.load(std::memory_order_relaxed)); + } const u64 fence = RequestSyncOperation([this, &raster_area]() { renderer->ReadRasterizer()->FlushRegion(raster_area.start_address, raster_area.end_address - raster_area.start_address); }); |
