spirv: replace discard with demote for incorrect HLSL->SPIR-V translations

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>
Cherry picked from 037d9fb278
This commit is contained in:
Rhys Perry 2020-10-07 20:07:42 +01:00 committed by Eric Engestrom
parent fe37936890
commit 7bf69260cd
4 changed files with 32 additions and 5 deletions

View file

@ -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
},

View file

@ -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);

View file

@ -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;
}

View file

@ -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;