On Thu, May 19, 2016 at 11:47 PM, Dave Airlie <airl...@gmail.com> wrote: > From: Dave Airlie <airl...@redhat.com> > > This fixes a bug that breaks cull distances. The problem > is the max array accessors can't tell the difference between > an never accessed unsized array and an accessed at location 0 > unsized array. This leads to converting an undeclared unused > gl_ClipDistance inside or outside gl_PerVertex to a size 1 > array. However we need to the number of active clip distances > to work out the starting point for the cull distances, and > this offset by one when it's not being used isn't possible > to distinguish from the case were only the first element is > accessed. I tried to use ->used for this, but that doesn't > work when gl_ClipDistance is part of an interface block. > > So this changes things so that max_array_access is an int > and initialised to -1. This also allows unsized arrays to > proceed further than that could before, but we really shouldn't > mind as they will get eliminated if nothing uses them later. > > For initialised uniforms we no longer change their array > size at runtime, if these are unused they will get eliminated > eventually. > > Signed-off-by: Dave Airlie <airl...@redhat.com> > --- > src/compiler/glsl/ast_array_index.cpp | 4 ++-- > src/compiler/glsl/ast_to_hir.cpp | 8 ++++---- > src/compiler/glsl/ir.cpp | 2 +- > src/compiler/glsl/ir.h | 15 +++++++++------ > src/compiler/glsl/ir_clone.cpp | 2 +- > src/compiler/glsl/ir_validate.cpp | 6 +++--- > src/compiler/glsl/link_functions.cpp | 4 ++-- > src/compiler/glsl/link_interface_blocks.cpp | 6 ------ > src/compiler/glsl/linker.cpp | 14 +++++++------- > src/mesa/main/ff_fragment_shader.cpp | 6 +++--- > 10 files changed, 32 insertions(+), 35 deletions(-) > > diff --git a/src/compiler/glsl/ast_array_index.cpp > b/src/compiler/glsl/ast_array_index.cpp > index 69322cf..2e36035 100644 > --- a/src/compiler/glsl/ast_array_index.cpp > +++ b/src/compiler/glsl/ast_array_index.cpp > @@ -92,12 +92,12 @@ update_max_array_access(ir_rvalue *ir, int idx, YYLTYPE > *loc, > deref_record->record->type->field_index(deref_record->field); > assert(field_index < > 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]) { > + if (idx > max_ifc_array_access[field_index]) { > max_ifc_array_access[field_index] = idx; > > /* Check whether this access will, as a side effect, > implicitly > diff --git a/src/compiler/glsl/ast_to_hir.cpp > b/src/compiler/glsl/ast_to_hir.cpp > index ecfe684..1455bdf 100644 > --- a/src/compiler/glsl/ast_to_hir.cpp > +++ b/src/compiler/glsl/ast_to_hir.cpp > @@ -976,7 +976,7 @@ do_assignment(exec_list *instructions, struct > _mesa_glsl_parse_state *state, > > assert(var != NULL); > > - if (var->data.max_array_access >= > unsigned(rhs->type->array_size())) { > + if (var->data.max_array_access >= rhs->type->array_size()) { > /* FINISHME: This should actually log the location of the RHS. */ > _mesa_glsl_error(& lhs_loc, state, "array size must be > %u due > to " > "previous access", > @@ -3858,7 +3858,7 @@ get_variable_being_redeclared(ir_variable *var, YYLTYPE > loc, > * FINISHME: required or not. > */ > > - const unsigned size = unsigned(var->type->array_size()); > + const int size = var->type->array_size(); > check_builtin_array_max_size(var->name, size, loc, state); > if ((size > 0) && (size <= earlier->data.max_array_access)) { > _mesa_glsl_error(& loc, state, "array size must be > %u due to " > @@ -7711,7 +7711,7 @@ ast_tcs_output_layout::hir(exec_list *instructions, > if (!var->type->is_unsized_array() || var->data.patch) > continue; > > - if (var->data.max_array_access >= num_vertices) { > + if (var->data.max_array_access >= (int)num_vertices) { > _mesa_glsl_error(&loc, state, > "this tessellation control shader output layout " > "specifies %u vertices, but an access to element " > @@ -7772,7 +7772,7 @@ ast_gs_input_layout::hir(exec_list *instructions, > */ > > if (var->type->is_unsized_array()) { > - if (var->data.max_array_access >= num_vertices) { > + if (var->data.max_array_access >= (int)num_vertices) { > _mesa_glsl_error(&loc, state, > "this geometry shader input layout implies %u" > " vertices, but an access to element %u of > input" > diff --git a/src/compiler/glsl/ir.cpp b/src/compiler/glsl/ir.cpp > index 9637d7a..5bb3ac3 100644 > --- a/src/compiler/glsl/ir.cpp > +++ b/src/compiler/glsl/ir.cpp > @@ -1668,7 +1668,7 @@ ir_variable::ir_variable(const struct glsl_type *type, > const char *name, > this->data.how_declared = ir_var_declared_normally; > this->data.mode = mode; > this->data.interpolation = INTERP_QUALIFIER_NONE; > - this->data.max_array_access = 0; > + this->data.max_array_access = -1; > this->data.offset = 0; > this->data.precision = GLSL_PRECISION_NONE; > this->data.image_read_only = false; > diff --git a/src/compiler/glsl/ir.h b/src/compiler/glsl/ir.h > index 6e0dc0b..4915f60 100644 > --- a/src/compiler/glsl/ir.h > +++ b/src/compiler/glsl/ir.h > @@ -484,7 +484,10 @@ public: > this->interface_type = type; > if (this->is_interface_instance()) { > this->u.max_ifc_array_access = > - rzalloc_array(this, unsigned, type->length); > + rzalloc_array(this, int, type->length);
This can just be ralloc_array now that you initialize it. Also you could do memset(-1), but that's probably a little hacky. With the change to ralloc_array, this patch is Reviewed-by: Ilia Mirkin <imir...@alum.mit.edu> BTW, I notice that you didn't update src/compiler/glsl/lower_tess_level.cpp: new_tess_level_outer_var->data.max_array_access = 0; src/compiler/glsl/lower_tess_level.cpp: new_tess_level_inner_var->data.max_array_access = 0; but that seems OK, since they end up as non-array types in the first place and that setting can probably go. > + for (unsigned i = 0; i < type->length; i++) { > + this->u.max_ifc_array_access[i] = -1; > + } > } > } > > @@ -520,7 +523,7 @@ public: > * zero. > */ > for (unsigned i = 0; i < this->interface_type->length; i++) > - assert(this->u.max_ifc_array_access[i] == 0); > + assert(this->u.max_ifc_array_access[i] == -1); > #endif > ralloc_free(this->u.max_ifc_array_access); > this->u.max_ifc_array_access = NULL; > @@ -540,7 +543,7 @@ public: > * A "set" function is not needed because the array is dynmically > allocated > * as necessary. > */ > - inline unsigned *get_max_ifc_array_access() > + inline int *get_max_ifc_array_access() > { > assert(this->data._num_state_slots == 0); > return this->u.max_ifc_array_access; > @@ -888,9 +891,9 @@ public: > /** > * Highest element accessed with a constant expression array index > * > - * Not used for non-array variables. > + * Not used for non-array variables. -1 is never accessed. > */ > - unsigned max_array_access; > + int max_array_access; > > /** > * Transform feedback buffer. > @@ -938,7 +941,7 @@ private: > * For variables whose type is not an interface block, this pointer is > * NULL. > */ > - unsigned *max_ifc_array_access; > + int *max_ifc_array_access; > > /** > * Built-in state that backs this uniform > diff --git a/src/compiler/glsl/ir_clone.cpp b/src/compiler/glsl/ir_clone.cpp > index 43ffffb..60d1526 100644 > --- a/src/compiler/glsl/ir_clone.cpp > +++ b/src/compiler/glsl/ir_clone.cpp > @@ -46,7 +46,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) > const > var->data.max_array_access = this->data.max_array_access; > if (this->is_interface_instance()) { > var->u.max_ifc_array_access = > - rzalloc_array(var, unsigned, this->interface_type->length); > + rzalloc_array(var, int, this->interface_type->length); > memcpy(var->u.max_ifc_array_access, this->u.max_ifc_array_access, > this->interface_type->length * sizeof(unsigned)); > } > diff --git a/src/compiler/glsl/ir_validate.cpp > b/src/compiler/glsl/ir_validate.cpp > index 2ec5a3f..9d05e7e 100644 > --- a/src/compiler/glsl/ir_validate.cpp > +++ b/src/compiler/glsl/ir_validate.cpp > @@ -727,7 +727,7 @@ ir_validate::visit(ir_variable *ir) > * to be out of bounds. > */ > if (ir->type->array_size() > 0) { > - if (ir->data.max_array_access >= ir->type->length) { > + if (ir->data.max_array_access >= (int)ir->type->length) { > printf("ir_variable has maximum access out of bounds (%d vs %d)\n", > ir->data.max_array_access, ir->type->length - 1); > ir->print(); > @@ -744,12 +744,12 @@ ir_validate::visit(ir_variable *ir) > ir->get_interface_type()->fields.structure; > for (unsigned i = 0; i < ir->get_interface_type()->length; i++) { > if (fields[i].type->array_size() > 0) { > - const unsigned *const max_ifc_array_access = > + const int *const max_ifc_array_access = > ir->get_max_ifc_array_access(); > > assert(max_ifc_array_access != NULL); > > - if (max_ifc_array_access[i] >= fields[i].type->length) { > + if (max_ifc_array_access[i] >= (int)fields[i].type->length) { > printf("ir_variable has maximum access out of bounds for " > "field %s (%d vs %d)\n", fields[i].name, > max_ifc_array_access[i], fields[i].type->length); > diff --git a/src/compiler/glsl/link_functions.cpp > b/src/compiler/glsl/link_functions.cpp > index 537f4dc..4e10287 100644 > --- a/src/compiler/glsl/link_functions.cpp > +++ b/src/compiler/glsl/link_functions.cpp > @@ -245,9 +245,9 @@ public: > /* Similarly, we need implicit sizes of arrays within > interface > * blocks to be sized by the maximal access in *any* shader. > */ > - unsigned *const linked_max_ifc_array_access = > + int *const linked_max_ifc_array_access = > var->get_max_ifc_array_access(); > - unsigned *const ir_max_ifc_array_access = > + int *const ir_max_ifc_array_access = > ir->var->get_max_ifc_array_access(); > > assert(linked_max_ifc_array_access != NULL); > diff --git a/src/compiler/glsl/link_interface_blocks.cpp > b/src/compiler/glsl/link_interface_blocks.cpp > index 2607259..4eda097 100644 > --- a/src/compiler/glsl/link_interface_blocks.cpp > +++ b/src/compiler/glsl/link_interface_blocks.cpp > @@ -154,12 +154,6 @@ static bool > interstage_match(struct gl_shader_program *prog, ir_variable *producer, > ir_variable *consumer, bool extra_array_level) > { > - /* Unsized arrays should not occur during interstage linking. They > - * should have all been assigned a size by link_intrastage_shaders. > - */ > - assert(!consumer->type->is_unsized_array()); > - assert(!producer->type->is_unsized_array()); > - > /* Types must match. */ > if (consumer->get_interface_type() != producer->get_interface_type()) { > /* Exception: if both the interface blocks are implicitly declared, > diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp > index de56945..b856631 100644 > --- a/src/compiler/glsl/linker.cpp > +++ b/src/compiler/glsl/linker.cpp > @@ -216,7 +216,7 @@ public: > * array using an index too large for its actual size assigned at link > * time. > */ > - if (var->data.max_array_access >= this->num_vertices) { > + if (var->data.max_array_access >= (int)this->num_vertices) { > linker_error(this->prog, "geometry shader accesses element %i of " > "%s, but only %i input vertices\n", > var->data.max_array_access, var->name, > this->num_vertices); > @@ -924,7 +924,7 @@ validate_intrastage_arrays(struct gl_shader_program *prog, > if ((var->type->fields.array == existing->type->fields.array) && > ((var->type->length == 0)|| (existing->type->length == 0))) { > if (var->type->length != 0) { > - if (var->type->length <= existing->data.max_array_access) { > + if ((int)var->type->length <= existing->data.max_array_access) { > linker_error(prog, "%s `%s' declared as type " > "`%s' but outermost dimension has an index" > " of `%i'\n", > @@ -935,7 +935,7 @@ validate_intrastage_arrays(struct gl_shader_program *prog, > existing->type = var->type; > return true; > } else if (existing->type->length != 0) { > - if(existing->type->length <= var->data.max_array_access && > + if((int)existing->type->length <= var->data.max_array_access && > !existing->data.from_ssbo_unsized_array) { > linker_error(prog, "%s `%s' declared as type " > "`%s' but outermost dimension has an index" > @@ -1593,7 +1593,7 @@ private: > */ > static const glsl_type * > resize_interface_members(const glsl_type *type, > - const unsigned *max_ifc_array_access, > + const int *max_ifc_array_access, > bool is_ssbo) > { > unsigned num_fields = type->length; > @@ -2399,10 +2399,10 @@ update_array_sizes(struct gl_shader_program *prog) > * Subroutine uniforms are not removed. > */ > if (var->is_in_buffer_block() || var->type->contains_atomic() || > - var->type->contains_subroutine()) > + var->type->contains_subroutine() || var->constant_initializer) > continue; > > - unsigned int size = var->data.max_array_access; > + int size = var->data.max_array_access; > for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) { > if (prog->_LinkedShaders[j] == NULL) > continue; > @@ -2419,7 +2419,7 @@ update_array_sizes(struct gl_shader_program *prog) > } > } > > - if (size + 1 != var->type->length) { > + if (size + 1 != (int)var->type->length) { > /* If this is a built-in uniform (i.e., it's backed by some > * fixed-function state), adjust the number of state slots to > * match the new array size. The number of slots per array entry > diff --git a/src/mesa/main/ff_fragment_shader.cpp > b/src/mesa/main/ff_fragment_shader.cpp > index b0ce8c4..26bf162 100644 > --- a/src/mesa/main/ff_fragment_shader.cpp > +++ b/src/mesa/main/ff_fragment_shader.cpp > @@ -517,7 +517,7 @@ get_current_attrib(texenv_fragment_program *p, GLuint > attrib) > > current = p->shader->symbols->get_variable("gl_CurrentAttribFragMESA"); > assert(current); > - current->data.max_array_access = MAX2(current->data.max_array_access, > attrib); > + current->data.max_array_access = MAX2(current->data.max_array_access, > (int)attrib); > val = new(p->mem_ctx) ir_dereference_variable(current); > ir_rvalue *index = new(p->mem_ctx) ir_constant(attrib); > return new(p->mem_ctx) ir_dereference_array(val, index); > @@ -561,7 +561,7 @@ get_source(texenv_fragment_program *p, > var = p->shader->symbols->get_variable("gl_TextureEnvColor"); > assert(var); > deref = new(p->mem_ctx) ir_dereference_variable(var); > - var->data.max_array_access = MAX2(var->data.max_array_access, unit); > + var->data.max_array_access = MAX2(var->data.max_array_access, > (int)unit); > return new(p->mem_ctx) ir_dereference_array(deref, > new(p->mem_ctx) > ir_constant(unit)); > > @@ -893,7 +893,7 @@ static void load_texture( texenv_fragment_program *p, > GLuint unit ) > texcoord = new(p->mem_ctx) ir_dereference_variable(tc_array); > ir_rvalue *index = new(p->mem_ctx) ir_constant(unit); > texcoord = new(p->mem_ctx) ir_dereference_array(texcoord, index); > - tc_array->data.max_array_access = > MAX2(tc_array->data.max_array_access, unit); > + tc_array->data.max_array_access = > MAX2(tc_array->data.max_array_access, (int)unit); > } > > if (!p->state->unit[unit].enabled) { > -- > 2.5.5 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev