Merge branch 'draw-instanced'
[mesa.git] / src / glsl / ast_to_hir.cpp
index 82b3f2e0ea99ba9088d37105b1d3d357382a25cb..365a6e2676fd225200ab9c2a35d0511baa2881ac 100644 (file)
@@ -60,7 +60,7 @@ void
 _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state)
 {
    _mesa_glsl_initialize_variables(instructions, state);
-   _mesa_glsl_initialize_functions(instructions, state);
+   _mesa_glsl_initialize_functions(state);
 
    state->symbols->language_version = state->language_version;
 
@@ -598,17 +598,15 @@ ir_rvalue *
 validate_assignment(struct _mesa_glsl_parse_state *state,
                    const glsl_type *lhs_type, ir_rvalue *rhs)
 {
-   const glsl_type *rhs_type = rhs->type;
-
    /* If there is already some error in the RHS, just return it.  Anything
     * else will lead to an avalanche of error message back to the user.
     */
-   if (rhs_type->is_error())
+   if (rhs->type->is_error())
       return rhs;
 
    /* If the types are identical, the assignment can trivially proceed.
     */
-   if (rhs_type == lhs_type)
+   if (rhs->type == lhs_type)
       return rhs;
 
    /* If the array element types are the same and the size of the LHS is zero,
@@ -625,8 +623,7 @@ validate_assignment(struct _mesa_glsl_parse_state *state,
 
    /* Check for implicit conversion in GLSL 1.20 */
    if (apply_implicit_conversion(lhs_type, rhs, state)) {
-      rhs_type = rhs->type;
-      if (rhs_type == lhs_type)
+      if (rhs->type == lhs_type)
         return rhs;
    }
 
@@ -1567,6 +1564,40 @@ ast_expression::hir(exec_list *instructions,
         }
       }
 
+      /* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
+       *
+       *    "Samplers aggregated into arrays within a shader (using square
+       *    brackets [ ]) can only be indexed with integral constant
+       *    expressions [...]."
+       *
+       * This restriction was added in GLSL 1.30.  Shaders using earlier version
+       * of the language should not be rejected by the compiler front-end for
+       * using this construct.  This allows useful things such as using a loop
+       * counter as the index to an array of samplers.  If the loop in unrolled,
+       * the code should compile correctly.  Instead, emit a warning.
+       */
+      if (array->type->is_array() &&
+          array->type->element_type()->is_sampler() &&
+          const_index == NULL) {
+
+        if (state->language_version == 100) {
+           _mesa_glsl_warning(&loc, state,
+                              "sampler arrays indexed with non-constant "
+                              "expressions is optional in GLSL ES 1.00");
+        } else if (state->language_version < 130) {
+           _mesa_glsl_warning(&loc, state,
+                              "sampler arrays indexed with non-constant "
+                              "expressions is forbidden in GLSL 1.30 and "
+                              "later");
+        } else {
+           _mesa_glsl_error(&loc, state,
+                            "sampler arrays indexed with non-constant "
+                            "expressions is forbidden in GLSL 1.30 and "
+                            "later");
+           error_emitted = true;
+        }
+      }
+
       if (error_emitted)
         result->type = glsl_type::error_type;
 
@@ -1592,6 +1623,7 @@ ast_expression::hir(exec_list *instructions,
       result = new(ctx) ir_dereference_variable(var);
 
       if (var != NULL) {
+        var->used = true;
         type = result->type;
       } else {
         _mesa_glsl_error(& loc, state, "`%s' undeclared",
@@ -1766,8 +1798,16 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                                 struct _mesa_glsl_parse_state *state,
                                 YYLTYPE *loc)
 {
-   if (qual->flags.q.invariant)
-      var->invariant = 1;
+   if (qual->flags.q.invariant) {
+      if (var->used) {
+        _mesa_glsl_error(loc, state,
+                         "variable `%s' may not be redeclared "
+                         "`invariant' after being used",
+                         var->name);
+      } else {
+        var->invariant = 1;
+      }
+   }
 
    /* FINISHME: Mark 'in' variables at global scope as read-only. */
    if (qual->flags.q.constant || qual->flags.q.attribute
@@ -1821,6 +1861,23 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
    else if (qual->flags.q.uniform)
       var->mode = ir_var_uniform;
 
+   if (state->all_invariant && (state->current_function == NULL)) {
+      switch (state->target) {
+      case vertex_shader:
+        if (var->mode == ir_var_out)
+           var->invariant = true;
+        break;
+      case geometry_shader:
+        if ((var->mode == ir_var_in) || (var->mode == ir_var_out))
+           var->invariant = true;
+        break;
+      case fragment_shader:
+        if (var->mode == ir_var_in)
+           var->invariant = true;
+        break;
+      }
+   }
+
    if (qual->flags.q.flat)
       var->interpolation = ir_var_flat;
    else if (qual->flags.q.noperspective)
@@ -1900,6 +1957,52 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
+   /* Does the declaration use the 'layout' keyword?
+    */
+   const bool uses_layout = qual->flags.q.pixel_center_integer
+      || qual->flags.q.origin_upper_left
+      || qual->flags.q.explicit_location;
+
+   /* Does the declaration use the deprecated 'attribute' or 'varying'
+    * keywords?
+    */
+   const bool uses_deprecated_qualifier = qual->flags.q.attribute
+      || qual->flags.q.varying;
+
+   /* Is the 'layout' keyword used with parameters that allow relaxed checking.
+    * Many implementations of GL_ARB_fragment_coord_conventions_enable and some
+    * implementations (only Mesa?) GL_ARB_explicit_attrib_location_enable
+    * allowed the layout qualifier to be used with 'varying' and 'attribute'.
+    * These extensions and all following extensions that add the 'layout'
+    * keyword have been modified to require the use of 'in' or 'out'.
+    *
+    * The following extension do not allow the deprecated keywords:
+    *
+    *    GL_AMD_conservative_depth
+    *    GL_ARB_gpu_shader5
+    *    GL_ARB_separate_shader_objects
+    *    GL_ARB_tesselation_shader
+    *    GL_ARB_transform_feedback3
+    *    GL_ARB_uniform_buffer_object
+    *
+    * It is unknown whether GL_EXT_shader_image_load_store or GL_NV_gpu_shader5
+    * allow layout with the deprecated keywords.
+    */
+   const bool relaxed_layout_qualifier_checking =
+      state->ARB_fragment_coord_conventions_enable;
+
+   if (uses_layout && uses_deprecated_qualifier) {
+      if (relaxed_layout_qualifier_checking) {
+        _mesa_glsl_warning(loc, state,
+                           "`layout' qualifier may not be used with "
+                           "`attribute' or `varying'");
+      } else {
+        _mesa_glsl_error(loc, state,
+                         "`layout' qualifier may not be used with "
+                         "`attribute' or `varying'");
+      }
+   }
+
    if (var->type->is_array() && state->language_version != 110) {
       var->array_lvalue = true;
    }
@@ -1957,6 +2060,11 @@ ast_declarator_list::hir(exec_list *instructions,
            _mesa_glsl_error(& loc, state,
                             "`%s' cannot be marked invariant, fragment shader "
                             "inputs only\n", decl->identifier);
+        } else if (earlier->used) {
+           _mesa_glsl_error(& loc, state,
+                            "variable `%s' may not be redeclared "
+                            "`invariant' after being used",
+                            earlier->name);
         } else {
            earlier->invariant = true;
         }
@@ -2026,20 +2134,23 @@ ast_declarator_list::hir(exec_list *instructions,
        *
        *     Local variables can only use the qualifier const."
        *
-       * This is relaxed in GLSL 1.30.
+       * This is relaxed in GLSL 1.30.  It is also relaxed by any extension
+       * that adds the 'layout' keyword.
        */
-      if (state->language_version < 120) {
+      if ((state->language_version < 130)
+         && !state->ARB_explicit_attrib_location_enable
+         && !state->ARB_fragment_coord_conventions_enable) {
         if (this->type->qualifier.flags.q.out) {
            _mesa_glsl_error(& loc, state,
                             "`out' qualifier in declaration of `%s' "
-                            "only valid for function parameters in GLSL 1.10.",
-                            decl->identifier);
+                            "only valid for function parameters in %s.",
+                            decl->identifier, state->version_string);
         }
         if (this->type->qualifier.flags.q.in) {
            _mesa_glsl_error(& loc, state,
                             "`in' qualifier in declaration of `%s' "
-                            "only valid for function parameters in GLSL 1.10.",
-                            decl->identifier);
+                            "only valid for function parameters in %s.",
+                            decl->identifier, state->version_string);
         }
         /* FINISHME: Test for other invalid qualifiers. */
       }
@@ -2147,6 +2258,25 @@ ast_declarator_list::hir(exec_list *instructions,
         }
       }
 
+      /* Integer vertex outputs must be qualified with 'flat'.
+       *
+       * From section 4.3.6 of the GLSL 1.30 spec:
+       *    "If a vertex output is a signed or unsigned integer or integer
+       *    vector, then it must be qualified with the interpolation qualifier
+       *    flat."
+       */
+      if (state->language_version >= 130
+          && state->target == vertex_shader
+          && state->current_function == NULL
+          && var->type->is_integer()
+          && var->mode == ir_var_out
+          && var->interpolation != ir_var_flat) {
+
+         _mesa_glsl_error(&loc, state, "If a vertex output is an integer, "
+                          "then it must be qualified with 'flat'");
+      }
+
+
       /* Process the initializer and add its instructions to a temporary
        * list.  This list will be added to the instruction stream (below) after
        * the declaration is added.  This is done because in some cases (such as
@@ -2228,6 +2358,17 @@ ast_declarator_list::hir(exec_list *instructions,
            if (this->type->qualifier.flags.q.constant)
               var->read_only = false;
 
+           /* Never emit code to initialize a uniform.
+            */
+           const glsl_type *initializer_type;
+           if (!this->type->qualifier.flags.q.uniform) {
+              result = do_assignment(&initializer_instructions, state,
+                                     lhs, rhs,
+                                     this->get_location());
+              initializer_type = result->type;
+           } else
+              initializer_type = rhs->type;
+
            /* If the declared variable is an unsized array, it must inherrit
             * its full type from the initializer.  A declaration such as
             *
@@ -2242,16 +2383,14 @@ ast_declarator_list::hir(exec_list *instructions,
             *
             * If the declared variable is not an array, the types must
             * already match exactly.  As a result, the type assignment
-            * here can be done unconditionally.
+            * here can be done unconditionally.  For non-uniforms the call
+            * to do_assignment can change the type of the initializer (via
+            * the implicit conversion rules).  For uniforms the initializer
+            * must be a constant expression, and the type of that expression
+            * was validated above.
             */
-           var->type = rhs->type;
+           var->type = initializer_type;
 
-           /* Never emit code to initialize a uniform.
-            */
-           if (!this->type->qualifier.flags.q.uniform)
-              result = do_assignment(&initializer_instructions, state,
-                                     lhs, rhs,
-                                     this->get_location());
            var->read_only = temp;
         }
       }
@@ -2324,6 +2463,27 @@ ast_declarator_list::hir(exec_list *instructions,
             */
            earlier->origin_upper_left = var->origin_upper_left;
            earlier->pixel_center_integer = var->pixel_center_integer;
+
+        /* According to section 4.3.7 of the GLSL 1.30 spec,
+         * the following built-in varaibles can be redeclared with an
+         * interpolation qualifier:
+         *    * gl_FrontColor
+         *    * gl_BackColor
+         *    * gl_FrontSecondaryColor
+         *    * gl_BackSecondaryColor
+         *    * gl_Color
+         *    * gl_SecondaryColor
+         */
+        } else if (state->language_version >= 130
+                   && (strcmp(var->name, "gl_FrontColor") == 0
+                        || strcmp(var->name, "gl_BackColor") == 0
+                        || strcmp(var->name, "gl_FrontSecondaryColor") == 0
+                        || strcmp(var->name, "gl_BackSecondaryColor") == 0
+                        || strcmp(var->name, "gl_Color") == 0
+                        || strcmp(var->name, "gl_SecondaryColor") == 0)
+                   && earlier->type == var->type
+                   && earlier->mode == var->mode) {
+           earlier->interpolation = var->interpolation;
         } else {
            YYLTYPE loc = this->get_location();
            _mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);