nvc0: do upload-time fixups for interpolation parameters
authorIlia Mirkin <imirkin@alum.mit.edu>
Tue, 20 Oct 2015 22:03:40 +0000 (18:03 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Thu, 29 Oct 2015 04:44:22 +0000 (00:44 -0400)
Unfortunately flatshading is an all-or-nothing proposition on nvc0,
while GL 3.0 calls for the ability to selectively specify explicit
interpolation parameters on gl_Color/gl_SecondaryColor which would
override the flatshading setting. This allows us to fix up the
interpolation settings after shader generation based on rasterizer
settings.

While we're at it, we can add support for dynamically forcing all
(non-flat) shader inputs to be interpolated per-sample, which allows
st/mesa to not generate variants for these.

Fixes the remaining failing glsl-1.30/execution/interpolation piglits.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
15 files changed:
src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gk110.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_gm107.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nvc0.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target.h
src/gallium/drivers/nouveau/nvc0/nvc0_program.c
src/gallium/drivers/nouveau/nvc0/nvc0_program.h
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
src/gallium/drivers/nouveau/nvc0/nvc0_shader_state.c
src/gallium/drivers/nouveau/nvc0/nvc0_state.c
src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c
src/gallium/drivers/nouveau/nvc0/nvc0_stateobj.h

index 2b9edcf9172be5da975a6bd58730a5acb0f697b6..3cc467fdb1347a4d3b13afe535654a6a9bbeefda 100644 (file)
@@ -99,6 +99,7 @@ struct nv50_ir_prog_info
       uint8_t sourceRep;  /* NV50_PROGRAM_IR */
       const void *source;
       void *relocData;
+      void *interpData;
       struct nv50_ir_prog_symbol *syms;
       uint16_t numSyms;
    } bin;
@@ -198,6 +199,10 @@ extern void nv50_ir_relocate_code(void *relocData, uint32_t *code,
                                   uint32_t libPos,
                                   uint32_t dataPos);
 
+extern void
+nv50_ir_change_interp(void *interpData, uint32_t *code,
+                      bool force_per_sample, bool flatshade);
+
 /* obtain code that will be shared among programs */
 extern void nv50_ir_get_target_library(uint32_t chipset,
                                        const uint32_t **code, uint32_t *size);
index 8f1542959c9c4a63561f5968631435285f0e4518..d712c9c300a45382e1fccd993d046947c8e90f95 100644 (file)
@@ -1437,6 +1437,30 @@ CodeEmitterGK110::emitInterpMode(const Instruction *i)
    code[1] |= (i->ipa & 0xc) << (19 - 2);
 }
 
