glsl: Fix handling of function calls inside nested loops.
[mesa.git] / src / glsl / ast_to_hir.cpp
index d30463aa61367e7cc5ba577eb8118294aa9f8a50..f35d8679e70e0d7414f48c586b55f4369f1ea6b4 100644 (file)
@@ -696,9 +696,15 @@ validate_assignment(struct _mesa_glsl_parse_state *state,
     * Note: Whole-array assignments are not permitted in GLSL 1.10, but this
     * is handled by ir_dereference::is_lvalue.
     */
-   if (is_initializer && lhs_type->is_unsized_array() && rhs->type->is_array()
+   if (lhs_type->is_unsized_array() && rhs->type->is_array()
        && (lhs_type->element_type() == rhs->type->element_type())) {
-      return rhs;
+      if (is_initializer) {
+         return rhs;
+      } else {
+         _mesa_glsl_error(&loc, state,
+                          "implicitly sized arrays cannot be assigned");
+         return NULL;
+      }
    }
 
    /* Check for implicit conversion in GLSL 1.20 */
@@ -1995,12 +2001,22 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state,
                           "exceeds the maximum number of texture image units "
                           "(%d)", qual->binding, elements, limit);
 
+         return false;
+      }
+   } else if (var->type->contains_atomic()) {
+      assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS);
+      if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) {
+         _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the "
+                          " maximum number of atomic counter buffer bindings"
+                          "(%d)", qual->binding,
+                          ctx->Const.MaxAtomicBufferBindings);
+
          return false;
       }
    } else {
       _mesa_glsl_error(loc, state,
                        "the \"binding\" qualifier only applies to uniform "
-                       "blocks, samplers, or arrays of samplers");
+                       "blocks, samplers, atomic counters, or arrays thereof");
       return false;
    }
 
@@ -2053,7 +2069,6 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
                            YYLTYPE *loc)
 {
    bool fail = false;
-   const char *string = "";
 
    /* In the vertex shader only shader inputs can be given explicit
     * locations.
@@ -2063,10 +2078,14 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
     */
    switch (state->target) {
    case vertex_shader:
-      if (var->mode != ir_var_shader_in) {
-         fail = true;
-         string = "input";
+      if (var->mode == ir_var_shader_in) {
+         if (!state->check_explicit_attrib_location_allowed(loc, var))
+            return;
+
+         break;
       }
+
+      fail = true;
       break;
 
    case geometry_shader:
@@ -2076,19 +2095,22 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
       return;
 
    case fragment_shader:
-      if (var->mode != ir_var_shader_out) {
-         fail = true;
-         string = "output";
+      if (var->mode == ir_var_shader_out) {
+         if (!state->check_explicit_attrib_location_allowed(loc, var))
+            return;
+
+         break;
       }
+
+      fail = true;
       break;
    };
 
    if (fail) {
       _mesa_glsl_error(loc, state,
-                       "only %s shader %s variables can be given an "
-                       "explicit location",
-                       _mesa_glsl_shader_target_name(state->target),
-                       string);
+                       "%s cannot be given an explicit location in %s shader",
+                       mode_string(var),
+                      _mesa_glsl_shader_target_name(state->target));
    } else {
       var->explicit_location = true;
 
@@ -2126,6 +2148,8 @@ validate_explicit_location(const struct ast_type_qualifier *qual,
          }
       }
    }
+
+   return;
 }
 
 static void
@@ -2156,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,
@@ -2292,6 +2319,29 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       var->binding = qual->binding;
    }
 
+   if (var->type->contains_atomic()) {
+      if (var->mode == ir_var_uniform) {
+         if (var->explicit_binding) {
+            unsigned *offset = &state->atomic_counter_offsets[var->binding];
+
+            if (*offset % ATOMIC_COUNTER_SIZE)
+               _mesa_glsl_error(loc, state,
+                                "misaligned atomic counter offset");
+
+            var->atomic.offset = *offset;
+            *offset += var->type->atomic_size();
+
+         } else {
+            _mesa_glsl_error(loc, state,
+                             "atomic counters require explicit binding point");
+         }
+      } else if (var->mode != ir_var_function_in) {
+         _mesa_glsl_error(loc, state, "atomic counters may only be declared as "
+                          "function parameters or uniform-qualified "
+                          "global variables");
+      }
+   }
+
    /* Does the declaration use the deprecated 'attribute' or 'varying'
     * keywords?
     */
