diff options
authorJason Ekstrand <>2017-06-20 09:06:44 -0700
committerAndres Gomez <>2017-06-28 20:15:04 +0300
commit6af4b0fdf3b061c0a3ff5231f4d97975f48c283d (patch)
parentb53e528e18616ce3a74de4397d24d362e928c338 (diff)
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: Cc: "17.1" <> Tested-by: Grazvydas Ignotas <> Reviewed-by: Dave Airlie <> (cherry picked from commit 1bd0acab21c250b263604a52ca6694941a6f02e0)
2 files changed, 28 insertions, 0 deletions
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index 5769c0c6cd2..a1594618f1a 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 293d07d68bf..1968b37deaf 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);
@@ -1609,6 +1613,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);