From 037d9fb278c44bf5bd8fea6c6c78af321555d141 Mon Sep 17 00:00:00 2001 From: Rhys Perry Date: Wed, 7 Oct 2020 20:07:42 +0100 Subject: [PATCH] spirv: replace discard with demote for incorrect HLSL->SPIR-V translations Fixes artifacts on decals in Path of Exile. Signed-off-by: Rhys Perry Reviewed-by: Caio Marcelo de Oliveira Filho Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3610 Cc: mesa-stable Part-of: --- src/compiler/spirv/spirv_to_nir.c | 21 +++++++++++++++++++-- src/compiler/spirv/vtn_cfg.c | 4 +++- src/compiler/spirv/vtn_private.h | 8 ++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index f236804cca7..d88ae4cd7aa 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -4090,6 +4090,8 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode, (count > 3) ? vtn_value(b, w[3], vtn_value_type_string)->str : ""; vtn_info("Parsing SPIR-V from %s %u source file %s", lang, version, file); + + b->source_lang = w[1]; break; } @@ -4350,6 +4352,7 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode, case SpvCapabilityDemoteToHelperInvocationEXT: spv_check_supported(demote_to_helper_invocation, cap); + b->uses_demote_to_helper_invocation = true; break; case SpvCapabilityShaderClockKHR: @@ -5448,7 +5451,7 @@ vtn_create_builder(const uint32_t *words, size_t word_count, goto fail; } - uint16_t generator_id = words[2] >> 16; + b->generator_id = words[2] >> 16; uint16_t generator_version = words[2]; /* In GLSLang commit 8297936dd6eb3, their handling of barrier() was fixed @@ -5457,7 +5460,7 @@ vtn_create_builder(const uint32_t *words, size_t word_count, * GLSLang fix caused them to bump to generator version 3. */ b->wa_glslang_cs_barrier = - (generator_id == vtn_generator_glslang_reference_front_end && + (b->generator_id == vtn_generator_glslang_reference_front_end && generator_version < 3); /* words[2] == generator magic */ @@ -5579,6 +5582,20 @@ spirv_to_nir(const uint32_t *words, size_t word_count, words = vtn_foreach_instruction(b, words, word_end, vtn_handle_preamble_instruction); + /* DirectXShaderCompiler and glslang/shaderc both create OpKill from HLSL's + * discard/clip, which uses demote semantics. DirectXShaderCompiler will use + * demote if the extension is enabled, so we disable this workaround in that + * case. + * + * Related glslang issue: https://github.com/KhronosGroup/glslang/issues/2416 + */ + bool glslang = b->generator_id == vtn_generator_glslang_reference_front_end || + b->generator_id == vtn_generator_shaderc_over_glslang; + bool dxsc = b->generator_id == vtn_generator_spiregg; + b->convert_discard_to_demote = ((dxsc && !b->uses_demote_to_helper_invocation) || + (glslang && b->source_lang == SpvSourceLanguageHLSL)) && + options->caps.demote_to_helper_invocation; + if (!options->create_library && b->entry_point == NULL) { vtn_fail("Entry point not found for %s shader \"%s\"", _mesa_shader_stage_to_string(stage), entry_point_name); diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c index 4914fc645ce..3ca1e54d8c9 100644 --- a/src/compiler/spirv/vtn_cfg.c +++ b/src/compiler/spirv/vtn_cfg.c @@ -944,8 +944,10 @@ vtn_emit_branch(struct vtn_builder *b, enum vtn_branch_type branch_type, nir_jump(&b->nb, nir_jump_return); break; case vtn_branch_type_discard: { + nir_intrinsic_op op = + b->convert_discard_to_demote ? nir_intrinsic_demote : nir_intrinsic_discard; nir_intrinsic_instr *discard = - nir_intrinsic_instr_create(b->nb.shader, nir_intrinsic_discard); + nir_intrinsic_instr_create(b->nb.shader, op); nir_builder_instr_insert(&b->nb, &discard->instr); break; } diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index a51a2bebde2..e7e7a643aed 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -659,9 +659,17 @@ struct vtn_builder { unsigned value_id_bound; struct vtn_value *values; + /* Information on the origin of the SPIR-V */ + enum vtn_generator generator_id; + SpvSourceLanguage source_lang; + /* True if we need to fix up CS OpControlBarrier */ bool wa_glslang_cs_barrier; + /* Workaround discard bugs in HLSL -> SPIR-V compilers */ + bool uses_demote_to_helper_invocation; + bool convert_discard_to_demote; + gl_shader_stage entry_point_stage; const char *entry_point_name; struct vtn_value *entry_point;