Просмотр исходного кода

VulkanBufferCache: Avoid adding barriers between multiple copies.

Fernando Sahmkow 4 лет назад
Родитель
Сommit
c5dbd93adb

+ 3 - 1
src/video_core/buffer_cache/buffer_cache.h

@@ -853,12 +853,14 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
     }
     if constexpr (USE_MEMORY_MAPS) {
         auto download_staging = runtime.DownloadStagingBuffer(total_size_bytes);
+        runtime.PreCopyBarrier();
         for (auto& [copy, buffer_id] : downloads) {
             // Have in mind the staging buffer offset for the copy
             copy.dst_offset += download_staging.offset;
             const std::array copies{copy};
-            runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies);
+            runtime.CopyBuffer(download_staging.buffer, slot_buffers[buffer_id], copies, false);
         }
+        runtime.PostCopyBarrier();
         runtime.Finish();
         for (const auto& [copy, buffer_id] : downloads) {
             const Buffer& buffer = slot_buffers[buffer_id];

+ 35 - 3
src/video_core/renderer_vulkan/vk_buffer_cache.cpp

@@ -146,7 +146,7 @@ void BufferCacheRuntime::Finish() {
 }
 
 void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
-                                    std::span<const VideoCommon::BufferCopy> copies) {
+                                    std::span<const VideoCommon::BufferCopy> copies, bool barrier) {
     static constexpr VkMemoryBarrier READ_BARRIER{
         .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
         .pNext = nullptr,
@@ -163,10 +163,42 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
     boost::container::small_vector<VkBufferCopy, 3> vk_copies(copies.size());
     std::ranges::transform(copies, vk_copies.begin(), MakeBufferCopy);
     scheduler.RequestOutsideRenderPassOperationContext();
-    scheduler.Record([src_buffer, dst_buffer, vk_copies](vk::CommandBuffer cmdbuf) {
+    scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
+        if (barrier) {
+            cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+                                   VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
+        }
+        cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies);
+        if (barrier) {
+            cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
+        }
+    });
+}
+
+void BufferCacheRuntime::PreCopyBarrier() {
+    static constexpr VkMemoryBarrier READ_BARRIER{
+        .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
+        .pNext = nullptr,
+        .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
+        .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
+    };
+    scheduler.RequestOutsideRenderPassOperationContext();
+    scheduler.Record([](vk::CommandBuffer cmdbuf) {
         cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
                                0, READ_BARRIER);
-        cmdbuf.CopyBuffer(src_buffer, dst_buffer, vk_copies);
+    });
+}
+
+void BufferCacheRuntime::PostCopyBarrier() {
+    static constexpr VkMemoryBarrier WRITE_BARRIER{
+        .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
+        .pNext = nullptr,
+        .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+        .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
+    };
+    scheduler.RequestOutsideRenderPassOperationContext();
+    scheduler.Record([](vk::CommandBuffer cmdbuf) {
         cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                                0, WRITE_BARRIER);
     });

+ 5 - 1
src/video_core/renderer_vulkan/vk_buffer_cache.h

@@ -69,8 +69,12 @@ public:
 
     [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size);
 
+    void PreCopyBarrier();
+
     void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
-                    std::span<const VideoCommon::BufferCopy> copies);
+                    std::span<const VideoCommon::BufferCopy> copies, bool barrier = true);
+
+    void PostCopyBarrier();
 
     void ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t size, u32 value);