nvc0/ir: add fixup to deal with interpolateAtSample with non-MSAA

The spec calls to always use sample 0 in this case, whereas we can do
undefined things for invalid sample id's in the MSAA case.

Fixes
dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_sample.non_multisample_buffer.sample_n_*

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8574>
This commit is contained in:
Ilia Mirkin 2021-01-19 05:17:45 -05:00
parent 0773cd33c2
commit 245a696741
13 changed files with 84 additions and 22 deletions

View file

@ -224,7 +224,7 @@ extern void nv50_ir_relocate_code(void *relocData, uint32_t *code,
extern void
nv50_ir_apply_fixups(void *fixupData, uint32_t *code,
bool force_per_sample, bool flatshade,
uint8_t alphatest);
uint8_t alphatest, bool msaa);
/* obtain code that will be shared among programs */
extern void nv50_ir_get_target_library(uint32_t chipset,

View file

@ -1213,7 +1213,16 @@ void
gk110_selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
{
int loc = entry->loc;
if (data.force_persample_interp)
bool val = false;
switch (entry->ipa) {
case 0:
val = data.force_persample_interp;
break;
case 1:
val = data.msaa;
break;
}
if (val)
code[loc + 1] |= 1 << 13;
else
code[loc + 1] &= ~(1 << 13);
@ -1226,8 +1235,8 @@ void CodeEmitterGK110::emitSELP(const Instruction *i)
if (i->src(2).mod & Modifier(NV50_IR_MOD_NOT))
code[1] |= 1 << 13;
if (i->subOp == 1) {
addInterp(0, 0, gk110_selpFlip);
if (i->subOp >= 1) {
addInterp(i->subOp - 1, 0, gk110_selpFlip);
}
}

View file

@ -953,7 +953,16 @@ void
gm107_selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
{
int loc = entry->loc;
if (data.force_persample_interp)
bool val = false;
switch (entry->ipa) {
case 0:
val = data.force_persample_interp;
break;
case 1:
val = data.msaa;
break;
}
if (val)
code[loc + 1] |= 1 << 10;
else
code[loc + 1] &= ~(1 << 10);
@ -985,8 +994,8 @@ CodeEmitterGM107::emitSEL()
emitGPR (0x08, insn->src(0));
emitGPR (0x00, insn->def(0));
if (insn->subOp == 1) {
addInterp(0, 0, gm107_selpFlip);
if (insn->subOp >= 1) {
addInterp(insn->subOp - 1, 0, gm107_selpFlip);
}
}

View file

@ -354,7 +354,16 @@ void
gv100_selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
{
int loc = entry->loc;
if (data.force_persample_interp)
bool val = false;
switch (entry->ipa) {
case 0:
val = data.force_persample_interp;
break;
case 1:
val = data.msaa;
break;
}
if (val)
code[loc + 2] |= 1 << 26;
else
code[loc + 2] &= ~(1 << 26);
@ -366,8 +375,8 @@ CodeEmitterGV100::emitSEL()
emitFormA(0x007, FA_RRR | FA_RIR | FA_RCR, __(0), __(1), EMPTY);
emitNOT (90, insn->src(2));
emitPRED (87, insn->src(2));
if (insn->subOp == 1)
addInterp(0, 0, gv100_selpFlip);
if (insn->subOp >= 1)
addInterp(insn->subOp - 1, 0, gv100_selpFlip);
}
void

View file

@ -1259,7 +1259,16 @@ void
nvc0_selpFlip(const FixupEntry *entry, uint32_t *code, const FixupData& data)
{
int loc = entry->loc;
if (data.force_persample_interp)
bool val = false;
switch (entry->ipa) {
case 0:
val = data.force_persample_interp;
break;
case 1:
val = data.msaa;
break;
}
if (val)
code[loc + 1] |= 1 << 20;
else
code[loc + 1] &= ~(1 << 20);
@ -1272,8 +1281,8 @@ void CodeEmitterNVC0::emitSELP(const Instruction *i)
if (i->src(2).mod & Modifier(NV50_IR_MOD_NOT))
code[1] |= 1 << 20;
if (i->subOp == 1) {
addInterp(0, 0, nvc0_selpFlip);
if (i->subOp >= 1) {
addInterp(i->subOp - 1, 0, nvc0_selpFlip);
}
}

View file

@ -1809,7 +1809,10 @@ Converter::visit(nir_intrinsic_instr *insn)
mode = NV50_IR_INTERP_DEFAULT;
} else if (op == nir_intrinsic_load_barycentric_at_sample) {
info_out->prop.fp.readsSampleLocations = true;
mkOp1(OP_PIXLD, TYPE_U32, newDefs[0], getSrc(&insn->src[0], 0))->subOp = NV50_IR_SUBOP_PIXLD_OFFSET;
Value *sample = getSSA();
mkOp3(OP_SELP, TYPE_U32, sample, mkImm(0), getSrc(&insn->src[0], 0), mkImm(0))
->subOp = 2;
mkOp1(OP_PIXLD, TYPE_U32, newDefs[0], sample)->subOp = NV50_IR_SUBOP_PIXLD_OFFSET;
mode = NV50_IR_INTERP_OFFSET;
} else {
unreachable("all intrinsics already handled above");

View file

@ -3047,11 +3047,19 @@ Converter::handleINTERP(Value *dst[4])
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));
case TGSI_OPCODE_INTERP_SAMPLE: {
// When using a non-MS buffer, we're supposed to always use the center
// (i.e. sample 0). This adds a SELP which will be always true or false
// based on a data fixup.
Value *sample = getScratch();
mkOp3(OP_SELP, TYPE_U32, sample, mkImm(0), fetchSrc(1, 0), mkImm(0))
->subOp = 2;
insn = mkOp1(OP_PIXLD, TYPE_U32, (offset = getScratch()), sample);
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

View file

@ -495,7 +495,7 @@ nv50_ir_relocate_code(void *relocData, uint32_t *code,
void
nv50_ir_apply_fixups(void *fixupData, uint32_t *code,
bool force_persample_interp, bool flatshade,
uint8_t alphatest)
uint8_t alphatest, bool msaa)
{
nv50_ir::FixupInfo *info = reinterpret_cast<nv50_ir::FixupInfo *>(
fixupData);
@ -503,7 +503,8 @@ nv50_ir_apply_fixups(void *fixupData, uint32_t *code,
// force_persample_interp: all non-flat -> per-sample
// flatshade: all color -> flat
// alphatest: PIPE_FUNC_* to use with alphatest
nv50_ir::FixupData data(force_persample_interp, flatshade, alphatest);
// msaa: false = sample id -> 0 for interpolateAtSample
nv50_ir::FixupData data(force_persample_interp, flatshade, alphatest, msaa);
for (unsigned i = 0; i < info->count; ++i)
info->entry[i].apply(&info->entry[i], code, data);
}

View file

@ -59,11 +59,12 @@ struct RelocInfo
};
struct FixupData {
FixupData(bool force, bool flat, uint8_t alphatest) :
force_persample_interp(force), flatshade(flat), alphatest(alphatest) {}
FixupData(bool force, bool flat, uint8_t alphatest, bool msaa) :
force_persample_interp(force), flatshade(flat), alphatest(alphatest), msaa(msaa) {}
bool force_persample_interp;
bool flatshade;
uint8_t alphatest;
bool msaa;
};
struct FixupEntry;

View file

@ -510,7 +510,8 @@ nv50_program_upload_code(struct nv50_context *nv50, struct nv50_program *prog)
nv50_ir_apply_fixups(prog->interps, prog->code,
prog->fp.force_persample_interp,
false /* flatshade */,
prog->fp.alphatest - 1);
prog->fp.alphatest - 1,
false /* msaa */);
nv50_sifc_linear_u8(&nv50->base, nv50->screen->code,
(prog_type << NV50_CODE_BO_SIZE_LOG2) + prog->code_base,

View file

@ -844,7 +844,8 @@ nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog)
nv50_ir_apply_fixups(prog->fixups, prog->code,
prog->fp.force_persample_interp,
prog->fp.flatshade,
0 /* alphatest */);
0 /* alphatest */,
prog->fp.msaa);
for (int i = 0; i < 2; i++) {
unsigned mask = prog->fp.color_interp[i] >> 4;
unsigned interp = prog->fp.color_interp[i] & 3;

View file

@ -54,6 +54,7 @@ struct nvc0_program {
bool flatshade;
bool reads_framebuffer;
bool post_depth_coverage;
bool msaa;
} fp;
struct {
uint32_t tess_mode; /* ~0 if defined by the other stage */

View file

@ -118,6 +118,16 @@ nvc0_fragprog_validate(struct nvc0_context *nvc0)
fp->fp.force_persample_interp = rast->force_persample_interp;
}
if (fp->fp.msaa != rast->multisample) {
/* Force the program to be reuploaded, which will trigger interp fixups
* to get applied
*/
if (fp->mem)
nouveau_heap_free(&fp->mem);
fp->fp.msaa = rast->multisample;
}
/* Shade model works well enough when both colors follow it. However if one
* (or both) is explicitly set, then we have to go the patching route.
*/