Module: Mesa Branch: main Commit: 4cda98c827f65ff7a834f0303f686da349d8f59f URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=4cda98c827f65ff7a834f0303f686da349d8f59f
Author: Mike Blumenkrantz <[email protected]> Date: Fri Feb 10 16:02:03 2023 -0500 zink: implement a scaling descriptor buffer size previously descriptor buffers were sized to allow for 25,000 descriptors this is a great number. but in some scenarios it's overkill, and it's theoretically possible that it might be underkill in others (citation needed), so add some handling for both cases to save small amounts of vram on average and not crash in the distant future when hypercomputers try running drawoverhead Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21246> --- src/gallium/drivers/zink/zink_descriptors.c | 59 +++++++++++++++++++++++++---- src/gallium/drivers/zink/zink_resource.c | 2 - src/gallium/drivers/zink/zink_resource.h | 1 - src/gallium/drivers/zink/zink_types.h | 5 +-- 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c index 157d5c045ce..a05bf1e7cd5 100644 --- a/src/gallium/drivers/zink/zink_descriptors.c +++ b/src/gallium/drivers/zink/zink_descriptors.c @@ -1036,6 +1036,25 @@ populate_sets(struct zink_context *ctx, struct zink_batch_state *bs, return true; } +static void +reinit_db(struct zink_screen *screen, struct zink_batch_state *bs) +{ + zink_batch_descriptor_deinit(screen, bs); + zink_batch_descriptor_init(screen, bs); +} + +static void +enlarge_db(struct zink_context *ctx) +{ + struct zink_screen *screen = zink_screen(ctx->base.screen); + struct zink_batch_state *bs = ctx->batch.state; + /* ensure current db surives */ + zink_batch_reference_resource(&ctx->batch, bs->dd.db); + /* rebinding a db mid-batch is extremely costly: scaling by 10x should ensure it never happens more than twice */ + ctx->dd.db.max_db_size *= 10; + reinit_db(screen, bs); +} + static void update_separable(struct zink_context *ctx, struct zink_program *pg) { @@ -1052,6 +1071,9 @@ update_separable(struct zink_context *ctx, struct zink_program *pg) prog->shaders[MESA_SHADER_FRAGMENT], }; + if (bs->dd.db_offset + shaders[0]->precompile.db_size + shaders[1]->precompile.db_size >= bs->dd.db->base.b.width0) + enlarge_db(ctx); + if (!bs->dd.db_bound) zink_batch_bind_db(ctx); @@ -1059,7 +1081,7 @@ update_separable(struct zink_context *ctx, struct zink_program *pg) if (!shaders[j]->precompile.dsl) continue; uint64_t offset = bs->dd.db_offset; - assert(bs->dd.db->obj->size > bs->dd.db_offset + shaders[j]->precompile.db_size); + assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + shaders[j]->precompile.db_size); for (unsigned i = 0; i < shaders[j]->precompile.num_bindings; i++) { info.type = shaders[j]->precompile.bindings[i].descriptorType; uint64_t desc_offset = offset + shaders[j]->precompile.db_offset[i]; @@ -1125,7 +1147,7 @@ zink_descriptors_update_masked_buffer(struct zink_context *ctx, bool is_compute, VkDescriptorGetInfoEXT info; info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT; info.pNext = NULL; - assert(bs->dd.db->obj->size > bs->dd.db_offset + pg->dd.db_size[type]); + assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + pg->dd.db_size[type]); for (unsigned i = 0; i < key->num_bindings; i++) { info.type = key->bindings[i].descriptorType; uint64_t desc_offset = offset + pg->dd.db_offset[type][i]; @@ -1282,8 +1304,24 @@ zink_descriptors_update(struct zink_context *ctx, bool is_compute) */ uint8_t bind_sets = bs->dd.pg[is_compute] && bs->dd.compat_id[is_compute] == pg->compat_id ? 0 : pg->dd.binding_usage; - if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB && !bs->dd.db_bound) - zink_batch_bind_db(ctx); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + size_t check_size = 0; + if (pg->dd.push_usage && ctx->dd.push_state_changed[is_compute]) + check_size += ctx->dd.db_size[is_compute]; + for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) { + if (changed_sets & BITFIELD_BIT(i)) + check_size += pg->dd.db_size[i]; + } + + if (bs->dd.db_offset + check_size >= bs->dd.db->base.b.width0) { + enlarge_db(ctx); + changed_sets = pg->dd.binding_usage; + ctx->dd.push_state_changed[is_compute] = true; + } + + if (!bs->dd.db_bound) + zink_batch_bind_db(ctx); + } if (pg->dd.push_usage && (ctx->dd.push_state_changed[is_compute] || bind_sets)) { if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { @@ -1292,7 +1330,7 @@ zink_descriptors_update(struct zink_context *ctx, bool is_compute) bs->dd.db_offset : bs->dd.cur_db_offset[ZINK_DESCRIPTOR_TYPE_UNIFORMS]; if (ctx->dd.push_state_changed[is_compute]) { - assert(bs->dd.db->obj->size > bs->dd.db_offset + ctx->dd.db_size[is_compute]); + assert(bs->dd.db->base.b.width0 > bs->dd.db_offset + ctx->dd.db_size[is_compute]); for (unsigned i = 0; i < (is_compute ? 1 : ZINK_GFX_SHADER_COUNT); i++) { VkDescriptorGetInfoEXT info; info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT; @@ -1425,6 +1463,9 @@ zink_batch_descriptor_deinit(struct zink_screen *screen, struct zink_batch_state pipe_buffer_unmap(&bs->ctx->base, bs->dd.db_xfer); if (bs->dd.db) screen->base.resource_destroy(&screen->base, &bs->dd.db->base.b); + bs->dd.db_bound = false; + bs->dd.db_offset = 0; + memset(bs->dd.cur_db_offset, 0, sizeof(bs->dd.cur_db_offset)); } /* ensure the idle/usable overflow set array always has as many members as possible by merging both arrays on batch state reset */ @@ -1453,6 +1494,8 @@ zink_batch_descriptor_reset(struct zink_screen *screen, struct zink_batch_state { if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { bs->dd.db_offset = 0; + if (bs->dd.db && bs->dd.db->base.b.width0 < bs->ctx->dd.db.max_db_size * screen->base_descriptor_size) + reinit_db(screen, bs); bs->dd.db_bound = false; } else { for (unsigned i = 0; i < ZINK_DESCRIPTOR_BASE_TYPES; i++) { @@ -1503,7 +1546,7 @@ zink_batch_descriptor_init(struct zink_screen *screen, struct zink_batch_state * if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB && !(bs->ctx->flags & ZINK_CONTEXT_COPY_ONLY)) { unsigned bind = ZINK_BIND_RESOURCE_DESCRIPTOR | ZINK_BIND_SAMPLER_DESCRIPTOR; - struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, screen->base_descriptor_size); + struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, bs->ctx->dd.db.max_db_size * screen->base_descriptor_size); if (!pres) return false; bs->dd.db = zink_resource(pres); @@ -1556,6 +1599,8 @@ zink_descriptors_init(struct zink_context *ctx) VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, ctx->dd.push_dsl[0]->layout, i, &val); ctx->dd.db_offset[i] = val; } + /* start small */ + ctx->dd.db.max_db_size = 250; } return true; @@ -1645,7 +1690,7 @@ zink_descriptors_init_bindless(struct zink_context *ctx) unsigned bind = ZINK_BIND_RESOURCE_DESCRIPTOR | ZINK_BIND_SAMPLER_DESCRIPTOR; VkDeviceSize size; VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, screen->bindless_layout, &size); - struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, ZINK_USAGE_BINDLESS, size); + struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, size); ctx->dd.db.bindless_db = zink_resource(pres); ctx->dd.db.bindless_db_map = pipe_buffer_map(&ctx->base, pres, PIPE_MAP_READ | PIPE_MAP_WRITE, &ctx->dd.db.bindless_db_xfer); zink_batch_bind_db(ctx); diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 3397b6318b2..a8b4eab3069 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -180,8 +180,6 @@ create_bci(struct zink_screen *screen, const struct pipe_resource *templ, unsign if (bind & ZINK_BIND_DESCRIPTOR) { /* gallium sizes are all uint32_t, while the total size of this buffer may exceed that limit */ - if (templ->usage != ZINK_USAGE_BINDLESS) - bci.size *= ZINK_DESCRIPTOR_BUFFER_MULTIPLIER; bci.usage = 0; if (bind & ZINK_BIND_SAMPLER_DESCRIPTOR) bci.usage |= VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT; diff --git a/src/gallium/drivers/zink/zink_resource.h b/src/gallium/drivers/zink/zink_resource.h index 2b368b1ca55..37da41827c9 100644 --- a/src/gallium/drivers/zink/zink_resource.h +++ b/src/gallium/drivers/zink/zink_resource.h @@ -27,7 +27,6 @@ #include "zink_types.h" #define ZINK_MAP_TEMPORARY (PIPE_MAP_DRV_PRV << 0) -#define ZINK_USAGE_BINDLESS 128 //this is used for bindless descriptors #define ZINK_BIND_SAMPLER_DESCRIPTOR (1u << 26) #define ZINK_BIND_RESOURCE_DESCRIPTOR (1u << 27) #define ZINK_BIND_DESCRIPTOR (ZINK_BIND_SAMPLER_DESCRIPTOR | ZINK_BIND_RESOURCE_DESCRIPTOR) diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index eb5365e1023..972bef014d1 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -79,10 +79,6 @@ /* enum zink_descriptor_type */ #define ZINK_MAX_DESCRIPTOR_SETS 6 #define ZINK_MAX_DESCRIPTORS_PER_TYPE (32 * ZINK_GFX_SHADER_COUNT) -/* the number of typed descriptors that can fit in a given batch; - * sized based on max values seen in drawoverhead - */ -#define ZINK_DESCRIPTOR_BUFFER_MULTIPLIER 25000 /* suballocator defines */ #define NUM_SLAB_ALLOCATORS 3 @@ -406,6 +402,7 @@ struct zink_descriptor_data { uint8_t *bindless_db_map; struct pipe_transfer *bindless_db_xfer; uint32_t bindless_db_offsets[4]; + unsigned max_db_size; } db; };
