From: Ian Romanick <ian.d.roman...@intel.com> Right now the lower_clip_distance_visitor lowers variable indexing into gl_ClipDistance into variable indexing into both the array gl_ClipDistanceMESA and the vectors of that array. For example,
gl_ClipDistance[i] = f; becomes gl_ClipDistanceMESA[i/4][i%4] = f; However, variable indexing into vectors using ir_dereference_array is being removed. Instead, ir_expression with ir_triop_vector_insert will be used. The above code will become gl_ClipDistanceMESA[i/4] = vector_insert(gl_ClipDistanceMESA[i/4], i % 4, f); In order to do this, an ir_rvalue_visitor will need to be used. This commit is really just a refactor to get ready for that. Signed-off-by: Ian Romanick <ian.d.roman...@intel.com> Cc: Paul Berry <stereotype...@gmail.com> --- src/glsl/lower_clip_distance.cpp | 136 +++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 50 deletions(-) diff --git a/src/glsl/lower_clip_distance.cpp b/src/glsl/lower_clip_distance.cpp index 643807d..26a0feb 100644 --- a/src/glsl/lower_clip_distance.cpp +++ b/src/glsl/lower_clip_distance.cpp @@ -46,10 +46,10 @@ */ #include "glsl_symbol_table.h" -#include "ir_hierarchical_visitor.h" +#include "ir_rvalue_visitor.h" #include "ir.h" -class lower_clip_distance_visitor : public ir_hierarchical_visitor { +class lower_clip_distance_visitor : public ir_rvalue_visitor { public: lower_clip_distance_visitor() : progress(false), old_clip_distance_var(NULL), @@ -59,11 +59,12 @@ public: virtual ir_visitor_status visit(ir_variable *); void create_indices(ir_rvalue*, ir_rvalue *&, ir_rvalue *&); - virtual ir_visitor_status visit_leave(ir_dereference_array *); virtual ir_visitor_status visit_leave(ir_assignment *); void visit_new_assignment(ir_assignment *ir); virtual ir_visitor_status visit_leave(ir_call *); + virtual void handle_rvalue(ir_rvalue **rvalue); + bool progress; /** @@ -173,33 +174,35 @@ lower_clip_distance_visitor::create_indices(ir_rvalue *old_index, } -/** - * Replace any expression that indexes into the gl_ClipDistance array with an - * expression that indexes into one of the vec4's in gl_ClipDistanceMESA and - * accesses the appropriate component. - */ -ir_visitor_status -lower_clip_distance_visitor::visit_leave(ir_dereference_array *ir) +void +lower_clip_distance_visitor::handle_rvalue(ir_rvalue **rv) { /* If the gl_ClipDistance var hasn't been declared yet, then * there's no way this deref can refer to it. */ - if (!this->old_clip_distance_var) - return visit_continue; - - ir_dereference_variable *old_var_ref = ir->array->as_dereference_variable(); - if (old_var_ref && old_var_ref->var == this->old_clip_distance_var) { - this->progress = true; - ir_rvalue *array_index; - ir_rvalue *swizzle_index; - this->create_indices(ir->array_index, array_index, swizzle_index); - void *mem_ctx = ralloc_parent(ir); - ir->array = new(mem_ctx) ir_dereference_array( - this->new_clip_distance_var, array_index); - ir->array_index = swizzle_index; + if (!this->old_clip_distance_var || *rv == NULL) + return; + + ir_dereference_array *const array = (*rv)->as_dereference_array(); + if (array != NULL) { + /* Replace any expression that indexes into the gl_ClipDistance array + * with an expression that indexes into one of the vec4's in + * gl_ClipDistanceMESA and accesses the appropriate component. + */ + ir_dereference_variable *old_var_ref = + array->array->as_dereference_variable(); + if (old_var_ref && old_var_ref->var == this->old_clip_distance_var) { + this->progress = true; + ir_rvalue *array_index; + ir_rvalue *swizzle_index; + this->create_indices(array->array_index, array_index, swizzle_index); + void *mem_ctx = ralloc_parent(array); + array->array = + new(mem_ctx) ir_dereference_array(this->new_clip_distance_var, + array_index); + array->array_index = swizzle_index; + } } - - return visit_continue; } @@ -214,38 +217,71 @@ lower_clip_distance_visitor::visit_leave(ir_assignment *ir) { ir_dereference_variable *lhs_var = ir->lhs->as_dereference_variable(); ir_dereference_variable *rhs_var = ir->rhs->as_dereference_variable(); - if ((lhs_var && lhs_var->var == this->old_clip_distance_var) - || (rhs_var && rhs_var->var == this->old_clip_distance_var)) { - /* LHS or RHS of the assignment is the entire gl_ClipDistance array. - * Since we are reshaping gl_ClipDistance from an array of floats to an - * array of vec4's, this isn't going to work as a bulk assignment - * anymore, so unroll it to element-by-element assignments and lower - * each of them. - * - * Note: to unroll into element-by-element assignments, we need to make - * clones of the LHS and RHS. This is only safe if the LHS and RHS are - * side-effect free. Fortunately, we know that they are, because the - * only kind of rvalue that can have side effects is an ir_call, and - * ir_calls only appear (a) as a statement on their own, or (b) as the - * RHS of an assignment that stores the result of the call in a - * temporary variable. - */ - void *ctx = ralloc_parent(ir); + void *ctx = ralloc_parent(ir); + + /* LHS or RHS of the assignment is the entire gl_ClipDistance array. + * Since we are reshaping gl_ClipDistance from an array of floats to an + * array of vec4's, this isn't going to work as a bulk assignment + * anymore, so unroll it to element-by-element assignments and lower + * each of them. + * + * Note: to unroll into element-by-element assignments, we need to make + * clones of the LHS and RHS. This is only safe if the LHS and RHS are + * side-effect free. Fortunately, we know that they are, because the + * only kind of rvalue that can have side effects is an ir_call, and + * ir_calls only appear (a) as a statement on their own, or (b) as the + * RHS of an assignment that stores the result of the call in a + * temporary variable. + */ + if (lhs_var && lhs_var->var == this->old_clip_distance_var) { int array_size = this->old_clip_distance_var->type->array_size(); for (int i = 0; i < array_size; ++i) { - ir_dereference_array *new_lhs = new(ctx) ir_dereference_array( - ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i)); - new_lhs->accept(this); + ir_dereference_variable *const new_deref = + new(ctx) ir_dereference_variable(new_clip_distance_var); + + ir_dereference_array *const new_lhs = + new(ctx) ir_dereference_array(new_deref, + new(ctx) ir_constant(i / 4)); + ir_dereference_array *new_rhs = new(ctx) ir_dereference_array( ir->rhs->clone(ctx, NULL), new(ctx) ir_constant(i)); - new_rhs->accept(this); - this->base_ir->insert_before( - new(ctx) ir_assignment(new_lhs, new_rhs)); + + const int mask = 1 << (i % 4); + + ir_assignment *const assign = + new(ctx) ir_assignment(new_lhs, new_rhs, NULL, mask); + + this->base_ir->insert_before(assign); } ir->remove(); + + return visit_continue; + } else if (rhs_var && rhs_var->var == this->old_clip_distance_var) { + int array_size = this->old_clip_distance_var->type->array_size(); + for (int i = 0; i < array_size; ++i) { + ir_dereference_array *new_lhs = new(ctx) ir_dereference_array( + ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i)); + + ir_dereference_variable *const new_deref = + new(ctx) ir_dereference_variable(new_clip_distance_var); + + ir_rvalue *const new_rhs = + new(ctx) ir_swizzle(new(ctx) ir_dereference_array(new_deref, + new(ctx) ir_constant(i / 4)), + i % 4, 0, 0, 0, 1); + + ir_assignment *const assign = + new(ctx) ir_assignment(new_lhs, new_rhs); + + this->base_ir->insert_before(assign); + } + ir->remove(); + + return visit_continue; } - return visit_continue; + handle_rvalue((ir_rvalue **)&ir->lhs); + return rvalue_visit(ir); } @@ -330,7 +366,7 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir) } } - return visit_continue; + return rvalue_visit(ir); } -- 1.8.1.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev