Mesa (main): zink: batch mem barrier hooks

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Aug 27 03:10:32 UTC 2021


Module: Mesa
Branch: main
Commit: 3674839d11055627eacf4ccaa7c6a4c47ba87d6c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3674839d11055627eacf4ccaa7c6a4c47ba87d6c

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Fri Jul 16 09:44:51 2021 -0400

zink: batch mem barrier hooks

memory barriers are redundant, so batch them and apply based on actual
usage to be slightly more efficient

Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12576>

---

 src/gallium/drivers/zink/zink_batch.h   |   1 +
 src/gallium/drivers/zink/zink_context.c | 101 +++++++++++++++++---------------
 src/gallium/drivers/zink/zink_context.h |   3 +
 src/gallium/drivers/zink/zink_draw.cpp  |   4 ++
 4 files changed, 63 insertions(+), 46 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_batch.h b/src/gallium/drivers/zink/zink_batch.h
index 0dc894ee34a..8e4bc582782 100644
--- a/src/gallium/drivers/zink/zink_batch.h
+++ b/src/gallium/drivers/zink/zink_batch.h
@@ -109,6 +109,7 @@ struct zink_batch {
    unsigned work_count;
 
    bool has_work;
+   bool last_was_compute;
    bool in_rp; //renderpass is currently active
 };
 
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 7ffe35e1cb3..7f0c60cd738 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -2696,71 +2696,80 @@ zink_texture_barrier(struct pipe_context *pctx, unsigned flags)
 }
 
 static inline void
-mem_barrier(struct zink_batch *batch, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlags src, VkAccessFlags dst)
+mem_barrier(struct zink_context *ctx, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlags src, VkAccessFlags dst)
 {
+   struct zink_batch *batch = &ctx->batch;
    VkMemoryBarrier mb;
    mb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
    mb.pNext = NULL;
    mb.srcAccessMask = src;
    mb.dstAccessMask = dst;
+   zink_end_render_pass(ctx, batch);
    vkCmdPipelineBarrier(batch->state->cmdbuf, src_stage, dst_stage, 0, 1, &mb, 0, NULL, 0, NULL);
 }
 
