summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-12-28 13:55:14 -0800
committerEric Anholt <eric@anholt.net>2010-12-28 15:35:00 -0800
commit54df8e48bcceacbfa468d5237f2981b26493df29 (patch)
tree17a52c5de58bab4ce5d4d88fdd648c4ae757eb47
parent74dffb39c3434b590b36833905f2b12a6e3477e9 (diff)
i965: Fix regression in FS comparisons on original gen4 due to gen6 changes.
Fixes 26 piglit cases on my GM965.
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.cpp18
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h18
2 files changed, 32 insertions, 4 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 983b29d779..30b28690ff 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -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;
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index de7b15312a..00a000855c 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -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;
};