On Wed, Jan 15, 2014 at 10:27 PM, Timothy Arceri <t_arc...@yahoo.com.au> wrote: > Signed-off-by: Timothy Arceri <t_arc...@yahoo.com.au> > --- > src/glsl/ast.h | 45 +++++++---- > src/glsl/ast_array_index.cpp | 13 +++ > src/glsl/ast_to_hir.cpp | 173 > +++++++++++++++++++++++++++------------- > src/glsl/ast_type.cpp | 8 +- > src/glsl/glsl_parser_extras.cpp | 30 +++---- > src/glsl/glsl_parser_extras.h | 2 + > 6 files changed, 179 insertions(+), 92 deletions(-) > > diff --git a/src/glsl/ast.h b/src/glsl/ast.h > index 76911f0..bbae9cd 100644 > --- a/src/glsl/ast.h > +++ b/src/glsl/ast.h > @@ -276,6 +276,21 @@ private: > bool cons; > }; > > +class ast_array_specifier : public ast_node { > +public: > + ast_array_specifier() > + : ast_node() > + { > + dimension_count = 1; > + } > + > + virtual void print(void) const; > + > + unsigned dimension_count; > + bool is_unsized_array; > + exec_list array_dimensions; > +}; > + > /** > * C-style aggregate initialization class > * > @@ -325,14 +340,15 @@ public: > > class ast_declaration : public ast_node { > public: > - ast_declaration(const char *identifier, bool is_array, ast_expression > *array_size, > - ast_expression *initializer); > + ast_declaration(const char *identifier, bool is_array, > + ast_array_specifier *array_specifier, > + ast_expression *initializer); > virtual void print(void) const; > > const char *identifier; > > bool is_array; > - ast_expression *array_size; > + ast_array_specifier *array_specifier; > > ast_expression *initializer; > }; > @@ -531,7 +547,6 @@ public: > }; > > > - > class ast_type_specifier : public ast_node { > public: > /** > @@ -542,9 +557,9 @@ public: > * be modified. Zeros the inherited ast_node's fields. > */ > ast_type_specifier(const ast_type_specifier *that, bool is_array, > - ast_expression *array_size) > + ast_array_specifier *array_specifier) > : ast_node(), type_name(that->type_name), structure(that->structure), > - is_array(is_array), array_size(array_size), > + is_array(is_array), array_specifier(array_specifier), > default_precision(that->default_precision) > { > /* empty */ > @@ -553,7 +568,7 @@ public: > /** Construct a type specifier from a type name */ > ast_type_specifier(const char *name) > : type_name(name), structure(NULL), > - is_array(false), array_size(NULL), > + is_array(false), array_specifier(NULL), > default_precision(ast_precision_none) > { > /* empty */ > @@ -562,7 +577,7 @@ public: > /** Construct a type specifier from a structure definition */ > ast_type_specifier(ast_struct_specifier *s) > : type_name(s->name), structure(s), > - is_array(false), array_size(NULL), > + is_array(false), array_specifier(NULL), > default_precision(ast_precision_none) > { > /* empty */ > @@ -580,7 +595,7 @@ public: > ast_struct_specifier *structure; > > bool is_array; > - ast_expression *array_size; > + ast_array_specifier *array_specifier; > > /** For precision statements, this is the given precision; otherwise > none. */ > unsigned default_precision:2; > @@ -634,7 +649,7 @@ public: > type(NULL), > identifier(NULL), > is_array(false), > - array_size(NULL), > + array_specifier(NULL), > formal_parameter(false), > is_void(false) > { > @@ -649,7 +664,7 @@ public: > ast_fully_specified_type *type; > const char *identifier; > bool is_array; > - ast_expression *array_size; > + ast_array_specifier *array_specifier; > > static void parameters_to_hir(exec_list *ast_parameters, > bool formal, exec_list *ir_parameters, > @@ -897,12 +912,12 @@ public: > ast_interface_block(ast_type_qualifier layout, > const char *instance_name, > bool is_array, > - ast_expression *array_size) > + ast_array_specifier *array_specifier) > : layout(layout), block_name(NULL), instance_name(instance_name), > - is_array(is_array), array_size(array_size) > + is_array(is_array), array_specifier(array_specifier) > { > if (!is_array) > - assert(array_size == NULL); > + assert(array_specifier == NULL); > } > > virtual ir_rvalue *hir(exec_list *instructions, > @@ -937,7 +952,7 @@ public: > * If the block is not declared as an array or if the block instance array > * is unsized, this field will be \c NULL. > */ > - ast_expression *array_size; > + ast_array_specifier *array_specifier; > }; > > > diff --git a/src/glsl/ast_array_index.cpp b/src/glsl/ast_array_index.cpp > index a5f2320..f3b060e 100644 > --- a/src/glsl/ast_array_index.cpp > +++ b/src/glsl/ast_array_index.cpp > @@ -25,6 +25,19 @@ > #include "glsl_types.h" > #include "ir.h" > > +void > +ast_array_specifier::print(void) const > +{ > + if (this->is_unsized_array) { > + printf("[ ] "); > + } > + > + foreach_list_typed (ast_node, array_dimension, link, > &this->array_dimensions) { > + printf("[ "); > + array_dimension->print(); > + printf("] "); > + } > +} > > /** > * If \c ir is a reference to an array for which we are tracking the max > array > diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp > index 4cc8eb1..c0e3443 100644 > --- a/src/glsl/ast_to_hir.cpp > +++ b/src/glsl/ast_to_hir.cpp > @@ -1771,67 +1771,131 @@ ast_compound_statement::hir(exec_list *instructions, > return NULL; > } > > +static const unsigned > +process_array_size(exec_node *node, > + struct _mesa_glsl_parse_state *state) > +{ > + int result = 0; > + exec_list dummy_instructions; > + > + ast_node *array_size = exec_node_data(ast_node, node, link); > + ir_rvalue *const ir = array_size->hir(& dummy_instructions, > + state); > + YYLTYPE loc = array_size->get_location(); > + > + if (ir != NULL) { > + if (!ir->type->is_integer()) { > + _mesa_glsl_error(& loc, state, > + "array size must be integer type"); > + } else if (!ir->type->is_scalar()) { > + _mesa_glsl_error(& loc, state, > + "array size must be scalar type"); > + } else { > + ir_constant *const size = ir->constant_expression_value(); > + > + if (size == NULL) { > + _mesa_glsl_error(& loc, state, "array size must be a " > + "constant valued expression"); > + } else if (size->value.i[0] <= 0) { > + _mesa_glsl_error(& loc, state, "array size must be > 0"); > + } else { > + assert(size->type == ir->type); > + result = size->value.u[0]; > + > + /* If the array size is const (and we've verified that > + * it is) then no instructions should have been emitted > + * when we converted it to HIR. If they were emitted, > + * then either the array size isn't const after all, or > + * we are emitting unnecessary instructions. > + */ > + assert(dummy_instructions.is_empty()); > + } > + } > + } > + return result; > +} > > static const glsl_type * > -process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, > - struct _mesa_glsl_parse_state *state) > +process_array_type(YYLTYPE *loc, const glsl_type *base, > + ast_array_specifier *array_specifier, > + struct _mesa_glsl_parse_state *state) > { > - unsigned length = 0; > + const glsl_type *array_type = NULL; > + const glsl_type *element_type = base; > + const glsl_type *array_type_temp = element_type; > + > + unsigned outer_dimension_count = 0; > + unsigned dimension_count = 1; > > if (base == NULL) > return glsl_type::error_type; > > - /* From page 19 (page 25) of the GLSL 1.20 spec: > - * > - * "Only one-dimensional arrays may be declared." > - */ > if (base->is_array()) { > - _mesa_glsl_error(loc, state, > - "invalid array of `%s' (only one-dimensional arrays " > - "may be declared)", > - base->name); > - return glsl_type::error_type; > + > + /* From page 19 (page 25) of the GLSL 1.20 spec: > + * > + * "Only one-dimensional arrays may be declared." > + */ > + if (!state->ARB_arrays_of_arrays_enable) { > + _mesa_glsl_error(loc, state, > + "invalid array of `%s'" > + "#version 120 / GL_ARB_arrays_of_arrays " > + "required for defining arrays of arrays", > + base->name); > + return glsl_type::error_type; > + } > + > + if (base->length == 0) { > + _mesa_glsl_error(loc, state, > + "only the outermost array dimension can " > + "be unsized", > + base->name); > + return glsl_type::error_type; > + } > + > + /* Settings these variables will cause > + * any array dimensions processed with the base type to > + * be appended onto the end of the array > + */ > + outer_dimension_count = base->dimension_count; > + dimension_count = base->dimension_count + 1; > + element_type = base->element_type(); > } > > - if (array_size != NULL) { > - exec_list dummy_instructions; > - ir_rvalue *const ir = array_size->hir(& dummy_instructions, state); > - YYLTYPE loc = array_size->get_location(); > + if (array_specifier != NULL) { > > - if (ir != NULL) { > - if (!ir->type->is_integer()) { > - _mesa_glsl_error(& loc, state, "array size must be integer type"); > - } else if (!ir->type->is_scalar()) { > - _mesa_glsl_error(& loc, state, "array size must be scalar type"); > - } else { > - ir_constant *const size = ir->constant_expression_value(); > - > - if (size == NULL) { > - _mesa_glsl_error(& loc, state, "array size must be a " > - "constant valued expression"); > - } else if (size->value.i[0] <= 0) { > - _mesa_glsl_error(& loc, state, "array size must be > 0"); > - } else { > - assert(size->type == ir->type); > - length = size->value.u[0]; > - > - /* If the array size is const (and we've verified that > - * it is) then no instructions should have been emitted > - * when we converted it to HIR. If they were emitted, > - * then either the array size isn't const after all, or > - * we are emitting unnecessary instructions. > - */ > - assert(dummy_instructions.is_empty()); > - } > - } > + exec_node *node = array_specifier->array_dimensions.tail_pred; > + outer_dimension_count += array_specifier->dimension_count; > + > + unsigned array_size; > + for (/* nothing */; !node->is_head_sentinel(); node = node->prev) { > + array_size = process_array_size(node, state); > + array_type_temp = glsl_type::get_array_instance(array_type_temp, > + array_size, > + dimension_count); > + dimension_count++; > + } > + > + if (array_specifier->is_unsized_array) { > + array_type_temp = glsl_type::get_array_instance(array_type_temp, > + 0, > + dimension_count); > + } > + > + if (array_type_temp == element_type) { > + /* we found no array sizes */ > + array_type = NULL; > + } else { > + array_type = array_type_temp; > } > } > > - const glsl_type *array_type = glsl_type::get_array_instance(base, length); > + /* make sure the ast count and the current count match */ > + assert(dimension_count == outer_dimension_count); > + > return array_type != NULL ? array_type : glsl_type::error_type; > } > > - > const glsl_type * > ast_type_specifier::glsl_type(const char **name, > struct _mesa_glsl_parse_state *state) const > @@ -1843,7 +1907,7 @@ ast_type_specifier::glsl_type(const char **name, > > if (this->is_array) { > YYLTYPE loc = this->get_location(); > - type = process_array_type(&loc, type, this->array_size, state); > + type = process_array_type(&loc, type, this->array_specifier, state); > } > > return type; > @@ -2824,7 +2888,7 @@ ast_declarator_list::hir(exec_list *instructions, > > foreach_list_typed (ast_declaration, decl, link, &this->declarations) { > assert(!decl->is_array); > - assert(decl->array_size == NULL); > + assert(decl->array_specifier == NULL); > assert(decl->initializer == NULL); > > ir_variable *const earlier = > @@ -2960,7 +3024,7 @@ ast_declarator_list::hir(exec_list *instructions, > } > > if (decl->is_array) { > - var_type = process_array_type(&loc, decl_type, decl->array_size, > + var_type = process_array_type(&loc, decl_type, decl->array_specifier, > state); > if (var_type->is_error()) > continue; > @@ -3524,7 +3588,7 @@ ast_parameter_declarator::hir(exec_list *instructions, > * call already handled the "vec4[..] foo" case. > */ > if (this->is_array) { > - type = process_array_type(&loc, type, this->array_size, state); > + type = process_array_type(&loc, type, this->array_specifier, state); > } > > if (!type->is_error() && type->is_unsized_array()) { > @@ -4654,8 +4718,8 @@ ast_process_structure_or_interface_block(exec_list > *instructions, > } > > if (decl->is_array) { > - field_type = process_array_type(&loc, decl_type, decl->array_size, > - state); > + field_type = process_array_type(&loc, decl_type, > + decl->array_specifier, state); > } > fields[i].type = field_type; > fields[i].name = decl->identifier; > @@ -5019,6 +5083,10 @@ ast_interface_block::hir(exec_list *instructions, > ir_variable *var; > > if (this->is_array) { > + > + const glsl_type *block_array_type = > + process_array_type(&loc, block_type, this->array_specifier, > state); > + > /* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says: > * > * For uniform blocks declared an array, each individual array > @@ -5038,7 +5106,7 @@ ast_interface_block::hir(exec_list *instructions, > * interface array size *doesn't* need to be specified is on a > * geometry shader input. > */ > - if (this->array_size == NULL && > + if (block_array_type->is_unsized_array() && > (state->stage != MESA_SHADER_GEOMETRY || > !this->layout.flags.q.in)) { > _mesa_glsl_error(&loc, state, > "only geometry shader inputs may be unsized " > @@ -5046,9 +5114,6 @@ ast_interface_block::hir(exec_list *instructions, > > } > > - const glsl_type *block_array_type = > - process_array_type(&loc, block_type, this->array_size, state); > - > var = new(state) ir_variable(block_array_type, > this->instance_name, > var_mode); > diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp > index d758bfa..ac48597 100644 > --- a/src/glsl/ast_type.cpp > +++ b/src/glsl/ast_type.cpp > @@ -33,13 +33,9 @@ ast_type_specifier::print(void) const > } > > if (is_array) { > - printf("[ "); > - > - if (array_size) { > - array_size->print(); > + if (array_specifier) { > + array_specifier->print(); > } > - > - printf("] "); > } > } > > diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp > index 21dc3ab..92076b5 100644 > --- a/src/glsl/glsl_parser_extras.cpp > +++ b/src/glsl/glsl_parser_extras.cpp > @@ -484,6 +484,7 @@ struct _mesa_glsl_extension { > static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { > /* API availability */ > /* name GL ES supported flag */ > + EXT(ARB_arrays_of_arrays, true, false, > ARB_arrays_of_arrays), > EXT(ARB_conservative_depth, true, false, > ARB_conservative_depth), > EXT(ARB_draw_buffers, true, false, dummy_true), > EXT(ARB_draw_instanced, true, false, ARB_draw_instanced), > @@ -769,7 +770,7 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier > *type, > link); > > bool is_array = decl_list->type->specifier->is_array; > - ast_expression *array_size = > decl_list->type->specifier->array_size; > + ast_array_specifier *array_specifier = > decl_list->type->specifier->array_specifier; > > /* Recognize variable declarations with the bracketed size > attached > * to the type rather than the variable name as arrays. E.g., > @@ -777,19 +778,18 @@ _mesa_ast_set_aggregate_type(const ast_type_specifier > *type, > * float a[2]; > * float[2] b; > * > - * are both arrays, but <a>'s array_size is decl->array_size, > while > - * <b>'s array_size is decl_list->type->specifier->array_size. > + * are both arrays, but <a>'s array_specifier is > decl->array_specifier, while > + * <b>'s array_specifier is > decl_list->type->specifier->array_specifier. > */ > if (!is_array) { > - /* FINISHME: Update when ARB_array_of_arrays is supported. */
There's another identical FINISHME in this function that I don't see in this patch. > is_array = decl->is_array; > - array_size = decl->array_size; > + array_specifier = decl->array_specifier; > } I don't think this is going to work for float[2] a[3] will it? is_array will be true, but the whole array_specifier won't be complete. > > /* Declaration shadows the <type> parameter. */ > ast_type_specifier *type = > new(ctx) ast_type_specifier(decl_list->type->specifier, > - is_array, array_size); > + is_array, array_specifier); > > if (expr->oper == ast_aggregate) > _mesa_ast_set_aggregate_type(type, expr, state); > @@ -876,15 +876,11 @@ ast_node::ast_node(void) > > > static void > -ast_opt_array_size_print(bool is_array, const ast_expression *array_size) > +ast_opt_array_dimensions_print(bool is_array, const ast_array_specifier > *array_specifier) > { > if (is_array) { > - printf("[ "); > - > - if (array_size) > - array_size->print(); > - > - printf("] "); > + if (array_specifier) > + array_specifier->print(); > } > } > > @@ -1108,7 +1104,7 @@ ast_parameter_declarator::print(void) const > type->print(); > if (identifier) > printf("%s ", identifier); > - ast_opt_array_size_print(is_array, array_size); > + ast_opt_array_dimensions_print(is_array, array_specifier); > } > > > @@ -1124,7 +1120,7 @@ void > ast_declaration::print(void) const > { > printf("%s ", identifier); > - ast_opt_array_size_print(is_array, array_size); > + ast_opt_array_dimensions_print(is_array, array_specifier); > > if (initializer) { > printf("= "); > @@ -1134,12 +1130,12 @@ ast_declaration::print(void) const > > > ast_declaration::ast_declaration(const char *identifier, bool is_array, > - ast_expression *array_size, > + ast_array_specifier *array_specifier, > ast_expression *initializer) > { > this->identifier = identifier; > this->is_array = is_array; > - this->array_size = array_size; > + this->array_specifier = array_specifier; > this->initializer = initializer; > } > > diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h > index 2444a96..1478f00 100644 > --- a/src/glsl/glsl_parser_extras.h > +++ b/src/glsl/glsl_parser_extras.h > @@ -294,6 +294,8 @@ struct _mesa_glsl_parse_state { > * \name Enable bits for GLSL extensions > */ > /*@{*/ > + bool ARB_arrays_of_arrays_enable; > + bool ARB_arrays_of_arrays_warn; > bool ARB_draw_buffers_enable; > bool ARB_draw_buffers_warn; > bool ARB_draw_instanced_enable; > -- > 1.8.3.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev