OSDN Git Service

nouveau,nvc0: fix/improve handling of multiple constant buffers
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 20 Oct 2011 20:42:59 +0000 (22:42 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Fri, 21 Oct 2011 21:00:40 +0000 (23:00 +0200)
src/gallium/drivers/nouveau/nouveau_buffer.c
src/gallium/drivers/nouveau/nouveau_context.h
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_transfer.c
src/gallium/drivers/nvc0/nvc0_context.c
src/gallium/drivers/nvc0/nvc0_context.h
src/gallium/drivers/nvc0/nvc0_state_validate.c
src/gallium/drivers/nvc0/nvc0_transfer.c

index 60d8e37..f822625 100644 (file)
@@ -24,14 +24,19 @@ static INLINE boolean
 nouveau_buffer_allocate(struct nouveau_screen *screen,
                         struct nv04_resource *buf, unsigned domain)
 {
+   uint32_t size = buf->base.width0;
+
+   if (buf->base.bind & PIPE_BIND_CONSTANT_BUFFER)
+      size = align(size, 0x100);
+
    if (domain == NOUVEAU_BO_VRAM) {
-      buf->mm = nouveau_mm_allocate(screen->mm_VRAM, buf->base.width0,
+      buf->mm = nouveau_mm_allocate(screen->mm_VRAM, size,
                                     &buf->bo, &buf->offset);
       if (!buf->bo)
          return nouveau_buffer_allocate(screen, buf, NOUVEAU_BO_GART);
    } else
    if (domain == NOUVEAU_BO_GART) {
-      buf->mm = nouveau_mm_allocate(screen->mm_GART, buf->base.width0,
+      buf->mm = nouveau_mm_allocate(screen->mm_GART, size,
                                     &buf->bo, &buf->offset);
       if (!buf->bo)
          return FALSE;
@@ -129,8 +134,12 @@ nouveau_buffer_upload(struct nouveau_context *nv, struct nv04_resource *buf,
    uint32_t offset;
 
    if (size <= 192) {
-      nv->push_data(nv, buf->bo, buf->offset + start, buf->domain,
-                    size, buf->data + start);
+      if (buf->base.bind & PIPE_BIND_CONSTANT_BUFFER)
+         nv->push_cb(nv, buf->bo, buf->domain, buf->offset, buf->base.width0,
+                     start, size / 4, (const uint32_t *)(buf->data + start));
+      else
+         nv->push_data(nv, buf->bo, buf->offset + start, buf->domain,
+                       size, buf->data + start);
       return TRUE;
    }
 
index 7b5f3f1..92aea76 100644 (file)
@@ -8,6 +8,7 @@ struct nouveau_context {
    struct nouveau_screen *screen;
 
    boolean vbo_dirty;
+   boolean cb_dirty;
 
    void (*copy_data)(struct nouveau_context *,
                      struct nouveau_bo *dst, unsigned, unsigned,
@@ -15,6 +16,11 @@ struct nouveau_context {
    void (*push_data)(struct nouveau_context *,
                      struct nouveau_bo *dst, unsigned, unsigned,
                      unsigned, const void *);
+   /* base, size refer to the whole constant buffer */
+   void (*push_cb)(struct nouveau_context *,
+                   struct nouveau_bo *, unsigned domain,
+                   unsigned base, unsigned size,
+                   unsigned offset, unsigned words, const uint32_t *);
 };
 
 static INLINE struct nouveau_context *
index edd7915..2bf634a 100644 (file)
@@ -53,6 +53,7 @@
 #define NV50_BUFCTX_TEXTURES 3
 #define NV50_BUFCTX_COUNT    4
 
+#define NV50_CB_TMP 123
 /* fixed constant buffer binding points - low indices for user's constbufs */
 #define NV50_CB_PVP 124
 #define NV50_CB_PGP 126
@@ -206,6 +207,11 @@ nv50_m2mf_copy_linear(struct nouveau_context *pipe,
                       struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
                       struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
                       unsigned size);
+void
+nv50_cb_push(struct nouveau_context *nv,
+             struct nouveau_bo *bo, unsigned domain,
+             unsigned base, unsigned size,
+             unsigned offset, unsigned words, const uint32_t *data);
 
 /* nv50_vbo.c */
 void nv50_draw_vbo(struct pipe_context *, const struct pipe_draw_info *);
index c86c417..6f860e7 100644 (file)
@@ -364,3 +364,36 @@ nv50_miptree_transfer_unmap(struct pipe_context *pctx,
    nouveau_bo_unmap(tx->rect[1].bo);
 }
 
+void
+nv50_cb_push(struct nouveau_context *nv,
+             struct nouveau_bo *bo, unsigned domain,
+             unsigned base, unsigned size,
+             unsigned offset, unsigned words, const uint32_t *data)
+{
+   struct nouveau_channel *chan = nv->screen->channel;
+
+   assert(!(offset & 3));
+   size = align(size, 0x100);
+
+   while (words) {
+      unsigned nr;
+
+      MARK_RING(chan, 24, 2);
+      nr = AVAIL_RING(chan);
+      nr = MIN2(nr - 7, words);
+      nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);
+
+      BEGIN_RING(chan, RING_3D(CB_DEF_ADDRESS_HIGH), 3);
+      OUT_RELOCh(chan, bo, base, domain | NOUVEAU_BO_WR);
+      OUT_RELOCl(chan, bo, base, domain | NOUVEAU_BO_WR);
+      OUT_RING  (chan, (NV50_CB_TMP << 16) | (size & 0xffff));
+      BEGIN_RING(chan, RING_3D(CB_ADDR), 1);
+      OUT_RING  (chan, (offset << 6) | NV50_CB_TMP);
+      BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nr);
+      OUT_RINGp (chan, data, nr);
+
+      words -= nr;
+      data += nr;
+      offset += nr * 4;
+   }
+}
index d493d4b..2927a09 100644 (file)
@@ -124,6 +124,7 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
    nvc0->base.screen    = &screen->base;
    nvc0->base.copy_data = nvc0_m2mf_copy_linear;
    nvc0->base.push_data = nvc0_m2mf_push_linear;
+   nvc0->base.push_cb = nvc0_cb_push;
 
    pipe->winsys = pipe_winsys;
    pipe->screen = pscreen;
index c46e743..4435c1b 100644 (file)
@@ -221,6 +221,11 @@ nvc0_m2mf_copy_linear(struct nouveau_context *nv,
                      struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom,
                      struct nouveau_bo *src, unsigned srcoff, unsigned srcdom,
                      unsigned size);
+void
+nvc0_cb_push(struct nouveau_context *,
+             struct nouveau_bo *bo, unsigned domain,
+             unsigned base, unsigned size,
+             unsigned offset, unsigned words, const uint32_t *data);
 
 /* nvc0_vbo.c */
 void nvc0_draw_vbo(struct pipe_context *, const struct pipe_draw_info *);
index e60ed97..1ec95b7 100644 (file)
@@ -340,7 +340,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
 
       while (nvc0->constbuf_dirty[s]) {
          unsigned base = 0;
-         unsigned offset = 0, words = 0;
+         unsigned words = 0;
          boolean rebind = TRUE;
 
          i = ffs(nvc0->constbuf_dirty[s]) - 1;
@@ -356,7 +356,7 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
          }
 
          if (!nouveau_resource_mapped_by_gpu(&res->base)) {
-            if (i == 0) {
+            if (i == 0 && (res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY)) {
                base = s << 16;
                bo = nvc0->screen->uniforms;
 
@@ -365,19 +365,16 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
                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 0
-            nvc0_m2mf_push_linear(nvc0, bo, NOUVEAU_BO_VRAM,
-                                  base, res->base.width0, res->data);
-            BEGIN_RING(chan, RING_3D_(0x021c), 1);
-            OUT_RING  (chan, 0x1111);
-#else
-            words = res->base.width0 / 4;
-#endif
          } else {
             bo = res->bo;
+            base = res->offset;
             if (i == 0)
                nvc0->state.uniform_buffer_bound[s] = 0;
          }
@@ -396,27 +393,10 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0)
             OUT_RING  (chan, (i << 4) | 1);
          }
 
-         while (words) {
-            unsigned nr = AVAIL_RING(chan);
-
-            if (nr < 16) {
-               FIRE_RING(chan);
-               continue;
-            }
-            nr = MIN2(MIN2(nr - 6, words), NV04_PFIFO_MAX_PACKET_LEN - 1);
-
-            MARK_RING (chan, nr + 5, 2);
-            BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
-            OUT_RING  (chan, align(res->base.width0, 0x100));
-            OUT_RELOCh(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-            OUT_RELOCl(chan, bo, base, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-            BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
-            OUT_RING  (chan, offset);
-            OUT_RINGp (chan, &res->data[offset], nr);
-
-            offset += nr * 4;
-            words -= nr;
-         }
+         if (words)
+            nvc0_cb_push(&nvc0->base,
+                         bo, NOUVEAU_BO_VRAM, base, res->base.width0,
+                         0, words, (const uint32_t *)res->data);
       }
    }
 }
index 6404c8c..f168637 100644 (file)
@@ -365,3 +365,39 @@ nvc0_miptree_transfer_unmap(struct pipe_context *pctx,
    nouveau_bo_unmap(tx->rect[1].bo);
 }
 
+void
+nvc0_cb_push(struct nouveau_context *nv,
+             struct nouveau_bo *bo, unsigned domain,
+             unsigned base, unsigned size,
+             unsigned offset, unsigned words, const uint32_t *data)
+{
+   struct nouveau_channel *chan = nv->screen->channel;
+
+   assert(!(offset & 3));
+   size = align(size, 0x100);
+
+   MARK_RING (chan, 16, 2);
+   BEGIN_RING(chan, RING_3D(CB_SIZE), 3);
+   OUT_RING  (chan, size);
+   OUT_RELOCh(chan, bo, base, domain | NOUVEAU_BO_WR);
+   OUT_RELOCl(chan, bo, base, domain | NOUVEAU_BO_WR);
+
+   while (words) {
+      unsigned nr = AVAIL_RING(chan);
+      nr = MIN2(nr, words);
+      nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1);
+
+      BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1);
+      OUT_RING  (chan, offset);
+      OUT_RINGp (chan, data, nr);
+
+      words -= nr;
+      data += nr;
+      offset += nr * 4;
+
+      if (words) {
+         MARK_RING(chan, 6, 1);
+         nouveau_bo_validate(chan, bo, domain | NOUVEAU_BO_WR);
+      }
+   }
+}