From d0fac4e4f88debc80b06018f73dd23d5e4e55bcb Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 25 May 2021 12:41:14 -0700 Subject: [PATCH] iris: Ref count the uncompiled shaders I tried /just/ ref counting the uncompiled shaders, but that is not sufficient. At the very least, it's a problem for blorp shaders that only have variants (and no uncompiled shader). This is in prepartion for using the live shader cache. Reviewed-by: Kenneth Graunke Part-of: --- src/gallium/drivers/iris/iris_context.h | 22 +++++++++++++ src/gallium/drivers/iris/iris_program.c | 43 +++++++++++++++++-------- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index 0674044fb6d..f8691421676 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -371,6 +371,8 @@ enum iris_predicate_state { * See iris_compiled_shader, which represents a compiled shader variant. */ struct iris_uncompiled_shader { + struct pipe_reference ref; + /** * NIR for the shader. * @@ -955,6 +957,26 @@ struct iris_compiled_shader *iris_upload_shader(struct iris_screen *screen, const struct iris_binding_table *bt); void iris_delete_shader_variant(struct iris_compiled_shader *shader); +void iris_destroy_shader_state(struct pipe_context *ctx, void *state); + +static inline void +iris_uncompiled_shader_reference(struct pipe_context *ctx, + struct iris_uncompiled_shader **dst, + struct iris_uncompiled_shader *src) +{ + if (*dst == src) + return; + + struct iris_uncompiled_shader *old_dst = *dst; + + if (pipe_reference(old_dst != NULL ? &old_dst->ref : NULL, + src != NULL ? &src->ref : NULL)) { + iris_destroy_shader_state(ctx, *dst); + } + + *dst = src; +} + static inline void iris_shader_variant_reference(struct iris_compiled_shader **dst, struct iris_compiled_shader *src) diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c index 91f4ad3f288..852c26a2aea 100644 --- a/src/gallium/drivers/iris/iris_program.c +++ b/src/gallium/drivers/iris/iris_program.c @@ -2282,6 +2282,7 @@ iris_create_uncompiled_shader(struct iris_screen *screen, if (!ish) return NULL; + pipe_reference_init(&ish->ref, 1); list_inithead(&ish->variants); simple_mtx_init(&ish->lock, mtx_plain); @@ -2537,9 +2538,35 @@ iris_create_shader_state(struct pipe_context *ctx, } /** - * The pipe->delete_[stage]_state() driver hooks. + * Called when the refcount on the iris_uncompiled_shader reaches 0. * * Frees the iris_uncompiled_shader. + * + * \sa iris_delete_shader_state + */ +void +iris_destroy_shader_state(struct pipe_context *ctx, void *state) +{ + struct iris_uncompiled_shader *ish = state; + + /* No need to take ish->lock; we hold the last reference to ish */ + list_for_each_entry_safe(struct iris_compiled_shader, shader, + &ish->variants, link) { + list_del(&shader->link); + + iris_shader_variant_reference(&shader, NULL); + } + + simple_mtx_destroy(&ish->lock); + + ralloc_free(ish->nir); + free(ish); +} + +/** + * The pipe->delete_[stage]_state() driver hooks. + * + * \sa iris_destroy_shader_state */ static void iris_delete_shader_state(struct pipe_context *ctx, void *state) @@ -2554,18 +2581,8 @@ iris_delete_shader_state(struct pipe_context *ctx, void *state) ice->state.stage_dirty |= IRIS_STAGE_DIRTY_UNCOMPILED_VS << stage; } - /* No need to take ish->lock; we hold the last reference to ish */ - list_for_each_entry_safe(struct iris_compiled_shader, shader, - &ish->variants, link) { - list_del(&shader->link); - - iris_shader_variant_reference(&shader, NULL); - } - - simple_mtx_destroy(&ish->lock); - - ralloc_free(ish->nir); - free(ish); + if (pipe_reference(&ish->ref, NULL)) + iris_destroy_shader_state(ctx, state); } /**