Mesa (master): nv50,nvc0: handle user constbufs without wrapping them in a resource

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Thu May 17 13:27:18 UTC 2012


Module: Mesa
Branch: master
Commit: fcb28682101dfa127486373411043d5d97a0ff8f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=fcb28682101dfa127486373411043d5d97a0ff8f

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Wed May 16 20:52:41 2012 +0200

nv50,nvc0: handle user constbufs without wrapping them in a resource

---

 src/gallium/drivers/nv50/nv50_context.c        |    5 +-
 src/gallium/drivers/nv50/nv50_context.h        |   17 ++++-
 src/gallium/drivers/nv50/nv50_screen.c         |    7 +-
 src/gallium/drivers/nv50/nv50_screen.h         |    3 +
 src/gallium/drivers/nv50/nv50_shader_state.c   |  109 +++++++++++-------------
 src/gallium/drivers/nv50/nv50_state.c          |   42 ++++++----
 src/gallium/drivers/nv50/nv50_stateobj.h       |   10 ++
 src/gallium/drivers/nvc0/nvc0_context.c        |    5 +-
 src/gallium/drivers/nvc0/nvc0_context.h        |   19 ++++-
 src/gallium/drivers/nvc0/nvc0_screen.c         |    2 +-
 src/gallium/drivers/nvc0/nvc0_screen.h         |    3 +
 src/gallium/drivers/nvc0/nvc0_state.c          |   45 +++++------
 src/gallium/drivers/nvc0/nvc0_state_validate.c |   89 ++++++++------------
 src/gallium/drivers/nvc0/nvc0_stateobj.h       |   10 ++
 14 files changed, 201 insertions(+), 165 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
index 558fe0b..1e6bbaf 100644
--- a/src/gallium/drivers/nv50/nv50_context.c
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -86,8 +86,9 @@ nv50_context_unreference_resources(struct nv50_context *nv50)
       for (i = 0; i < nv50->num_textures[s]; ++i)
          pipe_sampler_view_reference(&nv50->textures[s][i], NULL);
 
-      for (i = 0; i < 16; ++i)
-         pipe_resource_reference(&nv50->constbuf[s][i], NULL);
+      for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i)
+         if (!nv50->constbuf[s][i].user)
+            pipe_resource_reference(&nv50->constbuf[s][i].u.buf, NULL);
    }
 }
 
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index 44a0ba0..8f5363b 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -90,6 +90,7 @@ struct nv50_context {
       uint32_t semantic_color;
       uint32_t semantic_psize;
       int32_t index_bias;
+      boolean uniform_buffer_bound[3];
       boolean prim_restart;
       boolean point_sprite;
       boolean rt_serialize;
@@ -113,7 +114,7 @@ struct nv50_context {
    struct nv50_program *gmtyprog;
    struct nv50_program *fragprog;
 
-   struct pipe_resource *constbuf[3][16];
+   struct nv50_constbuf constbuf[3][NV50_MAX_PIPE_CONSTBUFS];
    uint16_t constbuf_dirty[3];
    uint16_t constbuf_valid[3];
 
@@ -163,6 +164,20 @@ nv50_context_screen(struct nv50_context *nv50)
    return nv50_screen(&nv50->base.screen->base);
 }
 
+/* return index used in nv50_context arrays for a specific shader type */
+static INLINE unsigned
+nv50_context_shader_stage(unsigned pipe)
+{
+   switch (pipe) {
+   case PIPE_SHADER_VERTEX: return 0;
+   case PIPE_SHADER_FRAGMENT: return 1;
+   case PIPE_SHADER_GEOMETRY: return 2;
+   case PIPE_SHADER_COMPUTE: return 3;
+   default:
+      assert(!"invalid/unhandled shader type");
+      return 0;
+   }
+}
 
 /* nv50_context.c */
 struct pipe_context *nv50_create(struct pipe_screen *, void *);
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index c96e028..9f356ff 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -196,7 +196,7 @@ nv50_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
    case PIPE_SHADER_CAP_MAX_CONSTS:
       return 65536 / 16;
    case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
-      return 14;
+      return NV50_MAX_PIPE_CONSTBUFS;
    case PIPE_SHADER_CAP_MAX_ADDRS:
       return 1;
    case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
@@ -437,10 +437,7 @@ nv50_screen_init_hwctx(struct nv50_screen *screen, unsigned tls_space)
    PUSH_DATA (push, screen->uniforms->offset + (3 << 16));
    PUSH_DATA (push, (NV50_CB_AUX << 16) | 0x0200);
 
-   BEGIN_NI04(push, NV50_3D(SET_PROGRAM_CB), 6);
-   PUSH_DATA (push, (NV50_CB_PVP << 12) | 0x001);
-   PUSH_DATA (push, (NV50_CB_PGP << 12) | 0x021);
-   PUSH_DATA (push, (NV50_CB_PFP << 12) | 0x031);
+   BEGIN_NI04(push, NV50_3D(SET_PROGRAM_CB), 3);
    PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf01);
    PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf21);
    PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf31);
diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h
index 9eae08e..4292f7f 100644
--- a/src/gallium/drivers/nv50/nv50_screen.h
+++ b/src/gallium/drivers/nv50/nv50_screen.h
@@ -12,6 +12,9 @@
 #define NV50_TIC_MAX_ENTRIES 2048
 #define NV50_TSC_MAX_ENTRIES 2048
 
+/* doesn't count reserved slots (for auxiliary constants, immediates, etc.) */
+#define NV50_MAX_PIPE_CONSTBUFS 14
+
 struct nv50_context;
 
 #define NV50_CODE_BO_SIZE_LOG2 19
diff --git a/src/gallium/drivers/nv50/nv50_shader_state.c b/src/gallium/drivers/nv50/nv50_shader_state.c
index d070f07..df6764b 100644
--- a/src/gallium/drivers/nv50/nv50_shader_state.c
+++ b/src/gallium/drivers/nv50/nv50_shader_state.c
@@ -35,9 +35,7 @@ nv50_constbufs_validate(struct nv50_context *nv50)
    unsigned s;
 
    for (s = 0; s < 3; ++s) {
-      struct nv04_resource *res;
-      int i;
-      unsigned p, b;
+      unsigned p;
 
       if (s == PIPE_SHADER_FRAGMENT)
          p = NV50_3D_SET_PROGRAM_CB_PROGRAM_FRAGMENT;
@@ -48,68 +46,63 @@ nv50_constbufs_validate(struct nv50_context *nv50)
          p = NV50_3D_SET_PROGRAM_CB_PROGRAM_VERTEX;
 
       while (nv50->constbuf_dirty[s]) {
-         struct nouveau_bo *bo;
-         unsigned start = 0;
-         unsigned words = 0;
-
-         i = ffs(nv50->constbuf_dirty[s]) - 1;
+         const int i = ffs(nv50->constbuf_dirty[s]) - 1;
          nv50->constbuf_dirty[s] &= ~(1 << i);
 
-         res = nv04_resource(nv50->constbuf[s][i]);
-         if (!res) {
-            if (i != 0) {
+         if (nv50->constbuf[s][i].user) {
+            const unsigned b = NV50_CB_PVP + s;
+            unsigned start = 0;
+            unsigned words = nv50->constbuf[s][0].size / 4;
+            if (i) {
+               NOUVEAU_ERR("user constbufs only supported in slot 0\n");
+               continue;
+            }
+            if (!nv50->state.uniform_buffer_bound[s]) {
+               nv50->state.uniform_buffer_bound[s] = TRUE;
                BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
-               PUSH_DATA (push, (i << 8) | p | 0);
+               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);
+
+               BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
+               PUSH_DATA (push, (start << 8) | b);
+               BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr);
+               PUSH_DATAp(push, &nv50->constbuf[s][0].u.data[start * 4], nr);
+
+               start += nr;
+               words -= nr;
             }
-            continue;
-         }
-
-         if (i == 0) {
-            b = NV50_CB_PVP + s;
-
-            /* always upload GL uniforms through CB DATA */
-            bo = nv50->screen->uniforms;
-            words = res->base.width0 / 4;
          } else {
-            b = s * 16 + i;
-
-            assert(0);
-
-            if (!nouveau_resource_mapped_by_gpu(&res->base)) {
-               nouveau_buffer_migrate(&nv50->base, res, NOUVEAU_BO_VRAM);
+            struct nv04_resource *res =
+               nv04_resource(nv50->constbuf[s][i].u.buf);
+            if (res) {
+               /* TODO: allocate persistent bindings */
+               const unsigned b = s * 16 + i;
+
+               assert(nouveau_resource_mapped_by_gpu(&res->base));
+
+               BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
+               PUSH_DATAh(push, res->address + nv50->constbuf[s][i].offset);
+               PUSH_DATA (push, res->address + nv50->constbuf[s][i].offset);
+               PUSH_DATA (push, (b << 16) |
+                          (nv50->constbuf[s][i].size & 0xffff));
+               BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
+               PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);
 
-               BEGIN_NV04(push, NV50_3D(CODE_CB_FLUSH), 1);
-               PUSH_DATA (push, 0);
+               BCTX_REFN(nv50->bufctx_3d, CB(s, i), res, RD);
+            } else {
+               BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
+               PUSH_DATA (push, (i << 8) | p | 0);
             }
-            BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
-            PUSH_DATAh(push, res->address);
-            PUSH_DATA (push, res->address);
-            PUSH_DATA (push, (b << 16) | (res->base.width0 & 0xffff));
-            BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
-            PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);
-
-            bo = res->bo;
-         }
-
-         if (bo != nv50->screen->uniforms)
-            BCTX_REFN(nv50->bufctx_3d, CB(s, i), res, RD);
-
-         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);
-
-            BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
-            PUSH_DATA (push, (start << 8) | b);
-            BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr);
-            PUSH_DATAp(push, &res->data[start * 4], nr);
-
-            start += nr;
-            words -= nr;
+            if (i == 0)
+               nv50->state.uniform_buffer_bound[s] = FALSE;
          }
       }
    }
diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c
index 7f840e2..eea3ffd 100644
--- a/src/gallium/drivers/nv50/nv50_state.c
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -751,28 +751,36 @@ nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
 {
    struct nv50_context *nv50 = nv50_context(pipe);
    struct pipe_resource *res = cb ? cb->buffer : NULL;
+   const unsigned s = nv50_context_shader_stage(shader);
+   const unsigned i = index;
 
-   if (cb && cb->user_buffer) {
-      res = nouveau_user_buffer_create(pipe->screen, cb->user_buffer,
-                                       cb->buffer_size,
-                                       PIPE_BIND_CONSTANT_BUFFER);
-   }
-
-   pipe_resource_reference(&nv50->constbuf[shader][index], res);
+   if (shader == PIPE_SHADER_COMPUTE)
+      return;
 
-   nv50->constbuf_dirty[shader] |= 1 << index;
-   if (res)
-      nv50->constbuf_valid[shader] |= 1 << index;
+   if (nv50->constbuf[s][i].user)
+      nv50->constbuf[s][i].u.buf = NULL;
    else
-      nv50->constbuf_valid[shader] &= ~(1 << index);
-
-   nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(shader, index));
+   if (nv50->constbuf[s][i].u.buf)
+      nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(s, i));
+
+   pipe_resource_reference(&nv50->constbuf[s][i].u.buf, res);
+
+   nv50->constbuf[s][i].user = (cb && cb->user_buffer) ? TRUE : FALSE;
+   if (nv50->constbuf[s][i].user) {
+      nv50->constbuf[s][i].u.data = cb->user_buffer;
+      nv50->constbuf[s][i].size = cb->buffer_size;
+      nv50->constbuf_valid[s] |= 1 << i;
+   } else
+   if (res) {
+      nv50->constbuf[s][i].offset = cb->buffer_offset;
+      nv50->constbuf[s][i].size = align(cb->buffer_size, 0x100);
+      nv50->constbuf_valid[s] |= 1 << i;
+   } else {
+      nv50->constbuf_valid[s] &= ~(1 << i);
+   }
+   nv50->constbuf_dirty[s] |= 1 << i;
 
    nv50->dirty |= NV50_NEW_CONSTBUF;
