Mesa (master): i965: Correctly emit the RNDZ instruction.
Kenneth Graunke
kwg at kemper.freedesktop.org
Thu Oct 14 19:40:19 UTC 2010
Module: Mesa
Branch: master
Commit: 897f6d3c7d06316b0535971cc2de318157c23692
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=897f6d3c7d06316b0535971cc2de318157c23692
Author: Kenneth Graunke <kenneth at whitecape.org>
Date: Thu Oct 14 11:40:19 2010 -0700
i965: Correctly emit the RNDZ instruction.
Simply using RNDU, RNDZ, or RNDE does not produce the desired result.
Rather, the RND* instructions place a value in the destination register
that may be 1 less than the correct answer. They can also set per-channel
"increment bits" in a flag register, which, if set, mean dest needs to
be incremented by 1. A second instruction - a predicated add -
completes the job.
Notably, RNDD always produces the correct answer in a single
instruction.
Fixes piglit test glsl-fs-trunc.
---
src/mesa/drivers/dri/i965/brw_eu.h | 9 +++++++--
src/mesa/drivers/dri/i965/brw_eu_emit.c | 25 ++++++++++++++++++++++++-
2 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h
index c0deb23..c16613e 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.h
+++ b/src/mesa/drivers/dri/i965/brw_eu.h
@@ -789,6 +789,10 @@ struct brw_instruction *brw_##OP(struct brw_compile *p, \
struct brw_reg src0, \
struct brw_reg src1);
+#define ROUND(OP) \
+void brw_##OP(struct brw_compile *p, struct brw_reg dest, struct brw_reg src0);
+
+
ALU1(MOV)
ALU2(SEL)
ALU1(NOT)
@@ -805,7 +809,6 @@ ALU2(ADD)
ALU2(MUL)
ALU1(FRC)
ALU1(RNDD)
-ALU1(RNDZ)
ALU2(MAC)
ALU2(MACH)
ALU1(LZD)
@@ -816,9 +819,11 @@ ALU2(DP2)
ALU2(LINE)
ALU2(PLN)
+ROUND(RNDZ)
+
#undef ALU1
#undef ALU2
-
+#undef ROUND
/* Helpers for SEND instruction:
diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c
index 4128638..68c6c47 100644
--- a/src/mesa/drivers/dri/i965/brw_eu_emit.c
+++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c
@@ -654,6 +654,26 @@ struct brw_instruction *brw_##OP(struct brw_compile *p, \
return brw_alu2(p, BRW_OPCODE_##OP, dest, src0, src1); \
}
+/* Rounding operations (other than RNDD) require two instructions - the first
+ * stores a rounded value (possibly the wrong way) in the dest register, but
+ * also sets a per-channel "increment bit" in the flag register. A predicated
+ * add of 1.0 fixes dest to contain the desired result.
+ */
+#define ROUND(OP) \
+void brw_##OP(struct brw_compile *p, \
+ struct brw_reg dest, \
+ struct brw_reg src) \
+{ \
+ struct brw_instruction *rnd, *add; \
+ rnd = next_insn(p, BRW_OPCODE_##OP); \
+ brw_set_dest(rnd, dest); \
+ brw_set_src0(rnd, src); \
+ rnd->header.destreg__conditionalmod = 0x7; /* turn on round-increments */ \
+ \
+ add = brw_ADD(p, dest, dest, brw_imm_f(1.0f)); \
+ add->header.predicate_control = BRW_PREDICATE_NORMAL; \
+}
+
ALU1(MOV)
ALU2(SEL)
@@ -668,7 +688,6 @@ ALU2(RSL)
ALU2(ASR)
ALU1(FRC)
ALU1(RNDD)
-ALU1(RNDZ)
ALU2(MAC)
ALU2(MACH)
ALU1(LZD)
@@ -679,6 +698,10 @@ ALU2(DP2)
ALU2(LINE)
ALU2(PLN)
+
+ROUND(RNDZ)
+
+
struct brw_instruction *brw_ADD(struct brw_compile *p,
struct brw_reg dest,
struct brw_reg src0,
More information about the mesa-commit
mailing list