glsl: fix uniform remap table cache when explicit locations used
[mesa.git] / src / compiler / glsl / ast_array_index.cpp
index 2e36035f9f427218cda4f1b7ac0d020aab232094..dfa44b703d42a71ed4c625dfbbf2842b910a2de1 100644 (file)
@@ -141,24 +141,24 @@ get_implicit_array_size(struct _mesa_glsl_parse_state *state,
 
 ir_rvalue *
 _mesa_ast_array_index_to_hir(void *mem_ctx,
-                            struct _mesa_glsl_parse_state *state,
-                            ir_rvalue *array, ir_rvalue *idx,
-                            YYLTYPE &loc, YYLTYPE &idx_loc)
+                             struct _mesa_glsl_parse_state *state,
+                             ir_rvalue *array, ir_rvalue *idx,
+                             YYLTYPE &loc, YYLTYPE &idx_loc)
 {
    if (!array->type->is_error()
        && !array->type->is_array()
        && !array->type->is_matrix()
        && !array->type->is_vector()) {
       _mesa_glsl_error(& idx_loc, state,
-                      "cannot dereference non-array / non-matrix / "
-                      "non-vector");
+                       "cannot dereference non-array / non-matrix / "
+                       "non-vector");
    }
 
    if (!idx->type->is_error()) {
       if (!idx->type->is_integer()) {
-        _mesa_glsl_error(& idx_loc, state, "array index must be integer type");
+         _mesa_glsl_error(& idx_loc, state, "array index must be integer type");
       } else if (!idx->type->is_scalar()) {
-        _mesa_glsl_error(& idx_loc, state, "array index must be scalar");
+         _mesa_glsl_error(& idx_loc, state, "array index must be scalar");
       }
    }
 
@@ -182,33 +182,32 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
        *    negative constant expression."
        */
       if (array->type->is_matrix()) {
-        if (array->type->row_type()->vector_elements <= idx) {
-           type_name = "matrix";
-           bound = array->type->row_type()->vector_elements;
-        }
+         if (array->type->row_type()->vector_elements <= idx) {
+            type_name = "matrix";
+            bound = array->type->row_type()->vector_elements;
+         }
       } else if (array->type->is_vector()) {
-        if (array->type->vector_elements <= idx) {
-           type_name = "vector";
-           bound = array->type->vector_elements;
-        }
+         if (array->type->vector_elements <= idx) {
+            type_name = "vector";
+            bound = array->type->vector_elements;
+         }
       } else {
-        /* glsl_type::array_size() returns -1 for non-array types.  This means
-         * that we don't need to verify that the type is an array before
-         * doing the bounds checking.
-         */
-        if ((array->type->array_size() > 0)
-            && (array->type->array_size() <= idx)) {
-           type_name = "array";
-           bound = array->type->array_size();
-        }
+         /* glsl_type::array_size() returns -1 for non-array types.  This means
+          * that we don't need to verify that the type is an array before
+          * doing the bounds checking.
+          */
+         if ((array->type->array_size() > 0)
+             && (array->type->array_size() <= idx)) {
+            type_name = "array";
+            bound = array->type->array_size();
+         }
       }
 
       if (bound > 0) {
-        _mesa_glsl_error(& loc, state, "%s index must be < %u",
-                         type_name, bound);
+         _mesa_glsl_error(& loc, state, "%s index must be < %u",
+                          type_name, bound);
       } else if (idx < 0) {
-        _mesa_glsl_error(& loc, state, "%s index must be >= 0",
-                         type_name);
+         _mesa_glsl_error(& loc, state, "%s index must be >= 0", type_name);
       }
 
       if (array->type->is_array())
@@ -234,6 +233,20 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
          else if (array->variable_referenced()->data.mode !=
                   ir_var_shader_storage) {
             _mesa_glsl_error(&loc, state, "unsized array index must be constant");
+         } else {
+            /* Unsized array non-constant indexing on SSBO is allowed only for
+             * the last member of the SSBO definition.
+             */
+            ir_variable *var = array->variable_referenced();
+            const glsl_type *iface_type = var->get_interface_type();
+            int field_index = iface_type->field_index(var->name);
+            /* Field index can be < 0 for instance arrays */
+            if (field_index >= 0 &&
+                field_index != (int) iface_type->length - 1) {
+               _mesa_glsl_error(&loc, state, "Indirect access on unsized "
+                                "array is limited to the last member of "
+                                "SSBO.");
+            }
          }
       } else if (array->type->without_array()->is_interface()
                  && ((array->variable_referenced()->data.mode == ir_var_uniform
@@ -253,18 +266,18 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
           * on uniform blocks but not shader storage blocks.
           *
           */
-        _mesa_glsl_error(&loc, state, "%s block array index must be constant",
+         _mesa_glsl_error(&loc, state, "%s block array index must be constant",
                           array->variable_referenced()->data.mode
                           == ir_var_uniform ? "uniform" : "shader storage");
       } else {
-        /* whole_variable_referenced can return NULL if the array is a
-         * member of a structure.  In this case it is safe to not update
-         * the max_array_access field because it is never used for fields
-         * of structures.
-         */
-        ir_variable *v = array->whole_variable_referenced();
-        if (v != NULL)
-           v->data.max_array_access = array->type->array_size() - 1;
+         /* whole_variable_referenced can return NULL if the array is a
+          * member of a structure.  In this case it is safe to not update
+          * the max_array_access field because it is never used for fields
+          * of structures.
+          */
+         ir_variable *v = array->whole_variable_referenced();
+         if (v != NULL)
+            v->data.max_array_access = array->type->array_size() - 1;
       }
 
       /* From page 23 (29 of the PDF) of the GLSL 1.30 spec: