If the 'dst' register is the same as the 'pass' register we'll generate invalid code. Use a temporary register in that case. --- src/gallium/drivers/svga/svga_tgsi_insn.c | 32 +++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c index c3a74c4..4cf5cf4 100644 --- a/src/gallium/drivers/svga/svga_tgsi_insn.c +++ b/src/gallium/drivers/svga/svga_tgsi_insn.c @@ -1245,6 +1245,20 @@ static boolean emit_kilp(struct svga_shader_emitter *emit, return submit_op0( emit, inst, temp ); } + +/** + * Test if r1 and r2 are the same register. + */ +static boolean +same_register(struct src_register r1, struct src_register r2) +{ + return (r1.base.num == r2.base.num && + r1.base.type_upper == r2.base.type_upper && + r1.base.type_lower == r2.base.type_lower); +} + + + /* Implement conditionals by initializing destination reg to 'fail', * then set predicate reg with UFOP_SETP, then move 'pass' to dest * based on predicate reg. @@ -1264,6 +1278,7 @@ emit_conditional(struct svga_shader_emitter *emit, { SVGA3dShaderDestToken pred_reg = dst_register( SVGA3DREG_PREDICATE, 0 ); SVGA3dShaderInstToken setp_token, mov_token; + struct src_register pass2; setp_token = inst_token( SVGA3DOP_SETP ); switch (compare_func) { @@ -1295,6 +1310,19 @@ emit_conditional(struct svga_shader_emitter *emit, break; } + if (same_register(src(dst), pass)) { + /* We'll get bad results if the dst and pass registers are the same + * so use a temp register containing pass. + */ + SVGA3dShaderDestToken temp = get_temp(emit); + if (!submit_op1(emit, inst_token(SVGA3DOP_MOV), temp, pass)) + return FALSE; + pass2 = src(temp); + } + else { + pass2 = pass; + } + /* SETP src0, COMPOP, src1 */ if (!submit_op2( emit, setp_token, pred_reg, src0, src1 )) @@ -1307,14 +1335,14 @@ emit_conditional(struct svga_shader_emitter *emit, fail )) return FALSE; - /* MOV dst, pass (predicated) + /* MOV dst, pass2 (predicated) * * Note that the predicate reg (and possible modifiers) is passed * as the first source argument. */ mov_token.predicated = 1; if (!submit_op2( emit, mov_token, dst, - src( pred_reg ), pass )) + src( pred_reg ), pass2 )) return FALSE; return TRUE; -- 1.7.7.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev