[Mesa-dev] [PATCH v2 4/5] gallium: Make a helper for doing Z32_FLOAT_S8X24_UINT mappings.

Rob Clark robdclark at gmail.com
Tue Nov 28 14:01:31 UTC 2017


On Tue, Nov 21, 2017 at 4:13 PM, Eric Anholt <eric at anholt.net> wrote:
> v2: Remove the callback, leave avoiding the recursion up to the caller
>     (probably by rewriting the vtbl either in pctx or u_resource_vtbl)

hmm, that is still a bit ugly..  and looking at the equiv thing that
Ilia implemented in freedreno, I think there is also so special
handling needed for ->transfer_flush_region()..

If you don't want to add it in u_resource/_vtbl (and I agree, a per
rsc vtbl is kinda unneeded), maybe we could introduce in a similar
way, u_transfer_vtbl/u_transfer_resource/u_transfer, ie.

  struct u_transfer_resource {
     struct pipe_resource b;
     struct pipe_resource *stencil; /* holds separate stencil buffer
for z32x24s8 */
  }

  struct u_transfer {
     struct pipe_transfer b;
     void *staging;
  }

  struct u_transfer_vtbl {
     struct pipe_resource (*resource_create)(...);
     void (*resource_destroy)(...);
     void *(*transfer_map)(...);
     void (*transfer_flush_region)(...);
     void (*transfer_unmap)(...);
     bool lower_z32s8;
     bool lower_rgtc;
  }

Note that I had schemes to move the rgtc handling that freedreno does
over to this new scheme too.  Probably the MSAA resolve stuff could be
folded into this same scheme, I haven't thought about that yet.

The vtbl ptr doesn't have to be global.  I think we can just stash a
pointer in pipe_context like what is done for draw module and a few
other things.

If you want, I can take a stab at this approach, since I'm also
messing w/ a staging buffer approach for uploads to flushed but busy
buffers/textures to avoid a stall, and that gets easier once the
staging stuff is separated ;-)

BR,
-R

