diff options
author | Eric Anholt <[email protected]> | 2010-08-17 13:24:50 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-08-17 13:50:45 -0700 |
commit | 0e6066df633f4594fd6fb8ceeb12b15561c57a48 (patch) | |
tree | 1741300d9e98bfc945b15aa2895b395461063019 | |
parent | f166d94fac8383b4c56f899ead0b7c06151e16d9 (diff) |
glsl: When doing algebraic simplification, make sure the type still matches.
When simplifying (vec4(1.0) / (float(x))) to rcp(float(x)), we forgot
to produce a vec4, angering ir_validate when starting alien-arena.
Fixes:
glsl-algebraic-add-zero-2
glsl-algebraic-div-one-2
glsl-algebraic-mul-one-2
glsl-algebraic-sub-zero-3
glsl-algebraic-rcp-sqrt-2
-rw-r--r-- | src/glsl/ir_algebraic.cpp | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/src/glsl/ir_algebraic.cpp b/src/glsl/ir_algebraic.cpp index 0092eea036b..b731ba05be9 100644 --- a/src/glsl/ir_algebraic.cpp +++ b/src/glsl/ir_algebraic.cpp @@ -60,8 +60,11 @@ public: int op1, ir_expression *ir2, int op2); + ir_rvalue *swizzle_if_required(ir_expression *expr, + ir_rvalue *operand); void *mem_ctx; + bool progress; }; @@ -219,11 +222,27 @@ ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index, return false; } +/* When eliminating an expression and just returning one of its operands, + * we may need to swizzle that operand out to a vector if the expression was + * vector type. + */ +ir_rvalue * +ir_algebraic_visitor::swizzle_if_required(ir_expression *expr, + ir_rvalue *operand) +{ + if (expr->type->is_vector() && operand->type->is_scalar()) { + return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0, + expr->type->vector_elements); + } else + return operand; +} + ir_rvalue * ir_algebraic_visitor::handle_expression(ir_expression *ir) { ir_constant *op_const[2] = {NULL, NULL}; ir_expression *op_expr[2] = {NULL, NULL}; + ir_expression *temp; unsigned int i; for (i = 0; i < ir->get_num_operands(); i++) { @@ -272,11 +291,11 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) case ir_binop_add: if (is_vec_zero(op_const[0])) { this->progress = true; - return ir->operands[1]; + return swizzle_if_required(ir, ir->operands[1]); } if (is_vec_zero(op_const[1])) { this->progress = true; - return ir->operands[0]; + return swizzle_if_required(ir, ir->operands[0]); } /* Reassociate addition of constants so that we can do constant @@ -293,25 +312,26 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) case ir_binop_sub: if (is_vec_zero(op_const[0])) { this->progress = true; - return new(mem_ctx) ir_expression(ir_unop_neg, - ir->type, + temp = new(mem_ctx) ir_expression(ir_unop_neg, + ir->operands[1]->type, ir->operands[1], NULL); + return swizzle_if_required(ir, temp); } if (is_vec_zero(op_const[1])) { this->progress = true; - return ir->operands[0]; + return swizzle_if_required(ir, ir->operands[0]); } break; case ir_binop_mul: if (is_vec_one(op_const[0])) { this->progress = true; - return ir->operands[1]; + return swizzle_if_required(ir, ir->operands[1]); } if (is_vec_one(op_const[1])) { this->progress = true; - return ir->operands[0]; + return swizzle_if_required(ir, ir->operands[0]); } if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) { @@ -334,14 +354,15 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) case ir_binop_div: if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) { this->progress = true; - return new(mem_ctx) ir_expression(ir_unop_rcp, - ir->type, + temp = new(mem_ctx) ir_expression(ir_unop_rcp, + ir->operands[1]->type, ir->operands[1], NULL); + return swizzle_if_required(ir, temp); } if (is_vec_one(op_const[1])) { this->progress = true; - return ir->operands[0]; + return swizzle_if_required(ir, ir->operands[0]); } break; @@ -359,10 +380,11 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) /* As far as we know, all backends are OK with rsq. */ if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) { this->progress = true; - return new(mem_ctx) ir_expression(ir_unop_rsq, - ir->type, + temp = new(mem_ctx) ir_expression(ir_unop_rsq, + op_expr[0]->operands[0]->type, op_expr[0]->operands[0], NULL); + return swizzle_if_required(ir, temp); } break; |