nir: Use a single list for all shader variables
[mesa.git] / src / compiler / glsl / ast_array_index.cpp
index f5baeb9ea32fad96bf093369c19afee1c5aab0a0..ea305b54701c6d9156336e6a56db07d72310e5b6 100644 (file)
@@ -88,23 +88,23 @@ update_max_array_access(ir_rvalue *ir, int idx, YYLTYPE *loc,
 
       if (deref_var != NULL) {
          if (deref_var->var->is_interface_instance()) {
-            unsigned field_index =
-               deref_record->record->type->field_index(deref_record->field);
-            assert(field_index < deref_var->var->get_interface_type()->length);
+            unsigned field_idx = deref_record->field_idx;
+            assert(field_idx < deref_var->var->get_interface_type()->length);
 
-            unsigned *const max_ifc_array_access =
+            int *const max_ifc_array_access =
                deref_var->var->get_max_ifc_array_access();
 
             assert(max_ifc_array_access != NULL);
 
-            if (idx > (int)max_ifc_array_access[field_index]) {
-               max_ifc_array_access[field_index] = idx;
+            if (idx > max_ifc_array_access[field_idx]) {
+               max_ifc_array_access[field_idx] = idx;
 
                /* Check whether this access will, as a side effect, implicitly
                 * cause the size of a built-in array to be too large.
                 */
-               check_builtin_array_max_size(deref_record->field, idx+1, *loc,
-                                            state);
+               const char *field_name =
+                  deref_record->record->type->fields.structure[field_idx].name;
+               check_builtin_array_max_size(field_name, idx+1, *loc, state);
             }
          }
       }
@@ -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");
+      if (!idx->type->is_integer_32()) {
+         _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");
       }
    }
 
@@ -167,8 +167,8 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
     * index is not a constant expression, ensure that the array has a
     * declared size.
     */
-   ir_constant *const const_index = idx->constant_expression_value();
-   if (const_index != NULL && idx->type->is_integer()) {
+   ir_constant *const const_index = idx->constant_expression_value(mem_ctx);
+   if (const_index != NULL && idx->type->is_integer_32()) {
       const int idx = const_index->value.i[0];
       const char *type_name = "error";
       unsigned bound = 0;
@@ -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,28 +233,51 @@ _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 ||
-                     array->variable_referenced()->data.mode == ir_var_shader_storage)
-                 && !state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) {
-        /* Page 50 in section 4.3.9 of the OpenGL ES 3.10 spec says:
-         *
-         *     "All indices used to index a uniform or shader storage block
-         *     array must be constant integral expressions."
-         */
-        _mesa_glsl_error(&loc, state, "%s block array index must be constant",
+                 && ((array->variable_referenced()->data.mode == ir_var_uniform
+                      && !state->is_version(400, 320)
+                      && !state->ARB_gpu_shader5_enable
+                      && !state->EXT_gpu_shader5_enable
+                      && !state->OES_gpu_shader5_enable) ||
+                     (array->variable_referenced()->data.mode == ir_var_shader_storage
+                      && !state->is_version(400, 0)
+                      && !state->ARB_gpu_shader5_enable))) {
+         /* Page 50 in section 4.3.9 of the OpenGL ES 3.10 spec says:
+          *
+          *     "All indices used to index a uniform or shader storage block
+          *     array must be constant integral expressions."
+          *
+          * But OES_gpu_shader5 (and ESSL 3.20) relax this to allow indexing
+          * on uniform blocks but not shader storage blocks.
+          *
+          */
+         _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:
@@ -277,9 +299,18 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
        * values must not diverge between shader invocations run together. If the
        * values *do* diverge, then the behavior of the operation requiring a
        * dynamically uniform expression is undefined.
+       *
+       * From section 4.1.7 of the ARB_bindless_texture spec:
+       *
+       *    "Samplers aggregated into arrays within a shader (using square
+       *    brackets []) can be indexed with arbitrary integer expressions."
        */
       if (array->type->without_array()->is_sampler()) {
-         if (!state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) {
+         if (!state->is_version(400, 320) &&
+             !state->ARB_gpu_shader5_enable &&
+             !state->EXT_gpu_shader5_enable &&
+             !state->OES_gpu_shader5_enable &&
+             !state->has_bindless()) {
             if (state->is_version(130, 300))
                _mesa_glsl_error(&loc, state,
                                 "sampler arrays indexed with non-constant "