diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index bdb969a8324..5b1ae9490dc 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -5721,6 +5721,9 @@ vtn_create_builder(const uint32_t *words, size_t word_count, b->value_id_bound = value_id_bound; b->values = rzalloc_array(b, struct vtn_value, value_id_bound); + if (b->options->environment == NIR_SPIRV_VULKAN) + b->vars_used_indirectly = _mesa_pointer_set_create(b); + return b; fail: ralloc_free(b); @@ -5798,6 +5801,13 @@ vtn_emit_kernel_entry_point_wrapper(struct vtn_builder *b, return main_entry_point; } +static bool +can_remove(nir_variable *var, void *data) +{ + const struct set *vars_used_indirectly = data; + return !_mesa_set_search(vars_used_indirectly, var); +} + nir_shader * spirv_to_nir(const uint32_t *words, size_t word_count, struct nir_spirv_specialization *spec, unsigned num_spec, @@ -5946,7 +5956,12 @@ spirv_to_nir(const uint32_t *words, size_t word_count, */ nir_lower_variable_initializers(b->shader, nir_var_shader_out | nir_var_system_value); - nir_remove_dead_variables(b->shader, ~nir_var_function_temp, NULL); + const nir_remove_dead_variables_options dead_opts = { + .can_remove_var = can_remove, + .can_remove_var_data = b->vars_used_indirectly, + }; + nir_remove_dead_variables(b->shader, ~nir_var_function_temp, + b->vars_used_indirectly ? &dead_opts : NULL); /* We sometimes generate bogus derefs that, while never used, give the * validator a bit of heartburn. Run dead code to get rid of them. diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index f230e6e8152..e3ea3eb25c0 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -674,6 +674,13 @@ struct vtn_builder { */ struct hash_table *phi_table; + /* In Vulkan, when lowering some modes variable access, the derefs of the + * variables are replaced with a resource index intrinsics, leaving the + * variable hanging. This set keeps track of them so they can be filtered + * (and not removed) in nir_remove_dead_variables. + */ + struct set *vars_used_indirectly; + unsigned num_specializations; struct nir_spirv_specialization *specializations; diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index 6cccb540090..1481e6b4e57 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -237,6 +237,11 @@ vtn_variable_resource_index(struct vtn_builder *b, struct vtn_variable *var, desc_array_index = nir_imm_int(&b->nb, 0); } + if (b->vars_used_indirectly) { + vtn_assert(var->var); + _mesa_set_add(b->vars_used_indirectly, var->var); + } + nir_intrinsic_instr *instr = nir_intrinsic_instr_create(b->nb.shader, nir_intrinsic_vulkan_resource_index);