glsl: Lower ir_binop_pow to a sequence of EXP2 and LOG2
This commit is contained in:
@@ -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);
|
||||
|
||||
|
@@ -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 *);
|
||||
};
|
||||
|
||||
@@ -180,6 +187,20 @@ lower_instructions_visitor::exp_to_exp2(ir_expression *ir)
|
||||
this->progress = true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -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;
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user