diff options
author | Eric Anholt <[email protected]> | 2009-08-11 17:52:44 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2009-11-06 21:08:54 -0800 |
commit | 06c1bc8a2222f00e5a51fa977130a719bdcd8f0b (patch) | |
tree | cbe596e2740bdd334dbf219a19c47db2579e2d4d /src | |
parent | 90629704ef51de4018055ee4b8ff68531f6712ae (diff) |
i965: Add generic GLSL code for unaliasing a 3-arg opcode, and share LRP code.
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_wm.h | 6 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_wm_emit.c | 12 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_wm_glsl.c | 98 |
3 files changed, 71 insertions, 45 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h index 93f79dbfe5d..66902bab657 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.h +++ b/src/mesa/drivers/dri/i965/brw_wm.h @@ -330,5 +330,11 @@ void emit_ddxy(struct brw_compile *p, GLuint mask, GLboolean is_ddx, const struct brw_reg *arg0); +void emit_lrp(struct brw_compile *p, + const struct brw_reg *dst, + GLuint mask, + const struct brw_reg *arg0, + const struct brw_reg *arg1, + const struct brw_reg *arg2); #endif diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c index 215515d10bd..9e637ef3f2b 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_emit.c +++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c @@ -422,12 +422,12 @@ static void emit_mad( struct brw_compile *p, } } -static void emit_lrp( struct brw_compile *p, - const struct brw_reg *dst, - GLuint mask, - const struct brw_reg *arg0, - const struct brw_reg *arg1, - const struct brw_reg *arg2 ) +void emit_lrp(struct brw_compile *p, + const struct brw_reg *dst, + GLuint mask, + const struct brw_reg *arg0, + const struct brw_reg *arg1, + const struct brw_reg *arg2) { GLuint i; diff --git a/src/mesa/drivers/dri/i965/brw_wm_glsl.c b/src/mesa/drivers/dri/i965/brw_wm_glsl.c index cd5a59463c3..458d06187a0 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_glsl.c +++ b/src/mesa/drivers/dri/i965/brw_wm_glsl.c @@ -650,6 +650,63 @@ static void invoke_subroutine( struct brw_wm_compile *c, } } +/* Workaround for using brw_wm_emit.c's emit functions, which expect + * destination regs to be uniquely written. Moves arguments out to + * temporaries as necessary for instructions which use their destination as + * a temporary. + */ +static void +unalias3(struct brw_wm_compile *c, + void (*func)(struct brw_compile *c, + const struct brw_reg *dst, + GLuint mask, + const struct brw_reg *arg0, + const struct brw_reg *arg1, + const struct brw_reg *arg2), + const struct brw_reg *dst, + GLuint mask, + const struct brw_reg *arg0, + const struct brw_reg *arg1, + const struct brw_reg *arg2) +{ + struct brw_compile *p = &c->func; + struct brw_reg tmp_arg0[4], tmp_arg1[4], tmp_arg2[4]; + int i, j; + int mark = mark_tmps(c); + + for (j = 0; j < 4; j++) { + tmp_arg0[j] = arg0[j]; + tmp_arg1[j] = arg1[j]; + tmp_arg2[j] = arg2[j]; + } + + for (i = 0; i < 4; i++) { + if (mask & (1<<i)) { + for (j = 0; j < 4; j++) { + if (arg0[j].file == dst[i].file && + dst[i].nr == arg0[j].nr) { + tmp_arg0[j] = alloc_tmp(c); + brw_MOV(p, tmp_arg0[j], arg0[j]); + } + if (arg1[j].file == dst[i].file && + dst[i].nr == arg1[j].nr) { + tmp_arg1[j] = alloc_tmp(c); + brw_MOV(p, tmp_arg1[j], arg1[j]); + } + if (arg2[j].file == dst[i].file && + dst[i].nr == arg2[j].nr) { + tmp_arg2[j] = alloc_tmp(c); + brw_MOV(p, tmp_arg2[j], arg2[j]); + } + } + } + } + + func(p, dst, mask, tmp_arg0, tmp_arg1, tmp_arg2); + + release_tmps(c, mark); +} + static void emit_pixel_xy(struct brw_wm_compile *c, const struct prog_instruction *inst) { @@ -1223,44 +1280,6 @@ static void emit_pow(struct brw_wm_compile *c, BRW_MATH_PRECISION_FULL); } -static void emit_lrp(struct brw_wm_compile *c, - const struct prog_instruction *inst) -{ - struct brw_compile *p = &c->func; - GLuint mask = inst->DstReg.WriteMask; - struct brw_reg dst, tmp1, tmp2, src0, src1, src2; - int i; - int mark = mark_tmps(c); - for (i = 0; i < 4; i++) { - if (mask & (1<<i)) { - dst = get_dst_reg(c, inst, i); - src0 = get_src_reg(c, inst, 0, i); - - src1 = get_src_reg_imm(c, inst, 1, i); - - if (src1.nr == dst.nr) { - tmp1 = alloc_tmp(c); - brw_MOV(p, tmp1, src1); - } else - tmp1 = src1; - - src2 = get_src_reg(c, inst, 2, i); - if (src2.nr == dst.nr) { - tmp2 = alloc_tmp(c); - brw_MOV(p, tmp2, src2); - } else - tmp2 = src2; - - brw_ADD(p, dst, negate(src0), brw_imm_f(1.0)); - brw_MUL(p, brw_null_reg(), dst, tmp2); - brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); - brw_MAC(p, dst, src0, tmp1); - brw_set_saturate(p, 0); - } - release_tmps(c, mark); - } -} - /** * For GLSL shaders, this KIL will be unconditional. * It may be contained inside an IF/ENDIF structure of course. @@ -2722,7 +2741,8 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c) emit_alu1(p, brw_RNDD, dst, dst_flags, args[0]); break; case OPCODE_LRP: - emit_lrp(c, inst); + unalias3(c, emit_lrp, + dst, dst_flags, args[0], args[1], args[2]); break; case OPCODE_TRUNC: emit_alu1(p, brw_RNDZ, dst, dst_flags, args[0]); |