-
-   if (cb && cb->user_buffer) {
-      pipe_resource_reference(&res, NULL);
-   }
 }
 
 /* =============================================================================
diff --git a/src/gallium/drivers/nv50/nv50_stateobj.h b/src/gallium/drivers/nv50/nv50_stateobj.h
index 8a9260c..eec1465 100644
--- a/src/gallium/drivers/nv50/nv50_stateobj.h
+++ b/src/gallium/drivers/nv50/nv50_stateobj.h
@@ -34,6 +34,16 @@ struct nv50_zsa_stateobj {
    uint32_t state[29];
 };
 
+struct nv50_constbuf {
+   union {
+      struct pipe_resource *buf;
+      const uint8_t *data;
+   } u;
+   uint32_t size; /* max 65536 */
+   uint16_t offset;
+   boolean user; /* should only be TRUE if u.data is valid and non-NULL */
+};
+
 struct nv50_vertex_element {
    struct pipe_vertex_element pipe;
    uint32_t state;
diff --git a/src/gallium/drivers/nvc0/nvc0_context.c b/src/gallium/drivers/nvc0/nvc0_context.c
index b0ab5bd..f930814 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.c
+++ b/src/gallium/drivers/nvc0/nvc0_context.c
@@ -72,8 +72,9 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0)
       for (i = 0; i < nvc0->num_textures[s]; ++i)
          pipe_sampler_view_reference(&nvc0->textures[s][i], NULL);
 
-      for (i = 0; i < 16; ++i)
-         pipe_resource_reference(&nvc0->constbuf[s][i], NULL);
+      for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i)
+         if (!nvc0->constbuf[s][i].user)
+            pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, NULL);
    }
 
    for (i = 0; i < nvc0->num_tfbbufs; ++i)
diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h
index d2dee03..261cfb1 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nvc0/nvc0_context.h
@@ -121,7 +121,7 @@ struct nvc0_context {
    struct nvc0_program *gmtyprog;
    struct nvc0_program *fragprog;
 
-   struct pipe_resource *constbuf[5][16];
+   struct nvc0_constbuf constbuf[5][NVC0_MAX_PIPE_CONSTBUFS];
    uint16_t constbuf_dirty[5];
 
    struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
@@ -168,6 +168,23 @@ nvc0_context(struct pipe_context *pipe)
    return (struct nvc0_context *)pipe;
 }
 
