diff --git a/.pick_status.json b/.pick_status.json index 7c5caa9a461..be0c32bae80 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -229,7 +229,7 @@ "description": "spirv: Don't remove variables used by resource indexing intrinsics", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "master_sha": null, "because_sha": "c4c9c780b131939fa10ede84e079a90fc090e17a" }, diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index cc992dafbf9..56a597e3a85 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -5640,6 +5640,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); @@ -5717,6 +5720,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, @@ -5864,7 +5874,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 a1e8fa51f51..86b5bede9a0 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -663,6 +663,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 83171160a59..0dca48e7b31 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);