nv50: allow per-sample interpolation to be forced via rast
authorIlia Mirkin <imirkin@alum.mit.edu>
Fri, 30 Oct 2015 02:18:25 +0000 (22:18 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Fri, 30 Oct 2015 02:42:38 +0000 (22:42 -0400)
Uses the same technique as for nvc0 of fixups before upload, and
evicting in case of state change. Removes one source of variants kept by
st/mesa.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nouveau/nv50/nv50_program.c
src/gallium/drivers/nouveau/nv50/nv50_program.h
src/gallium/drivers/nouveau/nv50/nv50_screen.c
src/gallium/drivers/nouveau/nv50/nv50_shader_state.c
src/gallium/drivers/nouveau/nv50/nv50_state_validate.c

index 391130e..c0cab32 100644 (file)
@@ -144,6 +144,7 @@ struct nv50_ir_prog_info
          bool earlyFragTests;
          bool separateFragData;
          bool usesDiscard;
+         bool sampleInterp;      /* perform sample interp on all fp inputs */
       } fp;
       struct {
          uint32_t inputOffset; /* base address for user args */
@@ -168,7 +169,6 @@ struct nv50_ir_prog_info
       int8_t viewportId;         /* output index of ViewportIndex */
       uint8_t fragDepth;         /* output index of FragDepth */
       uint8_t sampleMask;        /* output index of SampleMask */
-      bool sampleInterp;         /* perform sample interp on all fp inputs */
       uint8_t backFaceColor[2];  /* input/output indices of back face colour */
       uint8_t globalAccess;      /* 1 for read, 2 for wr, 3 for rw */
       bool fp64;                 /* program uses fp64 math */
index 9014766..e9b1cef 100644 (file)
@@ -876,6 +876,30 @@ CodeEmitterNV50::emitPFETCH(const Instruction *i)
    emitFlagsRd(i);
 }
 
+static void
+interpApply(const InterpEntry *entry, uint32_t *code,
+      bool force_persample_interp, bool flatshade)
+{
+   int ipa = entry->ipa;
+   int encSize = entry->reg;
+   int loc = entry->loc;
+
+   if ((ipa & NV50_IR_INTERP_SAMPLE_MASK) == NV50_IR_INTERP_DEFAULT &&
+       (ipa & NV50_IR_INTERP_MODE_MASK) != NV50_IR_INTERP_FLAT) {
+      if (force_persample_interp) {
+         if (encSize == 8)
+            code[loc + 1] |= 1 << 16;
+         else
+            code[loc + 0] |= 1 << 24;
+      } else {
+         if (encSize == 8)
+            code[loc + 1] &= ~(1 << 16);
+         else
+            code[loc + 0] &= ~(1 << 24);
+      }
+   }
+}
+
 void
 CodeEmitterNV50::emitINTERP(const Instruction *i)
 {
@@ -904,6 +928,8 @@ CodeEmitterNV50::emitINTERP(const Instruction *i)
       code[0] |= 1;
       emitFlagsRd(i);
    }
+
+   addInterp(i->ipa, i->encSize, interpApply);
 }
 
 void
index eb28622..0031b5e 100644 (file)
@@ -1125,7 +1125,7 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl)
          break;
       case TGSI_SEMANTIC_SAMPLEID:
       case TGSI_SEMANTIC_SAMPLEPOS:
-         info->io.sampleInterp = 1;
+         info->prop.fp.sampleInterp = 1;
          break;
       default:
          break;
@@ -1478,7 +1478,7 @@ Converter::translateInterpMode(const struct nv50_ir_varying *var, operation& op)
    op = (mode == NV50_IR_INTERP_PERSPECTIVE || mode == NV50_IR_INTERP_SC)
       ? OP_PINTERP : OP_LINTERP;
 
-   if (var->centroid || info->io.sampleInterp)
+   if (var->centroid || info->prop.fp.sampleInterp)
       mode |= NV50_IR_INTERP_CENTROID;
 
    return mode;
index eff4477..26ba2c2 100644 (file)
@@ -336,7 +336,6 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset)
    info->io.ucpCBSlot = 15;
    info->io.ucpBase = NV50_CB_AUX_UCP_OFFSET;
    info->io.genUserClip = prog->vp.clpd_nr;
