Module: Mesa Branch: master Commit: f4a53287de1a673566c7a4e14065e68e834b4cc7 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=f4a53287de1a673566c7a4e14065e68e834b4cc7
Author: Mike Blumenkrantz <[email protected]> Date: Tue Mar 16 00:34:31 2021 -0400 zink: handle cached descriptor set punting if an active set gets invalidated, it needs to be punted from the active hash table so it doesn't get reused Reviewed-by: Dave Airlie <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9543> --- src/gallium/drivers/zink/zink_descriptors.c | 68 ++++++++++++++++++++--------- src/gallium/drivers/zink/zink_descriptors.h | 1 + 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c index 070af735549..786291c724a 100644 --- a/src/gallium/drivers/zink/zink_descriptors.c +++ b/src/gallium/drivers/zink/zink_descriptors.c @@ -234,7 +234,7 @@ allocate_desc_set(struct zink_screen *screen, struct zink_program *pg, enum zink zds->hash = 0; zds->batch_uses = 0; zds->invalid = true; - zds->recycled = false; + zds->punted = zds->recycled = false; if (num_resources) { util_dynarray_init(&zds->barriers, alloc); if (!util_dynarray_grow(&zds->barriers, struct zink_descriptor_barrier, num_resources)) { @@ -274,6 +274,17 @@ populate_zds_key(struct zink_context *ctx, enum zink_descriptor_type type, bool } } +static void +punt_invalid_set(struct zink_descriptor_set *zds, struct hash_entry *he) +{ + /* this is no longer usable, so we punt it for now until it gets recycled */ + assert(!zds->recycled); + if (!he) + he = _mesa_hash_table_search_pre_hashed(zds->pool->desc_sets, zds->hash, &zds->key); + _mesa_hash_table_remove(zds->pool->desc_sets, he); + zds->punted = true; +} + struct zink_descriptor_set * zink_descriptor_set_get(struct zink_context *ctx, enum zink_descriptor_type type, @@ -296,29 +307,42 @@ zink_descriptor_set_get(struct zink_context *ctx, desc_state_equal(&pg->last_set[type]->key, &key)) { zds = pg->last_set[type]; *cache_hit = !zds->invalid; - if (pool->key.num_descriptors && zds->recycled) { - struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->free_desc_sets, hash, &key); - if (he) - _mesa_hash_table_remove(pool->free_desc_sets, he); + if (pool->key.num_descriptors) { + if (zds->recycled) { + struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->free_desc_sets, hash, &key); + if (he) + _mesa_hash_table_remove(pool->free_desc_sets, he); + zds->recycled = false; + } + if (zds->invalid) { + if (zds->batch_uses) + punt_invalid_set(zds, NULL); + else + /* this set is guaranteed to be in pool->alloc_desc_sets */ + goto skip_hash_tables; + zds = NULL; + } } - goto out; + if (zds) + goto out; } if (pool->key.num_descriptors) { struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->desc_sets, hash, &key); - bool recycled = false; + bool recycled = false, punted = false; if (he) { zds = (void*)he->data; - /* this shouldn't happen, but if we somehow get a cache hit on an invalidated, active desc set then - * we probably should just crash here rather than later - */ - assert(!zds->invalid); + if (zds->invalid && zds->batch_uses) { + punt_invalid_set(zds, he); + zds = NULL; + punted = true; + } } if (!he) { he = _mesa_hash_table_search_pre_hashed(pool->free_desc_sets, hash, &key); recycled = true; } - if (he) { + if (he && !punted) { zds = (void*)he->data; *cache_hit = !zds->invalid; if (recycled) { @@ -328,7 +352,7 @@ zink_descriptor_set_get(struct zink_context *ctx, } goto quick_out; } - +skip_hash_tables: if (util_dynarray_num_elements(&pool->alloc_desc_sets, struct zink_descriptor_set *)) { /* grab one off the allocated array */ zds = util_dynarray_pop(&pool->alloc_desc_sets, struct zink_descriptor_set *); @@ -380,7 +404,7 @@ out: quick_out: if (pool->key.num_descriptors && !*cache_hit) util_dynarray_clear(&zds->barriers); - zds->invalid = false; + zds->punted = zds->invalid = false; *need_resource_refs = false; if (zink_batch_add_desc_set(batch, zds)) { batch->descs_used += pool->key.num_descriptors; @@ -402,14 +426,18 @@ zink_descriptor_set_recycle(struct zink_descriptor_set *zds) if (!pool->key.num_descriptors) return; - struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->desc_sets, zds->hash, &zds->key); - if (!he) - /* desc sets can be used multiple times in the same batch */ - return; + if (zds->punted) + zds->invalid = true; + else { + /* if we've previously punted this set, then it won't have a hash or be in either of the tables */ + struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->desc_sets, zds->hash, &zds->key); + if (!he) + /* desc sets can be used multiple times in the same batch */ + return; + _mesa_hash_table_remove(pool->desc_sets, he); + } - _mesa_hash_table_remove(pool->desc_sets, he); if (zds->invalid) { - zink_descriptor_set_invalidate(zds); util_dynarray_append(&pool->alloc_desc_sets, struct zink_descriptor_set *, zds); } else { zds->recycled = true; diff --git a/src/gallium/drivers/zink/zink_descriptors.h b/src/gallium/drivers/zink/zink_descriptors.h index cc3ccd405e3..db09b42d586 100644 --- a/src/gallium/drivers/zink/zink_descriptors.h +++ b/src/gallium/drivers/zink/zink_descriptors.h @@ -92,6 +92,7 @@ struct zink_descriptor_set { VkDescriptorSet desc_set; uint32_t hash; bool invalid; + bool punted; bool recycled; struct zink_descriptor_state_key key; struct util_dynarray barriers; _______________________________________________ mesa-commit mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-commit