+static void
+interpApply(const InterpEntry *entry, uint32_t *code,
+      bool force_persample_interp, bool flatshade)
+{
+   int ipa = entry->ipa;
+   int reg = entry->reg;
+   int loc = entry->loc;
+
+   if (flatshade &&
+       (ipa & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_SC) {
+      ipa = NV50_IR_INTERP_FLAT;
+      reg = 0xff;
+   } else if (force_persample_interp &&
+              (ipa & NV50_IR_INTERP_SAMPLE_MASK) == NV50_IR_INTERP_DEFAULT &&
+              (ipa & NV50_IR_INTERP_MODE_MASK) != NV50_IR_INTERP_FLAT) {
+      ipa |= NV50_IR_INTERP_CENTROID;
+   }
+   code[loc + 1] &= ~(0xf << 19);
+   code[loc + 1] |= (ipa & 0x3) << 21;
+   code[loc + 1] |= (ipa & 0xc) << (19 - 2);
+   code[loc + 0] &= ~(0xff << 23);
+   code[loc + 0] |= reg << 23;
+}
+
 void
 CodeEmitterGK110::emitINTERP(const Instruction *i)
 {
@@ -1448,10 +1472,13 @@ CodeEmitterGK110::emitINTERP(const Instruction *i)
    if (i->saturate)
       code[1] |= 1 << 18;
 
-   if (i->op == OP_PINTERP)
+   if (i->op == OP_PINTERP) {
       srcId(i->src(1), 23);
-   else
+      addInterp(i->ipa, SDATA(i->src(1)).id, interpApply);
+   } else {
       code[0] |= 0xff << 23;
+      addInterp(i->ipa, 0xff, interpApply);
+   }
 
    srcId(i->src(0).getIndirect(0), 10);
    emitInterpMode(i);
index 6e22788341fdaa93c6c2c2d2b56ddec662485ac6..a327d5724704e51686a61167f89bfc80661b2b2d 100644 (file)
@@ -2217,6 +2217,30 @@ CodeEmitterGM107::emitAL2P()
    emitGPR  (0x00, insn->def(0));
 }
 
+static void
+interpApply(const InterpEntry *entry, uint32_t *code,
+      bool force_persample_interp, bool flatshade)
+{
+   int ipa = entry->ipa;
+   int reg = entry->reg;
+   int loc = entry->loc;
+
+   if (flatshade &&
+       (ipa & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_SC) {
+      ipa = NV50_IR_INTERP_FLAT;
+      reg = 0xff;
+   } else if (force_persample_interp &&
+              (ipa & NV50_IR_INTERP_SAMPLE_MASK) == NV50_IR_INTERP_DEFAULT &&
+              (ipa & NV50_IR_INTERP_MODE_MASK) != NV50_IR_INTERP_FLAT) {
+      ipa |= NV50_IR_INTERP_CENTROID;
+   }
+   code[loc + 1] &= ~(0xf << 0x14);
+   code[loc + 1] |= (ipa & 0x3) << 0x16;
+   code[loc + 1] |= (ipa & 0xc) << (0x14 - 2);
+   code[loc + 0] &= ~(0xff << 0x14);
+   code[loc + 0] |= reg << 0x14;
+}
+
 void
 CodeEmitterGM107::emitIPA()
 {
@@ -2255,10 +2279,12 @@ CodeEmitterGM107::emitIPA()
       emitGPR(0x14, insn->src(1));
       if (insn->getSampleMode() == NV50_IR_INTERP_OFFSET)
          emitGPR(0x27, insn->src(2));
+      addInterp(insn->ipa, insn->getSrc(1)->reg.data.id, interpApply);
    } else {
       if (insn->getSampleMode() == NV50_IR_INTERP_OFFSET)
          emitGPR(0x27, insn->src(1));
       emitGPR(0x14);
+      addInterp(insn->ipa, 0xff, interpApply);
    }
 
    if (insn->getSampleMode() != NV50_IR_INTERP_OFFSET)
index 6bf5219d346a9ef9ca1f01298bda02d7f7443998..fd103146c720a6bedcb2a6d00effd9c46077d4c4 100644 (file)
@@ -1618,6 +1618,29 @@ CodeEmitterNVC0::emitInterpMode(const Instruction *i)
    }
 }
 
+static void
+interpApply(const InterpEntry *entry, uint32_t *code,
+      bool force_persample_interp, bool flatshade)
+{
+   int ipa = entry->ipa;
+   int reg = entry->reg;
+   int loc = entry->loc;
+
+   if (flatshade &&
+       (ipa & NV50_IR_INTERP_MODE_MASK) == NV50_IR_INTERP_SC) {
+      ipa = NV50_IR_INTERP_FLAT;
+      reg = 0x3f;
+   } else if (force_persample_interp &&
+              (ipa & NV50_IR_INTERP_SAMPLE_MASK) == NV50_IR_INTERP_DEFAULT &&
+              (ipa & NV50_IR_INTERP_MODE_MASK) != NV50_IR_INTERP_FLAT) {
+      ipa |= NV50_IR_INTERP_CENTROID;
+   }
+   code[loc + 0] &= ~(0xf << 6);
+   code[loc + 0] |= ipa << 6;
+   code[loc + 0] &= ~(0x3f << 26);
+   code[loc + 0] |= reg << 26;
+}
+
 void
 CodeEmitterNVC0::emitINTERP(const Instruction *i)
 {
@@ -1630,10 +1653,13 @@ CodeEmitterNVC0::emitINTERP(const Instruction *i)
       if (i->saturate)
          code[0] |= 1 << 5;
 
-      if (i->op == OP_PINTERP)
+      if (i->op == OP_PINTERP) {
          srcId(i->src(1), 26);
-      else
+         addInterp(i->ipa, SDATA(i->src(1)).id, interpApply);
+      } else {
          code[0] |= 0x3f << 26;
+         addInterp(i->ipa, 0x3f, interpApply);
+      }
 
       srcId(i->src(0).getIndirect(0), 20);
    } else {
index c8efaf5947a84c692d65b0e0596a6acafa09ae39..f27a78e715dc6b5486fb5cc7f1778c316f343f60 100644 (file)
@@ -1054,7 +1054,7 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl)
                default:
                   break;
                }
-               if (decl->Interp.Location || info->io.sampleInterp)
+               if (decl->Interp.Location)
                   info->in[i].centroid = 1;
             }
 
@@ -1119,6 +1119,10 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl)
       case TGSI_SEMANTIC_VERTEXID:
          info->io.vertexId = first;
          break;
+      case TGSI_SEMANTIC_SAMPLEID:
+      case TGSI_SEMANTIC_SAMPLEPOS:
+         info->io.sampleInterp = 1;
+         break;
       default:
          break;
       }
@@ -1338,6 +1342,8 @@ private:
 
    void handleINTERP(Value *dst0[4]);
 
+   uint8_t translateInterpMode(const struct nv50_ir_varying *var,
+                               operation& op);
    Value *interpolate(tgsi::Instruction::SrcRegister, int c, Value *ptr);
 
    void insertConvergenceOps(BasicBlock *conv, BasicBlock *fork);
@@ -1451,8 +1457,8 @@ Converter::makeSym(uint tgsiFile, int fileIdx, int idx, int c, uint32_t address)
    return sym;
 }
 
-static inline uint8_t
-translateInterpMode(const struct nv50_ir_varying *var, operation& op)
+uint8_t
+Converter::translateInterpMode(const struct nv50_ir_varying *var, operation& op)
 {
    uint8_t mode = NV50_IR_INTERP_PERSPECTIVE;
 
@@ -1468,7 +1474,7 @@ 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)
+   if (var->centroid || info->io.sampleInterp)
       mode |= NV50_IR_INTERP_CENTROID;
 
    return mode;
index fe530c76b6266d372b1b488b1e2cb3bad0ea2c04..afc8ff1374f7125419af909c8d8a89292ef638d3 100644 (file)
@@ -166,7 +166,7 @@ void Target::destroy(Target *targ)
    delete targ;
 }
 
-CodeEmitter::CodeEmitter(const Target *target) : targ(target)
+CodeEmitter::CodeEmitter(const Target *target) : targ(target), interpInfo(NULL)
 {
 }
 
@@ -388,6 +388,7 @@ Program::emitBinary(struct nv50_ir_prog_info *info)
       }
    }
    info->bin.relocData = emit->getRelocInfo();
+   info->bin.interpData = emit->getInterpInfo();
 
    emitSymbolTable(info);
 
@@ -428,6 +429,29 @@ CodeEmitter::addReloc(RelocEntry::Type ty, int w, uint32_t data, uint32_t m,
    return true;
 }
 
