nv50: rename nv50_context::dirty to nv50_context::dirty_3d
[mesa.git] / src / gallium / drivers / nouveau / nv50 / nv50_shader_state.c
index c44d208670d8ecdd9c3197db424336aca7599693..7e8acd290e8a479fc3a1bb424b68bd35be604315 100644 (file)
@@ -27,6 +27,7 @@
 #include "util/u_inlines.h"
 
 #include "nv50/nv50_context.h"
+#include "nv50/nv50_query_hw.h"
 
 void
 nv50_constbufs_validate(struct nv50_context *nv50)
@@ -46,7 +47,7 @@ nv50_constbufs_validate(struct nv50_context *nv50)
          p = NV50_3D_SET_PROGRAM_CB_PROGRAM_VERTEX;
 
       while (nv50->constbuf_dirty[s]) {
-         const int i = ffs(nv50->constbuf_dirty[s]) - 1;
+         const unsigned i = (unsigned)ffs(nv50->constbuf_dirty[s]) - 1;
 
          assert(i < NV50_MAX_PIPE_CONSTBUFS);
          nv50->constbuf_dirty[s] &= ~(1 << i);
@@ -60,19 +61,14 @@ nv50_constbufs_validate(struct nv50_context *nv50)
                continue;
             }
             if (!nv50->state.uniform_buffer_bound[s]) {
-               nv50->state.uniform_buffer_bound[s] = TRUE;
+               nv50->state.uniform_buffer_bound[s] = true;
                BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
                PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);
             }
             while (words) {
-               unsigned nr;
-
-               if (!PUSH_SPACE(push, 16))
-                  break;
-               nr = PUSH_AVAIL(push);
-               assert(nr >= 16);
-               nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN);
+               unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN);
 
+               PUSH_SPACE(push, nr + 3);
                BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
                PUSH_DATA (push, (start << 8) | b);
                BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr);
@@ -99,33 +95,35 @@ nv50_constbufs_validate(struct nv50_context *nv50)
                PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);
 
                BCTX_REFN(nv50->bufctx_3d, CB(s, i), res, RD);
+
+               nv50->cb_dirty = 1; /* Force cache flush for UBO. */
             } else {
                BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
                PUSH_DATA (push, (i << 8) | p | 0);
             }
             if (i == 0)
-               nv50->state.uniform_buffer_bound[s] = FALSE;
+               nv50->state.uniform_buffer_bound[s] = false;
          }
       }
    }
 }
 
-static boolean
+static bool
 nv50_program_validate(struct nv50_context *nv50, struct nv50_program *prog)
 {
    if (!prog->translated) {
       prog->translated = nv50_program_translate(
-         prog, nv50->screen->base.device->chipset);
+         prog, nv50->screen->base.device->chipset, &nv50->base.debug);
       if (!prog->translated)
-         return FALSE;
+         return false;
    } else
    if (prog->mem)
-      return TRUE;
+      return true;
 
    return nv50_program_upload_code(nv50, prog);
 }
 
-static INLINE void
+static inline void
 nv50_program_update_context_state(struct nv50_context *nv50,
                                   struct nv50_program *prog, int stage)
 {
@@ -136,7 +134,7 @@ nv50_program_update_context_state(struct nv50_context *nv50,
          nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TLS);
       if (!nv50->state.tls_required || nv50->state.new_tls_space)
          BCTX_REFN_bo(nv50->bufctx_3d, TLS, flags, nv50->screen->tls_bo);
-      nv50->state.new_tls_space = FALSE;
+      nv50->state.new_tls_space = false;
       nv50->state.tls_required |= 1 << stage;
    } else {
       if (nv50->state.tls_required == (1 << stage))
@@ -171,9 +169,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;
+
+   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_3d & (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);
@@ -186,6 +198,17 @@ nv50_fragprog_validate(struct nv50_context *nv50)
    PUSH_DATA (push, fp->fp.flags[1]);
    BEGIN_NV04(push, NV50_3D(FP_START_ID), 1);
    PUSH_DATA (push, fp->code_base);
+
+   if (nv50->screen->tesla->oclass >= NVA3_3D_CLASS) {
+      BEGIN_NV04(push, SUBC_3D(NVA3_3D_FP_MULTISAMPLE), 1);
+      if (nv50->min_samples > 1 || fp->fp.has_samplemask)
+         PUSH_DATA(push,
+                   NVA3_3D_FP_MULTISAMPLE_FORCE_PER_SAMPLE |
+                   (NVA3_3D_FP_MULTISAMPLE_EXPORT_SAMPLE_MASK *
+                    fp->fp.has_samplemask));
+      else
+         PUSH_DATA(push, 0);
+   }
 }
 
 void
