nv50: fix code uploads bigger than 0x10000 bytes
authorKarol Herbst <git@karolherbst.de>
Tue, 15 Aug 2023 15:12:01 +0000 (17:12 +0200)
committerMarge Bot <emma+marge@anholt.net>
Wed, 16 Aug 2023 09:50:33 +0000 (09:50 +0000)
The hardware has a max limit on how much data we can upload in one go via
the 2D engine. Just split the uploads up.

Cc: mesa-stable
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9571
Acked-by: M Henning <drawoc@darkrefraction.com>
Signed-off-by: Karol Herbst <git@karolherbst.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24706>

src/gallium/drivers/nouveau/nv50/nv50_transfer.c

index 4c73695..5a9a5ba 100644 (file)
@@ -279,47 +279,56 @@ nv50_sifc_linear_u8(struct nouveau_context *nv,
    struct nv50_context *nv50 = nv50_context(&nv->pipe);
    struct nouveau_pushbuf *push = nv50->base.pushbuf;
    uint32_t *src = (uint32_t *)data;
-   unsigned count = (size + 3) / 4;
-   unsigned xcoord = offset & 0xff;
+   unsigned count = DIV_ROUND_UP(size, 4);
+   unsigned max_size = 0x10000;
 
    nouveau_bufctx_refn(nv50->bufctx, 0, dst, domain | NOUVEAU_BO_WR);
    nouveau_pushbuf_bufctx(push, nv50->bufctx);
+
    PUSH_VAL(push);
 
-   offset &= ~0xff;
+   while (count) {
+      unsigned xcoord = offset & 0xff;
+      offset &= ~0xff;
 
-   BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);
-   PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
-   PUSH_DATA (push, 1);
-   BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);
-   PUSH_DATA (push, 262144);
-   PUSH_DATA (push, 65536);
-   PUSH_DATA (push, 1);
-   PUSH_DATAh(push, dst->offset + offset);
-   PUSH_DATA (push, dst->offset + offset);
-   BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);
-   PUSH_DATA (push, 0);
-   PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
-   BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);
-   PUSH_DATA (push, size);
-   PUSH_DATA (push, 1);
-   PUSH_DATA (push, 0);
-   PUSH_DATA (push, 1);
-   PUSH_DATA (push, 0);
-   PUSH_DATA (push, 1);
-   PUSH_DATA (push, 0);
-   PUSH_DATA (push, xcoord);
-   PUSH_DATA (push, 0);
-   PUSH_DATA (push, 0);
+      BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2);
+      PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
+      PUSH_DATA (push, 1);
+      BEGIN_NV04(push, NV50_2D(DST_PITCH), 5);
+      PUSH_DATA (push, 262144);
+      PUSH_DATA (push, 65536);
+      PUSH_DATA (push, 1);
+      PUSH_DATAh(push, dst->offset + offset);
+      PUSH_DATA (push, dst->offset + offset);
+      BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2);
+      PUSH_DATA (push, 0);
+      PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM);
+      BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10);
+      PUSH_DATA (push, MIN2(size, max_size));
+      PUSH_DATA (push, 1);
+      PUSH_DATA (push, 0);
+      PUSH_DATA (push, 1);
+      PUSH_DATA (push, 0);
+      PUSH_DATA (push, 1);
+      PUSH_DATA (push, 0);
+      PUSH_DATA (push, xcoord);
+      PUSH_DATA (push, 0);
+      PUSH_DATA (push, 0);
 
-   while (count) {
-      unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN);
+      unsigned iter_count = MIN2(count, max_size / 4);
+      count -= iter_count;
+      offset += max_size;
+      size -= max_size;
+
+      while (iter_count) {
+         unsigned nr = MIN2(iter_count, NV04_PFIFO_MAX_PACKET_LEN);
 
-      BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr);
-      PUSH_DATAp(push, src, nr);
+         BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr);
+         PUSH_DATAp(push, src, nr);
 
-      src += nr;
-      count -= nr;
+         src += nr;
+         iter_count -= nr;
+      }
    }
 
    nouveau_bufctx_reset(nv50->bufctx, 0);