[Mesa-dev] [PATCH 09/12] glsl: Convert lower_clip_distance_visitor to be an ir_rvalue_visitor
Kenneth Graunke
kenneth at whitecape.org
Tue May 7 00:52:07 PDT 2013
On 05/03/2013 04:07 PM, Ian Romanick wrote:
> From: Ian Romanick <ian.d.romanick at 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.
>
> v2: Convert tabs to spaces. Suggested by Eric.
>
> Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
> Cc: Paul Berry <stereotype441 at 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..19068fb 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) {
Writing this as:
if (array == NULL)
return;
would have allowed the indentation to stay the same and probably made
the patch easier to follow. But at this point I'm not sure it matters.
> + /* 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)) {
Splitting this into LHS/RHS cases is fine, but it's unrelated to
converting this visitor to an rvalue visitor. I'd also prefer it to be
done in a separate patch.
> - /* 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);
This is a third change: making the RHS case do something different than
the LHS case. It looks fine as well, it just shouldn't be in the rvalue
refactor.
> + 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);
> }
More information about the mesa-dev
mailing list