+bool
+CodeEmitter::addInterp(int ipa, int reg, InterpApply apply)
+{
+   unsigned int n = interpInfo ? interpInfo->count : 0;
+
+   if (!(n % RELOC_ALLOC_INCREMENT)) {
+      size_t size = sizeof(InterpInfo) + n * sizeof(InterpEntry);
+      interpInfo = reinterpret_cast<InterpInfo *>(
+         REALLOC(interpInfo, n ? size : 0,
+                 size + RELOC_ALLOC_INCREMENT * sizeof(InterpEntry)));
+      if (!interpInfo)
+         return false;
+      if (n == 0)
+         memset(interpInfo, 0, sizeof(InterpInfo));
+   }
+   ++interpInfo->count;
+
+   interpInfo->entry[n] = InterpEntry(ipa, reg, codeSize >> 2);
+   interpInfo->apply = apply;
+
+   return true;
+}
+
 void
 RelocEntry::apply(uint32_t *binary, const RelocInfo *info) const
 {
@@ -471,6 +495,19 @@ nv50_ir_relocate_code(void *relocData, uint32_t *code,
       info->entry[i].apply(code, info);
 }
 
+void
+nv50_ir_change_interp(void *interpData, uint32_t *code,
+                      bool force_persample_interp, bool flatshade)
+{
+   nv50_ir::InterpInfo *info = reinterpret_cast<nv50_ir::InterpInfo *>(
+      interpData);
+
+   // force_persample_interp: all non-flat -> per-sample
+   // flatshade: all color -> flat
+   for (unsigned i = 0; i < info->count; ++i)
+      info->apply(&info->entry[i], code, force_persample_interp, flatshade);
+}
+
 void
 nv50_ir_get_target_library(uint32_t chipset,
                            const uint32_t **code, uint32_t *size)
index 591916eb4124dcc2e7e9d2c623a475fb1c2b5eb2..4e33997e1c1984cc5dc60e95f185d2d370f20d7a 100644 (file)
@@ -58,6 +58,23 @@ struct RelocInfo
    RelocEntry entry[0];
 };
 
+struct InterpEntry
+{
+   InterpEntry(int ipa, int reg, int loc) : ipa(ipa), reg(reg), loc(loc) {}
+   uint32_t ipa:4; // SC mode used to identify colors
+   uint32_t reg:8; // The reg used for perspective division
+   uint32_t loc:20; // Let's hope we don't have more than 1M-sized shaders
+};
+
+typedef void (*InterpApply)(const InterpEntry*, uint32_t*, bool, bool);
+
+struct InterpInfo
+{
+   uint32_t count;
+   InterpApply apply;
+   InterpEntry entry[0];
+};
+
 class CodeEmitter
 {
 public:
@@ -78,6 +95,9 @@ public:
 
    inline void *getRelocInfo() const { return relocInfo; }
 
+   bool addInterp(int ipa, int reg, InterpApply apply);
+   inline void *getInterpInfo() const { return interpInfo; }
+
    virtual void prepareEmission(Program *);
    virtual void prepareEmission(Function *);
    virtual void prepareEmission(BasicBlock *);
@@ -92,6 +112,7 @@ protected:
    uint32_t codeSizeLimit;
 
    RelocInfo *relocInfo;
+   InterpInfo *interpInfo;
 };
 
 
