From 46b356ca2dccc8966ae35da022115803e832564d Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Sun, 13 Dec 2020 17:47:26 -0500 Subject: [PATCH] zink: unset ctx->program pointers when an unref destroys the object if we destroy a program object which is currently the "active" program then we need to unset the pointer to avoid invalid access also unset injected tcs pointers where appropriate Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/zink/zink_batch.c | 8 ++++++-- src/gallium/drivers/zink/zink_compiler.c | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c index b2159bcbc23..7255eaf1264 100644 --- a/src/gallium/drivers/zink/zink_batch.c +++ b/src/gallium/drivers/zink/zink_batch.c @@ -65,10 +65,14 @@ zink_reset_batch(struct zink_context *ctx, struct zink_batch *batch) set_foreach(batch->programs, entry) { if (batch->batch_id == ZINK_COMPUTE_BATCH_ID) { struct zink_compute_program *comp = (struct zink_compute_program*)entry->key; - zink_compute_program_reference(screen, &comp, NULL); + bool in_use = comp == ctx->curr_compute; + if (zink_compute_program_reference(screen, &comp, NULL) && in_use) + ctx->curr_compute = NULL; } else { struct zink_gfx_program *prog = (struct zink_gfx_program*)entry->key; - zink_gfx_program_reference(screen, &prog, NULL); + bool in_use = prog == ctx->curr_program; + if (zink_gfx_program_reference(screen, &prog, NULL) && in_use) + ctx->curr_program = NULL; } _mesa_set_remove(batch->programs, entry); } diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 7ff8b30d88f..3d7f7417950 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -711,15 +711,27 @@ zink_shader_free(struct zink_context *ctx, struct zink_shader *shader) struct zink_compute_program *comp = (void*)entry->key; _mesa_hash_table_remove_key(ctx->compute_program_cache, &comp->shader->shader_id); comp->shader = NULL; - zink_compute_program_reference(screen, &comp, NULL); + bool in_use = comp == ctx->curr_compute; + if (in_use) + ctx->compute_stage = NULL; + if (zink_compute_program_reference(screen, &comp, NULL) && in_use) + ctx->curr_compute = NULL; } else { struct zink_gfx_program *prog = (void*)entry->key; - _mesa_hash_table_remove_key(ctx->program_cache, prog->shaders); - prog->shaders[pipe_shader_type_from_mesa(shader->nir->info.stage)] = NULL; + enum pipe_shader_type pstage = pipe_shader_type_from_mesa(shader->nir->info.stage); + bool in_use = prog == ctx->curr_program; + if (shader->nir->info.stage != MESA_SHADER_TESS_CTRL || !shader->is_generated) + _mesa_hash_table_remove_key(ctx->program_cache, prog->shaders); + prog->shaders[pstage] = NULL; if (shader->nir->info.stage == MESA_SHADER_TESS_EVAL && shader->generated) /* automatically destroy generated tcs shaders when tes is destroyed */ zink_shader_free(ctx, shader->generated); - zink_gfx_program_reference(screen, &prog, NULL); + if (in_use) { + ctx->gfx_pipeline_state.modules[pstage] = VK_NULL_HANDLE; + ctx->gfx_stages[pstage] = NULL; + } + if (zink_gfx_program_reference(screen, &prog, NULL) && in_use) + ctx->curr_program = NULL; } } _mesa_set_destroy(shader->programs, NULL);