From 0c3fe064215864e7966c8640ad36f173d78cb855 Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Tue, 12 Jan 2021 11:30:52 -0800 Subject: [PATCH] spirv: Skip creating unused variables in SPIR-V >= 1.4 Newer versions of SPIR-V require that all the global variables used by the entry point are declared (in contrast to only I/O in previous versions), so there's no need to remove dead variables or keep track of the indirectly used variables. Reviewed-by: Rhys Perry Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 13 +++++++------ src/compiler/spirv/vtn_variables.c | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 8060e24c9fb..84f572e03a6 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -4189,7 +4189,7 @@ vtn_handle_entry_point(struct vtn_builder *b, const uint32_t *w, vtn_assert(b->entry_point == NULL); b->entry_point = entry_point; - /* Entry points enumerate which I/O variables are used. */ + /* Entry points enumerate which global variables are used. */ size_t start = 3 + name_words; b->interface_ids_count = count - start; b->interface_ids = ralloc_array(b, uint32_t, b->interface_ids_count); @@ -5753,7 +5753,7 @@ 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) + if (b->options->environment == NIR_SPIRV_VULKAN && b->version < 0x10400) b->vars_used_indirectly = _mesa_pointer_set_create(b); return b; @@ -5975,11 +5975,12 @@ spirv_to_nir(const uint32_t *words, size_t word_count, /* A SPIR-V module can have multiple shaders stages and also multiple * shaders of the same stage. Global variables are declared per-module. * - * For I/O storage classes, OpEntryPoint will list the variables used, so - * only valid ones are created. Remove dead variables to clean up the - * remaining ones. + * Starting in SPIR-V 1.4 the list of global variables is part of + * OpEntryPoint, so only valid ones will be created. Previous versions + * only have Input and Output variables listed, so remove dead variables to + * clean up the remaining ones. */ - if (!options->create_library) { + if (!options->create_library && b->version < 0x10400) { const nir_remove_dead_variables_options dead_opts = { .can_remove_var = can_remove, .can_remove_var_data = b->vars_used_indirectly, diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index bda82103348..ae0f8a9cba7 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -2287,12 +2287,19 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, SpvStorageClass storage_class = w[3]; - /* Skip I/O variables that are not used by the entry point. */ + const bool is_global = storage_class != SpvStorageClassFunction; + const bool is_io = storage_class == SpvStorageClassInput || + storage_class == SpvStorageClassOutput; + + /* Skip global variables that are not used by the entrypoint. Before + * SPIR-V 1.4 the interface is only used for I/O variables, so extra + * variables will still need to be removed later. + */ if (!b->options->create_library && - (storage_class == SpvStorageClassInput || - storage_class == SpvStorageClassOutput) && - !bsearch(&w[2], b->interface_ids, b->interface_ids_count, 4, cmp_uint32_t)) - break; + (is_io || (b->version >= 0x10400 && is_global))) { + if (!bsearch(&w[2], b->interface_ids, b->interface_ids_count, 4, cmp_uint32_t)) + break; + } struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); struct vtn_value *initializer = count > 4 ? vtn_untyped_value(b, w[4]) : NULL;