diff options
| author | Ian Romanick <ian.d.romanick@intel.com> | 2010-11-24 22:21:10 -0800 | 
|---|---|---|
| committer | Ian Romanick <ian.d.romanick@intel.com> | 2010-12-01 12:01:13 -0800 | 
| commit | c4285be9a5bd1adaa89050989374b95a9a601cdc (patch) | |
| tree | 588f3788a24029512cdda1efe5f5831634243bbd | |
| parent | da61afa7388f1ce50ef612b89aba2302a052a3bb (diff) | |
glsl: Lower ir_binop_pow to a sequence of EXP2 and LOG2
| -rw-r--r-- | src/glsl/ir_optimization.h | 5 | ||||
| -rw-r--r-- | src/glsl/lower_instructions.cpp | 26 | ||||
| -rw-r--r-- | src/mesa/main/mtypes.h | 1 | ||||
| -rw-r--r-- | src/mesa/program/ir_to_mesa.cpp | 5 | 
4 files changed, 33 insertions, 4 deletions
| diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 1048ff982e..f264265f4b 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -32,8 +32,9 @@  #define SUB_TO_ADD_NEG 0x01  #define DIV_TO_MUL_RCP 0x02  #define EXP_TO_EXP2    0x04 -#define LOG_TO_LOG2    0x08 -#define MOD_TO_FRACT   0x10 +#define POW_TO_EXP2    0x08 +#define LOG_TO_LOG2    0x10 +#define MOD_TO_FRACT   0x20  bool do_common_optimization(exec_list *ir, bool linked, unsigned max_unroll_iterations); 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;     } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 80c20e09d9..82495714f2 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2197,6 +2197,7 @@ struct gl_shader_compiler_options     GLboolean EmitNoCont;                  /**< Emit CONT opcode? */     GLboolean EmitNoMainReturn;            /**< Emit CONT/RET opcodes? */     GLboolean EmitNoNoise;                 /**< Emit NOISE opcodes? */ +   GLboolean EmitNoPow;                   /**< Emit POW opcodes? */     /**      * \name Forms of indirect addressing the driver cannot do. diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index d9d86b6c29..b274a961b2 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -2849,8 +2849,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)  	 /* Lowering */  	 do_mat_op_to_vec(ir); -	 lower_instructions(ir, MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2 -			      | LOG_TO_LOG2); +	 lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2 +				 | LOG_TO_LOG2 +				 | ((options->EmitNoPow) ? POW_TO_EXP2 : 0)));  	 progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; | 
