result{IR::BreadthFirstSearch(
value, [&env, &host_info, &ambiguous](const IR::Inst* inst)
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index dd99a4facd..dd5c8e1d57 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1937,6 +1937,9 @@ void BufferCache::DownloadBufferMemory(Buffer& buffer, DAddr device_addr, u64
template
void BufferCache::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
+ if constexpr (requires { runtime.OnBufferDeleted(slot_buffers[buffer_id]); }) {
+ runtime.OnBufferDeleted(slot_buffers[buffer_id]);
+ }
bool dirty_index{false};
boost::container::small_vector dirty_vertex_buffers;
const auto scalar_replace = [buffer_id](Binding& binding) {
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 203da3f43d..80e57fb9fb 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -207,6 +207,10 @@ public:
multi_range_buffers.Invalidate(key);
}
+ void OnBufferDeleted(const Buffer& buffer) {
+ multi_range_buffers.DropOwner(buffer.Handle());
+ }
+
void BindUniformBuffer(const Buffer& buffer, u32 offset, u32 size) {
BindBuffer(buffer, offset, size);
}
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 6386e2661a..4d07081317 100644
--- a/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp
+++ b/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp
@@ -246,6 +246,12 @@ MultiRangeRef MultiRangeBufferCache::Get(u64 key, std::spansecond;
+ bool owned = false;
+ for (const VkBuffer handle : entry.owners) {
+ if (handle == owner) {
+ owned = true;
+ break;
+ }
+ }
+ if (owned) {
+ DestroySparse(entry.sparse_handle);
+ it = entries.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
void MultiRangeBufferCache::Invalidate(u64 key) {
const auto it = entries.find(key);
if (it != entries.end()) {
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 d64d1f2fa7..41d97b5239 100644
--- a/src/video_core/renderer_vulkan/vk_multi_range_buffer.h
+++ b/src/video_core/renderer_vulkan/vk_multi_range_buffer.h
@@ -59,6 +59,8 @@ public:
void Invalidate(u64 key);
+ void DropOwner(VkBuffer owner);
+
void Clear();
private:
@@ -74,6 +76,7 @@ private:
VkDeviceSize size{};
u64 geometry{};
bool dirty{true};
+ std::vector owners;
};
[[nodiscard]] u64 HashSources(std::span sources) const;
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index 763f0b16f5..bee7cd6e57 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -305,48 +305,13 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo &ci, MemoryUsa
.priority = 0.f,
};
- const VkDevice logical = *device.GetLogical();
- const auto &dld = device.GetDispatchLoader();
-
VkBuffer handle{};
- vk::Check(dld.vkCreateBuffer(logical, &ci, nullptr, &handle));
-
- const VkBufferMemoryRequirementsInfo2 reqs_info{
- .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
- .pNext = nullptr,
- .buffer = handle,
- };
- VkMemoryRequirements2 reqs2{
- .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
- .pNext = nullptr,
- .memoryRequirements = {},
- };
- dld.vkGetBufferMemoryRequirements2(logical, &reqs_info, &reqs2);
-
- VkMemoryRequirements reqs = reqs2.memoryRequirements;
- reqs.alignment = (std::max)(reqs.alignment, min_alignment);
- reqs.memoryTypeBits &= alloc_ci.memoryTypeBits;
-
- VmaAllocation allocation{};
VmaAllocationInfo alloc_info{};
- VkResult res = vmaAllocateMemory(allocator, &reqs, &alloc_ci, &allocation, &alloc_info);
- if (res != VK_SUCCESS) {
- auto relaxed = alloc_ci;
- relaxed.flags &= ~VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT;
- res = vmaAllocateMemory(allocator, &reqs, &relaxed, &allocation, &alloc_info);
- }
- if (res != VK_SUCCESS) {
- dld.vkDestroyBuffer(logical, handle, nullptr);
- vk::Check(res);
- }
- const VkResult bind_res = vmaBindBufferMemory(allocator, allocation, handle);
- if (bind_res != VK_SUCCESS) {
- vmaFreeMemory(allocator, allocation);
- dld.vkDestroyBuffer(logical, handle, nullptr);
- vk::Check(bind_res);
- }
-
+ VmaAllocation allocation{};
VkMemoryPropertyFlags property_flags{};
+
+ vk::Check(vmaCreateBufferWithAlignment(allocator, &ci, &alloc_ci, min_alignment, &handle,
+ &allocation, &alloc_info));
vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags);
u8 *data = reinterpret_cast(alloc_info.pMappedData);
@@ -356,7 +321,8 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo &ci, MemoryUsa
}
const bool is_coherent = (property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;
- return vk::Buffer(handle, logical, allocator, allocation, mapped_data, is_coherent, dld);
+ return vk::Buffer(handle, *device.GetLogical(), allocator, allocation, mapped_data, is_coherent,
+ device.GetDispatchLoader());
}
MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements &reqs, MemoryUsage usage)