-   info->io.sampleInterp = prog->fp.sample_interp;
 
    info->io.resInfoCBSlot = 15;
    info->io.suInfoBase = NV50_CB_AUX_TEX_MS_OFFSET;
@@ -374,6 +373,7 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset)
    prog->code = info->bin.code;
    prog->code_size = info->bin.codeSize;
    prog->fixups = info->bin.relocData;
+   prog->interps = info->bin.interpData;
    prog->max_gpr = MAX2(4, (info->bin.maxGPR >> 1) + 1);
    prog->tls_space = info->bin.tlsSpace;
 
@@ -456,6 +456,10 @@ nv50_program_upload_code(struct nv50_context *nv50, struct nv50_program *prog)
 
    if (prog->fixups)
       nv50_ir_relocate_code(prog->fixups, prog->code, prog->code_base, 0, 0);
+   if (prog->interps)
+      nv50_ir_change_interp(prog->interps, prog->code,
+                            prog->fp.force_persample_interp,
+                            false /* flatshade */);
 
    nv50_sifc_linear_u8(&nv50->base, nv50->screen->code,
                        (prog->type << NV50_CODE_BO_SIZE_LOG2) + prog->code_base,
index f4e8e94..24cc965 100644 (file)
@@ -86,7 +86,7 @@ struct nv50_program {
       uint32_t interp; /* 0x1988 */
       uint32_t colors; /* 0x1904 */
       uint8_t has_samplemask;
-      uint8_t sample_interp;
+      uint8_t force_persample_interp;
    } fp;
 
    struct {
@@ -99,6 +99,7 @@ struct nv50_program {
    } gp;
 
    void *fixups; /* relocation records */
+   void *interps; /* interpolation records */
 
    struct nouveau_heap *mem;
 
index bcad901..398abfb 100644 (file)
@@ -192,6 +192,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_INDEP_BLEND_FUNC:
    case PIPE_CAP_TEXTURE_QUERY_LOD:
    case PIPE_CAP_SAMPLE_SHADING:
+   case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
       return class_3d >= NVA3_3D_CLASS;
 
    /* unsupported caps */
@@ -216,7 +217,6 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
    case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
    case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
-   case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
    case PIPE_CAP_SHAREABLE_SHADERS:
       return 0;
 
index 941555f..b3fece0 100644 (file)
@@ -168,11 +168,23 @@ nv50_fragprog_validate(struct nv50_context *nv50)
 {
    struct nouveau_pushbuf *push = nv50->base.pushbuf;
    struct nv50_program *fp = nv50->fragprog;
+   struct pipe_rasterizer_state *rast = &nv50->rast->pipe;
 
-   fp->fp.sample_interp = nv50->min_samples > 1;
+   if (fp->fp.force_persample_interp != rast->force_persample_interp) {
+      /* Force the program to be reuploaded, which will trigger interp fixups
+       * to get applied
+       */
+      if (fp->mem)
+         nouveau_heap_free(&fp->mem);
+
+      fp->fp.force_persample_interp = rast->force_persample_interp;
+   }
+
+   if (fp->mem && !(nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_MIN_SAMPLES)))
+      return;
 
    if (!nv50_program_validate(nv50, fp))
-         return;
+      return;
    nv50_program_update_context_state(nv50, fp, 1);
 
    BEGIN_NV04(push, NV50_3D(FP_REG_ALLOC_TEMP), 1);
index 66dcf43..b6181ed 100644 (file)
@@ -487,7 +487,7 @@ static struct state_validate {
     { nv50_validate_viewport,      NV50_NEW_VIEWPORT },
     { nv50_vertprog_validate,      NV50_NEW_VERTPROG },
     { nv50_gmtyprog_validate,      NV50_NEW_GMTYPROG },
-    { nv50_fragprog_validate,      NV50_NEW_FRAGPROG |
+    { nv50_fragprog_validate,      NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
                                    NV50_NEW_MIN_SAMPLES },
     { nv50_fp_linkage_validate,    NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
                                    NV50_NEW_GMTYPROG | NV50_NEW_RASTERIZER },