nir: Add an option for lowering TessLevelInner/Outer to vecs
authorBrian Ho <brian@brkho.com>
Thu, 14 May 2020 19:17:48 +0000 (12:17 -0700)
committerMarge Bot <eric+marge@anholt.net>
Mon, 22 Jun 2020 14:35:45 +0000 (14:35 +0000)
The GLSL to NIR compiler supports the LowerTessLevel flag to convert
gl_TessLevelInner/Outer from their GLSL declarations as arrays of
floats to vec4/vec2s to better match how they are represented in
hardware.

This commit adds the similar support to the SPIR-V to NIR compiler so
turnip can use the same IR3/NIR tess lowering passes as freedreno.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5059>

src/compiler/spirv/nir_spirv.h
src/compiler/spirv/vtn_variables.c

index acfcc08..70f29fd 100644 (file)
@@ -69,6 +69,12 @@ struct spirv_to_nir_options {
     */
    bool tess_levels_are_sysvals;
 
+   /* Whether to lower TessLevelInner/Outer from their SPIR-V declarations
+    * as arrays of floats to vec4 and vec2 respectively. This is the same as
+    * LowerTessLevel in GLSL.
+    */
+   bool lower_tess_levels_to_vec;
+
    struct spirv_supported_capabilities caps;
 
    /* Address format for various kinds of pointers. */
index b36edba..aad07d7 100644 (file)
@@ -1617,6 +1617,11 @@ apply_var_decoration(struct vtn_builder *b,
       switch (builtin) {
       case SpvBuiltInTessLevelOuter:
       case SpvBuiltInTessLevelInner:
+         /* Since the compact flag is only valid on arrays, don't set it if
+          * we are lowering TessLevelInner/Outer to vec4/vec2. */
+         if (!b->options || !b->options->lower_tess_levels_to_vec)
+            var_data->compact = true;
+         break;
       case SpvBuiltInClipDistance:
       case SpvBuiltInCullDistance:
          var_data->compact = true;
@@ -1828,6 +1833,22 @@ var_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
    }
 }
 
+static void
+var_decoration_tess_level_vec_cb(
+      struct vtn_builder *b, struct vtn_value *val, int member,
+      const struct vtn_decoration *dec, void *void_var)
+{
+   struct vtn_variable *vtn_var = void_var;
+   if (dec->decoration == SpvDecorationBuiltIn) {
+      SpvBuiltIn builtin = dec->operands[0];
+      if (builtin == SpvBuiltInTessLevelOuter) {
+         vtn_var->var->type = glsl_vector_type(GLSL_TYPE_FLOAT, 4);
+      } else if (builtin == SpvBuiltInTessLevelInner) {
+         vtn_var->var->type = glsl_vector_type(GLSL_TYPE_FLOAT, 2);
+      }
+   }
+}
+
 enum vtn_variable_mode
 vtn_storage_class_to_mode(struct vtn_builder *b,
                           SpvStorageClass class,
@@ -2407,6 +2428,9 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
    vtn_foreach_decoration(b, val, var_decoration_cb, var);
    vtn_foreach_decoration(b, val, ptr_decoration_cb, val->pointer);
 
+   if (b->options && b->options->lower_tess_levels_to_vec)
+      vtn_foreach_decoration(b, val, var_decoration_tess_level_vec_cb, var);
+
    /* Propagate access flags from the OpVariable decorations. */
    val->pointer->access |= var->access;