diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 4cc85f8bd8..4c345dd213 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1014,7 +1014,7 @@ void BufferCache
::ResolveMultiRangeStorage(Binding& binding, bool is_written,
if (binding.gpu_addr == 0 || binding.size == 0) {
return;
}
- if (is_written) {
+ if (is_written && !runtime.PrefersSparseSources()) {
return;
}
const VirtualSegments* found =
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 0256306214..958f3b2a2e 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -411,7 +411,6 @@ u32 BufferCacheRuntime::GetStorageBufferAlignment() const {
}
void BufferCacheRuntime::TickFrame(Common::SlotVector& slot_buffers) noexcept {
- multi_range_buffers.TickFrame(scheduler);
for (auto it = slot_buffers.begin(); it != slot_buffers.end(); it++) {
if (scheduler.IsFree(it->LastUsageTick())) {
it->ResetUsageTracking();
diff --git a/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp b/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp
index a03c9174ef..4d84390002 100644
--- a/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp
+++ b/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp
@@ -168,22 +168,28 @@ SparseBuffer MultiRangeBufferCache::CreateSparse(const Device& device, Scheduler
return handle;
}
-bool MultiRangeBufferCache::RetireEntry(Scheduler& scheduler, Entry& entry) {
+void MultiRangeBufferCache::RetireEntry(Scheduler& scheduler, Entry& entry) {
if (!entry.sparse_handle && !entry.gathered) {
- return true;
+ return;
}
if (retired.size() == retired.capacity()) {
DrainRetired(scheduler);
}
if (retired.size() == retired.capacity()) {
- return false;
+ u64 oldest = retired.front().tick;
+ for (const Retired& item : retired) {
+ if (item.tick < oldest) {
+ oldest = item.tick;
+ }
+ }
+ scheduler.Wait(oldest);
+ DrainRetired(scheduler);
}
retired.push_back(Retired{
.handle = std::move(entry.sparse_handle),
.gathered = std::move(entry.gathered),
.tick = scheduler.CurrentTick(),
});
- return true;
}
void MultiRangeBufferCache::DrainRetired(Scheduler& scheduler) {
@@ -213,11 +219,8 @@ MultiRangeRef MultiRangeBufferCache::Get(const Device& device, Scheduler& schedu
const u64 geometry = HashSources(sources);
const u64 content = HashContent(sources);
const auto it = entries.find(key);
- if (it != entries.end() && !it->second.dead && it->second.geometry == geometry &&
- it->second.size == total) {
+ if (it != entries.end() && it->second.geometry == geometry && it->second.size == total) {
Entry& entry = it->second;
- entry.frame = frame_tick;
- entry.gpu_tick = scheduler.CurrentTick();
if (entry.content != content) {
entry.content = content;
entry.dirty = true;
@@ -237,9 +240,7 @@ MultiRangeRef MultiRangeBufferCache::Get(const Device& device, Scheduler& schedu
return ref;
}
if (it != entries.end()) {
- if (!RetireEntry(scheduler, it->second)) {
- return MultiRangeRef{};
- }
+ RetireEntry(scheduler, it->second);
entries.erase(it);
}
@@ -247,8 +248,6 @@ MultiRangeRef MultiRangeBufferCache::Get(const Device& device, Scheduler& schedu
entry.geometry = geometry;
entry.content = content;
entry.size = total;
- entry.frame = frame_tick;
- entry.gpu_tick = scheduler.CurrentTick();
if (CanBindSparse(sources)) {
entry.sparse_handle = CreateSparse(device, scheduler, sources, total);
if (entry.sparse_handle) {
@@ -325,13 +324,8 @@ void MultiRangeBufferCache::DropOwner(Scheduler& scheduler, VkBuffer owner) {
++it;
continue;
}
- if (RetireEntry(scheduler, entry)) {
- it = entries.erase(it);
- continue;
- }
- entry.dead = true;
- entry.owners.clear();
- ++it;
+ RetireEntry(scheduler, entry);
+ it = entries.erase(it);
}
}
@@ -341,24 +335,4 @@ void MultiRangeBufferCache::Invalidate(u64 key) {
}
}
-void MultiRangeBufferCache::TickFrame(Scheduler& scheduler) {
- ++frame_tick;
- if (!retired.empty()) {
- DrainRetired(scheduler);
- }
- if (entries.empty()) {
- return;
- }
- for (auto it = entries.begin(); it != entries.end();) {
- Entry& entry = it->second;
- const bool expired =
- frame_tick - entry.frame > FRAMES_TO_LIVE && scheduler.IsFree(entry.gpu_tick);
- if ((expired || entry.dead) && RetireEntry(scheduler, entry)) {
- it = entries.erase(it);
- } else {
- ++it;
- }
- }
-}
-
} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_multi_range_buffer.h b/src/video_core/renderer_vulkan/vk_multi_range_buffer.h
index 3022c61894..f40d3aa1f8 100644
--- a/src/video_core/renderer_vulkan/vk_multi_range_buffer.h
+++ b/src/video_core/renderer_vulkan/vk_multi_range_buffer.h
@@ -42,7 +42,6 @@ struct MultiRangeRef {
class MultiRangeBufferCache final {
public:
static constexpr VkDeviceSize DEFAULT_BLOCK_SIZE = 64 * 1024;
- static constexpr u64 FRAMES_TO_LIVE = 120;
static constexpr size_t MAX_RETIRED = 256;
explicit MultiRangeBufferCache(const Device& device);
@@ -60,8 +59,6 @@ public:
void DropOwner(Scheduler& scheduler, VkBuffer owner);
- void TickFrame(Scheduler& scheduler);
-
VkDeviceSize block_size{DEFAULT_BLOCK_SIZE};
bool use_sparse{};
@@ -80,10 +77,7 @@ private:
VkDeviceSize size{};
u64 geometry{};
u64 content{};
- u64 frame{};
- u64 gpu_tick{};
bool dirty{true};
- bool dead{};
};
[[nodiscard]] u64 HashSources(std::span sources) const;
@@ -98,13 +92,12 @@ private:
[[nodiscard]] VkDeviceSize QueryBlockSize(const Device& device, u32& memory_type_bits) const;
- bool RetireEntry(Scheduler& scheduler, Entry& entry);
+ void RetireEntry(Scheduler& scheduler, Entry& entry);
void DrainRetired(Scheduler& scheduler);
::Common::unordered_map entries;
boost::container::static_vector retired;
- u64 frame_tick{};
u32 sparse_memory_type_bits{};
VkBufferUsageFlags sparse_usage{};
};