From 75c7619253e60c0f798bc488f7390981442dc2ba Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Mon, 29 Mar 2021 16:40:52 -0400 Subject: [PATCH] zink: unblock last_set cached descriptor reuse when safe to do so if no changes at all have occurred to a given set since the last use, and if the program hasn't changed, then there is no possiblility for the set to have been invalidated, and so it can immediately be reused Reviewed-by: Hoe Hao Cheng Acked-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_descriptors.c | 19 ++++++++++++++++++- src/gallium/drivers/zink/zink_descriptors.h | 3 +++ .../drivers/zink/zink_descriptors_lazy.c | 3 +-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c index 814c2767894..535d04f3b31 100644 --- a/src/gallium/drivers/zink/zink_descriptors.c +++ b/src/gallium/drivers/zink/zink_descriptors.c @@ -715,11 +715,21 @@ zink_descriptor_set_get(struct zink_context *ctx, uint32_t hash = push_set ? ctx->dd->push_state[is_compute] : 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]; + /* if the current state hasn't changed since the last time it was used, + * it's impossible for this set to not be valid, which means that an + * 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]))) { + *cache_hit = true; + return last_set; + } + struct zink_descriptor_state_key key; populate_zds_key(ctx, type, is_compute, &key, pg->dd->push_usage); simple_mtx_lock(&pool->mtx); - struct zink_descriptor_set *last_set = push_set ? ctx->dd->last_set[is_compute] : pdd_cached(pg)->last_set[type]; if (last_set && last_set->hash == hash && desc_state_equal(&last_set->key, &key)) { zds = last_set; *cache_hit = !zds->invalid; @@ -1318,14 +1328,17 @@ zink_descriptors_update(struct zink_context *ctx, bool is_compute) VkDescriptorSet sets[ZINK_DESCRIPTOR_TYPES + 1]; struct zink_descriptor_set *zds[ZINK_DESCRIPTOR_TYPES + 1]; /* push set is indexed in vulkan as 0 but isn't in the general pool array */ + ctx->dd->changed[is_compute][ZINK_DESCRIPTOR_TYPES] |= ctx->dd->pg[is_compute] != pg; if (pg->dd->push_usage) zds[ZINK_DESCRIPTOR_TYPES] = zink_descriptor_set_get(ctx, ZINK_DESCRIPTOR_TYPES, is_compute, &cache_hit[ZINK_DESCRIPTOR_TYPES]); else { zds[ZINK_DESCRIPTOR_TYPES] = NULL; cache_hit[ZINK_DESCRIPTOR_TYPES] = false; } + ctx->dd->changed[is_compute][ZINK_DESCRIPTOR_TYPES] = false; sets[0] = zds[ZINK_DESCRIPTOR_TYPES] ? zds[ZINK_DESCRIPTOR_TYPES]->desc_set : ctx->dd->dummy_set; for (int h = 0; h < ZINK_DESCRIPTOR_TYPES; h++) { + ctx->dd->changed[is_compute][h] |= ctx->dd->pg[is_compute] != pg; if (pg->dsl[h + 1]) { /* null set has null pool */ if (pdd_cached(pg)->pool[h]) @@ -1339,6 +1352,7 @@ zink_descriptors_update(struct zink_context *ctx, bool is_compute) } if (!zds[h]) cache_hit[h] = false; + ctx->dd->changed[is_compute][h] = false; } struct zink_batch *batch = &ctx->batch; zink_batch_reference_program(batch, pg); @@ -1355,6 +1369,7 @@ zink_descriptors_update(struct zink_context *ctx, bool is_compute) vkCmdBindDescriptorSets(batch->state->cmdbuf, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, pg->layout, 0, pg->num_dsl, sets, dynamic_offset_idx, dynamic_offsets); + ctx->dd->pg[is_compute] = pg; } void @@ -1593,6 +1608,7 @@ zink_context_invalidate_descriptor_state(struct zink_context *ctx, enum pipe_sha ctx->dd->gfx_push_state[shader] = 0; ctx->dd->gfx_push_valid[shader] = false; } + ctx->dd->changed[shader == PIPE_SHADER_COMPUTE][ZINK_DESCRIPTOR_TYPES] = true; return; } if (shader != PIPE_SHADER_COMPUTE) { @@ -1601,6 +1617,7 @@ zink_context_invalidate_descriptor_state(struct zink_context *ctx, enum pipe_sha } ctx->dd->descriptor_states[shader == PIPE_SHADER_COMPUTE].valid[type] = false; ctx->dd->descriptor_states[shader == PIPE_SHADER_COMPUTE].state[type] = 0; + ctx->dd->changed[shader == PIPE_SHADER_COMPUTE][type] = true; } bool diff --git a/src/gallium/drivers/zink/zink_descriptors.h b/src/gallium/drivers/zink/zink_descriptors.h index fa04a173d50..56c87014cb8 100644 --- a/src/gallium/drivers/zink/zink_descriptors.h +++ b/src/gallium/drivers/zink/zink_descriptors.h @@ -118,6 +118,9 @@ struct zink_descriptor_data { VkDescriptorPool dummy_pool; VkDescriptorSetLayout dummy_dsl; VkDescriptorSet dummy_set; + + bool changed[2][ZINK_DESCRIPTOR_TYPES + 1]; + struct zink_program *pg[2]; //gfx, compute }; struct zink_program_descriptor_data { diff --git a/src/gallium/drivers/zink/zink_descriptors_lazy.c b/src/gallium/drivers/zink/zink_descriptors_lazy.c index 5272e2fb398..8b70ad2fbd3 100644 --- a/src/gallium/drivers/zink/zink_descriptors_lazy.c +++ b/src/gallium/drivers/zink/zink_descriptors_lazy.c @@ -39,7 +39,6 @@ struct zink_descriptor_data_lazy { VkDescriptorUpdateTemplateEntry push_entries[PIPE_SHADER_TYPES]; bool push_state_changed[2]; //gfx, compute uint8_t state_changed[2]; //gfx, compute - struct zink_program *pg[2]; //gfx, compute }; struct zink_descriptor_pool { @@ -470,7 +469,7 @@ zink_descriptors_update_lazy(struct zink_context *ctx, bool is_compute) } /* set again in case of flushing */ bdd_lazy(bs)->pg[is_compute] = pg; - dd_lazy(ctx)->pg[is_compute] = pg; + ctx->dd->pg[is_compute] = pg; } void