[Mesa-dev,22/46] glsl: add the patch in/out qualifier

Submitted by Marek Olšák on June 16, 2015, 11:01 p.m.

Details

Message ID 1434495702-27901-22-git-send-email-maraeo@gmail.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Marek Olšák June 16, 2015, 11:01 p.m.
From: Fabian Bieler <fabianbieler@fastmail.fm>

---
 src/glsl/ast.h                            |  1 +
 src/glsl/ast_to_hir.cpp                   | 45 ++++++++++++++++++++
 src/glsl/ast_type.cpp                     |  3 +-
 src/glsl/builtin_variables.cpp            |  8 ++--
 src/glsl/glsl_lexer.ll                    |  2 +-
 src/glsl/glsl_parser.yy                   | 15 ++++---
 src/glsl/glsl_parser_extras.cpp           |  2 +
 src/glsl/glsl_types.cpp                   |  5 +++
 src/glsl/glsl_types.h                     |  6 +++
 src/glsl/ir.cpp                           |  2 +
 src/glsl/ir.h                             |  1 +
 src/glsl/ir_print_visitor.cpp             |  5 ++-
 src/glsl/ir_reader.cpp                    |  2 +
 src/glsl/ir_set_program_inouts.cpp        | 69 +++++++++++++++++++++++++++----
 src/glsl/link_varyings.cpp                | 15 ++++++-
 src/glsl/lower_named_interface_blocks.cpp |  1 +
 src/glsl/lower_packed_varyings.cpp        |  1 +
 17 files changed, 161 insertions(+), 22 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 26ad3bf..87e1354 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -434,6 +434,7 @@  struct ast_type_qualifier {
 	 unsigned out:1;
 	 unsigned centroid:1;
          unsigned sample:1;
+	 unsigned patch:1;
 	 unsigned uniform:1;
 	 unsigned smooth:1;
 	 unsigned flat:1;
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 53daf13..837bac7 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2461,6 +2461,9 @@  apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       var->data.stream = qual->stream;
    }
 
+   if (qual->flags.q.patch)
+      var->data.patch = 1;
+
    if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) {
       var->type = glsl_type::error_type;
       _mesa_glsl_error(loc, state,
@@ -3119,6 +3122,17 @@  handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state,
       num_vertices = state->out_qualifier->vertices;
    }
 
+   if (!var->type->is_array() && !var->data.patch) {
+      _mesa_glsl_error(&loc, state,
+                       "tessellation control shader outputs must be arrays");
+
+      /* To avoid cascading failures, short circuit the checks below. */
+      return;
+   }
+
+   if (var->data.patch)
+      return;
+
    if (var->type->is_unsized_array()) {
       if (num_vertices != 0)
          var->type = glsl_type::get_array_instance(var->type->fields.array,
@@ -3940,6 +3954,33 @@  ast_declarator_list::hir(exec_list *instructions,
       }
 
 
+      /* From section 4.3.4 of the GLSL 4.00 spec:
+       *    "Input variables may not be declared using the patch in qualifier
+       *    in tessellation control or geometry shaders."
+       *
+       * From section 4.3.6 of the GLSL 4.00 spec:
+       *    "It is an error to use patch out in a vertex, tessellation
+       *    evaluation, or geometry shader."
+       *
+       * This doesn't explicitly forbid using them in a fragment shader, but
+       * that's probably just an oversight.
+       */
+      if (state->stage != MESA_SHADER_TESS_EVAL
+          && this->type->qualifier.flags.q.patch
+          && this->type->qualifier.flags.q.in) {
+
+         _mesa_glsl_error(&loc, state, "'patch in' can only be used in a "
+                          "tessellation evaluation shader");
+      }
+
+      if (state->stage != MESA_SHADER_TESS_CTRL
+          && this->type->qualifier.flags.q.patch
+          && this->type->qualifier.flags.q.out) {
+
+         _mesa_glsl_error(&loc, state, "'patch out' can only be used in a "
+                          "tessellation control shader");
+      }
+
       /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30.
        */
       if (this->type->qualifier.precision != ast_precision_none) {
@@ -5463,6 +5504,7 @@  ast_process_structure_or_interface_block(exec_list *instructions,
             interpret_interpolation_qualifier(qual, var_mode, state, &loc);
          fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
          fields[i].sample = qual->flags.q.sample ? 1 : 0;
+         fields[i].patch = qual->flags.q.patch ? 1 : 0;
 
          /* Only save explicitly defined streams in block's field */
          fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1;
@@ -5794,6 +5836,8 @@  ast_interface_block::hir(exec_list *instructions,
                earlier_per_vertex->fields.structure[j].centroid;
             fields[i].sample =
                earlier_per_vertex->fields.structure[j].sample;
+            fields[i].patch =
+               earlier_per_vertex->fields.structure[j].patch;
          }
       }
 
@@ -5973,6 +6017,7 @@  ast_interface_block::hir(exec_list *instructions,
          var->data.interpolation = fields[i].interpolation;
          var->data.centroid = fields[i].centroid;
          var->data.sample = fields[i].sample;
+         var->data.patch = fields[i].patch;
          var->init_interface_type(block_type);
 
          if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
index 5bebaab..0d3651d 100644
--- a/src/glsl/ast_type.cpp
+++ b/src/glsl/ast_type.cpp
@@ -85,7 +85,8 @@  bool
 ast_type_qualifier::has_auxiliary_storage() const
 {
    return this->flags.q.centroid
-          || this->flags.q.sample;
+          || this->flags.q.sample
+          || this->flags.q.patch;
 }
 
 const char*
diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp
index bb947a8..874cb10 100644
--- a/src/glsl/builtin_variables.cpp
+++ b/src/glsl/builtin_variables.cpp
@@ -881,10 +881,10 @@  builtin_variable_generator::generate_tcs_special_vars()
    add_system_value(SYSTEM_VALUE_VERTICES_IN, int_t, "gl_PatchVerticesIn");
    add_system_value(SYSTEM_VALUE_INVOCATION_ID, int_t, "gl_InvocationID");
 
-   add_output(VARYING_SLOT_TESS_LEVEL_OUTER,
-                    array(float_t, 4), "gl_TessLevelOuter");
-   add_output(VARYING_SLOT_TESS_LEVEL_INNER,
-                    array(float_t, 2), "gl_TessLevelInner");
+   add_output(VARYING_SLOT_TESS_LEVEL_OUTER, array(float_t, 4),
+              "gl_TessLevelOuter")->data.patch = 1;
+   add_output(VARYING_SLOT_TESS_LEVEL_INNER, array(float_t, 2),
+              "gl_TessLevelInner")->data.patch = 1;
 }
 
 
diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
index 10db5b8..68f1989 100644
--- a/src/glsl/glsl_lexer.ll
+++ b/src/glsl/glsl_lexer.ll
@@ -314,6 +314,7 @@  invariant	KEYWORD(120, 100, 120, 100, INVARIANT);
 flat		KEYWORD(130, 100, 130, 300, FLAT);
 smooth		KEYWORD(130, 300, 130, 300, SMOOTH);
 noperspective	KEYWORD(130, 300, 130, 0, NOPERSPECTIVE);
+patch		KEYWORD_WITH_ALT(0, 300, 400, 0, yyextra->ARB_tessellation_shader_enable, PATCH);
 
 sampler1D	DEPRECATED_ES_KEYWORD(SAMPLER1D);
 sampler2D	return SAMPLER2D;
@@ -575,7 +576,6 @@  usamplerBuffer	KEYWORD(140, 300, 140, 0, USAMPLERBUFFER);
 
     /* Additional reserved words in GLSL ES 3.00 */
 resource	KEYWORD(0, 300, 0, 0, RESOURCE);
-patch		KEYWORD(0, 300, 0, 0, PATCH);
 sample		KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE);
 subroutine	KEYWORD(0, 300, 0, 0, SUBROUTINE);
 
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index eaf0dd6..716d43b 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -136,8 +136,9 @@  static bool match_layout_qualifier(const char *s1, const char *s2,
 %token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK DOUBLE_TOK
 %token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
 %token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4 DVEC2 DVEC3 DVEC4
-%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING SAMPLE
+%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING PATCH SAMPLE
 %token NOPERSPECTIVE FLAT SMOOTH
+%token ROW_MAJOR PACKED_TOK
 %token MAT2X2 MAT2X3 MAT2X4
 %token MAT3X2 MAT3X3 MAT3X4
 %token MAT4X2 MAT4X3 MAT4X4
@@ -189,18 +190,18 @@  static bool match_layout_qualifier(const char *s1, const char *s2,
 
    /* Reserved words that are not actually used in the grammar.
     */
-%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO
+%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS GOTO
 %token INLINE_TOK NOINLINE PUBLIC_TOK STATIC EXTERN EXTERNAL
 %token LONG_TOK SHORT_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK
 %token HVEC2 HVEC3 HVEC4 FVEC2 FVEC3 FVEC4
 %token SAMPLER3DRECT
 %token SIZEOF CAST NAMESPACE USING
-%token RESOURCE PATCH
+%token RESOURCE
 %token SUBROUTINE
 
 %token ERROR_TOK
 
-%token COMMON PARTITION ACTIVE FILTER ROW_MAJOR
+%token COMMON PARTITION ACTIVE FILTER
 
 %type <identifier> variable_identifier
 %type <node> statement
@@ -1861,7 +1862,11 @@  auxiliary_storage_qualifier:
       memset(& $$, 0, sizeof($$));
       $$.flags.q.sample = 1;
    }
-   /* TODO: "patch" also goes here someday. */
+   | PATCH
+   {
+      memset(& $$, 0, sizeof($$));
+      $$.flags.q.patch = 1;
+   }
 
 storage_qualifier:
    CONST_TOK
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index 6f59022..b34c7b5 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -860,6 +860,8 @@  _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
       printf("centroid ");
    if (q->flags.q.sample)
       printf("sample ");
+   if (q->flags.q.patch)
+      printf("patch ");
    if (q->flags.q.uniform)
       printf("uniform ");
    if (q->flags.q.smooth)
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index f675e90..71fc211 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -122,6 +122,7 @@  glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
       this->fields.structure[i].centroid = fields[i].centroid;
       this->fields.structure[i].sample = fields[i].sample;
       this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
+      this->fields.structure[i].patch = fields[i].patch;
    }
 
    mtx_unlock(&glsl_type::mutex);
@@ -154,6 +155,7 @@  glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
       this->fields.structure[i].centroid = fields[i].centroid;
       this->fields.structure[i].sample = fields[i].sample;
       this->fields.structure[i].matrix_layout = fields[i].matrix_layout;
+      this->fields.structure[i].patch = fields[i].patch;
    }
 
    mtx_unlock(&glsl_type::mutex);
@@ -716,6 +718,9 @@  glsl_type::record_compare(const glsl_type *b) const
       if (this->fields.structure[i].sample
           != b->fields.structure[i].sample)
          return false;
+      if (this->fields.structure[i].patch
+          != b->fields.structure[i].patch)
+         return false;
    }
 
    return true;
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
index f54a939..50c9610 100644
--- a/src/glsl/glsl_types.h
+++ b/src/glsl/glsl_types.h
@@ -752,6 +752,12 @@  struct glsl_struct_field {
    unsigned matrix_layout:2;
 
    /**
+    * For interface blocks, 1 if this variable is a per-patch input or output
+    * (as in ir_variable::patch). 0 otherwise.
+    */
+   unsigned patch:1;
+
+   /**
     * For interface blocks, it has a value if this variable uses multiple vertex
     * streams (as in ir_variable::stream). -1 otherwise.
     */
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index dbd064f..ad525ab 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -1643,6 +1643,7 @@  ir_variable::ir_variable(const struct glsl_type *type, const char *name,
    this->data.read_only = false;
    this->data.centroid = false;
    this->data.sample = false;
+   this->data.patch = false;
    this->data.invariant = false;
    this->data.how_declared = ir_var_declared_normally;
    this->data.mode = mode;
@@ -1785,6 +1786,7 @@  ir_function_signature::qualifiers_match(exec_list *params)
 	  a->data.interpolation != b->data.interpolation ||
 	  a->data.centroid != b->data.centroid ||
           a->data.sample != b->data.sample ||
+          a->data.patch != b->data.patch ||
           a->data.image_read_only != b->data.image_read_only ||
           a->data.image_write_only != b->data.image_write_only ||
           a->data.image_coherent != b->data.image_coherent ||
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index f904555..0b992c3 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -618,6 +618,7 @@  public:
       unsigned read_only:1;
       unsigned centroid:1;
       unsigned sample:1;
+      unsigned patch:1;
       unsigned invariant:1;
       unsigned precise:1;
 
diff --git a/src/glsl/ir_print_visitor.cpp b/src/glsl/ir_print_visitor.cpp
index c991658..1df4408 100644
--- a/src/glsl/ir_print_visitor.cpp
+++ b/src/glsl/ir_print_visitor.cpp
@@ -167,6 +167,7 @@  void ir_print_visitor::visit(ir_variable *ir)
 
    const char *const cent = (ir->data.centroid) ? "centroid " : "";
    const char *const samp = (ir->data.sample) ? "sample " : "";
+   const char *const patc = (ir->data.patch) ? "patch " : "";
    const char *const inv = (ir->data.invariant) ? "invariant " : "";
    const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ",
                                 "in ", "out ", "inout ",
@@ -176,8 +177,8 @@  void ir_print_visitor::visit(ir_variable *ir)
    const char *const interp[] = { "", "smooth", "flat", "noperspective" };
    STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT);
 
-   fprintf(f, "(%s%s%s%s%s%s%s) ",
-           loc, cent, samp, inv, mode[ir->data.mode],
+   fprintf(f, "(%s%s%s%s%s%s%s%s) ",
+           loc, cent, samp, patc, inv, mode[ir->data.mode],
            stream[ir->data.stream],
            interp[ir->data.interpolation]);
 
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
index 4eae413..66c8af5 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -417,6 +417,8 @@  ir_reader::read_declaration(s_expression *expr)
 	 var->data.centroid = 1;
       } else if (strcmp(qualifier->value(), "sample") == 0) {
          var->data.sample = 1;
+      } else if (strcmp(qualifier->value(), "patch") == 0) {
+         var->data.patch = 1;
       } else if (strcmp(qualifier->value(), "invariant") == 0) {
 	 var->data.invariant = 1;
       } else if (strcmp(qualifier->value(), "uniform") == 0) {
diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
index b968a1e..fe4d6da 100644
--- a/src/glsl/ir_set_program_inouts.cpp
+++ b/src/glsl/ir_set_program_inouts.cpp
@@ -140,6 +140,24 @@  ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var)
       type = type->fields.array;
    }
 
+   if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
+       var->data.mode == ir_var_shader_in) {
+      assert(type->is_array());
+      type = type->fields.array;
+   }
+
+   if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
+       var->data.mode == ir_var_shader_out && !var->data.patch) {
+      assert(type->is_array());
+      type = type->fields.array;
+   }
+
+   if (this->shader_stage == MESA_SHADER_TESS_EVAL &&
+       var->data.mode == ir_var_shader_in && !var->data.patch) {
+      assert(type->is_array());
+      type = type->fields.array;
+   }
+
    mark(this->prog, var, 0, type->count_attribute_slots(),
         this->shader_stage == MESA_SHADER_FRAGMENT);
 }
