radeonsi: Copy all planes with multi-plane staging textures

Multi-plane format textures are allocated as a single buffer
for all planes, so when mapping first plane it will map
all planes.
However, when staging texture is used, only the first
plane will be available.

When asked to map first plane of multi-plane texture,
create a staging texture with matching multi-plane format
and copy all planes on map/unmap.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24389>
This commit is contained in:
David Rosca 2023-07-30 12:39:15 +02:00 committed by Marge Bot
parent 2cb3c2cbfb
commit 4f047c9583
2 changed files with 58 additions and 5 deletions

View file

@ -383,6 +383,7 @@ struct si_texture {
unsigned num_level0_transfers; unsigned num_level0_transfers;
unsigned plane_index; /* other planes are different pipe_resources */ unsigned plane_index; /* other planes are different pipe_resources */
unsigned num_planes; unsigned num_planes;
enum pipe_format multi_plane_format;
/* Depth buffer compression and fast clear. */ /* Depth buffer compression and fast clear. */
float depth_clear_value[RADEON_SURF_MAX_LEVELS]; float depth_clear_value[RADEON_SURF_MAX_LEVELS];

View file

@ -65,6 +65,44 @@ static void si_copy_region_with_blit(struct pipe_context *pipe, struct pipe_reso
} }
} }
/* Copy all planes of multi-plane texture */
static bool si_copy_multi_plane_texture(struct pipe_context *ctx, struct pipe_resource *dst,
unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *src, unsigned src_level,
const struct pipe_box *src_box)
{
unsigned i;
struct si_texture *src_tex = (struct si_texture *)src;
struct si_texture *dst_tex = (struct si_texture *)dst;
struct pipe_box sbox;
const struct util_format_description *desc;
if (src_tex->multi_plane_format == PIPE_FORMAT_NONE || src_tex->plane_index != 0)
return false;
assert(src_tex->multi_plane_format == dst_tex->multi_plane_format);
assert(dst_tex->plane_index == 0 && src_tex->num_planes == dst_tex->num_planes);
sbox = *src_box;
desc = util_format_description(src_tex->multi_plane_format);
for (i = 0; i < src_tex->num_planes; ++i) {
if (!src || !dst)
break;
si_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, src, src_level, &sbox);
src = src->next;
dst = dst->next;
if (i == 0) {
dstx /= desc->block.width;
dsty /= desc->block.height;
sbox.width /= desc->block.width;
sbox.height /= desc->block.height;
}
}
return true;
}
/* Copy from a full GPU texture to a transfer's staging one. */ /* Copy from a full GPU texture to a transfer's staging one. */
static void si_copy_to_staging_texture(struct pipe_context *ctx, struct si_transfer *stransfer) static void si_copy_to_staging_texture(struct pipe_context *ctx, struct si_transfer *stransfer)
{ {
@ -79,6 +117,9 @@ static void si_copy_to_staging_texture(struct pipe_context *ctx, struct si_trans
return; return;
} }
if (si_copy_multi_plane_texture(ctx, dst, 0, 0, 0, 0, src, src_level, &transfer->box))
return;
si_resource_copy_region(ctx, dst, 0, 0, 0, 0, src, src_level, &transfer->box); si_resource_copy_region(ctx, dst, 0, 0, 0, 0, src, src_level, &transfer->box);
} }
@ -101,6 +142,10 @@ static void si_copy_from_staging_texture(struct pipe_context *ctx, struct si_tra
return; return;
} }
if (si_copy_multi_plane_texture(ctx, dst, transfer->level, transfer->box.x, transfer->box.y,
transfer->box.z, src, 0, &sbox))
return;
if (util_format_is_compressed(dst->format)) { if (util_format_is_compressed(dst->format)) {
sbox.width = util_format_get_nblocksx(dst->format, sbox.width); sbox.width = util_format_get_nblocksx(dst->format, sbox.width);
sbox.height = util_format_get_nblocksx(dst->format, sbox.height); sbox.height = util_format_get_nblocksx(dst->format, sbox.height);
@ -1331,6 +1376,9 @@ si_texture_create_with_modifier(struct pipe_screen *screen,
si_set_tex_bo_metadata(sscreen, tex); si_set_tex_bo_metadata(sscreen, tex);
} }
if (num_planes >= 2)
plane0->multi_plane_format = templ->format;
return (struct pipe_resource *)plane0; return (struct pipe_resource *)plane0;
} }
@ -1753,8 +1801,12 @@ static void si_init_temp_resource_from_box(struct pipe_resource *res, struct pip
const struct pipe_box *box, unsigned level, const struct pipe_box *box, unsigned level,
unsigned usage, unsigned flags) unsigned usage, unsigned flags)
{ {
struct si_texture *tex = (struct si_texture *)orig;
enum pipe_format orig_format = tex->multi_plane_format != PIPE_FORMAT_NONE ?
tex->multi_plane_format : orig->format;
memset(res, 0, sizeof(*res)); memset(res, 0, sizeof(*res));
res->format = orig->format; res->format = orig_format;
res->width0 = box->width; res->width0 = box->width;
res->height0 = box->height; res->height0 = box->height;
res->depth0 = 1; res->depth0 = 1;
@ -1762,11 +1814,11 @@ static void si_init_temp_resource_from_box(struct pipe_resource *res, struct pip
res->usage = usage; res->usage = usage;
res->flags = flags; res->flags = flags;
if (flags & SI_RESOURCE_FLAG_FORCE_LINEAR && util_format_is_compressed(orig->format)) { if (flags & SI_RESOURCE_FLAG_FORCE_LINEAR && util_format_is_compressed(orig_format)) {
/* Transfer resources are allocated with linear tiling, which is /* Transfer resources are allocated with linear tiling, which is
* not supported for compressed formats. * not supported for compressed formats.
*/ */
unsigned blocksize = util_format_get_blocksize(orig->format); unsigned blocksize = util_format_get_blocksize(orig_format);
if (blocksize == 8) { if (blocksize == 8) {
res->format = PIPE_FORMAT_R16G16B16A16_UINT; res->format = PIPE_FORMAT_R16G16B16A16_UINT;
@ -1775,8 +1827,8 @@ static void si_init_temp_resource_from_box(struct pipe_resource *res, struct pip
res->format = PIPE_FORMAT_R32G32B32A32_UINT; res->format = PIPE_FORMAT_R32G32B32A32_UINT;
} }
res->width0 = util_format_get_nblocksx(orig->format, box->width); res->width0 = util_format_get_nblocksx(orig_format, box->width);
res->height0 = util_format_get_nblocksy(orig->format, box->height); res->height0 = util_format_get_nblocksy(orig_format, box->height);
} }
/* We must set the correct texture target and dimensions for a 3D box. */ /* We must set the correct texture target and dimensions for a 3D box. */