From 463fe06dce9ba6e075c76e190f6d2379501a3eaf Mon Sep 17 00:00:00 2001 From: Kravickas Date: Sat, 27 Jun 2026 09:24:19 +0200 Subject: [PATCH] Barrier vertex/index buffers written by compute (#4611) * Vertex/Index barriers * Vert/Index barrier param * barrrrrrrr * Add GPU modification checks for buffer barriers --- src/video_core/buffer_cache/buffer_cache.cpp | 20 +++++++++++++++++-- src/video_core/buffer_cache/buffer_cache.h | 6 ++++-- .../renderer_vulkan/vk_rasterizer.cpp | 8 ++++---- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 685d24cc5..0e6e5af38 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -144,7 +144,9 @@ void BufferCache::DownloadBufferMemory(Buffer& buffer, VAddr device_addr, u64 si } } -void BufferCache::BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline) { +void BufferCache::BindVertexBuffers( + const Vulkan::GraphicsPipeline& pipeline, + boost::container::small_vector& barriers) { const auto& regs = liverpool->regs; Vulkan::VertexInputs attributes; Vulkan::VertexInputs bindings; @@ -206,6 +208,13 @@ void BufferCache::BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline) { const auto [buffer, offset] = ObtainBuffer(range.base_address, size, false); range.vk_buffer = buffer->buffer; range.offset = offset; + if (IsRegionGpuModified(range.base_address, size)) { + if (auto barrier = + buffer->GetBarrier(vk::AccessFlagBits2::eVertexAttributeRead, + vk::PipelineStageFlagBits2::eVertexAttributeInput)) { + barriers.emplace_back(*barrier); + } + } } // Bind vertex buffers @@ -244,7 +253,8 @@ void BufferCache::BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline) { } } -void BufferCache::BindIndexBuffer(u32 index_offset) { +void BufferCache::BindIndexBuffer( + u32 index_offset, boost::container::small_vector& barriers) { const auto& regs = liverpool->regs; // Figure out index type and size. @@ -257,6 +267,12 @@ void BufferCache::BindIndexBuffer(u32 index_offset) { // Bind index buffer. const u32 index_buffer_size = regs.num_indices * index_size; const auto [vk_buffer, offset] = ObtainBuffer(index_address, index_buffer_size, false); + if (IsRegionGpuModified(index_address, index_buffer_size)) { + if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eIndexRead, + vk::PipelineStageFlagBits2::eIndexInput)) { + barriers.emplace_back(*barrier); + } + } const auto cmdbuf = scheduler.CommandBuffer(); cmdbuf.bindIndexBuffer(vk_buffer->Handle(), offset, index_type); } diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 73d70704e..48ccef524 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -112,10 +112,12 @@ public: void ReadMemory(VAddr device_addr, u64 size, bool is_write = false); /// Binds host vertex buffers for the current draw. - void BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline); + void BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline, + boost::container::small_vector& barriers); /// Bind host index buffer for the current draw. - void BindIndexBuffer(u32 index_offset); + void BindIndexBuffer(u32 index_offset, + boost::container::small_vector& barriers); /// Writes a value to GPU buffer. (uses command buffer to temporarily store the data) void FillBuffer(VAddr address, u32 num_bytes, u32 value, bool is_gds); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 56a70c7f7..6f89bd393 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -206,9 +206,9 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { } const auto state = BeginRendering(pipeline); - buffer_cache.BindVertexBuffers(*pipeline); + buffer_cache.BindVertexBuffers(*pipeline, buffer_barriers); if (is_indexed) { - buffer_cache.BindIndexBuffer(index_offset); + buffer_cache.BindIndexBuffer(index_offset, buffer_barriers); } pipeline->BindResources(set_writes, buffer_barriers, push_data); @@ -254,9 +254,9 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3 } const auto state = BeginRendering(pipeline); - buffer_cache.BindVertexBuffers(*pipeline); + buffer_cache.BindVertexBuffers(*pipeline, buffer_barriers); if (is_indexed) { - buffer_cache.BindIndexBuffer(0); + buffer_cache.BindIndexBuffer(0, buffer_barriers); } const auto& [buffer, base] =