Mesa (main): zink: add a "compact" descriptor mode

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed May 25 04:15:06 UTC 2022


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Mon May 16 17:28:59 2022 -0400

zink: add a "compact" descriptor mode

this compacts the ubo+ssbo and samplerview+image sets, enabling zink
to run fully featured with only 4 descriptor sets used

fixes #4964

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

---

 src/gallium/drivers/zink/zink_descriptors.c      | 245 ++++++++++++++++-------
 src/gallium/drivers/zink/zink_descriptors.h      |  50 ++++-
 src/gallium/drivers/zink/zink_descriptors_lazy.c |  34 +++-
 src/gallium/drivers/zink/zink_screen.c           |  24 ++-
 src/gallium/drivers/zink/zink_screen.h           |   6 +
 5 files changed, 280 insertions(+), 79 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c
index 3c647d2ccc4..c297295551b 100644
--- a/src/gallium/drivers/zink/zink_descriptors.c
+++ b/src/gallium/drivers/zink/zink_descriptors.c
@@ -60,6 +60,7 @@ struct zink_descriptor_set {
    bool invalid;
    bool punted;
    bool recycled;
+   uint8_t compacted; //bitmask of zink_descriptor_type
    struct zink_descriptor_state_key key;
    struct zink_batch_usage *batch_uses;
 #ifndef NDEBUG
@@ -730,6 +731,37 @@ populate_zds_key(struct zink_context *ctx, enum zink_descriptor_type type, bool
    }
 }
 