@@ -195,6 +218,8 @@ nv50_gmtyprog_validate(struct nv50_context *nv50)
    struct nv50_program *gp = nv50->gmtyprog;
 
    if (gp) {
+      if (!nv50_program_validate(nv50, gp))
+         return;
       BEGIN_NV04(push, NV50_3D(GP_REG_ALLOC_TEMP), 1);
       PUSH_DATA (push, gp->max_gpr);
       BEGIN_NV04(push, NV50_3D(GP_REG_ALLOC_RESULT), 1);
@@ -228,11 +253,11 @@ nv50_sprite_coords_validate(struct nv50_context *nv50)
          for (i = 0; i < 8; ++i)
             PUSH_DATA(push, 0);
 
-         nv50->state.point_sprite = FALSE;
+         nv50->state.point_sprite = false;
       }
       return;
    } else {
-      nv50->state.point_sprite = TRUE;
+      nv50->state.point_sprite = true;
    }
 
    memset(pntc, 0, sizeof(pntc));
@@ -284,7 +309,7 @@ nv50_validate_derived_rs(struct nv50_context *nv50)
       PUSH_DATA (push, !nv50->rast->pipe.rasterizer_discard);
    }
 
-   if (nv50->dirty & NV50_NEW_FRAGPROG)
+   if (nv50->dirty_3d & NV50_NEW_FRAGPROG)
       return;
    psize = nv50->state.semantic_psize & ~NV50_3D_SEMANTIC_PTSZ_PTSZ_EN__MASK;
    color = nv50->state.semantic_color & ~NV50_3D_SEMANTIC_COLOR_CLMP_EN;
@@ -344,6 +369,8 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
    struct nv50_varying dummy;
    int i, n, c, m;
    uint32_t primid = 0;
+   uint32_t layerid = 0;
+   uint32_t viewportid = 0;
    uint32_t psiz = 0x000;
    uint32_t interp = fp->fp.interp;
    uint32_t colors = fp->fp.colors;
@@ -351,9 +378,9 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
    uint8_t map[64];
    uint8_t so_map[64];
 
-   if (!(nv50->dirty & (NV50_NEW_VERTPROG |
-                        NV50_NEW_FRAGPROG |
-                        NV50_NEW_GMTYPROG))) {
+   if (!(nv50->dirty_3d & (NV50_NEW_VERTPROG |
+                           NV50_NEW_FRAGPROG |
+                           NV50_NEW_GMTYPROG))) {
       uint8_t bfc, ffc;
       ffc = (nv50->state.semantic_color & NV50_3D_SEMANTIC_COLOR_FFC0_ID__MASK);
       bfc = (nv50->state.semantic_color & NV50_3D_SEMANTIC_COLOR_BFC0_ID__MASK)
@@ -398,16 +425,29 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
          if (vp->out[n].sn == fp->in[i].sn &&
              vp->out[n].si == fp->in[i].si)
             break;
+      switch (fp->in[i].sn) {
+      case TGSI_SEMANTIC_PRIMID:
+         primid = m;
+         break;
+      case TGSI_SEMANTIC_LAYER:
+         layerid = m;
+         break;
+      case TGSI_SEMANTIC_VIEWPORT_INDEX:
+         viewportid = m;
+         break;
+      }
       m = nv50_vec4_map(map, m, lin,
                         &fp->in[i], (n < vp->out_nr) ? &vp->out[n] : &dummy);
    }
 
-   /* PrimitiveID either is replaced by the system value, or
-    * written by the geometry shader into an output register
-    */
-   if (fp->gp.primid < 0x80) {
-      primid = m;
-      map[m++] = vp->gp.primid;
+   if (vp->gp.has_layer && !layerid) {
+      layerid = m;
+      map[m++] = vp->gp.layerid;
+   }
+
+   if (vp->gp.has_viewport && !viewportid) {
+      viewportid = m;
+      map[m++] = vp->gp.viewportid;
    }
 
    if (nv50->rast->pipe.point_size_per_vertex) {
@@ -452,23 +492,31 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
       PUSH_DATAp(push, map, n);
    } else {
       BEGIN_NV04(push, NV50_3D(VP_GP_BUILTIN_ATTR_EN), 1);
-      PUSH_DATA (push, vp->vp.attrs[2]);
+      PUSH_DATA (push, vp->vp.attrs[2] | fp->vp.attrs[2]);
 
       BEGIN_NV04(push, NV50_3D(SEMANTIC_PRIM_ID), 1);
       PUSH_DATA (push, primid);
 
+      assert(m > 0);
       BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP_SIZE), 1);
       PUSH_DATA (push, m);
       BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP(0)), n);
       PUSH_DATAp(push, map, n);
    }
 
