summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nouveau
diff options
context:
space:
mode:
authorIlia Mirkin <imirkin@alum.mit.edu>2021-01-19 05:17:45 -0500
committerIlia Mirkin <imirkin@alum.mit.edu>2021-01-21 15:55:34 -0500
commit245a696741d2a4cd5f2aade38c2194e3030d659b (patch)
treef8aba9f001dea55a03995a0d703fdbf86a7df37f /src/gallium/drivers/nouveau
parent0773cd33c2bd14605eee471dd0dcc5306dd41cd4 (diff)
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>
Diffstat (limited to 'src/gallium/drivers/nouveau')
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h2
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp15
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp15
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gv100.cpp15
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp15
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp5
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp12
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp5
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_target.h5
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_program.c3
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.c3
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.h1
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c10
13 files changed, 84 insertions, 22 deletions
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
index c36e990735d..bacf95530da 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
@@ -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,
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
index e651d7fdcb0..8116fb58f7d 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
@@ -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);
}
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
index f7a2307c9f4..56bc9fc3cef 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
@@ -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);
}
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gv100.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gv100.cpp
index 8da45ad517d..415fbf385ac 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gv100.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gv100.cpp
@@ -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
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
index 0a82c6de20d..08863868b7a 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
@@ -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);
}
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
index 417800585da..b857d3cd6a9 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
@@ -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");
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 d4881af6281..19f070f44bb 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
@@ -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
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp
index 5d03f8f6055..fdaa75ea560 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp
@@ -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);
}
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_target.h b/src/gallium/drivers/nouveau/codegen/nv50_ir_target.h
index db8ae0ae99e..ce84ea367f1 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_target.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_target.h
@@ -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;
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c
index 21ffd951c26..8c14a6531ec 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_program.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c
@@ -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,
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
index 98dae6c703e..d2b37d1aaa1 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
@@ -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;
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.h b/src/gallium/drivers/nouveau/nvc0/nvc0_program.h
index 8f209d75ca1..74996fbc867 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.h
@@ -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 */
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c
index 5e2a6c0566e..a8203b5c6ce 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c
@@ -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.
*/