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.
This commit is contained in:
Kenneth Graunke 2010-10-14 11:40:19 -07:00
parent f541b685aa
commit 897f6d3c7d
2 changed files with 31 additions and 3 deletions

View file

@ -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:

View file

@ -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,