spirv: Relax the validation conditions of OpSelect
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 15 Dec 2017 03:53:05 +0000 (19:53 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Mon, 18 Dec 2017 17:48:58 +0000 (09:48 -0800)
The Talos Principle contains shaders with an OpSelect between two
vectors where the condition is a scalar boolean.  This is technically
against the spec bout nir_builder gracefully handles it by splatting
out the condition to all the channels.  So long as the condition is a
boolean, just emit a warning instead of failing.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104246

src/compiler/spirv/spirv_to_nir.c

index 0493dd3..39c0b5f 100644 (file)
@@ -3511,10 +3511,27 @@ vtn_handle_body_instruction(struct vtn_builder *b, SpvOp opcode,
          vtn_fail("Result type of OpSelect must be a scalar, vector, or pointer");
       }
 
-      vtn_fail_if(sel_val->type->type != sel_type,
-                  "Condition type of OpSelect must be a scalar or vector of "
-                  "Boolean type. It must have the same number of components "
-                  "as Result Type");
+      if (unlikely(sel_val->type->type != sel_type)) {
+         if (sel_val->type->type == glsl_bool_type()) {
+            /* This case is illegal but some older versions of GLSLang produce
+             * it.  The GLSLang issue was fixed on March 30, 2017:
+             *
+             * https://github.com/KhronosGroup/glslang/issues/809
+             *
+             * Unfortunately, there are applications in the wild which are
+             * shipping with this bug so it isn't nice to fail on them so we
+             * throw a warning instead.  It's not actually a problem for us as
+             * nir_builder will just splat the condition out which is most
+             * likely what the client wanted anyway.
+             */
+            vtn_warn("Condition type of OpSelect must have the same number "
+                     "of components as Result Type");
+         } else {
+            vtn_fail("Condition type of OpSelect must be a scalar or vector "
+                     "of Boolean type. It must have the same number of "
+                     "components as Result Type");
+         }
+      }
 
       vtn_fail_if(obj1_val->type != res_val->type ||
                   obj2_val->type != res_val->type,