nvc0: bind constant buffers for compute on Fermi
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 11 Jan 2016 14:35:21 +0000 (15:35 +0100)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Sun, 21 Feb 2016 09:41:25 +0000 (10:41 +0100)
Loosely based on 3D.

Changs from v3:
 - invalidate COMPUTE CBs after validating 3D CBs because they are
   aliased

Changes from v2:
 - get rid of the 's' param to nvc0_cb_bo_push() because it doesn't
   matter to upload constbufs for compute using the 3d chan

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/nvc0/nvc0_compute.c
src/gallium/drivers/nouveau/nvc0/nvc0_context.c
src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
src/gallium/drivers/nouveau/nvc0/nvc0_state.c
src/gallium/drivers/nouveau/nvc0/nvc0_state_validate.c

index 5c7dc0e1cf89086589960e1094dc0db3ab9706a9..0fe6353b2ab5255f7587892224ef7823b2c387fd 100644 (file)
@@ -138,11 +138,71 @@ nvc0_compute_validate_program(struct nvc0_context *nvc0)
    return false;
 }
 
+static void
+nvc0_compute_validate_constbufs(struct nvc0_context *nvc0)
+{
+   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+   const int s = 5;
+
+   while (nvc0->constbuf_dirty[s]) {
+      int i = ffs(nvc0->constbuf_dirty[s]) - 1;
+      nvc0->constbuf_dirty[s] &= ~(1 << i);
+
+      if (nvc0->constbuf[s][i].user) {
+         struct nouveau_bo *bo = nvc0->screen->uniform_bo;
+         const unsigned base = s << 16;
+         const unsigned size = nvc0->constbuf[s][0].size;
+         assert(i == 0); /* we really only want OpenGL uniforms here */
+         assert(nvc0->constbuf[s][0].u.data);
+
+         if (nvc0->state.uniform_buffer_bound[s] < size) {
+            nvc0->state.uniform_buffer_bound[s] = align(size, 0x100);
+
+            BEGIN_NVC0(push, NVC0_COMPUTE(CB_SIZE), 3);
+            PUSH_DATA (push, nvc0->state.uniform_buffer_bound[s]);
+            PUSH_DATAh(push, bo->offset + base);
+            PUSH_DATA (push, bo->offset + base);
+            BEGIN_NVC0(push, NVC0_COMPUTE(CB_BIND), 1);
+            PUSH_DATA (push, (0 << 8) | 1);
+         }
+         nvc0_cb_bo_push(&nvc0->base, bo, NV_VRAM_DOMAIN(&nvc0->screen->base),
+                         base, nvc0->state.uniform_buffer_bound[s],
+                         0, (size + 3) / 4,
+                         nvc0->constbuf[s][0].u.data);
+      } else {
+         struct nv04_resource *res =
+            nv04_resource(nvc0->constbuf[s][i].u.buf);
+         if (res) {
+            BEGIN_NVC0(push, NVC0_COMPUTE(CB_SIZE), 3);
+            PUSH_DATA (push, nvc0->constbuf[s][i].size);
+            PUSH_DATAh(push, res->address + nvc0->constbuf[s][i].offset);
+            PUSH_DATA (push, res->address + nvc0->constbuf[s][i].offset);
+            BEGIN_NVC0(push, NVC0_COMPUTE(CB_BIND), 1);
+            PUSH_DATA (push, (i << 8) | 1);
+
+            BCTX_REFN(nvc0->bufctx_cp, CP_CB(i), res, RD);
+
+            res->cb_bindings[s] |= 1 << i;
+         } else {
+            BEGIN_NVC0(push, NVC0_COMPUTE(CB_BIND), 1);
+            PUSH_DATA (push, (i << 8) | 0);
+         }
+         if (i == 0)
+            nvc0->state.uniform_buffer_bound[s] = 0;
+      }
+   }
+
+   BEGIN_NVC0(push, NVC0_COMPUTE(FLUSH), 1);
+   PUSH_DATA (push, NVC0_COMPUTE_FLUSH_CB);
+}
+
 static bool
 nvc0_compute_state_validate(struct nvc0_context *nvc0)
 {
    if (!nvc0_compute_validate_program(nvc0))
       return false;
+   if (nvc0->dirty_cp & NVC0_NEW_CP_CONSTBUF)
+      nvc0_compute_validate_constbufs(nvc0);
 
    /* TODO: textures, samplers, surfaces, global memory buffers */
 
@@ -188,7 +248,7 @@ nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
    struct nvc0_context *nvc0 = nvc0_context(pipe);
    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
    struct nvc0_program *cp = nvc0->compprog;
-   unsigned s, i;
+   unsigned s;
    int ret;
 
    ret = !nvc0_compute_state_validate(nvc0);
@@ -242,14 +302,10 @@ nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
    BEGIN_NVC0(push, SUBC_COMPUTE(0x0360), 1);
    PUSH_DATA (push, 0x1);
 
-   /* rebind all the 3D constant buffers
-    * (looks like binding a CB on COMPUTE clobbers 3D state) */
+   /* Invalidate all 3D constbufs because they are aliased with COMPUTE. */
    nvc0->dirty |= NVC0_NEW_CONSTBUF;
    for (s = 0; s < 5; s++) {
-      for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; i++)
-         if (nvc0->constbuf[s][i].u.buf)
-            nvc0->constbuf_dirty[s] |= 1 << i;
+      nvc0->constbuf_dirty[s] |= nvc0->constbuf_valid[s];
+      nvc0->state.uniform_buffer_bound[s] = 0;
    }
