From 7bf69260cd077a88690276d6ebe4864d0798c410 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: Cherry picked from 037d9fb278c44bf5bd8fea6c6c78af321555d141 --- .pick_status.json | 2 +- src/compiler/spirv/spirv_to_nir.c | 23 ++++++++++++++++++++--- src/compiler/spirv/vtn_cfg.c | 4 +++- src/compiler/spirv/vtn_private.h | 8 ++++++++ 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index f7bba05a2d7..b1f547945f4 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -5782,7 +5782,7 @@ "description": "spirv: replace discard with demote for incorrect HLSL->SPIR-V translations", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "master_sha": null, "because_sha": null }, diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index b37a24e916f..48b9a73de5e 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -3803,6 +3803,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; } @@ -4057,6 +4059,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: @@ -5112,14 +5115,14 @@ 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]; /* The first GLSLang version bump actually 1.5 years after #179 was fixed * but this should at least let us shut the workaround off for modern * versions of GLSLang. */ - b->wa_glslang_179 = (generator_id == 8 && generator_version == 1); + b->wa_glslang_179 = (b->generator_id == 8 && generator_version == 1); /* In GLSLang commit 8297936dd6eb3, their handling of barrier() was fixed * to provide correct memory semantics on compute shader barrier() @@ -5127,7 +5130,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 */ @@ -5240,6 +5243,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 (b->entry_point == NULL) { vtn_fail("Entry point not found"); ralloc_free(b); diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c index 3f157db009b..4a5866cef3b 100644 --- a/src/compiler/spirv/vtn_cfg.c +++ b/src/compiler/spirv/vtn_cfg.c @@ -1071,8 +1071,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 10577f5618a..aad1688108c 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -666,9 +666,17 @@ struct vtn_builder { /* True if we should watch out for GLSLang issue #179 */ bool wa_glslang_179; + /* 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;