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