-   memset(nvc0->state.uniform_buffer_bound, 0,
-          sizeof(nvc0->state.uniform_buffer_bound));
 }
index 547b8f5d309e0d20af1f4b268f3685cd1ba48b58..4fed7b24a765af11dfe54faab8b255de99062570 100644 (file)
@@ -241,15 +241,20 @@ nvc0_invalidate_resource_storage(struct nouveau_context *ctx,
       }
       }
 
-      for (s = 0; s < 5; ++s) {
+      for (s = 0; s < 6; ++s) {
       for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i) {
          if (!(nvc0->constbuf_valid[s] & (1 << i)))
             continue;
          if (!nvc0->constbuf[s][i].user &&
              nvc0->constbuf[s][i].u.buf == res) {
-            nvc0->dirty |= NVC0_NEW_CONSTBUF;
             nvc0->constbuf_dirty[s] |= 1 << i;
-            nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(s, i));
+            if (unlikely(s == 5)) {
+               nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF;
+               nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_CB(i));
+            } else {
+               nvc0->dirty |= NVC0_NEW_CONSTBUF;
+               nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(s, i));
+            }
             if (!--ref)
                return ref;
          }
index e86fe432e3624ef622dcfd10e58b1fcdf57365c5..8487abcf999c248508eef58b78fcccb16fed9b58 100644 (file)
@@ -51,7 +51,7 @@ struct nvc0_graph_state {
    uint8_t c14_bound; /* whether immediate array constbuf is bound */
    uint8_t clip_enable;
    uint32_t clip_mode;
-   uint32_t uniform_buffer_bound[5];
+   uint32_t uniform_buffer_bound[6];
    struct nvc0_transform_feedback_state *tfb;
    bool seamless_cube_map;
 };
index 448211fca14ded02c38bade920ffd6ddc359ffdf..157d628d8490fe2f8bf0ed856783cf8e58a5a269 100644 (file)
@@ -839,7 +839,9 @@ nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
    const unsigned i = index;
 
    if (unlikely(shader == PIPE_SHADER_COMPUTE)) {
-      assert(!cb || !cb->user_buffer);
+      if (nvc0->constbuf[s][i].user)
+         nvc0->constbuf[s][i].u.buf = NULL;
+      else
       if (nvc0->constbuf[s][i].u.buf)
          nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_CB(i));
 
index 5ac3676cb76193e63069fd8770a5ebc05447e43b..2a210e9902294016aaedb8212069a60969cfcdd4 100644 (file)
@@ -467,6 +467,11 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
          }
       }
    }
+
+   /* Invalidate all COMPUTE constbufs because they are aliased with 3D. */
+   nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF;
+   nvc0->constbuf_dirty[5] |= nvc0->constbuf_valid[5];
+   nvc0->state.uniform_buffer_bound[5] = 0;
 }
 
 static void