> ---
>  src/gallium/auxiliary/util/u_transfer.c | 114 ++++++++++++++++++++++++++++++++
>  src/gallium/auxiliary/util/u_transfer.h |  11 +++
>  2 files changed, 125 insertions(+)
>
> diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c
> index 104d0505aaa8..2d219721dcf8 100644
> --- a/src/gallium/auxiliary/util/u_transfer.c
> +++ b/src/gallium/auxiliary/util/u_transfer.c
> @@ -1,4 +1,5 @@
>  #include "pipe/p_context.h"
> +#include "util/u_format_zs.h"
>  #include "util/u_surface.h"
>  #include "util/u_inlines.h"
>  #include "util/u_transfer.h"
> @@ -272,3 +273,116 @@ void u_transfer_unmap_msaa_helper(struct pipe_context *pctx,
>     pipe_resource_reference(&trans->ss, NULL);
>     free(trans);
>  }
> +
> +struct u_transfer_z32f_s8_helper {
> +   struct pipe_transfer base;
> +   struct pipe_transfer *z_ptrans;
> +   struct pipe_transfer *s_ptrans;
> +   void *z, *s;
> +   void *merged;
> +};
> +
> +/**
> + * Helper to implement the PIPE_FORMAT_Z32_FLOAT_S8X24_UINT mappings when the
> + * driver stores the Z and S in separate resources.
> + *
> + * We malloc temporary storage, map each resource, and use the CPU to pack the
> + * values into the temporary.
> + *
> + * Note that the driver's unmap will be called with our ptrans: They need to
> + * detect it and call u_transfer_unmap_z32f_s8_helper() and return
> + * immediately.
> + *
> + * In both the map and unmap paths, the driver will need to be careful to
> + * unwrap its transfer_map()/unmap() method that would call us, so that it
> + * doesn't recurse when we call back into it.
> + */
> +void *
> +u_transfer_map_z32f_s8_helper(struct pipe_context *pctx,
> +                              struct pipe_resource *z,
> +                              struct pipe_resource *s,
> +                              unsigned level, unsigned usage,
> +                              const struct pipe_box *box,
> +                              struct pipe_transfer **pptrans)
> +{
> +   struct u_transfer_z32f_s8_helper *trans = calloc(1, sizeof(*trans));
> +   if (!trans)
> +      return NULL;
> +   struct pipe_transfer *ptrans = &trans->base;
> +
> +   pipe_resource_reference(&ptrans->resource, z);
> +   ptrans->level = level;
> +   ptrans->usage = usage;
> +   ptrans->box = *box;
> +
> +   trans->z = pctx->transfer_map(pctx, z, level, usage, box,
> +                                 &trans->z_ptrans);
> +   if (!trans->z)
> +      goto fail_unref;
> +   trans->s = pctx->transfer_map(pctx, s, level, usage, box,
> +                                 &trans->s_ptrans);
> +   if (!trans->s)
> +      goto fail_unmap_z;
> +
> +   ptrans->stride = 8 * box->width;
> +   trans->merged = malloc(ptrans->stride * box->height);
> +   if (!trans->merged)
> +      goto fail_unmap_s;
> +
> +   if (usage & PIPE_TRANSFER_READ) {
> +      util_format_z32_float_s8x24_uint_pack_z_float(trans->merged,
> +                                                    ptrans->stride,
> +                                                    trans->z,
> +                                                    trans->z_ptrans->stride,
> +                                                    box->width,
> +                                                    box->height);
> +      util_format_z32_float_s8x24_uint_pack_s_8uint(trans->merged,
> +                                                    ptrans->stride,
> +                                                    trans->s,
> +                                                    trans->s_ptrans->stride,
> +                                                    box->width,
> +                                                    box->height);
> +   }
> +
> +   *pptrans = ptrans;
> +   return trans->merged;
> +
> + fail_unmap_s:
> +   pctx->transfer_unmap(pctx, trans->s_ptrans);
> + fail_unmap_z:
> +   pctx->transfer_unmap(pctx, trans->z_ptrans);
> + fail_unref:
> +   pipe_resource_reference(&ptrans->resource, NULL);
> +   free(trans);
> +   return NULL;
> +}
> +
> +void u_transfer_unmap_z32f_s8_helper(struct pipe_context *pctx,
> +                                     struct pipe_transfer *ptrans)
> +{
> +   struct u_transfer_z32f_s8_helper *trans =
> +      (struct u_transfer_z32f_s8_helper *)ptrans;
> +
> +   if (ptrans->usage & PIPE_TRANSFER_WRITE) {
> +      uint32_t width = ptrans->box.width;
> +      uint32_t height = ptrans->box.height;
> +
> +      util_format_z32_float_s8x24_uint_unpack_z_float(trans->z,
> +                                                      trans->z_ptrans->stride,
> +                                                      trans->merged,
> +                                                      ptrans->stride,
> +                                                      width, height);
> +      util_format_z32_float_s8x24_uint_unpack_s_8uint(trans->s,
> +                                                      trans->s_ptrans->stride,
> +                                                      trans->merged,
> +                                                      ptrans->stride,
> +                                                      width, height);
> +   }
> +
> +   pctx->transfer_unmap(pctx, trans->s_ptrans);
> +   pctx->transfer_unmap(pctx, trans->z_ptrans);
> +
> +   pipe_resource_reference(&ptrans->resource, NULL);
> +   free(trans->merged);
> +   free(trans);
> +}
> diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h
> index 237930c06007..0a8a649df1f5 100644
> --- a/src/gallium/auxiliary/util/u_transfer.h
> +++ b/src/gallium/auxiliary/util/u_transfer.h
> @@ -24,6 +24,17 @@ u_transfer_map_msaa_helper(struct pipe_context *pctx,
>  void u_transfer_unmap_msaa_helper(struct pipe_context *pctx,
>                                    struct pipe_transfer *ptrans);
>
> +void *
> +u_transfer_map_z32f_s8_helper(struct pipe_context *pctx,
> +                              struct pipe_resource *z,
> +                              struct pipe_resource *s,
> +                              unsigned level, unsigned usage,
> +                              const struct pipe_box *box,
> +                              struct pipe_transfer **pptrans);
> +
> +void u_transfer_unmap_z32f_s8_helper(struct pipe_context *pctx,
> +                                     struct pipe_transfer *ptrans);
> +
>  boolean u_default_resource_get_handle(struct pipe_screen *screen,
>                                        struct pipe_resource *resource,
>                                        struct winsys_handle *handle);
> --
> 2.15.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list