index a168dd684ab14598f5e8c0693b65ecead37aa93b..b70b08a4a1ef1309393f383ad3a667826b9e92f3 100644 (file)
@@ -424,6 +424,11 @@ nvc0_fp_gen_header(struct nvc0_program *fp, struct nv50_ir_prog_info *info)
 
    for (i = 0; i < info->numInputs; ++i) {
       m = nvc0_hdr_interp_mode(&info->in[i]);
+      if (info->in[i].sn == TGSI_SEMANTIC_COLOR) {
+         fp->fp.colors |= 1 << info->in[i].si;
+         if (info->in[i].sc)
+            fp->fp.color_interp[info->in[i].si] = m | (info->in[i].mask << 4);
+      }
       for (c = 0; c < 4; ++c) {
          if (!(info->in[i].mask & (1 << c)))
             continue;
@@ -531,7 +536,6 @@ nvc0_program_translate(struct nvc0_program *prog, uint16_t chipset)
    info->io.genUserClip = prog->vp.num_ucps;
    info->io.ucpBase = 256;
    info->io.ucpCBSlot = 15;
-   info->io.sampleInterp = prog->fp.sample_interp;
 
    if (prog->type == PIPE_SHADER_COMPUTE) {
       if (chipset >= NVISA_GK104_CHIPSET) {
@@ -575,6 +579,7 @@ nvc0_program_translate(struct nvc0_program *prog, uint16_t chipset)
    prog->immd_data = info->immd.buf;
    prog->immd_size = info->immd.bufSize;
    prog->relocs = info->bin.relocData;
+   prog->interps = info->bin.interpData;
    prog->num_gprs = MAX2(4, (info->bin.maxGPR + 1));
    prog->num_barriers = info->numBarriers;
 
@@ -713,6 +718,23 @@ nvc0_program_upload_code(struct nvc0_context *nvc0, struct nvc0_program *prog)
 
    if (prog->relocs)
       nv50_ir_relocate_code(prog->relocs, prog->code, code_pos, lib_pos, 0);
+   if (prog->interps) {
+      nv50_ir_change_interp(prog->interps, prog->code,
+                            prog->fp.force_persample_interp,
+                            prog->fp.flatshade);
+      for (int i = 0; i < 2; i++) {
+         unsigned mask = prog->fp.color_interp[i] >> 4;
+         unsigned interp = prog->fp.color_interp[i] & 3;
+         if (!mask)
+            continue;
+         prog->hdr[14] &= ~(0xff << (8 * i));
+         if (prog->fp.flatshade)
+            interp = NVC0_INTERP_FLAT;
+         for (int c = 0; c < 4; c++)
+            if (mask & (1 << c))
+               prog->hdr[14] |= interp << (2 * (4 * i + c));
+      }
+   }
 
 #ifdef DEBUG
    if (debug_get_bool_option("NV50_PROG_DEBUG", false))
@@ -773,6 +795,7 @@ nvc0_program_destroy(struct nvc0_context *nvc0, struct nvc0_program *prog)
    FREE(prog->code); /* may be 0 for hardcoded shaders */
    FREE(prog->immd_data);
    FREE(prog->relocs);
+   FREE(prog->interps);
    if (prog->type == PIPE_SHADER_COMPUTE && prog->cp.syms)
       FREE(prog->cp.syms);
    if (prog->tfb) {
index 390e0c7a4f01208de865abc5ecc6906aabd2f1b0..9c45e7b3e31355f79f865dcbfe8172b4bcfccb74 100644 (file)
@@ -45,8 +45,10 @@ struct nvc0_program {
    } vp;
    struct {
       uint8_t early_z;
-      uint8_t in_pos[PIPE_MAX_SHADER_INPUTS];
-      uint8_t sample_interp;
+      uint8_t colors;
+      uint8_t color_interp[2];
+      bool force_persample_interp;
+      bool flatshade;
    } fp;
    struct {
       uint32_t tess_mode; /* ~0 if defined by the other stage */
@@ -61,6 +63,7 @@ struct nvc0_program {
    uint8_t num_barriers;
 
    void *relocs;
+   void *interps;
 
    struct nvc0_transform_feedback_state *tfb;
 
index 422d6d4536966ccefcd6f2ce8c9c719951b8cfc6..d48c32d2b9397566978404611c9240fa73fcca8b 100644 (file)
@@ -180,6 +180,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_DEPTH_BOUNDS_TEST:
    case PIPE_CAP_TGSI_TXQS:
    case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
+   case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
       return 1;
    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
       return (class_3d >= NVE4_3D_CLASS) ? 1 : 0;
@@ -202,7 +203,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_VERTEXID_NOBASE:
    case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
    case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
-   case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
    case PIPE_CAP_SHAREABLE_SHADERS:
       return 0;
 
@@ -828,6 +828,8 @@ nvc0_screen_create(struct nouveau_device *dev)
    PUSH_DATA (push, 1);
    BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE_COMMON), 1);
    PUSH_DATA (push, 0);
+   BEGIN_NVC0(push, NVC0_3D(SHADE_MODEL), 1);
+   PUSH_DATA (push, NVC0_3D_SHADE_MODEL_SMOOTH);
    if (screen->eng3d->oclass < NVE4_3D_CLASS) {
       BEGIN_NVC0(push, NVC0_3D(TEX_MISC), 1);
       PUSH_DATA (push, NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP);
index 857eb0316c7156bfb428896c8ca33d16b07ccbba..8b73102b98baca1d179031fc1ccb91f5f66b9cf6 100644 (file)
@@ -38,6 +38,7 @@ struct nvc0_graph_state {
    uint32_t constant_elts;
    int32_t index_bias;
    uint16_t scissor;
+   bool flatshade;
    uint8_t patch_vertices;
    uint8_t vbo_mode; /* 0 = normal, 1 = translate, 3 = translate, forced */
    uint8_t num_vtxbufs;
index af837fc4a33122527b89fe7d85c40dc31005604e..8595800592c231b7b286c315bacc519918aaed2d 100644 (file)
@@ -107,8 +107,54 @@ nvc0_fragprog_validate(struct nvc0_context *nvc0)
 {
    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    struct nvc0_program *fp = nvc0->fragprog;
+   struct pipe_rasterizer_state *rast = &nvc0->rast->pipe;
 
-   fp->fp.sample_interp = nvc0->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;
+   }
+
+   /* 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.
+    */
+   bool has_explicit_color = fp->fp.colors &&
+      (((fp->fp.colors & 1) && !fp->fp.color_interp[0]) ||
+       ((fp->fp.colors & 2) && !fp->fp.color_interp[1]));
+   bool hwflatshade = false;
+   if (has_explicit_color && fp->fp.flatshade != rast->flatshade) {
+      /* Force re-upload */
+      if (fp->mem)
+         nouveau_heap_free(&fp->mem);
+
+      fp->fp.flatshade = rast->flatshade;
+
+      /* Always smooth-shade in this mode, the shader will decide on its own
+       * when to flat-shade.
+       */
+   } else if (!has_explicit_color) {
+      hwflatshade = rast->flatshade;
+
+      /* No need to binary-patch the shader each time, make sure that it's set
+       * up for the default behaviour.
+       */
+      fp->fp.flatshade = 0;
+   }
+
+   if (hwflatshade != nvc0->state.flatshade) {
+      nvc0->state.flatshade = hwflatshade;
+      BEGIN_NVC0(push, NVC0_3D(SHADE_MODEL), 1);
+      PUSH_DATA (push, hwflatshade ? NVC0_3D_SHADE_MODEL_FLAT :
+                                     NVC0_3D_SHADE_MODEL_SMOOTH);
+   }
+
+   if (fp->mem && !(nvc0->dirty & NVC0_NEW_FRAGPROG)) {
+      return;
+   }
 
    if (!nvc0_program_validate(nvc0, fp))
          return;
index 742bef392473b93a94c030dc1cdbb81c4a2aa19f..e95554df12e64b6f5050b9d39a54b89e9930bd33 100644 (file)
@@ -212,9 +212,6 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe,
      * always emit 16 commands, one for each scissor rectangle, here.
      */
 
-    SB_BEGIN_3D(so, SHADE_MODEL, 1);
-    SB_DATA    (so, cso->flatshade ? NVC0_3D_SHADE_MODEL_FLAT :
-                                     NVC0_3D_SHADE_MODEL_SMOOTH);
     SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first);
     SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside);
 
index aec06097bbd075538a89770dd35454407ae0c7b2..f86de31c889dfd8fd8cad0f8dc0701b0368371e5 100644 (file)
@@ -645,7 +645,7 @@ static struct state_validate {
     { nvc0_tevlprog_validate,      NVC0_NEW_TEVLPROG },
     { nvc0_validate_tess_state,    NVC0_NEW_TESSFACTOR },
     { nvc0_gmtyprog_validate,      NVC0_NEW_GMTYPROG },
-    { nvc0_fragprog_validate,      NVC0_NEW_FRAGPROG },
+    { nvc0_fragprog_validate,      NVC0_NEW_FRAGPROG | NVC0_NEW_RASTERIZER },
     { nvc0_validate_derived_1,     NVC0_NEW_FRAGPROG | NVC0_NEW_ZSA |
                                    NVC0_NEW_RASTERIZER },
     { nvc0_validate_derived_2,     NVC0_NEW_ZSA | NVC0_NEW_FRAMEBUFFER },
index 8bc33c6a0e0c203e41192df9670ffd7cabed6de0..f9680f5a90f447ff6f8908a997419ea9ad6af341 100644 (file)
@@ -23,7 +23,7 @@ struct nvc0_blend_stateobj {
 struct nvc0_rasterizer_stateobj {
    struct pipe_rasterizer_state pipe;
    int size;
-   uint32_t state[44];
+   uint32_t state[42];
 };
 
 struct nvc0_zsa_stateobj {