i965: Fix regression in FS comparisons on original gen4 due to gen6 changes.
authorEric Anholt <eric@anholt.net>
Tue, 28 Dec 2010 21:55:14 +0000 (13:55 -0800)
committerEric Anholt <eric@anholt.net>
Tue, 28 Dec 2010 23:35:00 +0000 (15:35 -0800)
Fixes 26 piglit cases on my GM965.

src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h

index 983b29d779c6f96ce86675dd9a139d227875d4c4..30b28690ffa008d4bdcb17669d47373b13882008 100644 (file)
@@ -931,7 +931,12 @@ fs_visitor::visit(ir_expression *ir)
    case ir_binop_all_equal:
    case ir_binop_nequal:
    case ir_binop_any_nequal:
-      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], op[1]));
+      temp = this->result;
+      /* original gen4 does implicit conversion before comparison. */
+      if (intel->gen < 5)
+        temp.type = op[0].type;
+
+      inst = emit(fs_inst(BRW_OPCODE_CMP, temp, op[0], op[1]));
       inst->conditional_mod = brw_conditional_for_comparison(ir->operation);
       emit(fs_inst(BRW_OPCODE_AND, this->result, this->result, fs_reg(0x1)));
       break;
@@ -977,7 +982,12 @@ fs_visitor::visit(ir_expression *ir)
       break;
    case ir_unop_f2b:
    case ir_unop_i2b:
-      inst = emit(fs_inst(BRW_OPCODE_CMP, this->result, op[0], fs_reg(0.0f)));
+      temp = this->result;
+      /* original gen4 does implicit conversion before comparison. */
+      if (intel->gen < 5)
+        temp.type = op[0].type;
+
+      inst = emit(fs_inst(BRW_OPCODE_CMP, temp, op[0], fs_reg(0.0f)));
       inst->conditional_mod = BRW_CONDITIONAL_NZ;
       inst = emit(fs_inst(BRW_OPCODE_AND, this->result,
                          this->result, fs_reg(1)));
@@ -1560,7 +1570,7 @@ fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir)
            inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d,
                                op[0], fs_reg(0.0f)));
         } else {
-           inst = emit(fs_inst(BRW_OPCODE_MOV, reg_null_d, op[0]));
+           inst = emit(fs_inst(BRW_OPCODE_MOV, reg_null_f, op[0]));
         }
         inst->conditional_mod = BRW_CONDITIONAL_NZ;
         break;
@@ -1582,7 +1592,7 @@ fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir)
       case ir_binop_all_equal:
       case ir_binop_nequal:
       case ir_binop_any_nequal:
-        inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_d, op[0], op[1]));
+        inst = emit(fs_inst(BRW_OPCODE_CMP, reg_null_cmp, op[0], op[1]));
         inst->conditional_mod =
            brw_conditional_for_comparison(expr->operation);
         break;
index de7b15312a58d37f1a207e4e207bac42042c8d47..00a000855c51b3d2b6799297a5fda747a931defd 100644 (file)
@@ -348,6 +348,23 @@ public:
                                          hash_table_pointer_hash,
                                          hash_table_pointer_compare);
 
+      /* There's a question that appears to be left open in the spec:
+       * How do implicit dst conversions interact with the CMP
+       * instruction or conditional mods?  On gen6, the instruction:
+       *
+       * CMP null<d> src0<f> src1<f>
+       *
+       * will do src1 - src0 and compare that result as if it was an
+       * integer.  On gen4, it will do src1 - src0 as float, convert
+       * the result to int, and compare as int.  In between, it
+       * appears that it does src1 - src0 and does the compare in the
+       * execution type so dst type doesn't matter.
+       */
+      if (this->intel->gen > 4)
+        this->reg_null_cmp = reg_null_d;
+      else
+        this->reg_null_cmp = reg_null_f;
+
       this->frag_color = NULL;
       this->frag_data = NULL;
       this->frag_depth = NULL;
@@ -485,6 +502,7 @@ public:
    fs_reg pixel_w;
    fs_reg delta_x;
    fs_reg delta_y;
+   fs_reg reg_null_cmp;
 
    int grf_used;
 };