[Mesa-dev] [PATCH] i965/fs: Optimize [-]b2f([!]gl_FrontFacing).
Matt Turner
mattst88 at gmail.com
Thu Jan 15 16:38:50 PST 2015
The GLSL compiler optimizes the pattern
result = [!]gl_FrontFacing ? x : y;
where x and y are ±0.0 and ±1.0 into
result = [-]b2f([!]gl_FrontFacing);
We can do these expressions in two instructions.
total instructions in shared programs: 5928518 -> 5927775 (-0.01%)
instructions in affected programs: 190021 -> 189278 (-0.39%)
GAINED: 2
LOST: 0
(one of the GAINED programs had been lost in the previous commit)
---
This patch applies on top of
> glsl: Optimize certain if-statements to just casts from the condition
and replaces
> i965/fs: Optimize (gl_FrontFacing ? x : -1.0) where x is ±0.0.
src/mesa/drivers/dri/i965/brw_fs.h | 1 +
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 55 ++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index b5e7db0..60c1201 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -535,6 +535,7 @@ public:
bool try_emit_line(ir_expression *ir);
bool try_emit_mad(ir_expression *ir);
bool try_opt_frontfacing_ternary(ir_if *ir);
+ bool try_opt_b2f_frontfacing(ir_expression *ir);
void try_replace_with_sel();
bool opt_peephole_sel();
bool opt_peephole_predicated_break();
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 56b5fe1..5e3fb26 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -687,6 +687,9 @@ fs_visitor::visit(ir_expression *ir)
emit(NOT(this->result, op[0]));
break;
case ir_unop_neg:
+ if (try_opt_b2f_frontfacing(ir))
+ return;
+
op[0].negate = !op[0].negate;
emit(MOV(this->result, op[0]));
break;
@@ -964,6 +967,9 @@ fs_visitor::visit(ir_expression *ir)
emit(AND(this->result, op[0], fs_reg(1)));
break;
case ir_unop_b2f:
+ if (try_opt_b2f_frontfacing(ir))
+ return;
+
if (brw->gen <= 5) {
resolve_bool_comparison(ir->operands[0], &op[0]);
}
@@ -2806,6 +2812,55 @@ fs_visitor::try_opt_frontfacing_ternary(ir_if *ir)
return false;
}
+bool
+fs_visitor::try_opt_b2f_frontfacing(ir_expression *ir)
+{
+ bool invert = false, negated = false;
+
+ if (ir->operation == ir_unop_neg) {
+ ir = ir->operands[0]->as_expression();
+ if (!ir || ir->operation != ir_unop_b2f)
+ return false;
+
+ negated = true;
+ }
+ assert(ir->operation == ir_unop_b2f);
+
+ ir_dereference_variable *deref;
+ ir_expression *expr = ir->operands[0]->as_expression();
+ if (expr && expr->operation == ir_unop_logic_not) {
+ deref = expr->operands[0]->as_dereference_variable();
+ invert = true;
+ } else {
+ deref = ir->operands[0]->as_dereference_variable();
+ }
+
+ if (!deref || strcmp(deref->var->name, "gl_FrontFacing") != 0)
+ return false;
+
+ fs_reg tmp = fs_reg(this, glsl_type::int_type);
+ fs_inst *asr_inst;
+
+ if (brw->gen >= 6) {
+ /* Bit 15 of g0.0 is 0 if the polygon is front facing. */
+ fs_reg g0 = fs_reg(retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_W));
+ asr_inst = emit(ASR(tmp, g0, fs_reg(15)));
+ } else {
+ /* Bit 31 of g1.6 is 0 if the polygon is front facing. */
+ fs_reg g1_6 = fs_reg(retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_D));
+ asr_inst = emit(ASR(tmp, g1_6, fs_reg(31)));
+ }
+
+ if (!invert)
+ asr_inst->src[0].negate = true;
+
+ fs_inst *and_inst = emit(AND(this->result, tmp,
+ fs_reg(negated ? 0xbf800000 : 0x3f800000)));
+ and_inst->dst.type = BRW_REGISTER_TYPE_D;
+
+ return true;
+}
+
/**
* Try to replace IF/MOV/ELSE/MOV/ENDIF with SEL.
*
--
2.0.4
More information about the mesa-dev
mailing list