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

Author: Mike Blumenkrantz <[email protected]>
Date:   Fri Sep 17 11:54:09 2021 -0400

zink: force lazy descriptor set rebinds if pipeline compatibility changes

if the pipeline layout changes, it's technically illegal to not rebind the 
descriptor
set even if it hasn't changed

Reviewed-by: Dave Airlie <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12931>

---

 src/gallium/drivers/zink/zink_descriptors_lazy.c | 59 +++++++++++++++++-------
 src/gallium/drivers/zink/zink_program.c          |  4 +-
 src/gallium/drivers/zink/zink_program.h          |  3 +-
 3 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_descriptors_lazy.c 
b/src/gallium/drivers/zink/zink_descriptors_lazy.c
index 8908a6f1aa6..f82d1fc452f 100644
--- a/src/gallium/drivers/zink/zink_descriptors_lazy.c
+++ b/src/gallium/drivers/zink/zink_descriptors_lazy.c
@@ -57,7 +57,9 @@ struct zink_batch_descriptor_data_lazy {
    struct hash_table pools[ZINK_DESCRIPTOR_TYPES];
    struct zink_descriptor_pool *push_pool[2];
    struct zink_program *pg[2]; //gfx, compute
+   uint32_t compat_id[2];
    VkDescriptorSetLayout dsl[2][ZINK_DESCRIPTOR_TYPES];
+   VkDescriptorSet sets[2][ZINK_DESCRIPTOR_TYPES + 1];
    unsigned push_usage[2];
    bool has_fbfetch;
 };
@@ -208,7 +210,7 @@ zink_descriptor_program_init_lazy(struct zink_context *ctx, 
struct zink_program
       ralloc_free(pg->dd);
       pg->dd = NULL;
 
-      pg->layout = zink_pipeline_layout_create(screen, pg);
+      pg->layout = zink_pipeline_layout_create(screen, pg, &pg->compat_id);
       return !!pg->layout;
    }
 
@@ -232,7 +234,7 @@ zink_descriptor_program_init_lazy(struct zink_context *ctx, 
struct zink_program
          pg->dd->sizes[i].descriptorCount *= screen->descriptor_mode == 
ZINK_DESCRIPTOR_MODE_LAZY ? MAX_LAZY_DESCRIPTORS : ZINK_DEFAULT_MAX_DESCS;
    }
 
-   pg->layout = zink_pipeline_layout_create(screen, pg);
+   pg->layout = zink_pipeline_layout_create(screen, pg, &pg->compat_id);
    if (!pg->layout)
       return false;
    if (!screen->info.have_KHR_descriptor_update_template || 
screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_NOTEMPLATES)
@@ -444,7 +446,7 @@ zink_descriptor_set_update_lazy(struct zink_context *ctx, 
struct zink_program *p
 }
 
 void
