diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 11 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache_base.h | 2 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 14 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 2 |
4 files changed, 29 insertions, 0 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 53874e75cc..70d79c3535 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{}; @@ -1928,6 +1934,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 d8a61b7913..47f342932d 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -580,6 +580,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; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 33ca051482..77485a282e 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -320,6 +320,12 @@ void TextureCache<P>::TickFrame() { sentenced_image_view.Tick(); TickAsyncDecode(); TickAsyncUnswizzle(); + if (frame_tick % 600 == 0 && !uploaded_ranges.empty()) { + for (const auto& [address, size] : uploaded_ranges) { + device_memory.HintCold(address, size); + } + uploaded_ranges.clear(); + } runtime.TickFrame(); ++frame_tick; @@ -1365,6 +1371,14 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) { auto staging = runtime.UploadStagingBuffer(MapSizeBytes(image)); UploadImageContents(image, staging); runtime.InsertUploadMemoryBarrier(); + // The host GPU has its own copy now and the guest rarely reads this memory again: TickFrame + // marks it cold, so the OS pages it out before anything else when it needs RAM (title 1 + // streams several GB of textures through it). + constexpr u64 ColdHintMinBytes = 64_KiB; + if (image.guest_size_bytes >= ColdHintMinBytes && + False(image.flags & (ImageFlagBits::GpuModified | ImageFlagBits::Sparse))) { + uploaded_ranges.emplace_back(image.cpu_addr, image.guest_size_bytes); + } } template <class P> diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 141e5b76d5..12240287ff 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -578,6 +578,8 @@ private: Common::ThreadWorker texture_decode_worker{1, "TextureDecoder", {}, Common::ThreadPlacement::Efficiency}; std::vector<std::unique_ptr<AsyncDecodeContext>> async_decodes; + /// Guest memory images were uploaded from since the last cold hint (device address, size). + std::vector<std::pair<DAddr, u64>> uploaded_ranges; std::deque<PendingUnswizzle> unswizzle_queue; u8 current_unswizzle_frame; |
