glsl: Convert lower_clip_distance_visitor to be an ir_rvalue_visitor

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 >> 2][i & 3] = 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 >> 2] =
        vector_insert(gl_ClipDistanceMESA[i >> 2], i & 3, 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.

v4: Split the least amount of refactor from the rest of the code
changes.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
This commit is contained in:
Ian Romanick 2013-05-08 10:48:55 -07:00
parent 3acb21517b
commit 065da16508

View file

@ -46,10 +46,10 @@
*/ */
#include "glsl_symbol_table.h" #include "glsl_symbol_table.h"
#include "ir_hierarchical_visitor.h" #include "ir_rvalue_visitor.h"
#include "ir.h" #include "ir.h"
class lower_clip_distance_visitor : public ir_hierarchical_visitor { class lower_clip_distance_visitor : public ir_rvalue_visitor {
public: public:
lower_clip_distance_visitor() lower_clip_distance_visitor()
: progress(false), old_clip_distance_var(NULL), : progress(false), old_clip_distance_var(NULL),
@ -59,11 +59,12 @@ public:
virtual ir_visitor_status visit(ir_variable *); virtual ir_visitor_status visit(ir_variable *);
void create_indices(ir_rvalue*, ir_rvalue *&, ir_rvalue *&); 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 *); virtual ir_visitor_status visit_leave(ir_assignment *);
void visit_new_assignment(ir_assignment *ir); void visit_new_assignment(ir_assignment *ir);
virtual ir_visitor_status visit_leave(ir_call *); virtual ir_visitor_status visit_leave(ir_call *);
virtual void handle_rvalue(ir_rvalue **rvalue);
bool progress; bool progress;
/** /**
@ -173,33 +174,35 @@ lower_clip_distance_visitor::create_indices(ir_rvalue *old_index,
} }
/** void
* Replace any expression that indexes into the gl_ClipDistance array with an lower_clip_distance_visitor::handle_rvalue(ir_rvalue **rv)
* 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)
{ {
/* If the gl_ClipDistance var hasn't been declared yet, then /* If the gl_ClipDistance var hasn't been declared yet, then
* there's no way this deref can refer to it. * there's no way this deref can refer to it.
*/ */
if (!this->old_clip_distance_var) if (!this->old_clip_distance_var || *rv == NULL)
return visit_continue; return;
ir_dereference_variable *old_var_ref = ir->array->as_dereference_variable(); ir_dereference_array *const array_deref = (*rv)->as_dereference_array();
if (array_deref == NULL)
return;
/* 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_deref->array->as_dereference_variable();
if (old_var_ref && old_var_ref->var == this->old_clip_distance_var) { if (old_var_ref && old_var_ref->var == this->old_clip_distance_var) {
this->progress = true; this->progress = true;
ir_rvalue *array_index; ir_rvalue *array_index;
ir_rvalue *swizzle_index; ir_rvalue *swizzle_index;
this->create_indices(ir->array_index, array_index, swizzle_index); this->create_indices(array_deref->array_index, array_index, swizzle_index);
void *mem_ctx = ralloc_parent(ir); void *mem_ctx = ralloc_parent(array_deref);
ir->array = new(mem_ctx) ir_dereference_array( array_deref->array = new(mem_ctx) ir_dereference_array(
this->new_clip_distance_var, array_index); this->new_clip_distance_var, array_index);
ir->array_index = swizzle_index; array_deref->array_index = swizzle_index;
} }
return visit_continue;
} }
@ -235,17 +238,24 @@ lower_clip_distance_visitor::visit_leave(ir_assignment *ir)
for (int i = 0; i < array_size; ++i) { for (int i = 0; i < array_size; ++i) {
ir_dereference_array *new_lhs = new(ctx) ir_dereference_array( ir_dereference_array *new_lhs = new(ctx) ir_dereference_array(
ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i)); ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i));
new_lhs->accept(this); this->handle_rvalue((ir_rvalue **) &new_lhs);
ir_dereference_array *new_rhs = new(ctx) ir_dereference_array( ir_dereference_array *new_rhs = new(ctx) ir_dereference_array(
ir->rhs->clone(ctx, NULL), new(ctx) ir_constant(i)); ir->rhs->clone(ctx, NULL), new(ctx) ir_constant(i));
new_rhs->accept(this); this->handle_rvalue((ir_rvalue **) &new_rhs);
this->base_ir->insert_before( this->base_ir->insert_before(
new(ctx) ir_assignment(new_lhs, new_rhs)); new(ctx) ir_assignment(new_lhs, new_rhs));
} }
ir->remove(); ir->remove();
return visit_continue;
} }
return visit_continue; /* Handle the LHS as if it were an r-value. Normally
* rvalue_visit(ir_assignment *) only visits the RHS, but we need to lower
* expressions in the LHS as well.
*/
handle_rvalue((ir_rvalue **)&ir->lhs);
return rvalue_visit(ir);
} }
@ -330,7 +340,7 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir)
} }
} }
return visit_continue; return rvalue_visit(ir);
} }