@@ -165,6 +183,9 @@  ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
  *
  * *Except gl_PrimitiveIDIn, as noted below.
  *
+ * For tessellation control shaders all inputs and non-patch outputs are
+ * arrays. For tessellation evaluation shaders non-patch inputs are arrays.
+ *
  * If the index can't be interpreted as a constant, or some other problem
  * occurs, then nothing will be marked and false will be returned.
  */
@@ -184,6 +205,24 @@  ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var,
       type = type->fields.array;
    }
 
+   if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
+       var->data.mode == ir_var_shader_in) {
+      assert(type->is_array());
+      type = type->fields.array;
+   }
+
+   if (this->shader_stage == MESA_SHADER_TESS_CTRL &&
+       var->data.mode == ir_var_shader_out && !var->data.patch) {
+      assert(type->is_array());
+      type = type->fields.array;
+   }
+
+   if (this->shader_stage == MESA_SHADER_TESS_EVAL &&
+       var->data.mode == ir_var_shader_in && !var->data.patch) {
+      assert(type->is_array());
+      type = type->fields.array;
+   }
+
    /* The code below only handles:
     *
     * - Indexing into matrices
@@ -242,6 +281,22 @@  ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var,
    return true;
 }
 
+static bool
+is_multiple_vertices(gl_shader_stage stage, ir_variable *var)
+{
+   if (var->data.patch)
+      return false;
+
+   if (var->data.mode == ir_var_shader_in)
+      return stage == MESA_SHADER_GEOMETRY ||
+             stage == MESA_SHADER_TESS_CTRL ||
+             stage == MESA_SHADER_TESS_EVAL;
+   if (var->data.mode == ir_var_shader_out)
+      return stage == MESA_SHADER_TESS_CTRL;
+
+   return false;
+}
+
 ir_visitor_status
 ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
 {
@@ -256,10 +311,9 @@  ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
        */
       if (ir_dereference_variable * const deref_var =
           inner_array->array->as_dereference_variable()) {
-         if (this->shader_stage == MESA_SHADER_GEOMETRY &&
-             deref_var->var->data.mode == ir_var_shader_in) {
-            /* foo is a geometry shader input, so i is the vertex, and j the
-             * part of the input we're accessing.
+         if (is_multiple_vertices(this->shader_stage, deref_var->var)) {
+            /* foo is a geometry or tessellation shader input, so i is
+             * the vertex, and j the part of the input we're accessing.
              */
             if (try_mark_partial_variable(deref_var->var, ir->array_index))
             {
@@ -275,10 +329,9 @@  ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
    } else if (ir_dereference_variable * const deref_var =
               ir->array->as_dereference_variable()) {
       /* ir => foo[i], where foo is a variable. */
-      if (this->shader_stage == MESA_SHADER_GEOMETRY &&
-          deref_var->var->data.mode == ir_var_shader_in) {
-         /* foo is a geometry shader input, so i is the vertex, and we're
-          * accessing the entire input.
+      if (is_multiple_vertices(this->shader_stage, deref_var->var)) {
+         /* foo is a geometry or tessellation shader input, so i is
+          * the vertex, and we're accessing the entire input.
           */
          mark_whole_variable(deref_var->var);
          /* We've now taken care of foo, but i might contain a subexpression
diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp
index 7b2d4bd..c8f1bb9 100644
--- a/src/glsl/link_varyings.cpp
+++ b/src/glsl/link_varyings.cpp
@@ -116,6 +116,18 @@  cross_validate_types_and_qualifiers(struct gl_shader_program *prog,
       return;
    }
 
+   if (input->data.patch != output->data.patch) {
+      linker_error(prog,
+                   "%s shader output `%s' %s patch qualifier, "
+                   "but %s shader input %s patch qualifier\n",
+                   _mesa_shader_stage_to_string(producer_stage),
+                   output->name,
+                   (output->data.patch) ? "has" : "lacks",
+                   _mesa_shader_stage_to_string(consumer_stage),
+                   (input->data.patch) ? "has" : "lacks");
+      return;
+   }
+
    if (!prog->IsES && input->data.invariant != output->data.invariant) {
       linker_error(prog,
                    "%s shader output `%s' %s invariant qualifier, "
@@ -979,7 +991,8 @@  varying_matches::compute_packing_class(const ir_variable *var)
     *
     * Therefore, the packing class depends only on the interpolation type.
     */
-   unsigned packing_class = var->data.centroid | (var->data.sample << 1);
+   unsigned packing_class = var->data.centroid | (var->data.sample << 1) |
+                            (var->data.patch << 2);
    packing_class *= 4;
    packing_class += var->data.interpolation;
    return packing_class;
diff --git a/src/glsl/lower_named_interface_blocks.cpp b/src/glsl/lower_named_interface_blocks.cpp
index 7304c51..2f1e3af 100644
--- a/src/glsl/lower_named_interface_blocks.cpp
+++ b/src/glsl/lower_named_interface_blocks.cpp
@@ -158,6 +158,7 @@  flatten_named_interface_blocks_declarations::run(exec_list *instructions)
                iface_t->fields.structure[i].interpolation;
             new_var->data.centroid = iface_t->fields.structure[i].centroid;
             new_var->data.sample = iface_t->fields.structure[i].sample;
+            new_var->data.patch = iface_t->fields.structure[i].patch;
 
             new_var->init_interface_type(iface_t);
             hash_table_insert(interface_namespace, new_var,
diff --git a/src/glsl/lower_packed_varyings.cpp b/src/glsl/lower_packed_varyings.cpp
index d8bebb5..cfe414a 100644
--- a/src/glsl/lower_packed_varyings.cpp
+++ b/src/glsl/lower_packed_varyings.cpp
@@ -610,6 +610,7 @@  lower_packed_varyings_visitor::get_packed_varying_deref(
       }
       packed_var->data.centroid = unpacked_var->data.centroid;
       packed_var->data.sample = unpacked_var->data.sample;
+      packed_var->data.patch = unpacked_var->data.patch;
       packed_var->data.interpolation = unpacked_var->data.interpolation;
       packed_var->data.location = location;
       unpacked_var->insert_before(packed_var);

Comments

On Wednesday, June 17, 2015 01:01:18 AM Marek Olšák wrote:
> From: Fabian Bieler <fabianbieler@fastmail.fm>
> 
> ---
>  src/glsl/ast.h                            |  1 +
>  src/glsl/ast_to_hir.cpp                   | 45 ++++++++++++++++++++
>  src/glsl/ast_type.cpp                     |  3 +-
>  src/glsl/builtin_variables.cpp            |  8 ++--
>  src/glsl/glsl_lexer.ll                    |  2 +-
>  src/glsl/glsl_parser.yy                   | 15 ++++---
>  src/glsl/glsl_parser_extras.cpp           |  2 +
>  src/glsl/glsl_types.cpp                   |  5 +++
>  src/glsl/glsl_types.h                     |  6 +++
>  src/glsl/ir.cpp                           |  2 +
>  src/glsl/ir.h                             |  1 +
>  src/glsl/ir_print_visitor.cpp             |  5 ++-
>  src/glsl/ir_reader.cpp                    |  2 +
>  src/glsl/ir_set_program_inouts.cpp        | 69 +++++++++++++++++++++++++++----
>  src/glsl/link_varyings.cpp                | 15 ++++++-
>  src/glsl/lower_named_interface_blocks.cpp |  1 +
>  src/glsl/lower_packed_varyings.cpp        |  1 +
>  17 files changed, 161 insertions(+), 22 deletions(-)
> 
> diff --git a/src/glsl/ast.h b/src/glsl/ast.h
> index 26ad3bf..87e1354 100644
> --- a/src/glsl/ast.h
> +++ b/src/glsl/ast.h
> @@ -434,6 +434,7 @@ struct ast_type_qualifier {
>  	 unsigned out:1;
>  	 unsigned centroid:1;
>           unsigned sample:1;
> +	 unsigned patch:1;
>  	 unsigned uniform:1;
>  	 unsigned smooth:1;
>  	 unsigned flat:1;
> diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
> index 53daf13..837bac7 100644
> --- a/src/glsl/ast_to_hir.cpp
> +++ b/src/glsl/ast_to_hir.cpp
> @@ -2461,6 +2461,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
>        var->data.stream = qual->stream;
>     }
>  
> +   if (qual->flags.q.patch)
> +      var->data.patch = 1;
> +
>     if (qual->flags.q.attribute && state->stage != MESA_SHADER_VERTEX) {
>        var->type = glsl_type::error_type;
>        _mesa_glsl_error(loc, state,
> @@ -3119,6 +3122,17 @@ handle_tess_ctrl_shader_output_decl(struct _mesa_glsl_parse_state *state,
>        num_vertices = state->out_qualifier->vertices;
>     }
>  
> +   if (!var->type->is_array() && !var->data.patch) {
> +      _mesa_glsl_error(&loc, state,
> +                       "tessellation control shader outputs must be arrays");
> +
> +      /* To avoid cascading failures, short circuit the checks below. */
> +      return;
> +   }

Seems like this block should have gone in patch 20 and just the
!var->data.patch part added here.  But it's already a huge patch, so I
suppose it doesn't matter so much...

> +
> +   if (var->data.patch)
> +      return;
> +
>     if (var->type->is_unsized_array()) {
>        if (num_vertices != 0)
>           var->type = glsl_type::get_array_instance(var->type->fields.array,
> @@ -3940,6 +3954,33 @@ ast_declarator_list::hir(exec_list *instructions,
>        }
>  
>  
> +      /* From section 4.3.4 of the GLSL 4.00 spec:
> +       *    "Input variables may not be declared using the patch in qualifier
> +       *    in tessellation control or geometry shaders."
> +       *
> +       * From section 4.3.6 of the GLSL 4.00 spec:
> +       *    "It is an error to use patch out in a vertex, tessellation
> +       *    evaluation, or geometry shader."
> +       *
> +       * This doesn't explicitly forbid using them in a fragment shader, but
> +       * that's probably just an oversight.
> +       */
> +      if (state->stage != MESA_SHADER_TESS_EVAL
> +          && this->type->qualifier.flags.q.patch
> +          && this->type->qualifier.flags.q.in) {
> +
> +         _mesa_glsl_error(&loc, state, "'patch in' can only be used in a "
> +                          "tessellation evaluation shader");
> +      }
> +
> +      if (state->stage != MESA_SHADER_TESS_CTRL
> +          && this->type->qualifier.flags.q.patch
> +          && this->type->qualifier.flags.q.out) {
> +
> +         _mesa_glsl_error(&loc, state, "'patch out' can only be used in a "
> +                          "tessellation control shader");
> +      }
> +
>        /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30.
>         */
>        if (this->type->qualifier.precision != ast_precision_none) {
> @@ -5463,6 +5504,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
>              interpret_interpolation_qualifier(qual, var_mode, state, &loc);
>           fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
>           fields[i].sample = qual->flags.q.sample ? 1 : 0;
> +         fields[i].patch = qual->flags.q.patch ? 1 : 0;
>  
>           /* Only save explicitly defined streams in block's field */
>           fields[i].stream = qual->flags.q.explicit_stream ? qual->stream : -1;
> @@ -5794,6 +5836,8 @@ ast_interface_block::hir(exec_list *instructions,
>                 earlier_per_vertex->fields.structure[j].centroid;
>              fields[i].sample =
>                 earlier_per_vertex->fields.structure[j].sample;
> +            fields[i].patch =
> +               earlier_per_vertex->fields.structure[j].patch;
>           }
>        }
>  
> @@ -5973,6 +6017,7 @@ ast_interface_block::hir(exec_list *instructions,
>           var->data.interpolation = fields[i].interpolation;
>           var->data.centroid = fields[i].centroid;
>           var->data.sample = fields[i].sample;
> +         var->data.patch = fields[i].patch;
>           var->init_interface_type(block_type);
>  
>           if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
> diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
> index 5bebaab..0d3651d 100644
> --- a/src/glsl/ast_type.cpp
> +++ b/src/glsl/ast_type.cpp
> @@ -85,7 +85,8 @@ bool
>  ast_type_qualifier::has_auxiliary_storage() const
>  {
>     return this->flags.q.centroid
> -          || this->flags.q.sample;
> +          || this->flags.q.sample
> +          || this->flags.q.patch;
>  }
>  
>  const char*
> diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp
> index bb947a8..874cb10 100644
> --- a/src/glsl/builtin_variables.cpp
> +++ b/src/glsl/builtin_variables.cpp
> @@ -881,10 +881,10 @@ builtin_variable_generator::generate_tcs_special_vars()
>     add_system_value(SYSTEM_VALUE_VERTICES_IN, int_t, "gl_PatchVerticesIn");
>     add_system_value(SYSTEM_VALUE_INVOCATION_ID, int_t, "gl_InvocationID");
>  
> -   add_output(VARYING_SLOT_TESS_LEVEL_OUTER,
> -                    array(float_t, 4), "gl_TessLevelOuter");
> -   add_output(VARYING_SLOT_TESS_LEVEL_INNER,
> -                    array(float_t, 2), "gl_TessLevelInner");
> +   add_output(VARYING_SLOT_TESS_LEVEL_OUTER, array(float_t, 4),
> +              "gl_TessLevelOuter")->data.patch = 1;
> +   add_output(VARYING_SLOT_TESS_LEVEL_INNER, array(float_t, 2),
> +              "gl_TessLevelInner")->data.patch = 1;
>  }
>  
>  
> diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll
> index 10db5b8..68f1989 100644
> --- a/src/glsl/glsl_lexer.ll
> +++ b/src/glsl/glsl_lexer.ll
> @@ -314,6 +314,7 @@ invariant	KEYWORD(120, 100, 120, 100, INVARIANT);
>  flat		KEYWORD(130, 100, 130, 300, FLAT);
>  smooth		KEYWORD(130, 300, 130, 300, SMOOTH);
>  noperspective	KEYWORD(130, 300, 130, 0, NOPERSPECTIVE);
> +patch		KEYWORD_WITH_ALT(0, 300, 400, 0, yyextra->ARB_tessellation_shader_enable, PATCH);
>  
>  sampler1D	DEPRECATED_ES_KEYWORD(SAMPLER1D);
>  sampler2D	return SAMPLER2D;
> @@ -575,7 +576,6 @@ usamplerBuffer	KEYWORD(140, 300, 140, 0, USAMPLERBUFFER);
>  
>      /* Additional reserved words in GLSL ES 3.00 */
>  resource	KEYWORD(0, 300, 0, 0, RESOURCE);
> -patch		KEYWORD(0, 300, 0, 0, PATCH);
>  sample		KEYWORD_WITH_ALT(400, 300, 400, 0, yyextra->ARB_gpu_shader5_enable, SAMPLE);
>  subroutine	KEYWORD(0, 300, 0, 0, SUBROUTINE);
>  
> diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
> index eaf0dd6..716d43b 100644
> --- a/src/glsl/glsl_parser.yy
> +++ b/src/glsl/glsl_parser.yy
> @@ -136,8 +136,9 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
>  %token ATTRIBUTE CONST_TOK BOOL_TOK FLOAT_TOK INT_TOK UINT_TOK DOUBLE_TOK
>  %token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
>  %token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 UVEC2 UVEC3 UVEC4 VEC2 VEC3 VEC4 DVEC2 DVEC3 DVEC4
> -%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING SAMPLE
> +%token CENTROID IN_TOK OUT_TOK INOUT_TOK UNIFORM VARYING PATCH SAMPLE
>  %token NOPERSPECTIVE FLAT SMOOTH
> +%token ROW_MAJOR PACKED_TOK

A couple of the changes here look like unrelated reordering...this line

>  %token MAT2X2 MAT2X3 MAT2X4
>  %token MAT3X2 MAT3X3 MAT3X4
>  %token MAT4X2 MAT4X3 MAT4X4
> @@ -189,18 +190,18 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
>  
>     /* Reserved words that are not actually used in the grammar.
>      */
> -%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS PACKED_TOK GOTO
> +%token ASM CLASS UNION ENUM TYPEDEF TEMPLATE THIS GOTO

and this line

>  %token INLINE_TOK NOINLINE PUBLIC_TOK STATIC EXTERN EXTERNAL
>  %token LONG_TOK SHORT_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK
>  %token HVEC2 HVEC3 HVEC4 FVEC2 FVEC3 FVEC4
>  %token SAMPLER3DRECT
>  %token SIZEOF CAST NAMESPACE USING
> -%token RESOURCE PATCH
> +%token RESOURCE
>  %token SUBROUTINE
>  
>  %token ERROR_TOK
>  
> -%token COMMON PARTITION ACTIVE FILTER ROW_MAJOR
> +%token COMMON PARTITION ACTIVE FILTER

and this line...could probably all be dropped.