-zink_descriptors_update_lazy_masked(struct zink_context *ctx, bool is_compute, 
uint8_t changed_sets, bool need_push, bool update_push)
+zink_descriptors_update_lazy_masked(struct zink_context *ctx, bool is_compute, 
uint8_t changed_sets, bool need_push, bool is_lazy)
 {
    struct zink_screen *screen = zink_screen(ctx->base.screen);
    struct zink_batch *batch = &ctx->batch;
@@ -459,35 +461,57 @@ zink_descriptors_update_lazy_masked(struct zink_context 
*ctx, bool is_compute, u
    /* no flushing allowed */
    assert(ctx->batch.state == bs);
 
-   if (pg->dd->binding_usage && changed_sets) {
+   /*
+    * when binding a pipeline, the pipeline can correctly access any 
previously bound
+    * descriptor sets which were bound with compatible pipeline layouts
+    * VK 14.2.2
+    */
+   uint8_t bind_sets = !is_lazy || (bdd->pg[is_compute] && 
bdd->compat_id[is_compute] == pg->compat_id) ? 0 : pg->dd->binding_usage;
+   if (pg->dd->binding_usage && (changed_sets || bind_sets)) {
       u_foreach_bit(type, changed_sets) {
-         if (pg->dd->layout_key[type])
-            VKSCR(UpdateDescriptorSetWithTemplate)(screen->dev, desc_sets[type 
+ 1], pg->dd->layouts[type + 1]->desc_template, ctx);
          assert(type + 1 < pg->num_dsl);
+         if (pg->dd->layout_key[type]) {
+            VKSCR(UpdateDescriptorSetWithTemplate)(screen->dev, desc_sets[type 
+ 1], pg->dd->layouts[type + 1]->desc_template, ctx);
+            VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
+                                    is_compute ? 
VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
+                                    /* set index incremented by 1 to account 
for push set */
+                                    pg->layout, type + 1, 1, &desc_sets[type + 
1],
+                                    0, NULL);
+            bdd->sets[is_compute][type + 1] = desc_sets[type + 1];
+         }
+      }
+      u_foreach_bit(type, bind_sets & ~changed_sets) {
+         if (!pg->dd->layout_key[type])
+            bdd->sets[is_compute][type + 1] = ctx->dd->dummy_set;
+         assert(bdd->sets[is_compute][type + 1]);
          VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : 
VK_PIPELINE_BIND_POINT_GRAPHICS,
                                  /* set index incremented by 1 to account for 
push set */
-                                 pg->layout, type + 1, 1, &desc_sets[type + 1],
+                                 pg->layout, type + 1, 1, 
&bdd->sets[is_compute][type + 1],
                                  0, NULL);
       }
       dd_lazy(ctx)->state_changed[is_compute] = false;
    }
 
-   if (update_push) {
-      if (pg->dd->push_usage && dd_lazy(ctx)->push_state_changed[is_compute]) {
-         if (screen->info.have_KHR_push_descriptor)
-            VKSCR(CmdPushDescriptorSetWithTemplateKHR)(batch->state->cmdbuf, 
pg->dd->push_template,
-                                                        pg->layout, 0, ctx);
-         else {
-            assert(desc_sets[0]);
-            VKSCR(UpdateDescriptorSetWithTemplate)(screen->dev, desc_sets[0], 
pg->dd->push_template, ctx);
+   if (is_lazy) {
+      if (pg->dd->push_usage && (dd_lazy(ctx)->push_state_changed[is_compute] 
|| bind_sets)) {
+         if (screen->info.have_KHR_push_descriptor) {
+            if (dd_lazy(ctx)->push_state_changed[is_compute])
+               
VKSCR(CmdPushDescriptorSetWithTemplateKHR)(batch->state->cmdbuf, 
pg->dd->push_template,
+                                                           pg->layout, 0, ctx);
+         } else {
+            if (dd_lazy(ctx)->push_state_changed[is_compute]) {
+               VKSCR(UpdateDescriptorSetWithTemplate)(screen->dev, 
desc_sets[0], pg->dd->push_template, ctx);
+               bdd->sets[is_compute][0] = desc_sets[0];
+            }
+            assert(desc_sets[0] || bdd->sets[is_compute][0]);
             VKSCR(CmdBindDescriptorSets)(batch->state->cmdbuf,
                                     is_compute ? 
VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                    pg->layout, 0, 1, &desc_sets[0],
+                                    pg->layout, 0, 1, desc_sets[0] ? 
&desc_sets[0] : &bdd->sets[is_compute][0],
                                     0, NULL);
          }
          dd_lazy(ctx)->push_state_changed[is_compute] = false;
-      } else if (dd_lazy(ctx)->push_state_changed[is_compute]) {
+      } else if (dd_lazy(ctx)->push_state_changed[is_compute] || bind_sets) {
          VKSCR(CmdBindDescriptorSets)(bs->cmdbuf,
                                  is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : 
VK_PIPELINE_BIND_POINT_GRAPHICS,
                                  pg->layout, 0, 1, &ctx->dd->dummy_set,
@@ -497,6 +521,7 @@ zink_descriptors_update_lazy_masked(struct zink_context 
*ctx, bool is_compute, u
    }
    bdd->pg[is_compute] = pg;
    ctx->dd->pg[is_compute] = pg;
+   bdd->compat_id[is_compute] = pg->compat_id;
 }
 
 void
diff --git a/src/gallium/drivers/zink/zink_program.c 
b/src/gallium/drivers/zink/zink_program.c
index 0aedff77d4e..a735f67a6d6 100644
--- a/src/gallium/drivers/zink/zink_program.c
+++ b/src/gallium/drivers/zink/zink_program.c
@@ -249,7 +249,7 @@ zink_update_gfx_program(struct zink_context *ctx, struct 
zink_gfx_program *prog)
 }
 
 VkPipelineLayout
-zink_pipeline_layout_create(struct zink_screen *screen, struct zink_program 
*pg)
+zink_pipeline_layout_create(struct zink_screen *screen, struct zink_program 
*pg, uint32_t *compat)
 {
    VkPipelineLayoutCreateInfo plci = {0};
    plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
@@ -282,6 +282,8 @@ zink_pipeline_layout_create(struct zink_screen *screen, 
struct zink_program *pg)
       return VK_NULL_HANDLE;
    }
 
+   *compat = _mesa_hash_data(pg->dsl, pg->num_dsl * sizeof(pg->dsl[0]));
+
    return layout;
 }
 
diff --git a/src/gallium/drivers/zink/zink_program.h 
b/src/gallium/drivers/zink/zink_program.h
index f4c65f6c7e2..d1befbc84a7 100644
--- a/src/gallium/drivers/zink/zink_program.h
+++ b/src/gallium/drivers/zink/zink_program.h
@@ -84,6 +84,7 @@ struct zink_program {
 
    struct zink_program_descriptor_data *dd;
 
+   uint32_t compat_id;
    VkPipelineLayout layout;
    VkDescriptorSetLayout dsl[ZINK_DESCRIPTOR_TYPES + 1]; // one for each type 
+ push
    unsigned num_dsl;
@@ -267,7 +268,7 @@ zink_compute_program_reference(struct zink_screen *screen,
 }
 
 VkPipelineLayout
-zink_pipeline_layout_create(struct zink_screen *screen, struct zink_program 
*pg);
+zink_pipeline_layout_create(struct zink_screen *screen, struct zink_program 
*pg, uint32_t *compat);
 
 void
 zink_program_update_compute_pipeline_state(struct zink_context *ctx, struct 
zink_compute_program *comp, const uint block[3]);

Reply via email to