summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlia Mirkin <[email protected]>2016-05-12 23:42:47 -0400
committerIlia Mirkin <[email protected]>2016-05-15 14:12:56 -0400
commitbe2b13e3bf4e61aee96c9575e7781d053f0788a1 (patch)
treeb56f36536baf4140650660a6c562950dc771d03a
parent9323d084ac5a5f59936097b6f5bf9db41c1a89bd (diff)
nv50/ir: avoid asserts when the state tracker feeds us bogus inputs
INTERP is defined (by me) to have to have a INPUT source. However the state tracker does not always obey this. This happens due to varying packing logic introducing additional mov's which can't always be undone. Instead of just giving up, we instead try harder to find the original input. This won't always be possible, for example with indirect accesses. There's not much we can (easily) do about that though. This fixes the remaining interpolateAt* failures in dEQP: dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at* some of which were asserting due to INTERP_* being passed a non-input. Signed-off-by: Ilia Mirkin <[email protected]> Reviewed-by: Samuel Pitoiset <[email protected]>
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp60
1 files changed, 48 insertions, 12 deletions
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
index 69e1a341bc3..c085e3818ad 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
@@ -2733,24 +2733,60 @@ Converter::handleINTERP(Value *dst[4])
// Check whether the input is linear. All other attributes ignored.
Instruction *insn;
Value *offset = NULL, *ptr = NULL, *w = NULL;
+ Symbol *sym[4] = { NULL };
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;
+ // In some odd cases, in large part due to varying packing, the source
+ // might not actually be an input. This is illegal TGSI, but it's easier to
+ // account for it here than it is to fix it where the TGSI is being
+ // generated. In that case, it's going to be a straight up mov (or sequence
+ // of mov's) from the input in question. We follow the mov chain to see
+ // which input we need to use.
+ if (src.getFile() != TGSI_FILE_INPUT) {
+ if (src.isIndirect(0)) {
+ ERROR("Ignoring indirect input interpolation\n");
+ return;
+ }
+ FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
+ Value *val = fetchSrc(0, c);
+ assert(val->defs.size() == 1);
+ insn = val->getInsn();
+ while (insn->op == OP_MOV) {
+ assert(insn->getSrc(0)->defs.size() == 1);
+ insn = insn->getSrc(0)->getInsn();
+ if (!insn) {
+ ERROR("Miscompiling shader due to unhandled INTERP\n");
+ return;
+ }
+ }
+ if (insn->op != OP_LINTERP && insn->op != OP_PINTERP) {
+ ERROR("Trying to interpolate non-input, this is not allowed.\n");
+ return;
+ }
+ sym[c] = insn->getSrc(0)->asSym();
+ assert(sym[c]);
+ op = insn->op;
+ mode = insn->ipa;
+ }
} else {
- op = OP_PINTERP;
- mode = NV50_IR_INTERP_PERSPECTIVE;
+ if (src.isIndirect(0))
+ ptr = fetchSrc(src.getIndirect(0), 0, NULL);
+
+ // We can assume that the fixed index will point to an input of the same
+ // interpolation type in case of an indirect.
+ // TODO: Make use of ArrayID.
+ linear = info->in[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()) {
@@ -2793,7 +2829,7 @@ Converter::handleINTERP(Value *dst[4])
FOR_EACH_DST_ENABLED_CHANNEL(0, c, tgsi) {
- insn = mkOp1(op, TYPE_F32, dst[c], srcToSym(src, c));
+ insn = mkOp1(op, TYPE_F32, dst[c], sym[c] ? sym[c] : srcToSym(src, c));
if (op == OP_PINTERP)
insn->setSrc(1, w);
if (ptr)