aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 08:42:26 -0500
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 08:48:31 -0500
commit86968cb5ce3195cb131eeb0ef68d2d8a4860f7df (patch)
tree98c2a3117e0d2ac199d60a5e480d18d46f655eb1 /src
parente2c512916c6f5042d030fcf1708043233f8df08e (diff)
buffer_cache: mark guest memory large buffer uploads came from cold
Like the texture cache's uploads: guest ranges of 256 KiB or more uploaded to the host GPU are mostly geometry the guest rarely reads again, so every 600 frames they are marked cold and the OS pages them out first when it needs RAM. (cherry picked from commit 5c942a5158a0f9769553eeba21b6121f277d0dc5)
Diffstat (limited to 'src')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h11
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h2
2 files changed, 13 insertions, 0 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 42d7ba066d..633f8760e4 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -100,6 +100,12 @@ void BufferCache<P>::TickFrame() {
return;
}
runtime.TickFrame(slot_buffers);
+ if (frame_tick % 600 == 0 && !uploaded_buffer_ranges.empty()) {
+ for (const auto& [address, size] : uploaded_buffer_ranges) {
+ device_memory.HintCold(address, size);
+ }
+ uploaded_buffer_ranges.clear();
+ }
if (static u64 frames{}; ++frames % 600 == 0) {
u64 total{};
size_t count{};
@@ -1923,6 +1929,11 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer,
u8* const src_pointer = staging_pointer.data() + copy.src_offset;
const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
device_memory.ReadBlockUnsafe(device_addr, src_pointer, copy.size);
+ // Large uploads are mostly geometry the host GPU now has its own copy of: TickFrame
+ // marks their guest memory cold (see TextureCache::RefreshContents).
+ if (copy.size >= 256_KiB) {
+ uploaded_buffer_ranges.emplace_back(device_addr, copy.size);
+ }
// Apply the staging offset
copy.src_offset += upload_staging.offset;
}
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index 45a1836341..0db8bdb1eb 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -549,6 +549,8 @@ private:
size_t immediate_buffer_capacity = 0;
Common::ScratchBuffer<u8> immediate_buffer_alloc;
+ /// Guest memory large uploads came from since the last cold hint (device address, size).
+ std::vector<std::pair<DAddr, u64>> uploaded_buffer_ranges;
struct LRUItemParams {
using ObjectType = BufferId;