+static INLINE unsigned
+nvc0_shader_stage(unsigned pipe)
+{
+   switch (pipe) {
+   case PIPE_SHADER_VERTEX: return 0;
+/* case PIPE_SHADER_TESSELLATION_CONTROL: return 1; */
+/* case PIPE_SHADER_TESSELLATION_EVALUATION: return 2; */
+   case PIPE_SHADER_GEOMETRY: return 3;
+   case PIPE_SHADER_FRAGMENT: return 4;
+   case PIPE_SHADER_COMPUTE: return 5;
+   default:
+      assert(!"invalid PIPE_SHADER type");
+      return 0;
+   }
+}
+
+
 /* nvc0_context.c */
 struct pipe_context *nvc0_create(struct pipe_screen *, void *);
 void nvc0_bufctx_fence(struct nvc0_context *, struct nouveau_bufctx *,
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index 5d6befd..498207f 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -190,7 +190,7 @@ nvc0_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
    case PIPE_SHADER_CAP_MAX_CONSTS:
       return 65536 / 16;
    case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
-      return 14;
+      return NVC0_MAX_PIPE_CONSTBUFS;
    case PIPE_SHADER_CAP_MAX_ADDRS:
       return 1;
    case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.h b/src/gallium/drivers/nvc0/nvc0_screen.h
index 8bcc147..69cddf2 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.h
+++ b/src/gallium/drivers/nvc0/nvc0_screen.h
@@ -14,6 +14,9 @@
 #define NVC0_TIC_MAX_ENTRIES 2048
 #define NVC0_TSC_MAX_ENTRIES 2048
 
+/* doesn't count reserved slots (for auxiliary constants, immediates, etc.) */
+#define NVC0_MAX_PIPE_CONSTBUFS 14
+
 struct nvc0_context;
 
 struct nvc0_blitctx;
diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c
index 4016125..cab238e 100644
--- a/src/gallium/drivers/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nvc0/nvc0_state.c
@@ -620,38 +620,33 @@ nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
 {
    struct nvc0_context *nvc0 = nvc0_context(pipe);
    struct pipe_resource *res = cb ? cb->buffer : NULL;
+   const unsigned s = nvc0_shader_stage(shader);
+   const unsigned i = index;
 
-   if (cb && cb->user_buffer) {
-      res = nouveau_user_buffer_create(pipe->screen, cb->user_buffer,
-                                       cb->buffer_size,
-                                       PIPE_BIND_CONSTANT_BUFFER);
-   }
+   if (shader == PIPE_SHADER_COMPUTE)
+      return;
 
-   switch (shader) {
-   case PIPE_SHADER_VERTEX: shader = 0; break;
-      /*
-   case PIPE_SHADER_TESSELLATION_CONTROL: shader = 1; break;
-   case PIPE_SHADER_TESSELLATION_EVALUATION: shader = 2; break;
-      */
-   case PIPE_SHADER_GEOMETRY: shader = 3; break;
-   case PIPE_SHADER_FRAGMENT: shader = 4; break;
-   default:
-      assert(0);
-      break;
-   }
+   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_3d, NVC0_BIND_CB(s, i));
 
-   if (nvc0->constbuf[shader][index])
-      nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(shader, index));
+   pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, res);
 
-   pipe_resource_reference(&nvc0->constbuf[shader][index], res);
+   nvc0->constbuf[s][i].user = (cb && cb->user_buffer) ? TRUE : FALSE;
+   if (nvc0->constbuf[s][i].user) {
+      nvc0->constbuf[s][i].u.data = cb->user_buffer;
+      nvc0->constbuf[s][i].size = cb->buffer_size;
+   } else
+   if (cb) {
+      nvc0->constbuf[s][i].offset = cb->buffer_offset;
+      nvc0->constbuf[s][i].size = align(cb->buffer_size, 0x100);
+   }
 
-   nvc0->constbuf_dirty[shader] |= 1 << index;
+   nvc0->constbuf_dirty[s] |= 1 << i;
 
    nvc0->dirty |= NVC0_NEW_CONSTBUF;
