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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev