[PATCH] wined3d: Avoid read-to-read resource barriers.

Jan Sikorski jsikorski at codeweavers.com
Thu Aug 19 03:55:48 CDT 2021


We can generally skip them, but make sure that subsequent barriers
synchronize with all accumulated usages.

This is motivated by an issue where a program using a single buffer to
store both indices and vertex attributes causes superfluous barriers on
each draw call.

Signed-off-by: Jan Sikorski <jsikorski at codeweavers.com>
---
 dlls/wined3d/buffer.c          | 44 +++++++++++++++++++++-------------
 dlls/wined3d/texture.c         | 31 +++++++++++++++---------
 dlls/wined3d/wined3d_private.h | 15 ++++++++++++
 3 files changed, 62 insertions(+), 28 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 4420885b15f..ef5727030c8 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1588,28 +1588,38 @@ void wined3d_buffer_vk_barrier(struct wined3d_buffer_vk *buffer_vk,
     if (buffer_vk->bind_mask && buffer_vk->bind_mask != bind_mask)
     {
         const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+        VkAccessFlags src_access_mask, dst_access_mask;
         VkBufferMemoryBarrier vk_barrier;
 
         TRACE("    %s -> %s.\n",
                 wined3d_debug_bind_flags(buffer_vk->bind_mask), wined3d_debug_bind_flags(bind_mask));
 
-        wined3d_context_vk_end_current_render_pass(context_vk);
-
-        vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
-        vk_barrier.pNext = NULL;
-        vk_barrier.srcAccessMask = vk_access_mask_from_bind_flags(buffer_vk->bind_mask);
-        vk_barrier.dstAccessMask = vk_access_mask_from_bind_flags(bind_mask);
-        vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
-        vk_barrier.buffer = buffer_vk->bo.vk_buffer;
-        vk_barrier.offset = buffer_vk->bo.buffer_offset;
-        vk_barrier.size = buffer_vk->b.resource.size;
-        VK_CALL(vkCmdPipelineBarrier(wined3d_context_vk_get_command_buffer(context_vk),
-                vk_pipeline_stage_mask_from_bind_flags(buffer_vk->bind_mask),
-                vk_pipeline_stage_mask_from_bind_flags(bind_mask),
-                0, 0, NULL, 1, &vk_barrier, 0, NULL));
-    }
-    buffer_vk->bind_mask = bind_mask;
+        src_access_mask = vk_access_mask_from_bind_flags(buffer_vk->bind_mask);
+        dst_access_mask = vk_access_mask_from_bind_flags(bind_mask);
+
+        if (!vk_access_mask_is_read_only(src_access_mask | dst_access_mask))
+        {
+            wined3d_context_vk_end_current_render_pass(context_vk);
+
+            vk_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+            vk_barrier.pNext = NULL;
+            vk_barrier.srcAccessMask = src_access_mask;
+            vk_barrier.dstAccessMask = dst_access_mask;
+            vk_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+            vk_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+            vk_barrier.buffer = buffer_vk->bo.vk_buffer;
+            vk_barrier.offset = buffer_vk->bo.buffer_offset;
+            vk_barrier.size = buffer_vk->b.resource.size;
+            VK_CALL(vkCmdPipelineBarrier(wined3d_context_vk_get_command_buffer(context_vk),
+                    vk_pipeline_stage_mask_from_bind_flags(buffer_vk->bind_mask),
+                    vk_pipeline_stage_mask_from_bind_flags(bind_mask),
+                    0, 0, NULL, 1, &vk_barrier, 0, NULL));
+            buffer_vk->bind_mask = bind_mask;
+            return;
+        }
+    }
+
+    buffer_vk->bind_mask |= bind_mask;
 }
 
 HRESULT CDECL wined3d_buffer_create(struct wined3d_device *device, const struct wined3d_buffer_desc *desc,
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index c1247fbc56b..687626a0d56 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -5251,22 +5251,31 @@ void wined3d_texture_vk_barrier(struct wined3d_texture_vk *texture_vk,
 
     if (texture_vk->bind_mask && texture_vk->bind_mask != bind_mask)
     {
+        VkAccessFlags src_access_mask, dst_access_mask;
+
         TRACE("    %s -> %s.\n",
                 wined3d_debug_bind_flags(texture_vk->bind_mask), wined3d_debug_bind_flags(bind_mask));
 
-        vk_range.aspectMask = vk_aspect_mask_from_format(texture_vk->t.resource.format);
-        vk_range.baseMipLevel = 0;
-        vk_range.levelCount = VK_REMAINING_MIP_LEVELS;
-        vk_range.baseArrayLayer = 0;
-        vk_range.layerCount = VK_REMAINING_ARRAY_LAYERS;
+        src_access_mask = vk_access_mask_from_bind_flags(texture_vk->bind_mask);
+        dst_access_mask = vk_access_mask_from_bind_flags(bind_mask);
 
-        wined3d_context_vk_image_barrier(context_vk, wined3d_context_vk_get_command_buffer(context_vk),
-                vk_pipeline_stage_mask_from_bind_flags(texture_vk->bind_mask),
-                vk_pipeline_stage_mask_from_bind_flags(bind_mask),
-                vk_access_mask_from_bind_flags(texture_vk->bind_mask), vk_access_mask_from_bind_flags(bind_mask),
-                texture_vk->layout, texture_vk->layout, texture_vk->image.vk_image, &vk_range);
+        if (!vk_access_mask_is_read_only(src_access_mask | dst_access_mask))
+        {
+            vk_range.aspectMask = vk_aspect_mask_from_format(texture_vk->t.resource.format);
+            vk_range.baseMipLevel = 0;
+            vk_range.levelCount = VK_REMAINING_MIP_LEVELS;
+            vk_range.baseArrayLayer = 0;
+            vk_range.layerCount = VK_REMAINING_ARRAY_LAYERS;
+
+            wined3d_context_vk_image_barrier(context_vk, wined3d_context_vk_get_command_buffer(context_vk),
+                    vk_pipeline_stage_mask_from_bind_flags(texture_vk->bind_mask),
+                    vk_pipeline_stage_mask_from_bind_flags(bind_mask), src_access_mask, dst_access_mask,
+                    texture_vk->layout, texture_vk->layout, texture_vk->image.vk_image, &vk_range);
+            texture_vk->bind_mask = bind_mask;
+            return;
+        }
     }
-    texture_vk->bind_mask = bind_mask;
+    texture_vk->bind_mask |= bind_mask;
 }
 
 static void ffp_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 86eae149306..ae4ae1bf160 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -317,6 +317,21 @@ VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type,
 VkPipelineStageFlags vk_pipeline_stage_mask_from_bind_flags(uint32_t bind_flags) DECLSPEC_HIDDEN;
 VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type) DECLSPEC_HIDDEN;
 
+static inline bool vk_access_mask_is_read_only(VkAccessFlags flags)
+{
+    static const VkAccessFlags read_flags =
+            VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
+            VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
+            VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
+            VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_HOST_READ_BIT | VK_ACCESS_MEMORY_READ_BIT |
+            VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV | VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT |
+            VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR |
+            VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR | VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT |
+            VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT;
+
+    return (flags & read_flags) == flags;
+}
+
 static inline enum wined3d_cmp_func wined3d_sanitize_cmp_func(enum wined3d_cmp_func func)
 {
     if (func < WINED3D_CMP_NEVER || func > WINED3D_CMP_ALWAYS)
-- 
2.30.2




More information about the wine-devel mailing list