-   BEGIN_NV04(push, NV50_3D(SEMANTIC_COLOR), 4);
+   BEGIN_NV04(push, NV50_3D(GP_VIEWPORT_ID_ENABLE), 5);
+   PUSH_DATA (push, vp->gp.has_viewport);
    PUSH_DATA (push, colors);
    PUSH_DATA (push, (vp->vp.clpd_nr << 8) | 4);
-   PUSH_DATA (push, 0);
+   PUSH_DATA (push, layerid);
    PUSH_DATA (push, psiz);
 
+   BEGIN_NV04(push, NV50_3D(SEMANTIC_VIEWPORT), 1);
+   PUSH_DATA (push, viewportid);
+
+   BEGIN_NV04(push, NV50_3D(LAYER), 1);
+   PUSH_DATA (push, vp->gp.has_layer << 16);
+
    BEGIN_NV04(push, NV50_3D(FP_INTERPOLANT_CTRL), 1);
    PUSH_DATA (push, interp);
 
@@ -516,6 +564,8 @@ nv50_vp_gp_mapping(uint8_t *map, int m,
          oid += mv & 1;
       }
    }
+   if (!m)
+      map[m++] = 0;
    return m;
 }
 
@@ -540,6 +590,7 @@ nv50_gp_linkage_validate(struct nv50_context *nv50)
    BEGIN_NV04(push, NV50_3D(VP_GP_BUILTIN_ATTR_EN), 1);
    PUSH_DATA (push, vp->vp.attrs[2] | gp->vp.attrs[2]);
 
+   assert(m > 0);
    BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP_SIZE), 1);
    PUSH_DATA (push, m);
    BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP(0)), n);
@@ -591,27 +642,28 @@ nv50_stream_output_validate(struct nv50_context *nv50)
       const unsigned n = nv50->screen->base.class_3d >= NVA0_3D_CLASS ? 4 : 3;
 
       if (n == 4 && !targ->clean)
-         nv84_query_fifo_wait(push, targ->pq);
+         nv84_hw_query_fifo_wait(push, nv50_query(targ->pq));
       BEGIN_NV04(push, NV50_3D(STRMOUT_ADDRESS_HIGH(i)), n);
       PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset);
       PUSH_DATA (push, buf->address + targ->pipe.buffer_offset);
       PUSH_DATA (push, so->num_attribs[i]);
       if (n == 4) {
          PUSH_DATA(push, targ->pipe.buffer_size);
-
-         BEGIN_NV04(push, NVA0_3D(STRMOUT_OFFSET(i)), 1);
          if (!targ->clean) {
             assert(targ->pq);
-            nv50_query_pushbuf_submit(push, targ->pq, 0x4);
+            nv50_hw_query_pushbuf_submit(push, NVA0_3D_STRMOUT_OFFSET(i),
+                                         nv50_query(targ->pq), 0x4);
          } else {
+            BEGIN_NV04(push, NVA0_3D(STRMOUT_OFFSET(i)), 1);
             PUSH_DATA(push, 0);
-            targ->clean = FALSE;
+            targ->clean = false;
          }
       } else {
          const unsigned limit = targ->pipe.buffer_size /
             (so->stride[i] * nv50->state.prim_size);
          prims = MIN2(prims, limit);
       }
+      targ->stride = so->stride[i];
       BCTX_REFN(nv50->bufctx_3d, SO, buf, WR);
    }
    if (prims != ~0) {