int wrmask;
};
+#define IR3_INSTR_SRCS 10
+
struct ir3_instruction {
struct ir3_block *block;
int category;
} flags;
int repeat;
unsigned regs_count;
- struct ir3_register *regs[5];
+ struct ir3_register *regs[1 + IR3_INSTR_SRCS];
union {
struct {
char inv;
{
unsigned idx = regmask_idx(reg);
unsigned i;
- for (i = 0; i < 4; i++, idx++)
+ for (i = 0; i < IR3_INSTR_SRCS; i++, idx++)
if (reg->wrmask & (1 << i))
(*regmask)[idx / 8] |= 1 << (idx % 8);
}
{
unsigned idx = regmask_idx(reg);
unsigned i;
- for (i = 0; i < 4; i++, idx++)
+ for (i = 0; i < IR3_INSTR_SRCS; i++, idx++)
if (reg->wrmask & (1 << i))
if (!((*b)[idx / 8] & (1 << (idx % 8))))
(*a)[idx / 8] |= 1 << (idx % 8);
{
unsigned idx = regmask_idx(reg);
unsigned i;
- for (i = 0; i < 4; i++, idx++)
+ for (i = 0; i < IR3_INSTR_SRCS; i++, idx++)
if (reg->wrmask & (1 << i))
if ((*regmask)[idx / 8] & (1 << (idx % 8)))
return true;
info->flags |= IR3_INSTR_P;
/* fallthrough */
case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TXD:
info->args = 1;
break;
}
struct ir3_instruction *instr, *collect;
struct ir3_register *reg;
struct tgsi_dst_register *dst = &inst->Dst[0].Register;
- struct tgsi_src_register *orig, *coord, *samp, *offset;
+ struct tgsi_src_register *orig, *coord, *samp, *offset, *dpdx, *dpdy;
struct tgsi_src_register zero;
const struct target_info *tgt = &tex_targets[inst->Texture.Texture];
struct tex_info tinf;
coord = get_tex_coord(ctx, inst, &tinf);
get_immediate(ctx, &zero, 0);
- if (inst->Instruction.Opcode == TGSI_OPCODE_TXB2) {
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_TXB2:
orig = &inst->Src[1].Register;
samp = &inst->Src[2].Register;
- } else {
+ break;
+ case TGSI_OPCODE_TXD:
+ orig = &inst->Src[0].Register;
+ dpdx = &inst->Src[1].Register;
+ dpdy = &inst->Src[2].Register;
+ samp = &inst->Src[3].Register;
+ if (is_rel_or_const(dpdx))
+ dpdx = get_unconst(ctx, dpdx);
+ if (is_rel_or_const(dpdy))
+ dpdy = get_unconst(ctx, dpdy);
+ break;
+ default:
orig = &inst->Src[0].Register;
samp = &inst->Src[1].Register;
+ break;
}
if (tinf.args > 1 && is_rel_or_const(orig))
orig = get_unconst(ctx, orig);
instr->flags |= tinf.flags;
add_dst_reg_wrmask(ctx, instr, dst, 0, dst->WriteMask);
- add_src_reg_wrmask(ctx, instr, coord, coord->SwizzleX, tinf.src_wrmask);
+
+ reg = ir3_reg_create(instr, 0, IR3_REG_SSA);
+
+ collect = ir3_instr_create(ctx->block, -1, OPC_META_FI);
+ ir3_reg_create(collect, 0, 0);
+ for (i = 0; i < 4; i++)
+ if (tinf.src_wrmask & (1 << i))
+ ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA),
+ coord, src_swiz(coord, i));
+ else if (tinf.src_wrmask & ~((1 << i) - 1))
+ ir3_reg_create(collect, 0, 0);
+
+ /* Attach derivatives onto the end of the fan-in. Derivatives start after
+ * the 4th argument, so make sure that fi is padded up to 4 first.
+ */
+ if (inst->Instruction.Opcode == TGSI_OPCODE_TXD) {
+ while (collect->regs_count < 5)
+ ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA), &zero, 0);
+ for (i = 0; i < tgt->dims; i++)
+ ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA), dpdx, i);
+ if (tgt->dims < 2)
+ ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA), &zero, 0);
+ for (i = 0; i < tgt->dims; i++)
+ ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA), dpdy, i);
+ if (tgt->dims < 2)
+ ssa_src(ctx, ir3_reg_create(collect, 0, IR3_REG_SSA), &zero, 0);
+ tinf.src_wrmask |= ((1 << (2 * MAX2(tgt->dims, 2))) - 1) << 4;
+ }
+
+ reg->instr = collect;
+ reg->wrmask = tinf.src_wrmask;
/* The second argument contains the offsets, followed by the lod/bias
* argument. This is constructed more manually due to the dynamic nature.
INSTR(TXB, trans_samp, .opc = OPC_SAMB, .arg = TGSI_OPCODE_TXB),
INSTR(TXB2, trans_samp, .opc = OPC_SAMB, .arg = TGSI_OPCODE_TXB2),
INSTR(TXL, trans_samp, .opc = OPC_SAML, .arg = TGSI_OPCODE_TXL),
+ INSTR(TXD, trans_samp, .opc = OPC_SAMGQ, .arg = TGSI_OPCODE_TXD),
INSTR(TXQ, trans_txq),
INSTR(DDX, trans_deriv, .opc = OPC_DSX),
INSTR(DDY, trans_deriv, .opc = OPC_DSY),