Mesa (main): zink: use VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL when possible

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 4 15:19:43 UTC 2021


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Wed Mar  3 15:26:02 2021 -0500

zink: use VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL when possible

this is allowed for fb attachments, so we can use it to avoid needing to
change layouts for zs textures if we know that it isn't going to be written
to during a given subpass

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

---

 src/gallium/drivers/zink/zink_context.c     | 20 +++++++++++-----
 src/gallium/drivers/zink/zink_descriptors.c |  4 +++-
 src/gallium/drivers/zink/zink_draw.c        |  4 +++-
 src/gallium/drivers/zink/zink_render_pass.c | 36 +++++++++++++++++++++++++----
 src/gallium/drivers/zink/zink_render_pass.h |  7 +++++-
 src/gallium/drivers/zink/zink_state.c       |  5 ++++
 6 files changed, 63 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 4df38c98c4e..93e25e5b554 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -379,7 +379,9 @@ get_layout_for_binding(struct zink_resource *res, enum zink_descriptor_type type
    switch (type) {
    case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
       return res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_IMAGE) ?
-             VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+             VK_IMAGE_LAYOUT_GENERAL :
+             res->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ?
+                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    case ZINK_DESCRIPTOR_TYPE_IMAGE:
       return VK_IMAGE_LAYOUT_GENERAL;
    default:
@@ -1149,7 +1151,7 @@ unbind_shader_image(struct zink_context *ctx, enum pipe_shader_type stage, unsig
           !res->image_bind_count[is_compute]) {
          for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) {
             if (res->sampler_binds[i]) {
-               zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+               zink_resource_image_barrier(ctx, NULL, res, get_layout_for_binding(res, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW),
                                            VK_ACCESS_SHADER_READ_BIT,
                                            zink_pipeline_flags_from_stage(zink_shader_stage(i)));
                break;
@@ -1438,6 +1440,11 @@ get_render_pass(struct zink_context *ctx)
          clears |= PIPE_CLEAR_DEPTH;
       if (state.rts[fb->nr_cbufs].clear_stencil)
          clears |= PIPE_CLEAR_STENCIL;
+      const uint64_t outputs_written = ctx->gfx_stages[PIPE_SHADER_FRAGMENT] ?
+                                       ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir->info.outputs_written : 0;
+      bool needs_write = (ctx->dsa_state && ctx->dsa_state->hw_state.depth_write) ||
+                                            outputs_written & (BITFIELD64_BIT(FRAG_RESULT_DEPTH) | BITFIELD64_BIT(FRAG_RESULT_STENCIL));
+      state.rts[fb->nr_cbufs].needs_write = needs_write || state.rts[fb->nr_cbufs].clear_color || state.rts[fb->nr_cbufs].clear_stencil;
       state.num_rts++;
    }
    state.have_zsbuf = fb->zsbuf != NULL;
@@ -1594,11 +1601,12 @@ begin_render_pass(struct zink_context *ctx)
          zink_batch_reference_resource_rw(batch, zink_resource(surf->base.texture), true);
          zink_batch_reference_surface(batch, surf);
 
-         VkImageLayout layout = i == ctx->framebuffer->state.num_attachments - 1 && fb_state->zsbuf ?
-                                     VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
-                                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
          struct zink_resource *res = zink_resource(surf->base.texture);
-         zink_resource_image_barrier(ctx, NULL, res, layout, 0, 0);
+         VkAccessFlags access;
+         VkPipelineStageFlags pipeline;
+         VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass,
+                                                                             i, &pipeline, &access);
+         zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline);
       }
    }
 
diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c
index 8d67e6c9f9a..bd3a4aa651d 100644
--- a/src/gallium/drivers/zink/zink_descriptors.c
+++ b/src/gallium/drivers/zink/zink_descriptors.c
@@ -1237,7 +1237,9 @@ update_sampler_descriptors(struct zink_context *ctx, struct zink_descriptor_set
             } else if (res) {
                imageview = sampler_view->image_view->image_view;
                layout = (res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_IMAGE)) ?
-                        VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+                           VK_IMAGE_LAYOUT_GENERAL :
+                           res->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ?
+                              VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
                sampler = ctx->sampler_states[stage][index + k];
             }
             assert(num_resources < num_bindings);
diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c
index 7357c39a27c..0e70efed0de 100644
--- a/src/gallium/drivers/zink/zink_draw.c
+++ b/src/gallium/drivers/zink/zink_draw.c
@@ -385,7 +385,9 @@ update_barriers(struct zink_context *ctx, bool is_compute)
          if (res->base.b.target == PIPE_BUFFER)
             zink_resource_buffer_barrier(ctx, NULL, res, access, pipeline);
          else {
-            VkImageLayout layout = res->image_bind_count[is_compute] ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+            VkImageLayout layout = res->image_bind_count[is_compute] ? VK_IMAGE_LAYOUT_GENERAL :
+                                   res->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ?
+                                   VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
             zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline);
          }
          /* always barrier on draw if this resource has either multiple image write binds or
diff --git a/src/gallium/drivers/zink/zink_render_pass.c b/src/gallium/drivers/zink/zink_render_pass.c
index 38ddab7187c..26c19f74788 100644
--- a/src/gallium/drivers/zink/zink_render_pass.c
+++ b/src/gallium/drivers/zink/zink_render_pass.c
@@ -62,6 +62,8 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
    int num_attachments = state->num_cbufs;
    if (state->have_zsbuf)  {
       struct zink_rt_attrib *rt = state->rts + state->num_cbufs;
+      bool has_clear = rt->clear_color || rt->clear_stencil;
+      VkImageLayout layout = rt->needs_write || has_clear ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
       attachments[num_attachments].flags = 0;
       attachments[num_attachments].format = rt->format;
       attachments[num_attachments].samples = rt->samples;
@@ -69,17 +71,18 @@ create_render_pass(VkDevice dev, struct zink_render_pass_state *state)
       attachments[num_attachments].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
       attachments[num_attachments].stencilLoadOp = rt->clear_stencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
       attachments[num_attachments].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
-      attachments[num_attachments].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
-      attachments[num_attachments].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+      attachments[num_attachments].initialLayout = layout;
+      attachments[num_attachments].finalLayout = layout;
 
       dep_pipeline |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
-      dep_pipeline |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+      if (layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
+         dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
       if (attachments[num_attachments].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
           attachments[num_attachments].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
          dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
 
       zs_ref.attachment = num_attachments++;
-      zs_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+      zs_ref.layout = layout;
    }
 
    VkSubpassDependency deps[] = {
@@ -138,3 +141,28 @@ zink_destroy_render_pass(struct zink_screen *screen,
    vkDestroyRenderPass(screen->dev, rp->render_pass, NULL);
    FREE(rp);
 }
+
+VkImageLayout
+zink_render_pass_attachment_get_barrier_info(const struct zink_render_pass *rp, unsigned idx,
+                                             VkPipelineStageFlags *pipeline, VkAccessFlags *access)
+{
+   *access = 0;
+   assert(idx < rp->state.num_rts);
+   const struct zink_rt_attrib *rt = &rp->state.rts[idx];
+   if (idx < rp->state.num_cbufs) {
+      *pipeline = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+      *access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+      if (!rt->clear_color && (!rp->state.swapchain_init || !rt->swapchain))
+         *access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
+      return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+   }
+
+   assert(rp->state.have_zsbuf);
+   *pipeline = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+   if (!rp->state.rts[idx].clear_color && !rp->state.rts[idx].clear_stencil)
+      *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+   if (!rp->state.rts[idx].clear_color && !rp->state.rts[idx].clear_stencil && !rp->state.rts[idx].needs_write)
+      return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
+   *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+   return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+}
diff --git a/src/gallium/drivers/zink/zink_render_pass.h b/src/gallium/drivers/zink/zink_render_pass.h
index 2525695404c..8b4441e5fe3 100644
--- a/src/gallium/drivers/zink/zink_render_pass.h
+++ b/src/gallium/drivers/zink/zink_render_pass.h
@@ -36,7 +36,10 @@ struct zink_rt_attrib {
   VkSampleCountFlagBits samples;
   bool clear_color;
   bool clear_stencil;
-  bool swapchain;
+  union {
+     bool swapchain;
+     bool needs_write;
+  };
 };
 
 struct zink_render_pass_state {
@@ -61,4 +64,6 @@ void
 zink_destroy_render_pass(struct zink_screen *screen,
                          struct zink_render_pass *rp);
 
+VkImageLayout
+zink_render_pass_attachment_get_barrier_info(const struct zink_render_pass *rp, unsigned idx, VkPipelineStageFlags *pipeline, VkAccessFlags *access);
 #endif
diff --git a/src/gallium/drivers/zink/zink_state.c b/src/gallium/drivers/zink/zink_state.c
index 084f244f022..246669b2725 100644
--- a/src/gallium/drivers/zink/zink_state.c
+++ b/src/gallium/drivers/zink/zink_state.c
@@ -389,6 +389,7 @@ zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso)
 {
    struct zink_context *ctx = zink_context(pctx);
 
+   bool prev_zwrite = ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false;
    ctx->dsa_state = cso;
 
    if (cso) {
@@ -398,6 +399,10 @@ zink_bind_depth_stencil_alpha_state(struct pipe_context *pctx, void *cso)
          state->dirty |= !zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state;
       }
    }
+   if (prev_zwrite != (ctx->dsa_state ? ctx->dsa_state->hw_state.depth_write : false)) {
+      ctx->rp_changed = true;
+      zink_batch_no_rp(ctx);
+   }
 }
 
 static void



More information about the mesa-commit mailing list