Mesa (master): gallium/u_transfer_helper: add util functions for doing deinterleaving during map

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Aug 11 00:02:22 UTC 2020


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Thu Jun  4 11:31:28 2020 -0400

gallium/u_transfer_helper: add util functions for doing deinterleaving during map

in some cases (e.g., zink and d3d12) we only want to split the depth and stencil
buffers when we're mapping them, and we can handle packed buffers in other cases,
so being able to reuse the u_transfer_helper functionality is still desired but
only if we can preserve the underlying buffer the rest of the time

Kenneth Graunke notes during post-review:
Vulkan reads/copies on packed Z24S8 only return depth, so we need to use separate
Z24 and S8 reads and do packing tricks.

Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5338>

---

 src/gallium/auxiliary/util/u_transfer_helper.c | 125 ++++++++++++++++++++++++-
 src/gallium/auxiliary/util/u_transfer_helper.h |  10 ++
 2 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/src/gallium/auxiliary/util/u_transfer_helper.c b/src/gallium/auxiliary/util/u_transfer_helper.c
index 0ba8abdf782..0dc9ecf5afc 100644
--- a/src/gallium/auxiliary/util/u_transfer_helper.c
+++ b/src/gallium/auxiliary/util/u_transfer_helper.c
@@ -351,7 +351,8 @@ flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans,
              const struct pipe_box *box)
 {
    struct u_transfer_helper *helper = pctx->screen->transfer_helper;
-   struct u_transfer *trans = u_transfer(ptrans);
+   /* using the function here hits an assert for the deinterleave cases */
+   struct u_transfer *trans = (struct u_transfer *)ptrans;
    enum pipe_format iformat, format = ptrans->resource->format;
    unsigned width = box->width;
    unsigned height = box->height;
@@ -544,3 +545,125 @@ u_transfer_helper_destroy(struct u_transfer_helper *helper)
 {
    free(helper);
 }
+
+
+/* these two functions 'deinterleave' are meant to be used without the corresponding
+ * resource_create/destroy hooks, as they perform the interleaving on-the-fly
+ *
+ * drivers should expect to be passed the same buffer repeatedly with the format changed
+ * to indicate which component is being mapped
+ */
+void *
+u_transfer_helper_deinterleave_transfer_map(struct pipe_context *pctx,
+                                            struct pipe_resource *prsc,
+                                            unsigned level, unsigned usage,
+                                            const struct pipe_box *box,
+                                            struct pipe_transfer **pptrans)
+{
+   struct u_transfer_helper *helper = pctx->screen->transfer_helper;
+   struct u_transfer *trans;
+   struct pipe_transfer *ptrans;
+   enum pipe_format format = prsc->format;
+   unsigned width = box->width;
+   unsigned height = box->height;
+
+   if (!((helper->separate_stencil && util_format_is_depth_and_stencil(format)) ||
+       (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && helper->separate_z32s8)))
+      return helper->vtbl->transfer_map(pctx, prsc, level, usage, box, pptrans);
+
+   debug_assert(box->depth == 1);
+
+   trans = calloc(1, sizeof(*trans));
+   if (!trans)
+      return NULL;
+
+   ptrans = &trans->base;
+   pipe_resource_reference(&ptrans->resource, prsc);
+   ptrans->level = level;
+   ptrans->usage = usage;
+   ptrans->box   = *box;
+   ptrans->stride = util_format_get_stride(format, box->width);
+   ptrans->layer_stride = ptrans->stride * box->height;
+
+   trans->staging = malloc(ptrans->layer_stride);
+   if (!trans->staging)
+      goto fail;
+
+   trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level, usage | PIPE_TRANSFER_DEPTH_ONLY, box,
+                                           &trans->trans);
+   if (!trans->ptr)
+      goto fail;
+
+   trans->ptr2 = helper->vtbl->transfer_map(pctx, prsc, level,
+                                            usage | PIPE_TRANSFER_STENCIL_ONLY, box, &trans->trans2);
+   if (needs_pack(usage)) {
+      switch (prsc->format) {
+      case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
+         util_format_z32_float_s8x24_uint_pack_z_float(trans->staging,
+                                                       ptrans->stride,
+                                                       trans->ptr,
+                                                       trans->trans->stride,
+                                                       width, height);
+         util_format_z32_float_s8x24_uint_pack_s_8uint(trans->staging,
+                                                       ptrans->stride,
+                                                       trans->ptr2,
+                                                       trans->trans2->stride,
+                                                       width, height);
+         break;
+      case PIPE_FORMAT_Z24_UNORM_S8_UINT:
+         util_format_z24_unorm_s8_uint_pack_separate(trans->staging,
+                                                     ptrans->stride,
+                                                     trans->ptr,
+                                                     trans->trans->stride,
+                                                     trans->ptr2,
+                                                     trans->trans2->stride,
+                                                     width, height);
+         break;
+      default:
+         unreachable("Unexpected format");
+      }
+   }
+
+   *pptrans = ptrans;
+   return trans->staging;
+
+fail:
+   if (trans->trans)
+      helper->vtbl->transfer_unmap(pctx, trans->trans);
+   if (trans->trans2)
+      helper->vtbl->transfer_unmap(pctx, trans->trans2);
+   pipe_resource_reference(&ptrans->resource, NULL);
+   free(trans->staging);
+   free(trans);
+   return NULL;
+}
+
+void
+u_transfer_helper_deinterleave_transfer_unmap(struct pipe_context *pctx,
+                                              struct pipe_transfer *ptrans)
+{
+   struct u_transfer_helper *helper = pctx->screen->transfer_helper;
+   enum pipe_format format = ptrans->resource->format;
+
+   if ((helper->separate_stencil && util_format_is_depth_and_stencil(format)) ||
+       (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && helper->separate_z32s8)) {
+      struct u_transfer *trans = (struct u_transfer *)ptrans;
+
+      if (!(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
+         struct pipe_box box;
+         u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box);
+         flush_region(pctx, ptrans, &box);
+      }
+
+      helper->vtbl->transfer_unmap(pctx, trans->trans);
+      if (trans->trans2)
+         helper->vtbl->transfer_unmap(pctx, trans->trans2);
+
+      pipe_resource_reference(&ptrans->resource, NULL);
+
+      free(trans->staging);
+      free(trans);
+   } else {
+      helper->vtbl->transfer_unmap(pctx, ptrans);
+   }
+}
diff --git a/src/gallium/auxiliary/util/u_transfer_helper.h b/src/gallium/auxiliary/util/u_transfer_helper.h
index e27c3570499..1c866c626c8 100644
--- a/src/gallium/auxiliary/util/u_transfer_helper.h
+++ b/src/gallium/auxiliary/util/u_transfer_helper.h
@@ -129,6 +129,16 @@ struct u_transfer_helper * u_transfer_helper_create(const struct u_transfer_vtbl
 
 void u_transfer_helper_destroy(struct u_transfer_helper *helper);
 
+void *
+u_transfer_helper_deinterleave_transfer_map(struct pipe_context *pctx,
+                                            struct pipe_resource *prsc,
+                                            unsigned level, unsigned usage,
+                                            const struct pipe_box *box,
+                                            struct pipe_transfer **pptrans);
+
+void
+u_transfer_helper_deinterleave_transfer_unmap(struct pipe_context *pctx,
+                                              struct pipe_transfer *ptrans);
 #ifdef __cplusplus
 } // extern "C" {
 #endif



More information about the mesa-commit mailing list