Mesa (master): nv50: pass surface/buffer parameters to shader via aux buffer

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat May 1 20:13:55 UTC 2021


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

Author: Ilia Mirkin <imirkin at alum.mit.edu>
Date:   Tue Mar  2 18:54:37 2021 -0500

nv50: pass surface/buffer parameters to shader via aux buffer

These are needed to implement things like imageSize() as well as feed
data into lowering logic for various access types not handled by the
hardware.

Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
Reviewed-by: Pierre Moreau <dev at pmoreau.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10164>

---

 src/gallium/drivers/nouveau/nv50/nv50_compute.c | 97 +++++++++++++++++++++----
 src/gallium/drivers/nouveau/nv50/nv50_context.h |  5 +-
 src/gallium/drivers/nouveau/nv50/nv50_program.c |  1 +
 3 files changed, 88 insertions(+), 15 deletions(-)

diff --git a/src/gallium/drivers/nouveau/nv50/nv50_compute.c b/src/gallium/drivers/nouveau/nv50/nv50_compute.c
index 3cbc1be47f9..5c1b27f9beb 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_compute.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_compute.c
@@ -283,6 +283,7 @@ nv50_compute_validate_buffers(struct nv50_context *nv50)
 
    for (i = 0; i < 7; i++) {
       BEGIN_NV04(push, NV50_CP(GLOBAL(i)), 5);
+      unsigned width;
       if (nv50->buffers[i].buffer) {
          struct nv04_resource *res =
             nv04_resource(nv50->buffers[i].buffer);
@@ -296,13 +297,21 @@ nv50_compute_validate_buffers(struct nv50_context *nv50)
                         nv50->buffers[i].buffer_offset,
                         nv50->buffers[i].buffer_offset +
                         nv50->buffers[i].buffer_size);
+         width = nv50->buffers[i].buffer_size;
       } else {
          PUSH_DATA (push, 0);
          PUSH_DATA (push, 0);
          PUSH_DATA (push, 0);
          PUSH_DATA (push, 0);
          PUSH_DATA (push, 0);
+         width = 0;
       }
+
+      PUSH_SPACE(push, 1 + 3);
+      BEGIN_NV04(push, NV50_CP(CB_ADDR), 1);
+      PUSH_DATA (push, NV50_CB_AUX_BUF_INFO(i) << (8 - 2) | NV50_CB_AUX);
+      BEGIN_NI04(push, NV50_CP(CB_DATA(0)), 1);
+      PUSH_DATA (push, width);
    }
 }
 
@@ -354,6 +363,53 @@ nv50_mark_image_range_valid(const struct pipe_image_view *view)
                   view->u.buf.offset + view->u.buf.size);
 }
 
