diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index d4bc8d0ec5..7ef28929da 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -129,6 +129,10 @@ public: return master_semaphore->IsFree(tick); } + void RefreshTick() { + master_semaphore->Refresh(); + } + /// Waits for the given GPU tick, optionally pacing frames. void Wait(u64 tick, double target_fps = 0.0) { if (tick > 0) { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index a2a04379cd..549eedfe14 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -3235,6 +3235,14 @@ u64 TextureCacheRuntime::CurrentTick() const noexcept { return scheduler.CurrentTick(); } +bool TextureCacheRuntime::IsDirectUploadRetired(u64 tick) { + if (scheduler.IsFree(tick)) { + return true; + } + scheduler.RefreshTick(); + return scheduler.IsFree(tick); +} + void TextureCacheRuntime::TransitionImageLayout(Image& image) { if (!image.ExchangeInitialization()) { VkImageMemoryBarrier barrier{ diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 6ee1c52990..53c4da80bf 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -116,6 +116,8 @@ public: [[nodiscard]] u64 CurrentTick() const noexcept; + [[nodiscard]] bool IsDirectUploadRetired(u64 tick); + void InsertUploadMemoryBarrier() {} void TransitionImageLayout(Image& image); diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h index 4fd7eafe7d..6915a4d9af 100644 --- a/src/video_core/texture_cache/image_base.h +++ b/src/video_core/texture_cache/image_base.h @@ -95,7 +95,7 @@ struct ImageBase { u32 scale_rating = 0; u64 scale_tick = 0; bool has_scaled = false; - bool direct_upload_used = false; + u64 direct_upload_tick = 0; bool direct_upload_blocked = false; size_t channel = 0; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 75d1f42b31..2e4fb6e6a6 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -119,13 +119,16 @@ void TextureCache

::RunGarbageCollector() { bool aggressive_mode = false; u64 ticks_to_destroy = 0; size_t num_iterations = 0; + size_t num_downloads = 0; const auto Configure = [&](bool allow_aggressive) { high_priority_mode = total_used_memory >= expected_memory; aggressive_mode = allow_aggressive && total_used_memory >= critical_memory; ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL; num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10); + num_downloads = MAX_GC_DOWNLOADS_PER_PASS; }; - const auto Cleanup = [this, &num_iterations, &high_priority_mode, &aggressive_mode](ImageId image_id) { + const auto Cleanup = [this, &num_iterations, &num_downloads, &high_priority_mode, + &aggressive_mode](ImageId image_id) { if (num_iterations == 0) { return true; } @@ -139,6 +142,10 @@ void TextureCache

::RunGarbageCollector() { return false; } if (must_download) { + if (num_downloads == 0) { + return false; + } + --num_downloads; auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes); const auto copies = FixSmallVectorADL(FullDownloadCopies(image.info)); image.DownloadMemory(map, copies); @@ -585,9 +592,14 @@ FramebufferId TextureCache

::GetFramebufferId(const RenderTargets& key) { template void TextureCache

::WriteMemory(DAddr cpu_addr, size_t size) { ForEachImageInRegion(cpu_addr, size, [this](ImageId image_id, Image& image) { - if (image.direct_upload_used) { - image.direct_upload_used = false; - image.direct_upload_blocked = true; + if constexpr (USE_UNIFIED_MEMORY) { + if (image.direct_upload_tick != 0) { + const u64 upload_tick = image.direct_upload_tick; + image.direct_upload_tick = 0; + if (!runtime.IsDirectUploadRetired(upload_tick)) { + image.direct_upload_blocked = true; + } + } } if (True(image.flags & ImageFlagBits::CpuModified)) { return; @@ -1195,7 +1207,7 @@ bool TextureCache

::TryUploadFromUnifiedMemory([[maybe_unused]] Image& image) local_offset, FixSmallVectorADL(swizzles))) { return false; } - image.direct_upload_used = true; + image.direct_upload_tick = runtime.CurrentTick(); return true; } else { return false; diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 687c770794..44622a223c 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -121,6 +121,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches