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 ::ReclaimDeferredResources(u64 completed_sync_point) {
+ sentenced_buffers.Reclaim(completed_sync_point);
+}
+
template ::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 ::ReclaimMemory(u64 target_bytes, bool allow_download) {
return freed;
}
+template ::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 ::EnsureHeadroom(bool allow_download) {
if (reclaim_stalled) {
@@ -250,12 +256,10 @@ template ::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;