spirv: replace discard with demote for incorrect HLSL->SPIR-V translations
authorRhys Perry <pendingchaos02@gmail.com>
Wed, 7 Oct 2020 19:07:42 +0000 (20:07 +0100)
committerMarge Bot <eric+marge@anholt.net>
Mon, 12 Oct 2020 11:07:38 +0000 (11:07 +0000)
Fixes artifacts on decals in Path of Exile.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3610
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7062>

src/compiler/spirv/spirv_to_nir.c
src/compiler/spirv/vtn_cfg.c
src/compiler/spirv/vtn_private.h

index f236804..d88ae4c 100644 (file)
@@ -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);
index 4914fc6..3ca1e54 100644 (file)
@@ -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;
    }
index a51a2be..e7e7a64 100644 (file)
@@ -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;