Mesa (master): nvc0/ir: add fixup to deal with interpolateAtSample with non-MSAA

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 21 21:03:20 UTC 2021


Module: Mesa
Branch: master
Commit: 245a696741d2a4cd5f2aade38c2194e3030d659b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=245a696741d2a4cd5f2aade38c2194e3030d659b

Author: Ilia Mirkin <imirkin at alum.mit.edu>
Date:   Tue Jan 19 05:17:45 2021 -0500

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 at alum.mit.edu>
Reviewed-by: Karol Herbst <kherbst at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8574>

---

 src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h      |  2 +-
 .../drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp        | 15 ++++++++++++---
 .../drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp        | 15 ++++++++++++---
 .../drivers/nouveau/codegen/nv50_ir_emit_gv100.cpp        | 15 ++++++++++++---
 src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp | 15 ++++++++++++---
 src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp  |  5 ++++-
 src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp | 12 ++++++++++--
 src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp    |  5 +++--
 src/gallium/drivers/nouveau/codegen/nv50_ir_target.h      |  5 +++--
 src/gallium/drivers/nouveau/nv50/nv50_program.c           |  3 ++-
 src/gallium/drivers/nouveau/nvc0/nvc0_program.c           |  3 ++-
 src/gallium/drivers/nouveau/nvc0/nvc0_program.h           |  1 +
 src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c      | 10 ++++++++++
 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.
     */



More information about the mesa-commit mailing list