+void
+zink_flush_memory_barrier(struct zink_context *ctx, bool is_compute)
+{
+   const VkPipelineStageFlags gfx_flags = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
+                                          VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
+                                          VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
+                                          VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
+                                          VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+   const VkPipelineStageFlags cs_flags = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+   VkPipelineStageFlags src = ctx->batch.last_was_compute ? cs_flags : gfx_flags;
+   VkPipelineStageFlags dst = is_compute ? cs_flags : gfx_flags;
+
+   if (ctx->memory_barrier & (PIPE_BARRIER_TEXTURE | PIPE_BARRIER_SHADER_BUFFER | PIPE_BARRIER_IMAGE))
+      mem_barrier(ctx, src, dst, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
+
+   if (ctx->memory_barrier & PIPE_BARRIER_CONSTANT_BUFFER)
+      mem_barrier(ctx, src, dst,
+                  VK_ACCESS_SHADER_WRITE_BIT,
+                  VK_ACCESS_UNIFORM_READ_BIT);
+
+   if (!is_compute) {
+      if (ctx->memory_barrier & PIPE_BARRIER_INDIRECT_BUFFER)
+         mem_barrier(ctx, src, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
+                     VK_ACCESS_SHADER_WRITE_BIT,
+                     VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
+      if (ctx->memory_barrier & PIPE_BARRIER_VERTEX_BUFFER)
+         mem_barrier(ctx, gfx_flags, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
+                     VK_ACCESS_SHADER_WRITE_BIT,
+                     VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
+
+      if (ctx->memory_barrier & PIPE_BARRIER_INDEX_BUFFER)
+         mem_barrier(ctx, gfx_flags, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
+                     VK_ACCESS_SHADER_WRITE_BIT,
+                     VK_ACCESS_INDEX_READ_BIT);
+      if (ctx->memory_barrier & PIPE_BARRIER_FRAMEBUFFER)
+         zink_texture_barrier(&ctx->base, 0);
+      if (ctx->memory_barrier & PIPE_BARRIER_STREAMOUT_BUFFER)
+         mem_barrier(ctx, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
+                            VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
+                            VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
+                     VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
+                     VK_ACCESS_SHADER_READ_BIT,
+                     VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT |
+                     VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT);
+   }
+   ctx->memory_barrier = 0;
+}
+
 static void
 zink_memory_barrier(struct pipe_context *pctx, unsigned flags)
 {
    struct zink_context *ctx = zink_context(pctx);
 
-   VkPipelineStageFlags all_flags = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
-                                    VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
-                                    VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
-                                    VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
-                                    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
-                                    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
-
-   if (!(flags & ~PIPE_BARRIER_UPDATE))
+   flags &= ~PIPE_BARRIER_UPDATE;
+   if (!flags)
       return;
 
-   struct zink_batch *batch = &ctx->batch;
-   zink_end_render_pass(ctx, batch);
-
    if (flags & PIPE_BARRIER_MAPPED_BUFFER) {
       /* TODO: this should flush all persistent buffers in use as I think */
+      flags &= ~PIPE_BARRIER_MAPPED_BUFFER;
    }
-
-   if (flags & (PIPE_BARRIER_TEXTURE | PIPE_BARRIER_SHADER_BUFFER | PIPE_BARRIER_IMAGE))
-      mem_barrier(batch, all_flags, all_flags, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
-
-   if (flags & PIPE_BARRIER_VERTEX_BUFFER)
-      mem_barrier(batch, all_flags, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
-                  VK_ACCESS_SHADER_WRITE_BIT,
-                  VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
-
-   if (flags & PIPE_BARRIER_INDEX_BUFFER)
-      mem_barrier(batch, all_flags, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
-                  VK_ACCESS_SHADER_WRITE_BIT,
-                  VK_ACCESS_INDEX_READ_BIT);
-
-   if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
-      mem_barrier(batch, all_flags, all_flags,
-                  VK_ACCESS_SHADER_WRITE_BIT,
-                  VK_ACCESS_UNIFORM_READ_BIT);
-
-   if (flags & PIPE_BARRIER_INDIRECT_BUFFER)
-      mem_barrier(batch, all_flags, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
-                  VK_ACCESS_SHADER_WRITE_BIT,
-                  VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
-
-   if (flags & PIPE_BARRIER_FRAMEBUFFER)
-      zink_texture_barrier(pctx, 0);
-   if (flags & PIPE_BARRIER_STREAMOUT_BUFFER)
-      mem_barrier(batch, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
-                         VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
-                         VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
-                  VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
-                  VK_ACCESS_SHADER_READ_BIT,
-                  VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT |
-                  VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT);
+   ctx->memory_barrier = flags;
 }
 
 static void
diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h
index 594f5fd19a5..bfb979f7ad6 100644
--- a/src/gallium/drivers/zink/zink_context.h
+++ b/src/gallium/drivers/zink/zink_context.h
@@ -300,6 +300,7 @@ struct zink_context {
    struct set *need_barriers[2]; //gfx, compute
    struct set update_barriers[2][2]; //[gfx, compute][current, next]
    uint8_t barrier_set_idx[2];
+   unsigned memory_barrier;
 
    uint32_t num_so_targets;
    struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_OUTPUTS];
@@ -417,6 +418,8 @@ zink_pipeline_flags_from_pipe_stage(enum pipe_shader_type pstage)
 void
 zink_rebind_all_buffers(struct zink_context *ctx);
 
+void
+zink_flush_memory_barrier(struct zink_context *ctx, bool is_compute);
 void
 zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen);
 void
diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp
index 315d882cd74..441ce986111 100644
--- a/src/gallium/drivers/zink/zink_draw.cpp
+++ b/src/gallium/drivers/zink/zink_draw.cpp
@@ -430,6 +430,7 @@ zink_draw_vbo(struct pipe_context *pctx,
    unsigned work_count = ctx->batch.work_count;
    enum pipe_prim_type mode = (enum pipe_prim_type)dinfo->mode;
 
+   zink_flush_memory_barrier(ctx, false);
    update_barriers(ctx, false);
 
    if (unlikely(ctx->buffer_rebind_counter < screen->buffer_rebind_counter)) {
@@ -756,6 +757,7 @@ zink_draw_vbo(struct pipe_context *pctx,
       screen->vk.CmdEndTransformFeedbackEXT(batch->state->cmdbuf, 0, ctx->num_so_targets, counter_buffers, counter_buffer_offsets);
    }
    batch->has_work = true;
+   batch->last_was_compute = false;
    ctx->batch.work_count = work_count;
    /* flush if there's >100k draws */
    if (unlikely(work_count >= 30000) || ctx->oom_flush)
@@ -771,6 +773,7 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
    struct zink_batch *batch = &ctx->batch;
 
    update_barriers(ctx, true);
+   zink_flush_memory_barrier(ctx, true);
 
    if (zink_program_has_descriptors(&ctx->curr_compute->base))
       screen->descriptors_update(ctx, true);
@@ -804,6 +807,7 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
    } else
       vkCmdDispatch(batch->state->cmdbuf, info->grid[0], info->grid[1], info->grid[2]);
    batch->has_work = true;
+   batch->last_was_compute = true;
    /* flush if there's >100k computes */
    if (unlikely(ctx->batch.work_count >= 30000) || ctx->oom_flush)
       pctx->flush(pctx, NULL, 0);



More information about the mesa-commit mailing list