+static inline void
+nv50_set_surface_info(struct nouveau_pushbuf *push,
+                      const struct pipe_image_view *view,
+                      int width, int height, int depth)
+{
+   struct nv04_resource *res;
+   uint32_t *const info = push->cur;
+
+   push->cur += 12;
+
+   /* Make sure to always initialize the surface information area because it's
+    * used to check if the given image is bound or not. */
+   memset(info, 0, 12 * sizeof(*info));
+
+   if (!view || !view->resource)
+      return;
+   res = nv04_resource(view->resource);
+
+   /* Stick the image dimensions for the imageSize() builtin. */
+   info[0] = width;
+   info[1] = height;
+   info[2] = depth;
+
+   /* Stick the blockwidth (ie. number of bytes per pixel) to calculate pixel
+    * offset and to check if the format doesn't mismatch. */
+   info[3] = util_format_get_blocksize(view->format);
+
+   if (res->base.target != PIPE_BUFFER) {
+      struct nv50_miptree *mt = nv50_miptree(&res->base);
+      struct nv50_miptree_level *lvl = &mt->level[view->u.tex.level];
+      unsigned nby = align(util_format_get_nblocksy(view->format, height),
+                           NV50_TILE_SIZE_Y(lvl->tile_mode));
+
+      if (mt->layout_3d) {
+         info[4] = nby;
+         info[11] = view->u.tex.first_layer;
+      } else {
+         info[4] = mt->layer_stride / lvl->pitch;
+      }
+      info[6] = mt->ms_x;
+      info[7] = mt->ms_y;
+      info[8] = NV50_TILE_SHIFT_X(lvl->tile_mode);
+      info[9] = NV50_TILE_SHIFT_Y(lvl->tile_mode);
+      info[10] = NV50_TILE_SHIFT_Z(lvl->tile_mode);
+   }
+}
+
 static void
 nv50_compute_validate_surfaces(struct nv50_context *nv50)
 {
@@ -389,29 +445,36 @@ nv50_compute_validate_surfaces(struct nv50_context *nv50)
             struct nv50_miptree *mt = nv50_miptree(view->resource);
             struct nv50_miptree_level *lvl = &mt->level[view->u.tex.level];
             const unsigned z = view->u.tex.first_layer;
+            unsigned max_size;
 
             if (mt->layout_3d) {
-               address += nv50_mt_zslice_offset(mt, view->u.tex.level, z);
-               if (depth >= 1) {
-                  pipe_debug_message(&nv50->base.debug, CONFORMANCE,
-                                     "3D images are not supported!");
-                  debug_printf("3D images are not supported!\n");
-               }
+               address += nv50_mt_zslice_offset(mt, view->u.tex.level, 0);
+               max_size = mt->total_size;
             } else {
                address += mt->layer_stride * z;
+               max_size = mt->layer_stride * (view->u.tex.last_layer - view->u.tex.first_layer + 1);
             }
             address += lvl->offset;
 
             PUSH_DATAh(push, address);
             PUSH_DATA (push, address);
-            if (nouveau_bo_memtype(res->bo)) {
-               unsigned h = height << mt->ms_y;
-               unsigned nby = util_format_get_nblocksy(view->format, h);
-               unsigned tsy = NV50_TILE_SIZE_Y(lvl->tile_mode) * depth;
-
-               PUSH_DATA (push, lvl->pitch * tsy);
-               PUSH_DATA (push, (align(nby, tsy) - 1) << 16 | (lvl->pitch - 1));
-               PUSH_DATA (push, (lvl->tile_mode & 0xff) << 4); /* mask out z-tiling */
+            if (mt->layout_3d) {
+               // We have to adjust the size of the 3d surface to be
+               // accessible within 2d limits. The size of each z tile goes
+               // into the x direction, while the number of z tiles goes into
+               // the y direction.
+               const unsigned nby = util_format_get_nblocksy(view->format, height);
+               const unsigned tsy = NV50_TILE_SIZE_Y(lvl->tile_mode);
+               const unsigned tsz = NV50_TILE_SIZE_Z(lvl->tile_mode);
+               const unsigned pitch = lvl->pitch * tsz;
+               const unsigned maxy = align(nby, tsy) * align(depth, tsz) >> NV50_TILE_SHIFT_Z(lvl->tile_mode);
+               PUSH_DATA (push, pitch * tsy);
+               PUSH_DATA (push, (maxy - 1) << 16 | (pitch - 1));
+               PUSH_DATA (push, (lvl->tile_mode & 0xff) << 4);
+            } else if (nouveau_bo_memtype(res->bo)) {
+               PUSH_DATA (push, lvl->pitch * NV50_TILE_SIZE_Y(lvl->tile_mode));
+               PUSH_DATA (push, (max_size / lvl->pitch - 1) << 16 | (lvl->pitch - 1));
+               PUSH_DATA (push, (lvl->tile_mode & 0xff) << 4);
             } else {
                PUSH_DATA (push, lvl->pitch);
                PUSH_DATA (push, align(lvl->pitch * height, 0x100) - 1);
@@ -427,6 +490,12 @@ nv50_compute_validate_surfaces(struct nv50_context *nv50)
          PUSH_DATA (push, 0);
          PUSH_DATA (push, 0);
       }
+
+      PUSH_SPACE(push, 12 + 3);
+      BEGIN_NV04(push, NV50_CP(CB_ADDR), 1);
+      PUSH_DATA (push, NV50_CB_AUX_BUF_INFO(7 + i) << (8 - 2) | NV50_CB_AUX);
+      BEGIN_NI04(push, NV50_CP(CB_DATA(0)), 12);
+      nv50_set_surface_info(push, view, width, height, depth);
    }
 }
 
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h
index 29d1e5f3dbc..afd04d99ba6 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.h
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h
@@ -120,7 +120,10 @@
 /* Alpha test ref value */
 #define NV50_CB_AUX_ALPHATEST_OFFSET 0x3c0
 #define NV50_CB_AUX_ALPHATEST_SIZE (4)
-/* next spot: 0x344 */
+/* Compute buffer info: 16 surfaces, 12 32-bit integers each */
+#define NV50_CB_AUX_BUF_INFO(i)   (0x3c4 + (i) * 12 * 4)
+#define NV50_CB_AUX_BUF_SIZE      (NV50_MAX_GLOBALS * 12 * 4)
+/* next spot: 0x644 */
 /* 4 32-bit floats for the vertex runout, put at the end */
 #define NV50_CB_AUX_RUNOUT_OFFSET (NV50_CB_AUX_SIZE - 0x10)
 
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c
index b496d4f2549..42f29b8c54a 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_program.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c
@@ -359,6 +359,7 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset,
       info->io.alphaRefBase = NV50_CB_AUX_ALPHATEST_OFFSET;
 
    info->io.suInfoBase = NV50_CB_AUX_TEX_MS_OFFSET;
+   info->io.bufInfoBase = NV50_CB_AUX_BUF_INFO(0);
    info->io.sampleInfoBase = NV50_CB_AUX_SAMPLE_OFFSET;
    info->io.msInfoCBSlot = 15;
    info->io.msInfoBase = NV50_CB_AUX_MS_OFFSET;



More information about the mesa-commit mailing list