glsl: Add ir support for `sample` qualifier; adjust compiler and linker
authorChris Forbes <chrisf@ijw.co.nz>
Fri, 29 Nov 2013 08:26:10 +0000 (21:26 +1300)
committerChris Forbes <chrisf@ijw.co.nz>
Sat, 7 Dec 2013 04:14:58 +0000 (17:14 +1300)
Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Francisco Jerez <currojerez@riseup.net>
13 files changed:
src/glsl/ast_to_hir.cpp
src/glsl/builtin_variables.cpp
src/glsl/glsl_types.cpp
src/glsl/glsl_types.h
src/glsl/ir.cpp
src/glsl/ir.h
src/glsl/ir_clone.cpp
src/glsl/ir_print_visitor.cpp
src/glsl/ir_reader.cpp
src/glsl/link_varyings.cpp
src/glsl/linker.cpp
src/glsl/lower_named_interface_blocks.cpp
src/glsl/lower_packed_varyings.cpp

index 37be1cb75623ec9d08ea663a3de71edec332f7db..f35d8679e70e0d7414f48c586b55f4369f1ea6b4 100644 (file)
@@ -2180,6 +2180,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    if (qual->flags.q.centroid)
       var->centroid = 1;
 
+   if (qual->flags.q.sample)
+      var->sample = 1;
+
    if (qual->flags.q.attribute && state->target != vertex_shader) {
       var->type = glsl_type::error_type;
       _mesa_glsl_error(loc, state,
@@ -3277,6 +3280,14 @@ ast_declarator_list::hir(exec_list *instructions,
                           "'centroid in' cannot be used in a vertex shader");
       }
 
+      if (state->target == vertex_shader
+          && this->type->qualifier.flags.q.sample
+          && this->type->qualifier.flags.q.in) {
+
+         _mesa_glsl_error(&loc, state,
+                        "'sample in' cannot be used in a vertex shader");
+      }
+
       /* Section 4.3.6 of the GLSL 1.30 specification states:
        * "It is an error to use centroid out in a fragment shader."
        *
@@ -4662,6 +4673,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
          fields[i].interpolation =
             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;
 
          if (qual->flags.q.row_major || qual->flags.q.column_major) {
             if (!qual->flags.q.uniform) {
@@ -4930,6 +4942,8 @@ ast_interface_block::hir(exec_list *instructions,
                earlier_per_vertex->fields.structure[j].interpolation;
             fields[i].centroid =
                earlier_per_vertex->fields.structure[j].centroid;
+            fields[i].sample =
+               earlier_per_vertex->fields.structure[j].sample;
          }
       }
 
@@ -5084,6 +5098,7 @@ ast_interface_block::hir(exec_list *instructions,
                                    var_mode);
          var->interpolation = fields[i].interpolation;
          var->centroid = fields[i].centroid;
+         var->sample = fields[i].sample;
          var->init_interface_type(block_type);
 
          if (redeclaring_per_vertex) {
index d57324c2fba8481cc197cfeae8a661608c1a10cd..d0e76e3a402b682d6eb45d0291061c27b56e5bb4 100644 (file)
@@ -332,6 +332,7 @@ per_vertex_accumulator::add_field(int slot, const glsl_type *type,
    this->fields[this->num_fields].location = slot;
    this->fields[this->num_fields].interpolation = INTERP_QUALIFIER_NONE;
    this->fields[this->num_fields].centroid = 0;
+   this->fields[this->num_fields].sample = 0;
    this->num_fields++;
 }
 
@@ -937,6 +938,7 @@ builtin_variable_generator::generate_varyings()
                          fields[i].location);
          var->interpolation = fields[i].interpolation;
          var->centroid = fields[i].centroid;
+         var->sample = fields[i].sample;
          var->init_interface_type(per_vertex_out_type);
       }
    }
index f740130968c1cdbc3695c1e450daa018092c0a5c..12d4ac0eeba038b8e7474d355e82b8d851383428 100644 (file)
@@ -103,6 +103,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
       this->fields.structure[i].location = fields[i].location;
       this->fields.structure[i].interpolation = fields[i].interpolation;
       this->fields.structure[i].centroid = fields[i].centroid;
+      this->fields.structure[i].sample = fields[i].sample;
       this->fields.structure[i].row_major = fields[i].row_major;
    }
 }
@@ -130,6 +131,7 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields,
       this->fields.structure[i].location = fields[i].location;
       this->fields.structure[i].interpolation = fields[i].interpolation;
       this->fields.structure[i].centroid = fields[i].centroid;
+      this->fields.structure[i].sample = fields[i].sample;
       this->fields.structure[i].row_major = fields[i].row_major;
    }
 }
@@ -483,6 +485,9 @@ glsl_type::record_key_compare(const void *a, const void *b)
       if (key1->fields.structure[i].centroid
           != key2->fields.structure[i].centroid)
          return 1;
+      if (key1->fields.structure[i].sample
+          != key2->fields.structure[i].sample)
+         return 1;
    }
 
    return 0;
index 96eee5e64eb69b483512fed80187fa1feec90fde..fb7c9288d3fa3dea007cd44697f211a095e78a76 100644 (file)
@@ -634,6 +634,12 @@ struct glsl_struct_field {
     * in ir_variable::centroid).  0 otherwise.
     */
    unsigned centroid:1;
+
+   /**
+    * For interface blocks, 1 if this variable uses sample interpolation (as
+    * in ir_variable::sample). 0 otherwise.
+    */
+   unsigned sample:1;
 };
 
 static inline unsigned int