-
-   if (cb->user_buffer) {
-      pipe_resource_reference(&res, NULL);
-   }
 }
 
 /* =============================================================================
diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c
index 5d34f2b..c2d115e 100644
--- a/src/gallium/drivers/nvc0/nvc0_state_validate.c
+++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c
@@ -355,70 +355,53 @@ static void
 nvc0_constbufs_validate(struct nvc0_context *nvc0)
 {
    struct nouveau_pushbuf *push = nvc0->base.pushbuf;
-   struct nouveau_bo *bo;
    unsigned s;
 
    for (s = 0; s < 5; ++s) {
-      struct nv04_resource *res;
-      int i;
-
       while (nvc0->constbuf_dirty[s]) {
-         unsigned base = 0;
-         unsigned words = 0;
-         boolean rebind = TRUE;
-
-         i = ffs(nvc0->constbuf_dirty[s]) - 1;
+         int i = ffs(nvc0->constbuf_dirty[s]) - 1;
          nvc0->constbuf_dirty[s] &= ~(1 << i);
 
-         res = nv04_resource(nvc0->constbuf[s][i]);
-         if (!res) {
-            BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
-            PUSH_DATA (push, (i << 4) | 0);
-            if (i == 0)
-               nvc0->state.uniform_buffer_bound[s] = 0;
-            continue;
-         }
-
-         if (!nouveau_resource_mapped_by_gpu(&res->base)) {
-            if (i == 0 && (res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY)) {
-               base = s << 16;
-               bo = nvc0->screen->uniform_bo;
-
-               if (nvc0->state.uniform_buffer_bound[s] >= res->base.width0)
-                  rebind = FALSE;
-               else
-                  nvc0->state.uniform_buffer_bound[s] =
-                     align(res->base.width0, 0x100);
-
-               words = res->base.width0 / 4;
-            } else {
-               nouveau_buffer_migrate(&nvc0->base, res, NOUVEAU_BO_VRAM);
-               bo = res->bo;
-               base = res->offset;
+         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_3D(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_3D(CB_BIND(s)), 1);
+               PUSH_DATA (push, (0 << 4) | 1);
             }
+            nvc0_cb_push(&nvc0->base, bo, NOUVEAU_BO_VRAM,
+                         base, nvc0->state.uniform_buffer_bound[s],
+                         0, (size + 3) / 4,
+                         nvc0->constbuf[s][0].u.data);
          } else {
-            bo = res->bo;
-            base = res->offset;
+            struct nv04_resource *res =
+               nv04_resource(nvc0->constbuf[s][i].u.buf);
+            if (res) {
+               BEGIN_NVC0(push, NVC0_3D(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_3D(CB_BIND(s)), 1);
+               PUSH_DATA (push, (i << 4) | 1);
+
+               BCTX_REFN(nvc0->bufctx_3d, CB(s, i), res, RD);
+            } else {
+               BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
+               PUSH_DATA (push, (i << 4) | 0);
+            }
             if (i == 0)
                nvc0->state.uniform_buffer_bound[s] = 0;
          }
-
-         if (bo != nvc0->screen->uniform_bo)
-            BCTX_REFN(nvc0->bufctx_3d, CB(s, i), res, RD);
-
-         if (rebind) {
-            BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
-            PUSH_DATA (push, align(res->base.width0, 0x100));
-            PUSH_DATAh(push, bo->offset + base);
-            PUSH_DATA (push, bo->offset + base);
-            BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
-            PUSH_DATA (push, (i << 4) | 1);
-         }
-
-         if (words)
-            nvc0_cb_push(&nvc0->base,
-                         bo, NOUVEAU_BO_VRAM, base, res->base.width0,
-                         0, words, (const uint32_t *)res->data);
       }
    }
 }
diff --git a/src/gallium/drivers/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nvc0/nvc0_stateobj.h
index 16d336c..5afbffb 100644
--- a/src/gallium/drivers/nvc0/nvc0_stateobj.h
+++ b/src/gallium/drivers/nvc0/nvc0_stateobj.h
@@ -32,6 +32,16 @@ struct nvc0_zsa_stateobj {
    uint32_t state[26];
 };
 
+struct nvc0_constbuf {
+   union {
+      struct pipe_resource *buf;
+      const void *data;
+   } u;
+   uint32_t size;
+   uint16_t offset;
+   boolean user; /* should only be TRUE if u.data is valid and non-NULL */
+};
+
 struct nvc0_vertex_element {
    struct pipe_vertex_element pipe;
    uint32_t state;




More information about the mesa-commit mailing list