diff options
Diffstat (limited to 'src')
| -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 0092eea036..b731ba05be 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;  | 
