[Mesa-dev] [PATCH 03/12] nvc0: bind constant buffers for compute on Fermi

Samuel Pitoiset samuel.pitoiset at gmail.com
Sat Feb 6 22:38:02 UTC 2016


Loosely based on 3D.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
 src/gallium/drivers/nouveau/nvc0/nvc0_compute.c | 60 +++++++++++++++++++++++++
 src/gallium/drivers/nouveau/nvc0/nvc0_context.c | 11 +++--
 src/gallium/drivers/nouveau/nvc0/nvc0_screen.h  |  2 +-
 src/gallium/drivers/nouveau/nvc0/nvc0_state.c   |  4 +-
 4 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c
index 5c7dc0e..3ac7ce1 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_compute.c
@@ -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], 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 */
 
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
index 547b8f5..4fed7b2 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c
@@ -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;
          }
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
index 1a56177..d7c427b 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
@@ -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;
 };
 
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
index cf3d349..1246a9c 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
@@ -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));
 
-- 
2.6.4



More information about the mesa-dev mailing list