glsl: validate and store component layout qualifier in GLSL IR
authorTimothy Arceri <timothy.arceri@collabora.com>
Tue, 10 Nov 2015 19:24:53 +0000 (06:24 +1100)
committerTimothy Arceri <timothy.arceri@collabora.com>
Sun, 1 May 2016 13:13:05 +0000 (23:13 +1000)
We make use of the existing IR field location_frac used for tracking
component locations.

Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/compiler/glsl/ast_to_hir.cpp
src/compiler/glsl/ir.h

index dd8e4e0553ded84edbb3a7a89cd5873d929544c0..c5cd48f536f42205e12aad61f17353a6ea1ceaa2 100644 (file)
@@ -3346,10 +3346,42 @@ apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
 
    if (qual->flags.q.explicit_location) {
       apply_explicit_location(qual, var, state, loc);
+
+      if (qual->flags.q.explicit_component) {
+         unsigned qual_component;
+         if (process_qualifier_constant(state, loc, "component",
+                                        qual->component, &qual_component)) {
+            const glsl_type *type = var->type->without_array();
+            unsigned components = type->component_slots();
+
+            if (type->is_matrix() || type->is_record()) {
+               _mesa_glsl_error(loc, state, "component layout qualifier "
+                                "cannot be applied to a matrix, a structure, "
+                                "a block, or an array containing any of "
+                                "these.");
+            } else if (qual_component != 0 &&
+                (qual_component + components - 1) > 3) {
+               _mesa_glsl_error(loc, state, "component overflow (%u > 3)",
+                                (qual_component + components - 1));
+            } else if (qual_component == 1 && type->is_double()) {
+               /* We don't bother checking for 3 as it should be caught by the
+                * overflow check above.
+                */
+               _mesa_glsl_error(loc, state, "doubles cannot begin at "
+                                "component 1 or 3");
+            } else {
+               var->data.explicit_component = true;
+               var->data.location_frac = qual_component;
+            }
+         }
+      }
    } else if (qual->flags.q.explicit_index) {
       if (!qual->flags.q.subroutine_def)
          _mesa_glsl_error(loc, state,
                           "explicit index requires explicit location");
+   } else if (qual->flags.q.explicit_component) {
+      _mesa_glsl_error(loc, state,
+                       "explicit component requires explicit location");
    }
 
    if (qual->flags.q.explicit_binding) {
@@ -7007,6 +7039,12 @@ ast_interface_block::hir(exec_list *instructions,
                        "Interface block sets both readonly and writeonly");
    }
 
+   if (this->layout.flags.q.explicit_component) {
+      _mesa_glsl_error(&loc, state, "component layout qualifier cannot be "
+                       "applied to a matrix, a structure, a block, or an "
+                       "array containing any of these.");
+   }
+
    unsigned qual_stream;
    if (!process_qualifier_constant(state, &loc, "stream", this->layout.stream,
                                    &qual_stream) ||
index b1a1d5656d140621744895510bf5f99fecb83a67..0c319ea8f27788d2259321841d47b0e923004234 100644 (file)
@@ -702,6 +702,11 @@ public:
        */
       unsigned explicit_binding:1;
 
+      /**
+       * Was an initial component explicitly set in the shader?
+       */
+      unsigned explicit_component:1;
+
       /**
        * Does this variable have an initializer?
        *