From d8a0ef73e23adb79361929c05b84a17249775e4c Mon Sep 17 00:00:00 2001 From: Framer Date: Sun, 8 Nov 2026 05:06:01 +0100 Subject: [PATCH 1/2] perf(nx2): keep repeatedly uploaded guest memory hot --- src/video_core/texture_cache/texture_cache.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 1d4b4c82d0..c9cb4af90b 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -467,10 +467,21 @@ void TextureCache

::TickFrame() { TickAsyncDecode(); TickAsyncUnswizzle(); if (frame_tick % 600 == 0 && !uploaded_ranges.empty()) { - for (const auto& [address, size] : uploaded_ranges) { - device_memory.HintCold(address, size); + // A range uploaded repeatedly in this window is still actively used by the guest. + // Avoid evicting it from the working set only to fault it back in shortly after. + auto& ranges = uploaded_ranges; + std::sort(ranges.begin(), ranges.end()); + for (size_t i = 0; i < ranges.size();) { + size_t next = i + 1; + while (next < ranges.size() && ranges[next] == ranges[i]) { + ++next; + } + if (next - i == 1) { + device_memory.HintCold(ranges[i].first, ranges[i].second); + } + i = next; } - uploaded_ranges.clear(); + ranges.clear(); } runtime.TickFrame(); From a5720e7a7f30f669c7320f34001899ae8a251b65 Mon Sep 17 00:00:00 2001 From: Framer Date: Sun, 8 Nov 2026 05:06:04 +0100 Subject: [PATCH 2/2] perf(nx2): keep repeatedly uploaded guest memory hot --- src/video_core/buffer_cache/buffer_cache.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index be9b80c39b..ceb08ed7d9 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -109,10 +109,21 @@ void BufferCache

::TickFrame() { runtime.TickFrame(slot_buffers); native_indirect_uniforms_this_frame.clear(); if (frame_tick % 600 == 0 && !uploaded_buffer_ranges.empty()) { - for (const auto& [address, size] : uploaded_buffer_ranges) { - device_memory.HintCold(address, size); + // A range uploaded repeatedly in this window is still actively used by the guest. + // Avoid evicting it from the working set only to fault it back in shortly after. + auto& ranges = uploaded_buffer_ranges; + std::sort(ranges.begin(), ranges.end()); + for (size_t i = 0; i < ranges.size();) { + size_t next = i + 1; + while (next < ranges.size() && ranges[next] == ranges[i]) { + ++next; + } + if (next - i == 1) { + device_memory.HintCold(ranges[i].first, ranges[i].second); + } + i = next; } - uploaded_buffer_ranges.clear(); + ranges.clear(); } if (static u64 frames{}; ++frames % 600 == 0) { u64 total{};