u_transfer_helper: Merge in-place and split z/s interleaved map handling.

The paths were mostly the same, except that in-place was missing the
appropriate layering for MSAA helper re-mapping.  We can instead share
more code, making the differences between the interleave packing clear,
and have the MSAA resolve blit happen once before we do the split
mappings.

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20523>
This commit is contained in:
Emma Anholt 2023-01-04 12:17:27 -08:00 committed by Marge Bot
parent 4372069f5a
commit 823e34f938

View file

@ -39,8 +39,13 @@ struct u_transfer_helper {
bool interleave_in_place;
};
static inline bool need_interleave_path(struct u_transfer_helper *helper,
enum pipe_format format)
/* If we need to take the path for PIPE_MAP_DEPTH/STENCIL_ONLY on the parent
* depth/stencil resource an interleaving those to/from a staging buffer. The
* other path for z/s interleave is when separate z and s resources are
* created at resource create time.
*/
static inline bool needs_in_place_zs_interleave(struct u_transfer_helper *helper,
enum pipe_format format)
{
if (!helper->interleave_in_place)
return false;
@ -68,6 +73,9 @@ static inline bool handle_transfer(struct pipe_resource *prsc)
if (helper->msaa_map && (prsc->nr_samples > 1))
return true;
if (needs_in_place_zs_interleave(helper, prsc->format))
return true;
return false;
}
@ -263,10 +271,9 @@ u_transfer_helper_transfer_map(struct pipe_context *pctx,
enum pipe_format format = prsc->format;
unsigned width = box->width;
unsigned height = box->height;
bool in_place_zs_interleave = needs_in_place_zs_interleave(helper, format);
if (need_interleave_path(helper, format))
return u_transfer_helper_deinterleave_transfer_map(pctx, prsc, level, usage, box, pptrans);
else if (!handle_transfer(prsc))
if (!handle_transfer(prsc))
return helper->vtbl->transfer_map(pctx, prsc, level, usage, box, pptrans);
if (helper->msaa_map && (prsc->nr_samples > 1))
@ -290,15 +297,22 @@ u_transfer_helper_transfer_map(struct pipe_context *pctx,
if (!trans->staging)
goto fail;
trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level, usage, box,
&trans->trans);
trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level,
usage | (in_place_zs_interleave ? PIPE_MAP_DEPTH_ONLY : 0),
box, &trans->trans);
if (!trans->ptr)
goto fail;
if (util_format_is_depth_and_stencil(prsc->format)) {
struct pipe_resource *stencil = helper->vtbl->get_stencil(prsc);
struct pipe_resource *stencil;
if (in_place_zs_interleave)
stencil = prsc;
else
stencil = helper->vtbl->get_stencil(prsc);
trans->ptr2 = helper->vtbl->transfer_map(pctx, stencil, level,
usage, box, &trans->trans2);
usage | (in_place_zs_interleave ? PIPE_MAP_STENCIL_ONLY : 0),
box, &trans->trans2);
if (needs_pack(usage)) {
switch (prsc->format) {
@ -315,27 +329,53 @@ u_transfer_helper_transfer_map(struct pipe_context *pctx,
width, height);
break;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
if (helper->z24_in_z32f) {
util_format_z24_unorm_s8_uint_pack_z_float(trans->staging,
ptrans->stride,
trans->ptr,
trans->trans->stride,
width, height);
util_format_z24_unorm_s8_uint_pack_s_8uint(trans->staging,
ptrans->stride,
trans->ptr2,
trans->trans2->stride,
width, height);
if (in_place_zs_interleave) {
if (helper->z24_in_z32f) {
util_format_z24_unorm_s8_uint_pack_separate_z32(trans->staging,
ptrans->stride,
trans->ptr,
trans->trans->stride,
trans->ptr2,
trans->trans2->stride,
width, height);
} else {
util_format_z24_unorm_s8_uint_pack_separate(trans->staging,
ptrans->stride,
trans->ptr,
trans->trans->stride,
trans->ptr2,
trans->trans2->stride,
width, height);
}
} else {
util_format_z24_unorm_s8_uint_pack_separate(trans->staging,
ptrans->stride,
trans->ptr,
trans->trans->stride,
trans->ptr2,
trans->trans2->stride,
width, height);
if (helper->z24_in_z32f) {
util_format_z24_unorm_s8_uint_pack_z_float(trans->staging,
ptrans->stride,
trans->ptr,
trans->trans->stride,
width, height);
util_format_z24_unorm_s8_uint_pack_s_8uint(trans->staging,
ptrans->stride,
trans->ptr2,
trans->trans2->stride,
width, height);
} else {
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;
case PIPE_FORMAT_Z24X8_UNORM:
assert(helper->z24_in_z32f);
util_format_z24x8_unorm_pack_z_float(trans->staging, ptrans->stride,
trans->ptr, trans->trans->stride,
width, height);
break;
default:
unreachable("Unexpected format");
}
@ -500,9 +540,8 @@ u_transfer_helper_transfer_unmap(struct pipe_context *pctx,
struct pipe_transfer *ptrans)
{
struct u_transfer_helper *helper = pctx->screen->transfer_helper;
bool interleave = need_interleave_path(helper, ptrans->resource->format);
if (handle_transfer(ptrans->resource) || interleave) {
if (handle_transfer(ptrans->resource)) {
struct u_transfer *trans = u_transfer(ptrans);
if (!(ptrans->usage & PIPE_MAP_FLUSH_EXPLICIT)) {
@ -555,111 +594,3 @@ 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
*/
static 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;
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;
bool has_stencil = util_format_is_depth_and_stencil(format);
trans->staging = malloc(ptrans->layer_stride);
if (!trans->staging)
goto fail;
trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level, usage | PIPE_MAP_DEPTH_ONLY, box,
&trans->trans);
if (!trans->ptr)
goto fail;
trans->ptr2 = NULL;
if (has_stencil)
trans->ptr2 = helper->vtbl->transfer_map(pctx, prsc, level,
usage | PIPE_MAP_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:
if (helper->z24_in_z32f) {
util_format_z24_unorm_s8_uint_pack_separate_z32(trans->staging,
ptrans->stride,
trans->ptr,
trans->trans->stride,
trans->ptr2,
trans->trans2->stride,
width, height);
} else {
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;
case PIPE_FORMAT_Z24X8_UNORM:
assert(helper->z24_in_z32f);
util_format_z24x8_unorm_pack_z_float(trans->staging, ptrans->stride,
trans->ptr, trans->trans->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;
}