From 8636717270f1ecd7d6a99f165f99b201c20dbf80 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Mon, 16 May 2022 17:28:59 -0400 Subject: [PATCH] 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 Part-of: --- src/gallium/drivers/zink/zink_descriptors.c | 251 +++++++++++++----- src/gallium/drivers/zink/zink_descriptors.h | 50 +++- .../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, 283 insertions(+), 82 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); - 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); - } + desc_set_res_add(zds, res, num_resources++, cache_hit); + wds[num_wds].pBufferInfo = info; } - if (is_buffer) - wds[num_wds].pTexelBufferView = buffer_info; - else - wds[num_wds].pImageInfo = image_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++) { + 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; + } + break; + default: + unreachable("unknown descriptor type"); + } + num_wds = init_write_descriptor(shader, zds->desc_set, type, j, &wds[num_wds], num_wds); } - break; - default: - unreachable("unknown descriptor type"); - } - 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);