i965/fs: Handle conditional discards.
authorKenneth Graunke <kenneth@whitecape.org>
Tue, 19 Aug 2014 22:22:43 +0000 (15:22 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Tue, 24 Feb 2015 23:24:52 +0000 (15:24 -0800)
The discard condition tells us which channels we want killed.  We want
to invert that condition to get the channels that should survive (remain
live) in f0.1.  Emit a CMP to negate it.

Nothing generates these today, but that will change shortly.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/brw_fs_nir.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 03e9ee80e137b409f33612ff41a0d26f67e0a239..388e63601611d9fd7e33118f36bb9db64b0bab7a 100644 (file)
@@ -1258,16 +1258,22 @@ fs_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr)
    bool has_indirect = false;
 
    switch (instr->intrinsic) {
-   case nir_intrinsic_discard: {
+   case nir_intrinsic_discard:
+   case nir_intrinsic_discard_if: {
       /* We track our discarded pixels in f0.1.  By predicating on it, we can
-       * update just the flag bits that aren't yet discarded.  By emitting a
-       * CMP of g0 != g0, all our currently executing channels will get turned
-       * off.
+       * update just the flag bits that aren't yet discarded.  If there's no
+       * condition, we emit a CMP of g0 != g0, so all currently executing
+       * channels will get turned off.
        */
-      fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0),
-                                    BRW_REGISTER_TYPE_UW));
-      fs_inst *cmp = emit(CMP(reg_null_f, some_reg, some_reg,
-                              BRW_CONDITIONAL_NZ));
+      fs_inst *cmp;
+      if (instr->intrinsic == nir_intrinsic_discard_if) {
+         cmp = emit(CMP(reg_null_f, get_nir_src(instr->src[0]),
+                        fs_reg(0), BRW_CONDITIONAL_Z));
+      } else {
+         fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0),
+                                       BRW_REGISTER_TYPE_UW));
+         cmp = emit(CMP(reg_null_f, some_reg, some_reg, BRW_CONDITIONAL_NZ));
+      }
       cmp->predicate = BRW_PREDICATE_NORMAL;
       cmp->flag_subreg = 1;
 
index 7c447af489ed595d3c303e7d72b66fbc17ece4a6..13a3bf29da81b8d2f90d4e2c1f8036295dbd8658 100644 (file)
@@ -2415,17 +2415,20 @@ fs_visitor::visit(ir_swizzle *ir)
 void
 fs_visitor::visit(ir_discard *ir)
 {
-   assert(ir->condition == NULL); /* FINISHME */
-
    /* We track our discarded pixels in f0.1.  By predicating on it, we can
-    * update just the flag bits that aren't yet discarded.  By emitting a
-    * CMP of g0 != g0, all our currently executing channels will get turned
-    * off.
+    * update just the flag bits that aren't yet discarded.  If there's no
+    * condition, we emit a CMP of g0 != g0, so all currently executing
+    * channels will get turned off.
     */
-   fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0),
-                                   BRW_REGISTER_TYPE_UW));
-   fs_inst *cmp = emit(CMP(reg_null_f, some_reg, some_reg,
-                           BRW_CONDITIONAL_NZ));
+   fs_inst *cmp;
+   if (ir->condition) {
+      ir->condition->accept(this);
+      cmp = emit(CMP(reg_null_f, this->result, fs_reg(0), BRW_CONDITIONAL_Z));
+   } else {
+      fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0),
+                                      BRW_REGISTER_TYPE_UW));
+      cmp = emit(CMP(reg_null_f, some_reg, some_reg, BRW_CONDITIONAL_NZ));
+   }
    cmp->predicate = BRW_PREDICATE_NORMAL;
    cmp->flag_subreg = 1;