diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c index df40f94..24f1cf0 100644 --- a/src/gallium/drivers/r600/r600_shader.c +++ b/src/gallium/drivers/r600/r600_shader.c @@ -8396,19 +8396,54 @@ static int tgsi_r600_arl(struct r600_shader_ctx *ctx) } break; case TGSI_OPCODE_ARR: - memset(&alu, 0, sizeof(alu)); - alu.op = ALU_OP1_FLT_TO_INT; - alu.dst.sel = ctx->bc->ar_reg; - alu.dst.write = 1; - /* FLT_TO_INT is trans-only on r600/r700 */ - alu.last = TRUE; - for (i = 0; i <= lasti; ++i) { - if (inst->Dst[0].Register.WriteMask & (1 << i)) { + switch (ctx->bc->chip_class) { + case R600: + case R700: + /* pre-r8xx truncates on ALU_OP1_FLT_TO_INT */ + memset(&alu, 0, sizeof(alu)); + alu.op = ALU_OP1_RNDNE; + alu.dst.sel = ctx->bc->ar_reg; + alu.dst.write = 1; + for (i = 0; i <= lasti; ++i) { + if (inst->Dst[0].Register.WriteMask & (1 << i)) { + alu.dst.chan = i; + r600_bytecode_src(&alu.src[0], &ctx->src[0], i); + alu.last = i == lasti; + if ((r = r600_bytecode_add_alu(ctx->bc, &alu))) + return r; + } + } + + memset(&alu, 0, sizeof(alu)); + alu.op = ALU_OP1_FLT_TO_INT; + alu.src[0].sel = ctx->bc->ar_reg; + alu.dst.sel = ctx->bc->ar_reg; + alu.dst.write = 1; + /* FLT_TO_INT is trans-only on r600/r700 */ + alu.last = TRUE; + for (i = 0; i <= lasti; ++i) { alu.dst.chan = i; - r600_bytecode_src(&alu.src[0], &ctx->src[0], i); + alu.src[0].chan = i; if ((r = r600_bytecode_add_alu(ctx->bc, &alu))) return r; } + break; + default: + memset(&alu, 0, sizeof(alu)); + alu.op = ALU_OP1_FLT_TO_INT; + alu.dst.sel = ctx->bc->ar_reg; + alu.dst.write = 1; + /* FLT_TO_INT is trans-only on r600/r700 */ + alu.last = TRUE; + for (i = 0; i <= lasti; ++i) { + if (inst->Dst[0].Register.WriteMask & (1 << i)) { + alu.dst.chan = i; + r600_bytecode_src(&alu.src[0], &ctx->src[0], i); + if ((r = r600_bytecode_add_alu(ctx->bc, &alu))) + return r; + } + } + break; } break; case TGSI_OPCODE_UARL: