From a17d24d9017c8e1e6ac57dab68aa9ece793dece6 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 24 Sep 2021 15:19:50 +0300 Subject: [PATCH] spirv: workaround LLVM-SPIRV Undef variable initializers The LLVM-SPIRV translator creates variables with initializers, but most of those are actually undef initializers. We can just skip composites that are entirely made of undefs, but for partially undefs, we will still zero initialize. v2: Rename wa_llvm_spirv_undef_initializer to wa_llvm_spirv_ignore_workgroup_initializer (Caio) Limit workaround to OpenCL (Caio) Make workaround clearer (Caio) v3: Only apply workaround on workgroup storage (Caio) Signed-off-by: Lionel Landwerlin Reviewed-by: Jesse Natalie Reviewed-by: Caio Marcelo de Oliveira Filho Part-of: --- src/compiler/spirv/spirv_to_nir.c | 23 +++++++++++++++++++++++ src/compiler/spirv/vtn_private.h | 3 +++ src/compiler/spirv/vtn_variables.c | 6 ++++++ 3 files changed, 32 insertions(+) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 64eca17..d2f8c3a 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -6039,6 +6039,29 @@ vtn_create_builder(const uint32_t *words, size_t word_count, (b->generator_id == vtn_generator_glslang_reference_front_end && generator_version < 3); + /* Identifying the LLVM-SPIRV translator: + * + * The LLVM-SPIRV translator currently doesn't store any generator ID [1]. + * Our use case involving the SPIRV-Tools linker also mean we want to check + * for that tool instead. Finally the SPIRV-Tools linker also stores its + * generator ID in the wrong location [2]. + * + * [1] : https://github.com/KhronosGroup/SPIRV-LLVM-Translator/pull/1223 + * [2] : https://github.com/KhronosGroup/SPIRV-Tools/pull/4549 + */ + const bool is_llvm_spirv_translator = + (b->generator_id == 0 && + generator_version == vtn_generator_spirv_tools_linker) || + b->generator_id == vtn_generator_spirv_tools_linker; + + /* The LLVM-SPIRV translator generates Undef initializers for _local + * variables [1]. + * + * [1] : https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1224 + */ + b->wa_llvm_spirv_ignore_workgroup_initializer = + b->options->environment == NIR_SPIRV_OPENCL && is_llvm_spirv_translator; + /* words[2] == generator magic */ unsigned value_id_bound = words[3]; if (words[4] != 0) { diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index d95e3c7..0b2beda 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -696,6 +696,9 @@ struct vtn_builder { /* True if we need to fix up CS OpControlBarrier */ bool wa_glslang_cs_barrier; + /* True if we need to ignore undef initializers */ + bool wa_llvm_spirv_ignore_workgroup_initializer; + /* Workaround discard bugs in HLSL -> SPIR-V compilers */ bool uses_demote_to_helper_invocation; bool convert_discard_to_demote; diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index efa18c9..e67bee4 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -2015,6 +2015,12 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val, unreachable("Should have been caught before"); } + /* Ignore incorrectly generated Undef initializers. */ + if (b->wa_llvm_spirv_ignore_workgroup_initializer && + initializer && + storage_class == SpvStorageClassWorkgroup) + initializer = NULL; + if (initializer) { switch (storage_class) { case SpvStorageClassWorkgroup: -- 2.7.4