index 3be7d51707a48df8e65c52eebf03523953dab7ab..330b4dccbb58809fac49619c57b172ff909e2a48 100644 (file)
@@ -1585,7 +1585,7 @@ ir_swizzle::variable_referenced() const
 ir_variable::ir_variable(const struct glsl_type *type, const char *name,
                         ir_variable_mode mode)
    : max_array_access(0), max_ifc_array_access(NULL),
-     read_only(false), centroid(false), invariant(false),
+     read_only(false), centroid(false), sample(false), invariant(false),
      how_declared(ir_var_declared_normally), mode(mode),
      interpolation(INTERP_QUALIFIER_NONE), atomic()
 {
@@ -1709,7 +1709,8 @@ ir_function_signature::qualifiers_match(exec_list *params)
       if (a->read_only != b->read_only ||
          !modes_match(a->mode, b->mode) ||
          a->interpolation != b->interpolation ||
-         a->centroid != b->centroid) {
+         a->centroid != b->centroid ||
+         a->sample != b->sample) {
 
         /* parameter a's qualifiers don't match */
         return a->name;
index 57f3bcac026df32390c645eb5ae93338a5593eab..e60ffc0834fe6f4c444487c294f0c001238209b3 100644 (file)
@@ -529,6 +529,7 @@ public:
     */
    unsigned read_only:1;
    unsigned centroid:1;
+   unsigned sample:1;
    unsigned invariant:1;
 
    /**
index 8f57499ec978c75a830ad81a670b33c83166a777..a66864a61d13b4c26d287ab48f3ebadc6bc2d3aa 100644 (file)
@@ -52,6 +52,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
    }
    var->read_only = this->read_only;
    var->centroid = this->centroid;
+   var->sample = this->sample;
    var->invariant = this->invariant;
    var->interpolation = this->interpolation;
    var->location = this->location;
index 6ad22fe33e8de32dece4d802917ea9273210e8a3..f4109fb1f4cc8ff2ba7b0e18365694ebd1aa3f3e 100644 (file)
@@ -149,6 +149,7 @@ void ir_print_visitor::visit(ir_variable *ir)
    printf("(declare ");
 
    const char *const cent = (ir->centroid) ? "centroid " : "";
+   const char *const samp = (ir->sample) ? "sample " : "";
    const char *const inv = (ir->invariant) ? "invariant " : "";
    const char *const mode[] = { "", "uniform ", "shader_in ", "shader_out ",
                                 "in ", "out ", "inout ",
@@ -157,8 +158,8 @@ void ir_print_visitor::visit(ir_variable *ir)
    const char *const interp[] = { "", "smooth", "flat", "noperspective" };
    STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_QUALIFIER_COUNT);
 
-   printf("(%s%s%s%s) ",
-         cent, inv, mode[ir->mode], interp[ir->interpolation]);
+   printf("(%s%s%s%s%s) ",
+         cent, samp, inv, mode[ir->mode], interp[ir->interpolation]);
 
    print_type(ir->type);
    printf(" %s)", unique_name(ir));
index 00e2db9a3f06b842c0c7b779e407a278c87ad442..7fcb34d2390eb352b0eaddf6a25b6a52749867df 100644 (file)
@@ -413,6 +413,8 @@ ir_reader::read_declaration(s_expression *expr)
       // FINISHME: Check for duplicate/conflicting qualifiers.
       if (strcmp(qualifier->value(), "centroid") == 0) {
         var->centroid = 1;
+      } else if (strcmp(qualifier->value(), "sample") == 0) {
+         var->sample = 1;
       } else if (strcmp(qualifier->value(), "invariant") == 0) {
         var->invariant = 1;
       } else if (strcmp(qualifier->value(), "uniform") == 0) {
index be36b5f8f6b911affd771a0a8101fe2f296504f2..d2a4fc82d3ca9604617f3b6c86bafdcd544c40bd 100644 (file)
@@ -105,6 +105,18 @@ cross_validate_types_and_qualifiers(struct gl_shader_program *prog,
       return;
    }
 
+   if (input->sample != output->sample) {
+      linker_error(prog,
+                   "%s shader output `%s' %s sample qualifier, "
+                   "but %s shader input %s sample qualifier\n",
+                   _mesa_glsl_shader_target_name(producer_type),
+                   output->name,
+                   (output->sample) ? "has" : "lacks",
+                   _mesa_glsl_shader_target_name(consumer_type),
+                   (input->sample) ? "has" : "lacks");
+      return;
+   }
+
    if (input->invariant != output->invariant) {
       linker_error(prog,
                    "%s shader output `%s' %s invariant qualifier, "
@@ -753,10 +765,12 @@ varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
        * requirement by changing the interpolation type to flat here.
        */
       producer_var->centroid = false;
+      producer_var->sample = false;
       producer_var->interpolation = INTERP_QUALIFIER_FLAT;
 
       if (consumer_var) {
          consumer_var->centroid = false;
+         consumer_var->sample = false;
          consumer_var->interpolation = INTERP_QUALIFIER_FLAT;
       }
    }
index 21c1bdd10f15b8bc1dfc861b1efd95f03408f8db..9e8eca5cc9e41742fb231e5a1a31129b351f8628 100644 (file)
@@ -765,6 +765,12 @@ cross_validate_globals(struct gl_shader_program *prog,
                            mode_string(var), var->name);
                return;
             }