+static void
+populate_zds_key_compact(struct zink_context *ctx, enum zink_descriptor_type type, bool is_compute,
+                         struct zink_descriptor_state_key *key, uint32_t push_usage)
+{
+   if (is_compute) {
+      for (unsigned i = 1; i < ZINK_SHADER_COUNT; i++)
+         key->exists[i] = false;
+      key->exists[0] = true;
+      if (type == ZINK_DESCRIPTOR_TYPES)
+         key->state[0] = ctx->dd->push_state[is_compute];
+      else {
+         assert(ctx->dd->compact_descriptor_states[is_compute].valid[type]);
+         key->state[0] = ctx->dd->compact_descriptor_states[is_compute].state[type];
+      }
+   } else if (type == ZINK_DESCRIPTOR_TYPES) {
+      /* gfx only */
+      for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
+         if (push_usage & BITFIELD_BIT(i)) {
+            key->exists[i] = true;
+            key->state[i] = ctx->dd->gfx_push_state[i];
+         } else
+            key->exists[i] = false;
+      }
+   } else {
+      for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
+         key->exists[i] = ctx->dd->compact_gfx_descriptor_states[i].valid[type];
+         key->state[i] = ctx->dd->compact_gfx_descriptor_states[i].state[type];
+      }
+   }
+}
+
 static void
 punt_invalid_set(struct zink_descriptor_set *zds, struct hash_entry *he)
 {
@@ -748,6 +780,7 @@ zink_descriptor_set_get(struct zink_context *ctx,
                                bool *cache_hit)
 {
    *cache_hit = false;
+   struct zink_screen *screen = zink_screen(ctx->base.screen);
    struct zink_descriptor_set *zds;
    struct zink_program *pg = is_compute ? (struct zink_program *)ctx->curr_compute : (struct zink_program *)ctx->curr_program;
    struct zink_batch *batch = &ctx->batch;
@@ -757,7 +790,10 @@ zink_descriptor_set_get(struct zink_context *ctx,
    assert(type <= ZINK_DESCRIPTOR_TYPES);
 
    assert(pool->key->layout->num_bindings);
+   assert(!screen->compact_descriptors || (type != ZINK_DESCRIPTOR_TYPE_SSBO && type != ZINK_DESCRIPTOR_TYPE_IMAGE));
    uint32_t hash = push_set ? ctx->dd->push_state[is_compute] :
+                              screen->compact_descriptors ?
+                              ctx->dd->compact_descriptor_states[is_compute].state[type] :
                               ctx->dd->descriptor_states[is_compute].state[type];
 
    struct zink_descriptor_set *last_set = push_set ? ctx->dd->last_set[is_compute] : pdd_cached(pg)->last_set[type];
@@ -766,13 +802,18 @@ zink_descriptor_set_get(struct zink_context *ctx,
     * early return here can be done safely and with no locking
     */
    if (last_set && ((push_set && !ctx->dd->changed[is_compute][ZINK_DESCRIPTOR_TYPES]) ||
-                    (!push_set && !ctx->dd->changed[is_compute][type]))) {
+                    (!push_set && (screen->compact_descriptors ?
+                                   !ctx->dd->changed[is_compute][type] && !ctx->dd->changed[is_compute][type+2] :
+                                   !ctx->dd->changed[is_compute][type])))) {
       *cache_hit = true;
       return last_set;
    }
 
    struct zink_descriptor_state_key key;
-   populate_zds_key(ctx, type, is_compute, &key, pg->dd->push_usage);
+   if (screen->compact_descriptors)
+      populate_zds_key_compact(ctx, type, is_compute, &key, pg->dd->push_usage);
+   else
+      populate_zds_key(ctx, type, is_compute, &key, pg->dd->push_usage);
 
    simple_mtx_lock(&pool->mtx);
    if (last_set && last_set->hash == hash && desc_state_equal(&last_set->key, &key)) {
@@ -860,10 +901,26 @@ out:
                 _mesa_hash_table_num_entries(pool->free_desc_sets) < ZINK_DEFAULT_MAX_DESCS - ZINK_DEFAULT_DESC_CLAMP))
       ctx->oom_flush = ctx->oom_stall = true;
    zds->hash = hash;
-   populate_zds_key(ctx, type, is_compute, &zds->key, pg->dd->push_usage);
+   if (screen->compact_descriptors)
+      populate_zds_key_compact(ctx, type, is_compute, &zds->key, pg->dd->push_usage);
+   else
+      populate_zds_key(ctx, type, is_compute, &zds->key, pg->dd->push_usage);
    zds->recycled = false;
    _mesa_hash_table_insert_pre_hashed(pool->desc_sets, hash, &zds->key, zds);
 quick_out:
+   if (!push_set) {
+      if (screen->compact_descriptors) {
+         if (zink_desc_type_from_vktype(pool->key->sizes[0].type) == type)
+            zds->compacted |= BITFIELD_BIT(type);
+         for (unsigned i = 0; i < pool->key->num_type_sizes; i++) {
+            if (zink_desc_type_from_vktype(pool->key->sizes[0].type) == type + 2) {
+               zds->compacted |= BITFIELD_BIT(type + 2);
+               break;
+            }
+         }
+      } else
+         zds->compacted |= BITFIELD_BIT(type);
+   }
    zds->punted = zds->invalid = false;
    batch_add_desc_set(batch, zds);
    if (push_set)
@@ -1282,19 +1339,26 @@ update_push_ubo_descriptors(struct zink_context *ctx, struct zink_descriptor_set
 static void
 set_descriptor_set_refs(struct zink_context *ctx, struct zink_descriptor_set *zds, struct zink_program *pg, bool cache_hit)
 {
-   enum zink_descriptor_type type = zds->pool->type;
-   for (unsigned i = 0; i < pdd_cached(pg)->num_refs[type]; i++) {
-      switch (type) {
-      case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
-         desc_set_sampler_add(ctx, zds, pdd_cached(pg)->refs[type][i].sampler.dsurf,
-                                        *pdd_cached(pg)->refs[type][i].sampler.sampler_state, i, cache_hit);
-         break;
-      case ZINK_DESCRIPTOR_TYPE_IMAGE:
-         desc_set_descriptor_surface_add(ctx, zds, pdd_cached(pg)->refs[type][i].dsurf, i, cache_hit);
-         break;
-      default:
-         desc_set_res_add(zds, *pdd_cached(pg)->refs[type][i].res, i, cache_hit);
-         break;
+   const bool compact_descriptors = zink_screen(ctx->base.screen)->compact_descriptors;
+   STATIC_ASSERT(ZINK_DESCRIPTOR_TYPE_UBO + 2 == ZINK_DESCRIPTOR_TYPE_SSBO);
+   STATIC_ASSERT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW + 2 == ZINK_DESCRIPTOR_TYPE_IMAGE);
+   const enum zink_descriptor_type types[] = {zds->pool->type, zds->pool->type + 2};
+   unsigned num_types = compact_descriptors ? 2 : 1;
+   for (unsigned n = 0; n < num_types; n++) {
+      const enum zink_descriptor_type type = types[n];
+      for (unsigned i = 0; i < pdd_cached(pg)->num_refs[type]; i++) {
+         switch (type) {
+         case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
+            desc_set_sampler_add(ctx, zds, pdd_cached(pg)->refs[type][i].sampler.dsurf,
+                                           *pdd_cached(pg)->refs[type][i].sampler.sampler_state, i, cache_hit);
+            break;
+         case ZINK_DESCRIPTOR_TYPE_IMAGE:
+            desc_set_descriptor_surface_add(ctx, zds, pdd_cached(pg)->refs[type][i].dsurf, i, cache_hit);
+            break;
+         default:
+            desc_set_res_add(zds, *pdd_cached(pg)->refs[type][i].res, i, cache_hit);
+            break;
+         }
       }
    }
 }
@@ -1326,64 +1390,70 @@ update_descriptors_internal(struct zink_context *ctx, enum zink_descriptor_type
    VkWriteDescriptorSet wds[ZINK_MAX_DESCRIPTORS_PER_TYPE];
    unsigned num_wds = 0;
 
-   for (int i = 0; i < num_stages; i++) {
-      struct zink_shader *shader = stages[i];
-      if (!shader)
+   const enum zink_descriptor_type types[2] = {type, type + 2};
+   for (unsigned n = 0; n < ARRAY_SIZE(types); n++) {
+      if (!(zds->compacted & BITFIELD_BIT(types[n])))
          continue;
-      enum pipe_shader_type stage = pipe_shader_type_from_mesa(shader->nir->info.stage);
-      for (int j = 0; j < shader->num_bindings[type]; j++) {
-         int index = shader->bindings[type][j].index;
-         switch (type) {
-         case ZINK_DESCRIPTOR_TYPE_UBO:
-            if (!index)
-               continue;
-         FALLTHROUGH;
-         case ZINK_DESCRIPTOR_TYPE_SSBO: {
-            VkDescriptorBufferInfo *info;
-            struct zink_resource *res = ctx->di.descriptor_res[type][stage][index];
-            if (type == ZINK_DESCRIPTOR_TYPE_UBO)
-               info = &ctx->di.ubos[stage][index];
-            else
-               info = &ctx->di.ssbos[stage][index];
-            assert(num_resources < num_bindings);
-            desc_set_res_add(zds, res, num_resources++, cache_hit);
-            wds[num_wds].pBufferInfo = info;
-         }
-         break;
-         case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
-         case ZINK_DESCRIPTOR_TYPE_IMAGE: {
-            VkDescriptorImageInfo *image_info;
-            VkBufferView *buffer_info;
-            if (type == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW) {
-               image_info = &ctx->di.textures[stage][index];
-               buffer_info = &ctx->di.tbos[stage][index];
-            } else {
-               image_info = &ctx->di.images[stage][index];
-               buffer_info = &ctx->di.texel_images[stage][index];
-            }
-            bool is_buffer = zink_shader_descriptor_is_buffer(shader, type, j);
-            for (unsigned k = 0; k < shader->bindings[type][j].size; k++) {
+      type = types[n];
+      for (int i = 0; i < num_stages; i++) {
+         struct zink_shader *shader = stages[i];
+         if (!shader)
+            continue;
+         enum pipe_shader_type stage = pipe_shader_type_from_mesa(shader->nir->info.stage);
+         for (int j = 0; j < shader->num_bindings[type]; j++) {
+            int index = shader->bindings[type][j].index;
+            switch (type) {
+            case ZINK_DESCRIPTOR_TYPE_UBO:
+               if (!index)
+                  continue;
+            FALLTHROUGH;
+            case ZINK_DESCRIPTOR_TYPE_SSBO: {
+               VkDescriptorBufferInfo *info;
+               struct zink_resource *res = ctx->di.descriptor_res[type][stage][index];
+               if (type == ZINK_DESCRIPTOR_TYPE_UBO)
+                  info = &ctx->di.ubos[stage][index];
+               else
+                  info = &ctx->di.ssbos[stage][index];
                assert(num_resources < num_bindings);
+               desc_set_res_add(zds, res, num_resources++, cache_hit);
+               wds[num_wds].pBufferInfo = info;
+            }
+            break;
+            case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
+            case ZINK_DESCRIPTOR_TYPE_IMAGE: {
+               VkDescriptorImageInfo *image_info;
+               VkBufferView *buffer_info;
                if (type == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW) {
-                  struct zink_sampler_state *sampler = NULL;
-                  if (!is_buffer && image_info->imageView)
-                     sampler = ctx->sampler_states[stage][index + k];;
-
-                  desc_set_sampler_add(ctx, zds, &ctx->di.sampler_surfaces[stage][index + k], sampler, num_resources++, cache_hit);
+                  image_info = &ctx->di.textures[stage][index];
+                  buffer_info = &ctx->di.tbos[stage][index];
                } else {
-                  desc_set_image_add(ctx, zds, &ctx->di.image_surfaces[stage][index + k], num_resources++, cache_hit);
+                  image_info = &ctx->di.images[stage][index];
+                  buffer_info = &ctx->di.texel_images[stage][index];
+               }
+               bool is_buffer = zink_shader_descriptor_is_buffer(shader, type, j);
+               for (unsigned k = 0; k < shader->bindings[type][j].size; k++) {
+                  assert(num_resources < num_bindings);
+                  if (type == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW) {
+                     struct zink_sampler_state *sampler = NULL;
+                     if (!is_buffer && image_info->imageView)
+                        sampler = ctx->sampler_states[stage][index + k];;
+
+                     desc_set_sampler_add(ctx, zds, &ctx->di.sampler_surfaces[stage][index + k], sampler, num_resources++, cache_hit);
+                  } else {
+                     desc_set_image_add(ctx, zds, &ctx->di.image_surfaces[stage][index + k], num_resources++, cache_hit);
+                  }
                }
+               if (is_buffer)
+                  wds[num_wds].pTexelBufferView = buffer_info;
+               else
+                  wds[num_wds].pImageInfo = image_info;
             }
-            if (is_buffer)
-               wds[num_wds].pTexelBufferView = buffer_info;
-            else
-               wds[num_wds].pImageInfo = image_info;
-         }
-         break;
-         default:
-            unreachable("unknown descriptor type");
+            break;
+            default:
+               unreachable("unknown descriptor type");
+            }
+            num_wds = init_write_descriptor(shader, zds->desc_set, type, j, &wds[num_wds], num_wds);
          }
-         num_wds = init_write_descriptor(shader, zds->desc_set, type, j, &wds[num_wds], num_wds);
       }
    }
    if (num_wds)
@@ -1556,6 +1626,11 @@ calc_descriptor_state_hash_ssbo(struct zink_context *ctx, struct zink_shader *zs
       struct pipe_shader_buffer *ssbo = &ctx->ssbos[shader][idx];
       hash = XXH32(&ssbo->buffer_offset, sizeof(ssbo->buffer_offset), hash);
       hash = XXH32(&ssbo->buffer_size, sizeof(ssbo->buffer_size), hash);
+      /* compacted sets need a way to differentiate between a buffer bound as a ubo vs ssbo */
+      if (zink_screen(ctx->base.screen)->compact_descriptors) {
+         uint32_t writable = ctx->writable_ssbos[shader] & BITFIELD_BIT(idx);
+         hash = XXH32(&writable, sizeof(writable), hash);
+      }
    }
    return hash;
 }
@@ -1705,9 +1780,45 @@ zink_context_update_descriptor_states(struct zink_context *ctx, struct zink_prog
    }
    for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
       if (pdd_cached(pg)->pool[screen->desc_set_id[i] - 1] && pdd_cached(pg)->cache_misses[i] < MAX_CACHE_MISSES &&
+          ctx->dd->changed[pg->is_compute][i] &&
           !ctx->dd->descriptor_states[pg->is_compute].valid[i])
          update_descriptor_state(ctx, i, pg->is_compute);
    }
+
+   if (!screen->compact_descriptors)
+      return;
+
+   for (unsigned n = 0; n < 2; n++) {
+      ctx->dd->compact_descriptor_states[pg->is_compute].valid[n] = ctx->dd->descriptor_states[pg->is_compute].valid[n] |
+                                                                    ctx->dd->descriptor_states[pg->is_compute].valid[n + 2];
+      if (ctx->dd->compact_descriptor_states[pg->is_compute].valid[n]) {
+         if (pg->is_compute) {
+            ctx->dd->compact_descriptor_states[pg->is_compute].state[n] = ctx->dd->descriptor_states[pg->is_compute].state[n] ^
+                                                                          ctx->dd->descriptor_states[pg->is_compute].state[n + 2];
+         } else {
+            uint32_t hash = 0;
+            bool first = true;
+            for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
+               ctx->dd->compact_gfx_descriptor_states[i].valid[n] = ctx->dd->gfx_descriptor_states[i].valid[n] |
+                                                                    ctx->dd->gfx_descriptor_states[i].valid[n + 2];
+               if (ctx->dd->compact_gfx_descriptor_states[i].valid[n]) {
+                  ctx->dd->compact_gfx_descriptor_states[i].state[n] = ctx->dd->gfx_descriptor_states[i].state[n] ^
+                                                                       ctx->dd->gfx_descriptor_states[i].state[n + 2];
+                  if (first)
+                     hash = ctx->dd->compact_gfx_descriptor_states[i].state[n];
+                  else
+                     hash = XXH32(&ctx->dd->compact_gfx_descriptor_states[i].state[n], sizeof(uint32_t), hash);
+                  first = false;
+               } else {
+                  ctx->dd->compact_gfx_descriptor_states[i].state[n] = 0;
+               }
+            }
+            ctx->dd->compact_descriptor_states[pg->is_compute].state[n] = hash;
+         }
+      } else {
+         ctx->dd->compact_descriptor_states[pg->is_compute].state[n] = 0;
+      }
+   }
 }
 
 void
diff --git a/src/gallium/drivers/zink/zink_descriptors.h b/src/gallium/drivers/zink/zink_descriptors.h
index d60a15abdc1..d0ea7a95d20 100644
--- a/src/gallium/drivers/zink/zink_descriptors.h
+++ b/src/gallium/drivers/zink/zink_descriptors.h
@@ -73,6 +73,15 @@ enum zink_descriptor_size_index {
    ZDS_INDEX_STORAGE_TEXELS,
 };
 
+enum zink_descriptor_size_index_compact {
+   ZDS_INDEX_COMP_UBO,
+   ZDS_INDEX_COMP_STORAGE_BUFFER,
+   ZDS_INDEX_COMP_COMBINED_SAMPLER,
+   ZDS_INDEX_COMP_UNIFORM_TEXELS,
+   ZDS_INDEX_COMP_STORAGE_IMAGE,
+   ZDS_INDEX_COMP_STORAGE_TEXELS,
+};
+
 struct hash_table;
 
 struct zink_context;
@@ -103,7 +112,7 @@ struct zink_descriptor_pool_key {
    unsigned use_count;
    unsigned num_type_sizes;
    struct zink_descriptor_layout_key *layout;
-   VkDescriptorPoolSize sizes[2];
+   VkDescriptorPoolSize sizes[4];
 };
 
 struct zink_descriptor_reference {
@@ -114,6 +123,8 @@ struct zink_descriptor_reference {
 struct zink_descriptor_data {
    struct zink_descriptor_state gfx_descriptor_states[ZINK_SHADER_COUNT]; // keep incremental hashes here
    struct zink_descriptor_state descriptor_states[2]; // gfx, compute
+   struct zink_descriptor_state compact_gfx_descriptor_states[ZINK_SHADER_COUNT]; // keep incremental hashes here
+   struct zink_descriptor_state compact_descriptor_states[2]; // gfx, compute
    struct hash_table *descriptor_pools[ZINK_DESCRIPTOR_TYPES];
 
    struct zink_descriptor_layout_key *push_layout_keys[2]; //gfx, compute
@@ -178,6 +189,28 @@ zink_vktype_to_size_idx(VkDescriptorType type)
    unreachable("unknown type");
 }
 
+static inline enum zink_descriptor_size_index_compact
+zink_vktype_to_size_idx_comp(VkDescriptorType type)
+{
+   switch (type) {
+   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+      return ZDS_INDEX_COMP_UBO;
+   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+      return ZDS_INDEX_COMP_COMBINED_SAMPLER;
+   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+      return ZDS_INDEX_COMP_UNIFORM_TEXELS;
+   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+      return ZDS_INDEX_COMP_STORAGE_BUFFER;
+   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+      return ZDS_INDEX_COMP_STORAGE_IMAGE;
+   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+      return ZDS_INDEX_COMP_STORAGE_TEXELS;
+   default: break;
+   }
+   unreachable("unknown type");
+}
+
 static inline enum zink_descriptor_size_index
 zink_descriptor_type_to_size_idx(enum zink_descriptor_type type)
 {
@@ -194,6 +227,21 @@ zink_descriptor_type_to_size_idx(enum zink_descriptor_type type)
    }
    unreachable("unknown type");
 }
+
+static inline enum zink_descriptor_size_index_compact
+zink_descriptor_type_to_size_idx_comp(enum zink_descriptor_type type)
+{
+   switch (type) {
+   case ZINK_DESCRIPTOR_TYPE_UBO:
+      return ZDS_INDEX_COMP_UBO;
+   case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
+      return ZDS_INDEX_COMP_COMBINED_SAMPLER;
+   case ZINK_DESCRIPTOR_TYPE_SSBO:
+   case ZINK_DESCRIPTOR_TYPE_IMAGE:
+   default: break;
+   }
+   unreachable("unknown type");
+}
 bool
 zink_descriptor_layouts_init(struct zink_context *ctx);
 
diff --git a/src/gallium/drivers/zink/zink_descriptors_lazy.c b/src/gallium/drivers/zink/zink_descriptors_lazy.c
index d6d0bbcbe3e..f878706143b 100644
--- a/src/gallium/drivers/zink/zink_descriptors_lazy.c
+++ b/src/gallium/drivers/zink/zink_descriptors_lazy.c
@@ -141,12 +141,30 @@ descriptor_program_num_sizes(VkDescriptorPoolSize *sizes, enum zink_descriptor_t
    unreachable("unknown type");
 }
 
+static uint16_t
+descriptor_program_num_sizes_compact(VkDescriptorPoolSize *sizes, unsigned desc_set)
+{
+   switch (desc_set) {
+   case ZINK_DESCRIPTOR_TYPE_UBO:
+      return !!sizes[ZDS_INDEX_COMP_UBO].descriptorCount + !!sizes[ZDS_INDEX_COMP_STORAGE_BUFFER].descriptorCount;
+   case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
+      return !!sizes[ZDS_INDEX_COMP_COMBINED_SAMPLER].descriptorCount +
+             !!sizes[ZDS_INDEX_COMP_UNIFORM_TEXELS].descriptorCount +
+             !!sizes[ZDS_INDEX_COMP_STORAGE_IMAGE].descriptorCount +
+             !!sizes[ZDS_INDEX_COMP_STORAGE_TEXELS].descriptorCount;
+   case ZINK_DESCRIPTOR_TYPE_SSBO:
+   case ZINK_DESCRIPTOR_TYPE_IMAGE:
+   default: break;
+   }
+   unreachable("unknown type");
+}
+
 bool
 zink_descriptor_program_init_lazy(struct zink_context *ctx, struct zink_program *pg)
 {
    struct zink_screen *screen = zink_screen(ctx->base.screen);
-   VkDescriptorSetLayoutBinding bindings[ZINK_DESCRIPTOR_TYPES][PIPE_SHADER_TYPES * 32];
-   VkDescriptorUpdateTemplateEntry entries[ZINK_DESCRIPTOR_TYPES][PIPE_SHADER_TYPES * 32];
+   VkDescriptorSetLayoutBinding bindings[ZINK_DESCRIPTOR_TYPES][PIPE_SHADER_TYPES * 64];
+   VkDescriptorUpdateTemplateEntry entries[ZINK_DESCRIPTOR_TYPES][PIPE_SHADER_TYPES * 64];
    unsigned num_bindings[ZINK_DESCRIPTOR_TYPES] = {0};
    uint8_t has_bindings = 0;
    unsigned push_count = 0;
@@ -200,14 +218,17 @@ zink_descriptor_program_init_lazy(struct zink_context *ctx, struct zink_program
             binding->stageFlags = stage_flags;
             binding->pImmutableSamplers = NULL;
 
-            enum zink_descriptor_size_index idx = zink_vktype_to_size_idx(shader->bindings[j][k].type);
+            unsigned idx = screen->compact_descriptors ? zink_vktype_to_size_idx_comp(shader->bindings[j][k].type) :
+                                                         zink_vktype_to_size_idx(shader->bindings[j][k].type);
             sizes[idx].descriptorCount += shader->bindings[j][k].size;
             sizes[idx].type = shader->bindings[j][k].type;
             init_template_entry(shader, j, k, &entries[desc_set][entry_idx[desc_set]], &entry_idx[desc_set], screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY);
             num_bindings[desc_set]++;
             has_bindings |= BITFIELD_BIT(desc_set);
          }
-         num_type_sizes[desc_set] = descriptor_program_num_sizes(sizes, j);
+         num_type_sizes[desc_set] = screen->compact_descriptors ?
+                                    descriptor_program_num_sizes_compact(sizes, desc_set) :
+                                    descriptor_program_num_sizes(sizes, j);
       }
       pg->dd->bindless |= shader->bindless;
    }
@@ -630,8 +651,11 @@ zink_context_invalidate_descriptor_state_lazy(struct zink_context *ctx, enum pip
 {
    if (type == ZINK_DESCRIPTOR_TYPE_UBO && !start)
       dd_lazy(ctx)->push_state_changed[shader == PIPE_SHADER_COMPUTE] = true;
-   else
+   else {
+      if (zink_screen(ctx->base.screen)->compact_descriptors && type > ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)
+         type -= 2;
       dd_lazy(ctx)->state_changed[shader == PIPE_SHADER_COMPUTE] |= BITFIELD_BIT(type);
+   }
 }
 
 void
diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c
index 494321c3d27..57e781e2d50 100644
--- a/src/gallium/drivers/zink/zink_screen.c
+++ b/src/gallium/drivers/zink/zink_screen.c
@@ -79,6 +79,7 @@ zink_debug_options[] = {
    { "tgsi", ZINK_DEBUG_TGSI, "Dump TGSI during program compile" },
    { "validation", ZINK_DEBUG_VALIDATION, "Dump Validation layer output" },
    { "sync", ZINK_DEBUG_SYNC, "Force synchronization before draws/dispatches" },
+   { "compact", ZINK_DEBUG_COMPACT, "Use only 4 descriptor sets" },
    DEBUG_NAMED_VALUE_END
 };
 
@@ -2180,12 +2181,23 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
 
    zink_verify_device_extensions(screen);
 
-   screen->desc_set_id[ZINK_DESCRIPTOR_TYPES] = 0;
-   screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UBO] = 1;
-   screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = 2;
-   screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SSBO] = 3;
-   screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_IMAGE] = 4;
-   screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS] = 5;
+   if ((zink_debug & ZINK_DEBUG_COMPACT) ||
+       screen->info.props.limits.maxBoundDescriptorSets < ZINK_MAX_DESCRIPTOR_SETS) {
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPES] = 0;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UBO] = 1;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SSBO] = 1;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = 2;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_IMAGE] = 2;
+      screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS] = 3;
+      screen->compact_descriptors = true;
+   } else {
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPES] = 0;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_UBO] = 1;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = 2;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_SSBO] = 3;
+      screen->desc_set_id[ZINK_DESCRIPTOR_TYPE_IMAGE] = 4;
+      screen->desc_set_id[ZINK_DESCRIPTOR_BINDLESS] = 5;
+   }
 
    if (screen->info.have_EXT_calibrated_timestamps && !check_have_device_time(screen))
       goto fail;
diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h
index a39b5f35e4b..3dc925108e9 100644
--- a/src/gallium/drivers/zink/zink_screen.h
+++ b/src/gallium/drivers/zink/zink_screen.h
@@ -67,6 +67,7 @@ enum zink_descriptor_type;
 #define ZINK_DEBUG_TGSI 0x4
 #define ZINK_DEBUG_VALIDATION 0x8
 #define ZINK_DEBUG_SYNC 0x10
+#define ZINK_DEBUG_COMPACT (1<<5)
 
 #define NUM_SLAB_ALLOCATORS 3
 #define MIN_SLAB_ORDER 8
@@ -78,8 +79,12 @@ enum zink_descriptor_mode {
    ZINK_DESCRIPTOR_MODE_LAZY,
    ZINK_DESCRIPTOR_MODE_NOFALLBACK,
    ZINK_DESCRIPTOR_MODE_NOTEMPLATES,
+   ZINK_DESCRIPTOR_MODE_COMPACT,
 };
 
+//keep in sync with zink_descriptor_type since headers can't be cross-included
+#define ZINK_MAX_DESCRIPTOR_SETS 6
+
 struct zink_modifier_prop {
     uint32_t                             drmFormatModifierCount;
     VkDrmFormatModifierPropertiesEXT*    pDrmFormatModifierProperties;
@@ -164,6 +169,7 @@ struct zink_screen {
 
    struct vk_dispatch_table vk;
 
+   bool compact_descriptors;
    uint8_t desc_set_id[ZINK_MAX_DESCRIPTOR_SETS];
    bool (*descriptor_program_init)(struct zink_context *ctx, struct zink_program *pg);
    void (*descriptor_program_deinit)(struct zink_context *ctx, struct zink_program *pg);



More information about the mesa-commit mailing list