From 6df35d859a231d82be9e8604a3bd8d8321f58f77 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sat, 29 Nov 2025 18:20:54 -0400 Subject: [PATCH] [vk] BufferCache NullBuffer handling --- .../renderer_vulkan/vk_buffer_cache.cpp | 39 +++++++++++++++---- .../renderer_vulkan/vk_buffer_cache.h | 5 +++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index f4af76e310..69b2c08024 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -705,22 +705,41 @@ void BufferCacheRuntime::ReserveNullBuffer() { } } +VkBufferUsageFlags BufferCacheRuntime::NullBufferUsageFlags() const { + VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | + VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | + VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; + if (device.IsExtTransformFeedbackSupported()) { + usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; + } + return usage; +} + +void BufferCacheRuntime::RefreshNullBuffer() { + if (!null_buffer) { + return; + } + scheduler.Finish(); + null_buffer.reset(); + null_buffer = CreateNullBuffer(); +} + vk::Buffer BufferCacheRuntime::CreateNullBuffer() { VkBufferCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, .size = 4, - .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | - VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, + .usage = NullBufferUsageFlags(), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, }; - if (device.IsExtTransformFeedbackSupported()) { - create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; - } vk::Buffer ret = memory_allocator.CreateBuffer(create_info, MemoryUsage::DeviceLocal); + null_buffer_usage_flags = create_info.usage; if (device.HasDebuggingToolAttached()) { ret.SetObjectNameEXT("Null buffer"); } @@ -731,6 +750,10 @@ vk::Buffer BufferCacheRuntime::CreateNullBuffer() { }); return ret; -} - -} // namespace Vulkan + const VkBufferUsageFlags expected_usage = NullBufferUsageFlags(); + if (null_buffer && null_buffer_usage_flags != expected_usage) { + RefreshNullBuffer(); + } + if (!null_buffer) { + null_buffer = CreateNullBuffer(); + } diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 8d4020e0e5..6ff3187282 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -131,6 +131,9 @@ public: void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings); + /// Forces destruction and recreation of the shared null buffer so new usage flags take effect. + void RefreshNullBuffer(); + std::span BindMappedUniformBuffer([[maybe_unused]] size_t /*stage*/, [[maybe_unused]] u32 /*binding_index*/, u32 size) { @@ -174,6 +177,7 @@ private: void ReserveNullBuffer(); vk::Buffer CreateNullBuffer(); + VkBufferUsageFlags NullBufferUsageFlags() const; struct UniformRing { static constexpr size_t NUM_FRAMES = 3; @@ -203,6 +207,7 @@ private: std::shared_ptr quad_strip_index_buffer; vk::Buffer null_buffer; + VkBufferUsageFlags null_buffer_usage_flags = 0; std::unique_ptr uint8_pass; QuadIndexedPass quad_index_pass;