+            if (existing->sample != var->sample) {
+               linker_error(prog, "declarations for %s `%s` have "
+                            "mismatching sample qualifiers\n",
+                            mode_string(var), var->name);
+               return;
+            }
         } else
            variables.add_variable(var);
       }
index d59d11150e0cad81ae9c0c065fcbc76897dea950..aa4c11070e5490285d7be6658b4446314ed080c3 100644 (file)
@@ -157,6 +157,7 @@ flatten_named_interface_blocks_declarations::run(exec_list *instructions)
             new_var->interpolation =
                iface_t->fields.structure[i].interpolation;
             new_var->centroid = iface_t->fields.structure[i].centroid;
+            new_var->sample = iface_t->fields.structure[i].sample;
 
             new_var->init_interface_type(iface_t);
             hash_table_insert(interface_namespace, new_var,
index 61ee692f6b0cbd3d788cae11c848f6e27daf93bb..e097e81f1b3f336af68574f11617b46d4f060f89 100644 (file)
@@ -565,6 +565,7 @@ lower_packed_varyings_visitor::get_packed_varying_deref(
          packed_var->max_array_access = this->gs_input_vertices - 1;
       }
       packed_var->centroid = unpacked_var->centroid;
+      packed_var->sample = unpacked_var->sample;
       packed_var->interpolation = unpacked_var->interpolation;
       packed_var->location = location;
       unpacked_var->insert_before(packed_var);