mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-22 07:30:37 +02:00
nvc0/ir: add support for interpolating with non-default settings
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
This commit is contained in:
parent
7c9161521a
commit
acaed8f41d
3 changed files with 94 additions and 1 deletions
|
|
@ -163,6 +163,7 @@ BuildUtil::mkInterp(unsigned mode, Value *dst, int32_t offset, Value *rel)
|
|||
|
||||
Instruction *insn = mkOp1(op, ty, dst, sym);
|
||||
insn->setIndirect(0, 0, rel);
|
||||
insn->setInterpolate(mode);
|
||||
return insn;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1202,6 +1202,8 @@ private:
|
|||
void handleSTORE();
|
||||
void handleATOM(Value *dst0[4], DataType, uint16_t subOp);
|
||||
|
||||
void handleINTERP(Value *dst0[4]);
|
||||
|
||||
Value *interpolate(tgsi::Instruction::SrcRegister, int c, Value *ptr);
|
||||
|
||||
void insertConvergenceOps(BasicBlock *conv, BasicBlock *fork);
|
||||
|
|
@ -2132,6 +2134,84 @@ Converter::handleATOM(Value *dst0[4], DataType ty, uint16_t subOp)
|
|||
dst0[c] = dst; // not equal to rDst so handleInstruction will do mkMov
|
||||
}
|
||||
|
||||
void
|
||||
Converter::handleINTERP(Value *dst[4])
|
||||
{
|
||||
// Check whether the input is linear. All other attributes ignored.
|
||||
Instruction *insn;
|
||||
Value *offset = NULL, *ptr = NULL, *w;
|
||||
bool linear;
|
||||
operation op;
|
||||
int c, mode;
|
||||
|
||||
tgsi::Instruction::SrcRegister src = tgsi.getSrc(0);
|
||||
assert(src.getFile() == TGSI_FILE_INPUT);
|
||||
|
||||
if (src.isIndirect(0))
|
||||
ptr = fetchSrc(src.getIndirect(0), 0, NULL);
|
||||
|
||||
// XXX: no way to know interp mode if we don't know the index
|
||||
linear = info->in[ptr ? 0 : src.getIndex(0)].linear;
|
||||
if (linear) {
|
||||
op = OP_LINTERP;
|
||||
mode = NV50_IR_INTERP_LINEAR;
|
||||
} else {
|
||||
op = OP_PINTERP;
|
||||
mode = NV50_IR_INTERP_PERSPECTIVE;
|
||||
}
|
||||
|
||||
switch (tgsi.getOpcode()) {
|
||||
case TGSI_OPCODE_INTERP_CENTROID:
|
||||
mode |= NV50_IR_INTERP_CENTROID;
|
||||
break;
|
||||
case TGSI_OPCODE_INTERP_SAMPLE:
|
||||
insn = mkOp1(OP_PIXLD, TYPE_U32, (offset = getScratch()), fetchSrc(1, 0));
|
||||
insn->subOp = NV50_IR_SUBOP_PIXLD_OFFSET;
|
||||
mode |= NV50_IR_INTERP_OFFSET;
|
||||
break;
|
||||
case TGSI_OPCODE_INTERP_OFFSET: {
|
||||
// The input in src1.xy is float, but we need a single 32-bit value
|
||||
// where the upper and lower 16 bits are encoded in S0.12 format. We need
|
||||
// to clamp the input coordinates to (-0.5, 0.4375), multiply by 4096,
|
||||
// and then convert to s32.
|
||||
Value *offs[2];
|
||||
for (c = 0; c < 2; c++) {
|
||||
offs[c] = fetchSrc(1, c);
|
||||
mkOp2(OP_MIN, TYPE_F32, offs[c], offs[c], loadImm(NULL, 0.4375f));
|
||||
mkOp2(OP_MAX, TYPE_F32, offs[c], offs[c], loadImm(NULL, -0.5f));
|
||||
mkOp2(OP_MUL, TYPE_F32, offs[c], offs[c], loadImm(NULL, 4096.0f));
|
||||
mkCvt(OP_CVT, TYPE_S32, offs[c], TYPE_F32, offs[c]);
|
||||
}
|
||||
offset = mkOp3v(OP_INSBF, TYPE_U32, getScratch(),
|
||||
offs[1], mkImm(0x1010), offs[0]);
|
||||
mode |= NV50_IR_INTERP_OFFSET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (op == OP_PINTERP) {
|
||||
if (offset) {
|
||||
w = mkOp2v(OP_RDSV, TYPE_F32, getSSA(), mkSysVal(SV_POSITION, 3), offset);
|
||||
mkOp1(OP_RCP, TYPE_F32, w, w);
|
||||
} else {
|
||||
w = fragCoord[3];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
|
||||
insn = mkOp1(op, TYPE_F32, dst[c], srcToSym(src, c));
|
||||
if (op == OP_PINTERP)
|
||||
insn->setSrc(1, w);
|
||||
if (ptr)
|
||||
insn->setIndirect(0, 0, ptr);
|
||||
if (offset)
|
||||
insn->setSrc(op == OP_PINTERP ? 2 : 1, offset);
|
||||
|
||||
insn->setInterpolate(mode);
|
||||
}
|
||||
}
|
||||
|
||||
Converter::Subroutine *
|
||||
Converter::getSubroutine(unsigned ip)
|
||||
{
|
||||
|
|
@ -2796,6 +2876,11 @@ Converter::handleInstruction(const struct tgsi_full_instruction *insn)
|
|||
mkOp2(OP_POPCNT, TYPE_U32, dst0[c], src0, src0);
|
||||
}
|
||||
break;
|
||||
case TGSI_OPCODE_INTERP_CENTROID:
|
||||
case TGSI_OPCODE_INTERP_SAMPLE:
|
||||
case TGSI_OPCODE_INTERP_OFFSET:
|
||||
handleINTERP(dst0);
|
||||
break;
|
||||
default:
|
||||
ERROR("unhandled TGSI opcode: %u\n", tgsi.getOpcode());
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -1354,7 +1354,14 @@ NVC0LoweringPass::handleRDSV(Instruction *i)
|
|||
switch (sv) {
|
||||
case SV_POSITION:
|
||||
assert(prog->getType() == Program::TYPE_FRAGMENT);
|
||||
bld.mkInterp(NV50_IR_INTERP_LINEAR, i->getDef(0), addr, NULL);
|
||||
if (i->srcExists(1)) {
|
||||
// Pass offset through to the interpolation logic
|
||||
ld = bld.mkInterp(NV50_IR_INTERP_LINEAR | NV50_IR_INTERP_OFFSET,
|
||||
i->getDef(0), addr, NULL);
|
||||
ld->setSrc(1, i->getSrc(1));
|
||||
} else {
|
||||
bld.mkInterp(NV50_IR_INTERP_LINEAR, i->getDef(0), addr, NULL);
|
||||
}
|
||||
break;
|
||||
case SV_FACE:
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue