diff options
Diffstat (limited to 'src/glsl/lower_instructions.cpp')
| -rw-r--r-- | src/glsl/lower_instructions.cpp | 26 | 
1 files changed, 26 insertions, 0 deletions
| diff --git a/src/glsl/lower_instructions.cpp b/src/glsl/lower_instructions.cpp index 0d9374d73b..a5f61f213d 100644 --- a/src/glsl/lower_instructions.cpp +++ b/src/glsl/lower_instructions.cpp @@ -33,6 +33,7 @@   * - SUB_TO_ADD_NEG   * - DIV_TO_MUL_RCP   * - EXP_TO_EXP2 + * - POW_TO_EXP2   * - LOG_TO_LOG2   * - MOD_TO_FRACT   * @@ -61,6 +62,11 @@   * do have base 2 versions, so this pass converts exp and log to exp2   * and log2 operations.   * + * POW_TO_EXP2: + * ----------- + * Many older GPUs don't have an x**y instruction.  For these GPUs, convert + * x**y to 2**(y * log2(x)). + *   * MOD_TO_FRACT:   * -------------   * Breaks an ir_unop_mod expression down to (op1 * fract(op0 / op1)) @@ -91,6 +97,7 @@ private:     void div_to_mul_rcp(ir_expression *);     void mod_to_fract(ir_expression *);     void exp_to_exp2(ir_expression *); +   void pow_to_exp2(ir_expression *);     void log_to_log2(ir_expression *);  }; @@ -181,6 +188,20 @@ lower_instructions_visitor::exp_to_exp2(ir_expression *ir)  }  void +lower_instructions_visitor::pow_to_exp2(ir_expression *ir) +{ +   ir_expression *const log2_x = +      new(ir) ir_expression(ir_unop_log2, ir->operands[0]->type, +			    ir->operands[0]); + +   ir->operation = ir_unop_exp2; +   ir->operands[0] = new(ir) ir_expression(ir_binop_mul, ir->operands[1]->type, +					   ir->operands[1], log2_x); +   ir->operands[1] = NULL; +   this->progress = true; +} + +void  lower_instructions_visitor::log_to_log2(ir_expression *ir)  {     ir->operation = ir_binop_mul; @@ -254,6 +275,11 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)  	 mod_to_fract(ir);        break; +   case ir_binop_pow: +      if (lowering(POW_TO_EXP2)) +	 pow_to_exp2(ir); +      break; +     default:        return visit_continue;     } | 
