diff options
-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 1048ff982e0..f264265f4b1 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 0d9374d73bd..a5f61f213d0 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 80c20e09d9a..82495714f21 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 d9d86b6c29f..b274a961b28 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; |