Merge branch 'draw-instanced'
[mesa.git] / src / glsl / ast_to_hir.cpp
index f5b1120f785fbe614337cfb6d890a883dc519dea..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;
    }
 
@@ -759,6 +756,7 @@ static ir_rvalue *
 do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
 {
    int join_op;
+   ir_rvalue *cmp = NULL;
 
    if (operation == ir_binop_all_equal)
       join_op = ir_binop_logic_and;
@@ -773,8 +771,6 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
       return new(mem_ctx) ir_expression(operation, op0, op1);
 
    case GLSL_TYPE_ARRAY: {
-      ir_rvalue *last = NULL;
-
       for (unsigned int i = 0; i < op0->type->length; i++) {
         ir_rvalue *e0, *e1, *result;
 
@@ -784,22 +780,19 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
                                                new(mem_ctx) ir_constant(i));
         result = do_comparison(mem_ctx, operation, e0, e1);
 
-        if (last) {
-           last = new(mem_ctx) ir_expression(join_op, last, result);
+        if (cmp) {
+           cmp = new(mem_ctx) ir_expression(join_op, cmp, result);
         } else {
-           last = result;
+           cmp = result;
         }
       }
 
       mark_whole_array_access(op0);
       mark_whole_array_access(op1);
-
-      return last;
+      break;
    }
 
    case GLSL_TYPE_STRUCT: {
-      ir_rvalue *last = NULL;
-
       for (unsigned int i = 0; i < op0->type->length; i++) {
         ir_rvalue *e0, *e1, *result;
         const char *field_name = op0->type->fields.structure[i].name;
@@ -810,13 +803,13 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
                                                 field_name);
         result = do_comparison(mem_ctx, operation, e0, e1);
 
-        if (last) {
-           last = new(mem_ctx) ir_expression(join_op, last, result);
+        if (cmp) {
+           cmp = new(mem_ctx) ir_expression(join_op, cmp, result);
         } else {
-           last = result;
+           cmp = result;
         }
       }
-      return last;
+      break;
    }
 
    case GLSL_TYPE_ERROR:
@@ -825,10 +818,17 @@ do_comparison(void *mem_ctx, int operation, ir_rvalue *op0, ir_rvalue *op1)
       /* I assume a comparison of a struct containing a sampler just
        * ignores the sampler present in the type.
        */
-      return new(mem_ctx) ir_constant(true);
+      break;
+
+   default:
+      assert(!"Should not get here.");
+      break;
    }
 
-   return NULL;
+   if (cmp == NULL)
+      cmp = new(mem_ctx) ir_constant(true);
+
+   return cmp;
 }
 
 ir_rvalue *
@@ -1029,7 +1029,7 @@ ast_expression::hir(exec_list *instructions,
       result = do_comparison(ctx, operations[this->oper], op[0], op[1]);
       type = glsl_type::bool_type;
 
-      assert(result->type == glsl_type::bool_type);
+      assert(error_emitted || (result->type == glsl_type::bool_type));
       break;
 
    case ast_bit_and:
@@ -1564,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;
 
@@ -1589,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",
@@ -1763,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
@@ -1818,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)
@@ -1897,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;
    }
@@ -1954,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;
         }
@@ -2023,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. */
       }
@@ -2144,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
@@ -2227,10 +2360,37 @@ ast_declarator_list::hir(exec_list *instructions,
 
            /* Never emit code to initialize a uniform.
             */
-           if (!this->type->qualifier.flags.q.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
+            *
+            *     uniform float a[] = float[](1.0, 2.0, 3.0, 3.0);
+            *
+            * becomes
+            *
+            *     uniform float a[4] = float[](1.0, 2.0, 3.0, 3.0);
+            *
+            * The assignment generated in the if-statement (below) will also
+            * automatically handle this case for non-uniforms.
+            *
+            * 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.  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 = initializer_type;
+
            var->read_only = temp;
         }
       }
@@ -2303,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);
@@ -2477,6 +2658,27 @@ ast_parameter_declarator::parameters_to_hir(exec_list *ast_parameters,
 }
 
 
+void
+emit_function(_mesa_glsl_parse_state *state, exec_list *instructions,
+             ir_function *f)
+{
+   /* Emit the new function header */
+   if (state->current_function == NULL) {
+      instructions->push_tail(f);
+   } else {
+      /* IR invariants disallow function declarations or definitions nested
+       * within other function definitions.  Insert the new ir_function
+       * block in the instruction sequence before the ir_function block
+       * containing the current ir_function_signature.
+       */
+      ir_function *const curr =
+        const_cast<ir_function *>(state->current_function->function());
+
+      curr->insert_before(f);
+   }
+}
+
+
 ir_rvalue *
 ast_function::hir(exec_list *instructions,
                  struct _mesa_glsl_parse_state *state)
@@ -2588,24 +2790,7 @@ ast_function::hir(exec_list *instructions,
         return NULL;
       }
 
-      /* Emit the new function header */
-      if (state->current_function == NULL)
-        instructions->push_tail(f);
-      else {
-        /* IR invariants disallow function declarations or definitions nested
-         * within other function definitions.  Insert the new ir_function
-         * block in the instruction sequence before the ir_function block
-         * containing the current ir_function_signature.
-         *
-         * This can only happen in a GLSL 1.10 shader.  In all other GLSL
-         * versions this nesting is disallowed.  There is a check for this at
-         * the top of this function.
-         */
-        ir_function *const curr =
-           const_cast<ir_function *>(state->current_function->function());
-
-        curr->insert_before(f);
-      }
+      emit_function(state, instructions, f);
    }
 
    /* Verify the return type of main() */