From b8f384f3bd9bde69e7da7f732a4efa07caf39b93 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 2 Aug 2026 01:04:19 -0400 Subject: [PATCH] Adjustments on the memory reclamations 2 --- src/video_core/buffer_cache/buffer_cache.h | 7 +++- .../buffer_cache/buffer_cache_base.h | 2 ++ .../renderer_vulkan/vk_rasterizer.cpp | 33 ++++++++++++++----- src/video_core/texture_cache/texture_cache.h | 20 ++++++----- .../texture_cache/texture_cache_base.h | 2 ++ 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 603f5f4932..d9fb98f58b 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -92,6 +92,11 @@ u64 BufferCache

::ReclaimMemory(u64 target_bytes, bool allow_download) { return freed; } +template +void BufferCache

::ReclaimDeferredResources(u64 completed_sync_point) { + sentenced_buffers.Reclaim(completed_sync_point); +} + template void BufferCache

::EnsureHeadroom(bool allow_download) { if (reclaim_stalled) { @@ -139,9 +144,9 @@ void BufferCache

::TickFrame() { usage_refresh_countdown = 0; reclaim_stalled = false; + ReclaimDeferredResources(runtime.CompletedSyncPoint()); EnsureHeadroom(true); ++frame_tick; - sentenced_buffers.Reclaim(runtime.CompletedSyncPoint()); for (auto& buffer : async_buffers_death_ring) { runtime.FreeDeferredStagingBuffer(buffer); diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 0b4896fbe8..804a5ca056 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -221,6 +221,8 @@ public: u64 ReclaimMemory(u64 target_bytes, bool allow_download); + void ReclaimDeferredResources(u64 completed_sync_point); + void WriteMemory(DAddr device_addr, u64 size); void CachedWriteMemory(DAddr device_addr, u64 size); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 9773fd32ac..d6a60e8439 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -247,17 +247,32 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra device_memory.GetBackingHardwareBufferBase()); } memory_allocator.SetReclaimCallback([this](u64 bytes) -> u64 { - u64 freed = staging_pool.ReclaimMemory(bytes); - if (freed < bytes) { - freed += texture_cache.ReclaimMemory(bytes - freed, false); - } - if (freed < bytes) { - freed += buffer_cache.ReclaimMemory(bytes - freed, false); - } auto& master_semaphore = scheduler.GetMasterSemaphore(); + const u64 usage_before = device.GetMemoryBudgetInfo().allocation_bytes; master_semaphore.Refresh(); - vk::TickDeletionQueue(master_semaphore.KnownGpuTick()); - return freed; + const u64 completed = master_semaphore.KnownGpuTick(); + texture_cache.ReclaimDeferredResources(completed); + buffer_cache.ReclaimDeferredResources(completed); + vk::TickDeletionQueue(completed); + const u64 usage_after = device.GetMemoryBudgetInfo().allocation_bytes; + const u64 drained = usage_before > usage_after ? usage_before - usage_after : 0; + if (drained >= bytes) { + return drained; + } + const u64 remaining = bytes - drained; + u64 evicted = staging_pool.ReclaimMemory(remaining); + if (evicted < remaining) { + evicted += texture_cache.ReclaimMemory(remaining - evicted, false); + } + if (evicted < remaining) { + evicted += buffer_cache.ReclaimMemory(remaining - evicted, false); + } + master_semaphore.Refresh(); + const u64 completed_after = master_semaphore.KnownGpuTick(); + texture_cache.ReclaimDeferredResources(completed_after); + buffer_cache.ReclaimDeferredResources(completed_after); + vk::TickDeletionQueue(completed_after); + return drained + evicted; }); } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index dc3e8dfe2d..4d100b67bd 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -182,10 +182,9 @@ u64 TextureCache

::ReclaimMemory(u64 target_bytes, bool allow_download) { } const bool must_download = image.IsSafeDownload(); if (must_download && True(image.flags & ImageFlagBits::BadOverlap)) { - LOG_WARNING(HW_GPU, - "Recovering bad overlap on eviction: gpu_addr=0x{:x} fmt={} {}x{}x{}", - image.gpu_addr, static_cast(image.info.format), image.info.size.width, - image.info.size.height, image.info.size.depth); + LOG_DEBUG(HW_GPU, "Recovering bad overlap on eviction: gpu_addr=0x{:x} fmt={} {}x{}x{}", + image.gpu_addr, static_cast(image.info.format), image.info.size.width, + image.info.size.height, image.info.size.depth); } bool queued_download = false; if (must_download) { @@ -226,6 +225,13 @@ u64 TextureCache

::ReclaimMemory(u64 target_bytes, bool allow_download) { return freed; } +template +void TextureCache

::ReclaimDeferredResources(u64 completed_sync_point) { + sentenced_images.Reclaim(completed_sync_point); + sentenced_framebuffers.Reclaim(completed_sync_point); + sentenced_image_view.Reclaim(completed_sync_point); +} + template void TextureCache

::EnsureHeadroom(bool allow_download) { if (reclaim_stalled) { @@ -250,12 +256,10 @@ template void TextureCache

::TickFrame() { usage_refresh_countdown = 0; reclaim_stalled = false; - EnsureHeadroom(true); const u64 completed_sync_point = runtime.CompletedSyncPoint(); TickEvictionDownloads(completed_sync_point); - sentenced_images.Reclaim(completed_sync_point); - sentenced_framebuffers.Reclaim(completed_sync_point); - sentenced_image_view.Reclaim(completed_sync_point); + ReclaimDeferredResources(completed_sync_point); + EnsureHeadroom(true); TickAsyncDecode(); TickAsyncUnswizzle(); diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 9817fadf3f..59132db9b3 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -159,6 +159,8 @@ public: u64 ReclaimMemory(u64 target_bytes, bool allow_download); + void ReclaimDeferredResources(u64 completed_sync_point); + /// Return a constant reference to the given image view id [[nodiscard]] const ImageView& GetImageView(ImageViewId id) const noexcept;