From 38a23517fdc2c4bce5d72cc32cac2b543b460d77 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 30 Jul 2018 15:20:00 -0700 Subject: [PATCH] gallium/u_transfer_helper: Add support for separate Z24/S8 as well. u_transfer_helper already had code to handle treating packed Z32_S8 as separate Z32_FLOAT and S8_UINT resources, since some drivers can't handle that interleaved format natively. Other hardware needs depth and stencil as separate resources for all formats. For example, V3D3 needs this for 24-bit depth as well. This patch adds a new flag to lower all depth/stencils formats, and implements support for Z24_UNORM_S8_UINT. (S8_UINT_Z24_UNORM is left as an exercise to the reader, preferably someone who has access to a machine that uses that format.) Reviewed-by: Eric Anholt --- .../auxiliary/util/u_transfer_helper.c | 63 ++++++++++++++----- .../auxiliary/util/u_transfer_helper.h | 11 ++-- .../drivers/freedreno/freedreno_resource.c | 2 +- src/gallium/drivers/v3d/v3d_resource.c | 3 +- src/gallium/drivers/vc4/vc4_resource.c | 3 +- 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/gallium/auxiliary/util/u_transfer_helper.c b/src/gallium/auxiliary/util/u_transfer_helper.c index df67f828852..14c4d56392d 100644 --- a/src/gallium/auxiliary/util/u_transfer_helper.c +++ b/src/gallium/auxiliary/util/u_transfer_helper.c @@ -33,7 +33,8 @@ struct u_transfer_helper { const struct u_transfer_vtbl *vtbl; - bool separate_z32s8; + bool separate_z32s8; /**< separate z32 and s8 */ + bool separate_stencil; /**< separate stencil for all formats */ bool fake_rgtc; bool msaa_map; }; @@ -88,11 +89,12 @@ u_transfer_helper_resource_create(struct pipe_screen *pscreen, enum pipe_format format = templ->format; struct pipe_resource *prsc; - if ((format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) && helper->separate_z32s8) { + if ((helper->separate_stencil && util_format_is_depth_and_stencil(format)) || + (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && helper->separate_z32s8)) { struct pipe_resource t = *templ; struct pipe_resource *stencil; - t.format = PIPE_FORMAT_Z32_FLOAT; + t.format = util_format_get_depth_only(format); prsc = helper->vtbl->resource_create(pscreen, &t); if (!prsc) @@ -266,22 +268,37 @@ u_transfer_helper_transfer_map(struct pipe_context *pctx, if (!trans->ptr) goto fail; - if (prsc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) { + if (util_format_is_depth_and_stencil(prsc->format)) { struct pipe_resource *stencil = helper->vtbl->get_stencil(prsc); trans->ptr2 = helper->vtbl->transfer_map(pctx, stencil, level, usage, box, &trans->trans2); if (needs_pack(usage)) { - 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); + 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"); + } } } else if (needs_pack(usage) && util_format_description(prsc->format)->layout == UTIL_FORMAT_LAYOUT_RGTC) { @@ -395,6 +412,22 @@ flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, ptrans->stride, width, height); break; + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + /* just do a strided 32-bit copy for depth; s8 can become garbage x8 */ + util_format_z32_unorm_unpack_z_32unorm(dst, trans->trans->stride, + src, ptrans->stride, + width, height); + /* fallthru */ + case PIPE_FORMAT_X24S8_UINT: + dst = (uint8_t *)trans->ptr2 + + (box->y * trans->trans2->stride) + + (box->x * util_format_get_blocksize(PIPE_FORMAT_S8_UINT)); + + util_format_z24_unorm_s8_uint_unpack_s_8uint(dst, trans->trans2->stride, + src, ptrans->stride, + width, height); + break; + case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_LATC1_UNORM: @@ -487,6 +520,7 @@ u_transfer_helper_transfer_unmap(struct pipe_context *pctx, struct u_transfer_helper * u_transfer_helper_create(const struct u_transfer_vtbl *vtbl, bool separate_z32s8, + bool separate_stencil, bool fake_rgtc, bool msaa_map) { @@ -494,6 +528,7 @@ u_transfer_helper_create(const struct u_transfer_vtbl *vtbl, helper->vtbl = vtbl; helper->separate_z32s8 = separate_z32s8; + helper->separate_stencil = separate_stencil; helper->fake_rgtc = fake_rgtc; helper->msaa_map = msaa_map; diff --git a/src/gallium/auxiliary/util/u_transfer_helper.h b/src/gallium/auxiliary/util/u_transfer_helper.h index b13a1ec06c1..9e5f889f9d8 100644 --- a/src/gallium/auxiliary/util/u_transfer_helper.h +++ b/src/gallium/auxiliary/util/u_transfer_helper.h @@ -33,7 +33,7 @@ extern "C" { /* A helper to implement various "lowering" for transfers: * - * - exposing separate z32 and s8 as z32x24s8 + * - exposing separate depth and stencil resources as packed depth-stencil * - fake RGTC support for GLES class hardware which needs it to expose GL3+ * - MSAA resolves * @@ -79,16 +79,16 @@ struct u_transfer_vtbl { */ /** - * Must be implemented if separate_z32s8 or fake_rgtc is used. The + * Must be implemented if separate stencil or fake_rgtc is used. The * internal_format is the format the resource was created with. In - * the case of separate_z32s8 or fake_rgtc, prsc->format is set back - * to the state tracker visible format (Z32_FLOAT_S8X24_UINT or + * the case of separate stencil or fake_rgtc, prsc->format is set back + * to the state tracker visible format (e.g. Z32_FLOAT_S8X24_UINT or * PIPE_FORMAT_{RTGC,LATC}* after the resource is created. */ enum pipe_format (*get_internal_format)(struct pipe_resource *prsc); /** - * Must be implemented if separate_z32s8 is used. Used to set/get + * Must be implemented if separate stencil is lowered. Used to set/get * the separate s8 stencil buffer. * * These two do not get/put references to the pipe_resource. The @@ -123,6 +123,7 @@ struct u_transfer_helper; struct u_transfer_helper * u_transfer_helper_create(const struct u_transfer_vtbl *vtbl, bool separate_z32s8, + bool separate_stencil, bool fake_rgtc, bool msaa_map); diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 8fbc7819303..c82be3e2032 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -1183,7 +1183,7 @@ fd_resource_screen_init(struct pipe_screen *pscreen) pscreen->resource_destroy = u_transfer_helper_resource_destroy; pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, - true, fake_rgtc, true); + true, false, fake_rgtc, true); if (!screen->setup_slices) screen->setup_slices = fd_setup_slices; diff --git a/src/gallium/drivers/v3d/v3d_resource.c b/src/gallium/drivers/v3d/v3d_resource.c index 8bf6a97c394..dd0db8cfd89 100644 --- a/src/gallium/drivers/v3d/v3d_resource.c +++ b/src/gallium/drivers/v3d/v3d_resource.c @@ -909,7 +909,8 @@ v3d_resource_screen_init(struct pipe_screen *pscreen) pscreen->resource_get_handle = v3d_resource_get_handle; pscreen->resource_destroy = u_transfer_helper_resource_destroy; pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, - true, true, true); + true, false, + true, true); } void diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c index e169303f4a3..94784bbdc0a 100644 --- a/src/gallium/drivers/vc4/vc4_resource.c +++ b/src/gallium/drivers/vc4/vc4_resource.c @@ -1129,7 +1129,8 @@ vc4_resource_screen_init(struct pipe_screen *pscreen) pscreen->resource_get_handle = vc4_resource_get_handle; pscreen->resource_destroy = vc4_resource_destroy; pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, - false, false, true); + false, false, + false, true); /* Test if the kernel has GET_TILING; it will return -EINVAL if the * ioctl does not exist, but -ENOENT if we pass an impossible handle. -- 2.30.2