@@ -2827,6 +2877,18 @@ ast_declarator_list::hir(exec_list *instructions,
    (void) this->type->specifier->hir(instructions, state);
 
    decl_type = this->type->glsl_type(& type_name, state);
+
+   /* An offset-qualified atomic counter declaration sets the default
+    * offset for the next declaration within the same atomic counter
+    * buffer.
+    */
+   if (decl_type && decl_type->contains_atomic()) {
+      if (type->qualifier.flags.q.explicit_binding &&
+          type->qualifier.flags.q.explicit_offset)
+         state->atomic_counter_offsets[type->qualifier.binding] =
+            type->qualifier.offset;
+   }
+
    if (this->declarations.is_empty()) {
       /* If there is no structure involved in the program text, there are two
        * possible scenarios:
@@ -2856,6 +2918,11 @@ ast_declarator_list::hir(exec_list *instructions,
          _mesa_glsl_error(&loc, state,
                           "invalid type `%s' in empty declaration",
                           type_name);
+      } else if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) {
+         /* Empty atomic counter declarations are allowed and useful
+          * to set the default offset qualifier.
+          */
+         return NULL;
       } else if (this->type->qualifier.precision != ast_precision_none) {
          if (this->type->specifier->structure != NULL) {
             _mesa_glsl_error(&loc, state,
@@ -2876,7 +2943,7 @@ ast_declarator_list::hir(exec_list *instructions,
                                precision_names[this->type->qualifier.precision],
                                type_name);
          }
-      } else {
+      } else if (this->type->specifier->structure == NULL) {
          _mesa_glsl_warning(&loc, state, "empty declaration");
       }
    }
@@ -3213,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."
        *
@@ -3297,6 +3372,15 @@ ast_declarator_list::hir(exec_list *instructions,
       ir_variable *earlier =
          get_variable_being_redeclared(var, decl->get_location(), state,
                                        false /* allow_all_redeclarations */);
+      if (earlier != NULL) {
+         if (strncmp(var->name, "gl_", 3) == 0 &&
+             earlier->how_declared == ir_var_declared_in_block) {
+            _mesa_glsl_error(&loc, state,
+                             "`%s' has already been redeclared using "
+                             "gl_PerVertex", var->name);
+         }
+         earlier->how_declared = ir_var_declared_normally;
+      }
 
       if (decl->initializer != NULL) {
         result = process_initializer((earlier == NULL) ? var : earlier,
@@ -4557,6 +4641,17 @@ ast_process_structure_or_interface_block(exec_list *instructions,
                              "uniform in non-default uniform block contains sampler");
          }
 
+         if (field_type->contains_atomic()) {
+            /* FINISHME: Add a spec quotation here once updated spec
+             * FINISHME: language is available.  See Khronos bug #10903
+             * FINISHME: on whether atomic counters are allowed in
+             * FINISHME: structures.
+             */
+            YYLTYPE loc = decl_list->get_location();
+            _mesa_glsl_error(&loc, state, "atomic counter in structure or "
+                             "uniform block");
+         }
+
          const struct ast_type_qualifier *const qual =
             & decl_list->type->qualifier;
          if (qual->flags.q.std140 ||
@@ -4578,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) {
@@ -4846,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;
          }
       }
 
@@ -4979,6 +5077,7 @@ ast_interface_block::hir(exec_list *instructions,
             _mesa_glsl_error(&loc, state, "`%s' redeclared",
                              this->instance_name);
          }
+         earlier->how_declared = ir_var_declared_normally;
          earlier->type = var->type;
          earlier->reinit_interface_type(block_type);
          delete var;
@@ -4999,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) {
@@ -5009,7 +5109,11 @@ ast_interface_block::hir(exec_list *instructions,
                _mesa_glsl_error(&loc, state,
                                 "redeclaration of gl_PerVertex can only "
                                 "include built-in variables");
+            } else if (earlier->how_declared == ir_var_declared_normally) {
+               _mesa_glsl_error(&loc, state,
+                                "`%s' has already been redeclared", var->name);
             } else {
+               earlier->how_declared = ir_var_declared_in_block;
                earlier->reinit_interface_type(block_type);
             }
             continue;
@@ -5056,6 +5160,12 @@ ast_interface_block::hir(exec_list *instructions,
             if (var != NULL &&
                 var->get_interface_type() == earlier_per_vertex &&
                 var->mode == var_mode) {
+               if (var->how_declared == ir_var_declared_normally) {
+                  _mesa_glsl_error(&loc, state,
+                                   "redeclaration of gl_PerVertex cannot "
+                                   "follow a redeclaration of `%s'",
+                                   var->name);
+               }
                state->symbols->disable_variable(var->name);
                var->remove();
             }