[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