nv50: reinstate dedicated constbuf push path
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 5 Jun 2016 23:02:29 +0000 (19:02 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Sat, 11 Jun 2016 16:18:43 +0000 (12:18 -0400)
This was disabled due to occasionally incorrect behavior when trying to
upload data. It later became apparent that nvc0 also had a similar but
slightly different issue, which was resolved in commit e50c01d5. This
takes the same logic as nvc0 and applies it to nv50 (which has somewhat
different interfaces).

Unfortunately I did not note down precisely what was broken with UBOs
when removing the support from nv50, but I've tested a bunch of local
traces, and none of them appear to regress. This should hopefully
improve performance when UBOs are used, but this was not directly
verified.

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
src/gallium/drivers/nouveau/nv50/nv50_context.c
src/gallium/drivers/nouveau/nv50/nv50_context.h
src/gallium/drivers/nouveau/nv50/nv50_shader_state.c
src/gallium/drivers/nouveau/nv50/nv50_state.c
src/gallium/drivers/nouveau/nv50/nv50_transfer.c

index 5af0e9b3a27e3d6f9c22fd1f4c5df87ec16c302b..fc852d7068c8a1d1e305ba6809ed33ef8a1c814a 100644 (file)
@@ -310,14 +310,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags)
    nv50->base.screen    = &screen->base;
    nv50->base.copy_data = nv50_m2mf_copy_linear;
    nv50->base.push_data = nv50_sifc_linear_u8;
-   /* FIXME: Make it possible to use this again. The problem is that there is
-    * some clever logic in the card that allows for multiple renders to happen
-    * when there are only constbuf changes. However that relies on the
-    * constbuf updates happening to the right constbuf slots. Currently
-    * implementation just makes it go through a separate slot which doesn't
-    * properly update the right constbuf data.
    nv50->base.push_cb   = nv50_cb_push;
-    */
 
    nv50->screen = screen;
    pipe->screen = pscreen;
index 2317fa2ccf84831affcab6a102631b5bbb9021b5..d5de255b3320c01e419e68d3550a2caf2d6eedb8 100644 (file)
@@ -281,8 +281,7 @@ nv50_m2mf_copy_linear(struct nouveau_context *pipe,
                       unsigned size);
 void
 nv50_cb_push(struct nouveau_context *nv,
-             struct nouveau_bo *bo, unsigned domain,
-             unsigned base, unsigned size,
+             struct nv04_resource *res,
              unsigned offset, unsigned words, const uint32_t *data);
 
 /* nv50_vbo.c */
index f838d151161c6664a0f45d803aea3483ea49c407..23263945bdc8bcf8ffa2f050edcd085d0ec0a98f 100644 (file)
@@ -99,6 +99,7 @@ nv50_constbufs_validate(struct nv50_context *nv50)
                BCTX_REFN(nv50->bufctx_3d, 3D_CB(s, i), res, RD);
 
                nv50->cb_dirty = 1; /* Force cache flush for UBO. */
+               res->cb_bindings[s] |= 1 << i;
             } else {
                BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
                PUSH_DATA (push, (i << 8) | p | 0);
index 86e74d68b11333f45b13bb2b6cf1cbbfd462be25..3231aba20c1351591f0de7b7c88815a8820faae1 100644 (file)
@@ -856,9 +856,10 @@ nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
    if (nv50->constbuf[s][i].user)
       nv50->constbuf[s][i].u.buf = NULL;
    else
-   if (nv50->constbuf[s][i].u.buf)
+   if (nv50->constbuf[s][i].u.buf) {
       nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_3D_CB(s, i));
-
+      nv04_resource(nv50->constbuf[s][i].u.buf)->cb_bindings[s] &= ~(1 << i);
+   }
    pipe_resource_reference(&nv50->constbuf[s][i].u.buf, res);
 
    nv50->constbuf[s][i].user = (cb && cb->user_buffer) ? true : false;
index 86a8c15946989355ef174c5b026f624c5303599b..8209f1f1e826edd8222123b0b5ac3d2e50bf66aa 100644 (file)
@@ -371,32 +371,24 @@ nv50_miptree_transfer_unmap(struct pipe_context *pctx,
    FREE(tx);
 }
 
-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)
+static void
+nv50_cb_bo_push(struct nouveau_context *nv,
+                struct nouveau_bo *bo, unsigned domain,
+                unsigned bufid,
+                unsigned offset, unsigned words,
+                const uint32_t *data)
 {
    struct nouveau_pushbuf *push = nv->pushbuf;
-   struct nouveau_bufctx *bctx = nv50_context(&nv->pipe)->bufctx;
 
    assert(!(offset & 3));
-   size = align(size, 0x100);
-
-   nouveau_bufctx_refn(bctx, 0, bo, NOUVEAU_BO_WR | domain);
-   nouveau_pushbuf_bufctx(push, bctx);
-   nouveau_pushbuf_validate(push);
 
    while (words) {
       unsigned nr = MIN2(words, NV04_PFIFO_MAX_PACKET_LEN);
 
-      PUSH_SPACE(push, nr + 7);
-      BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
-      PUSH_DATAh(push, bo->offset + base);
-      PUSH_DATA (push, bo->offset + base);
-      PUSH_DATA (push, (NV50_CB_TMP << 16) | (size & 0xffff));
+      PUSH_SPACE(push, nr + 3);
+      PUSH_REFN (push, bo, NOUVEAU_BO_WR | domain);
       BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
-      PUSH_DATA (push, (offset << 6) | NV50_CB_TMP);
+      PUSH_DATA (push, (offset << 6) | bufid);
       BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr);
       PUSH_DATAp(push, data, nr);
 
@@ -404,6 +396,41 @@ nv50_cb_push(struct nouveau_context *nv,
       data += nr;
       offset += nr * 4;
    }
+}
 
-   nouveau_bufctx_reset(bctx, 0);
+void
+nv50_cb_push(struct nouveau_context *nv,
+             struct nv04_resource *res,
+             unsigned offset, unsigned words, const uint32_t *data)
+{
+   struct nv50_context *nv50 = nv50_context(&nv->pipe);
+   struct nv50_constbuf *cb = NULL;
+   int s, bufid;
+   /* Go through all the constbuf binding points of this buffer and try to
+    * find one which contains the region to be updated.
+    */
+   /* XXX compute? */
+   for (s = 0; s < 3 && !cb; s++) {
+      uint16_t bindings = res->cb_bindings[s];
+      while (bindings) {
+         int i = ffs(bindings) - 1;
+         uint32_t cb_offset = nv50->constbuf[s][i].offset;
+
+         bindings &= ~(1 << i);
+         if (cb_offset <= offset &&
+             cb_offset + nv50->constbuf[s][i].size >= offset + words * 4) {
+            cb = &nv50->constbuf[s][i];
+            bufid = s * 16 + i;
+            break;
+         }
+      }
+   }
+
+   if (cb) {
+      nv50_cb_bo_push(nv, res->bo, res->domain,
+                      bufid, offset - cb->offset, words, data);
+   } else {
+      nv->push_data(nv, res->bo, res->offset + offset, res->domain,
+                    words * 4, data);
+   }
 }