From: Eric Anholt Date: Mon, 23 Aug 2010 17:32:01 +0000 (-0700) Subject: glsl: Trim the size of uniform arrays to the maximum element used. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a721abfbd1724e83381b46fc670bb38fbde76f69;p=mesa.git glsl: Trim the size of uniform arrays to the maximum element used. Fixes glsl-getactiveuniform-array-size. --- diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index b60bb2f0a0a..8e4c3299aa6 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -1258,6 +1258,11 @@ ast_expression::hir(exec_list *instructions, } } else if (array->type->array_size() == 0) { _mesa_glsl_error(&loc, state, "unsized array index must be constant"); + } else { + if (array->type->is_array()) { + ir_variable *v = array->whole_variable_referenced(); + v->max_array_access = array->type->array_size(); + } } if (error_emitted) diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 2dc569777e7..deb30d7fecf 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -809,6 +809,56 @@ struct uniform_node { unsigned slots; }; +/** + * Update the sizes of linked shader uniform arrays to the maximum + * array index used. + * + * From page 81 (page 95 of the PDF) of the OpenGL 2.1 spec: + * + * If one or more elements of an array are active, + * GetActiveUniform will return the name of the array in name, + * subject to the restrictions listed above. The type of the array + * is returned in type. The size parameter contains the highest + * array element index used, plus one. The compiler or linker + * determines the highest index used. There will be only one + * active uniform reported by the GL per uniform array. + + */ +static void +update_uniform_array_sizes(struct gl_shader_program *prog) +{ + for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { + foreach_list(node, prog->_LinkedShaders[i]->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if ((var == NULL) || (var->mode != ir_var_uniform) || + !var->type->is_array()) + continue; + + unsigned int size = var->max_array_access; + for (unsigned j = 0; j < prog->_NumLinkedShaders; j++) { + foreach_list(node2, prog->_LinkedShaders[j]->ir) { + ir_variable *other_var = ((ir_instruction *) node2)->as_variable(); + if (!other_var) + continue; + + if (strcmp(var->name, other_var->name) == 0 && + other_var->max_array_access > size) { + size = other_var->max_array_access; + } + } + } + if (size + 1 != var->type->fields.array->length) { + var->type = glsl_type::get_array_instance(var->type->fields.array, + size + 1); + /* FINISHME: We should update the types of array + * dereferences of this variable now. + */ + } + } + } +} + void assign_uniform_locations(struct gl_shader_program *prog) { @@ -818,6 +868,8 @@ assign_uniform_locations(struct gl_shader_program *prog) hash_table *ht = hash_table_ctor(32, hash_table_string_hash, hash_table_string_compare); + update_uniform_array_sizes(prog); + for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) { unsigned next_position = 0;