From 1bd0acab21c250b263604a52ca6694941a6f02e0 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 20 Jun 2017 09:06:44 -0700 Subject: [PATCH] spirv: Work around the Doom shader bug Doom shipped with a broken version of GLSLang which handles samplers as function arguments in a way that isn't spec-compliant. In particular, it creates a temporary local sampler variable and copies the sampler into it. While Dave has had a hack patch out for a while that gets it working, we've never landed it because we've been hoping that a game update would come out with fixed shaders. Unfortunately, no game update appears on to be on the horizon and I've found this issue in yet another application so I think we're stuck working around it. Hopefully, we can delete this code one day. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99467 Cc: "17.1" Tested-by: Grazvydas Ignotas Reviewed-by: Dave Airlie --- src/compiler/spirv/vtn_private.h | 14 ++++++++++++++ src/compiler/spirv/vtn_variables.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index 59fcc94..a377c90 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -288,6 +288,20 @@ struct vtn_variable { nir_variable *var; nir_variable **members; + /** + * In some early released versions of GLSLang, it implemented all function + * calls by making copies of all parameters into temporary variables and + * passing those variables into the function. It even did so for samplers + * and images which violates the SPIR-V spec. Unfortunately, two games + * (Talos Principle and Doom) shipped with this old version of GLSLang and + * also happen to pass samplers into functions. Talos Principle received + * an update fairly shortly after release with an updated GLSLang. Doom, + * on the other hand, has never received an update so we need to work + * around this GLSLang issue in SPIR-V -> NIR. Hopefully, we can drop this + * hack at some point in the future. + */ + struct vtn_access_chain *copy_prop_sampler; + struct vtn_access_chain chain; }; diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index 0f0cc1c..974adb5 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -96,6 +96,10 @@ rewrite_deref_types(nir_deref *deref, const struct glsl_type *type) nir_deref_var * vtn_access_chain_to_deref(struct vtn_builder *b, struct vtn_access_chain *chain) { + /* Do on-the-fly copy propagation for samplers. */ + if (chain->var->copy_prop_sampler) + return vtn_access_chain_to_deref(b, chain->var->copy_prop_sampler); + nir_deref_var *deref_var; if (chain->var->var) { deref_var = nir_deref_var_create(b, chain->var->var); @@ -1613,6 +1617,16 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, case SpvOpStore: { struct vtn_access_chain *dest = vtn_value(b, w[1], vtn_value_type_access_chain)->access_chain; + + if (glsl_type_is_sampler(dest->var->type->type)) { + vtn_warn("OpStore of a sampler detected. Doing on-the-fly copy " + "propagation to workaround the problem."); + assert(dest->var->copy_prop_sampler == NULL); + dest->var->copy_prop_sampler = + vtn_value(b, w[2], vtn_value_type_access_chain)->access_chain; + break; + } + struct vtn_ssa_value *src = vtn_ssa_value(b, w[2]); vtn_variable_store(b, src, dest); break; -- 2.7.4