From 20a97c928e580720523e90746e6e638b701bbbb8 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 19 May 2025 17:57:40 +0200 Subject: [PATCH] pan/layout: Add an option to enforce WSI row pitch at layout init time At the moment, we check that the WSI pitch is big enough to cover the resource width, but we don't validate that it's tile aligned, and we also don't use the user provided pitch when AFBC is requested, meaning we don't allow row tile padding. Add an option to force using the explicit WSI pitch, and fail if the pitch doesn't give a tile aligned row stride. Signed-off-by: Boris Brezillon Tested-by: Eric R. Smith Reviewed-by: Eric R. Smith Reviewed-by: Mary Guillemard Part-of: --- src/panfrost/lib/pan_layout.c | 27 +++++++++++++++++++++++--- src/panfrost/lib/pan_layout.h | 1 + src/panfrost/lib/tests/test-layout.cpp | 5 +++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index 7ab3951a218..1592c5f7454 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -215,6 +215,18 @@ wsi_row_pitch_to_row_stride(unsigned arch, const struct pan_image_props *props, (afbc_tile_payload_row_stride_B / afbc_tile_payload_size_B) * afbc_tile_extent_px.width; *row_stride_B = pan_afbc_row_stride(modifier, width_px); + + /* For quite some time, we've been accepting WSI row pitch that + * didn't match exactly the image size and have been assuming tightly + * packed tile rows instead of using the explicit stride in that case. + * This is something we can't change without risking breaking existing + * users, so we enforce this explicit tile alignment only if we were + * asked to. */ + if (wsi_layout->strict && + (afbc_tile_payload_row_stride_B % afbc_tile_payload_size_B)) { + mesa_loge("WSI pitch is not aligned on an AFBC tile"); + return false; + } } else if (drm_is_afrc(modifier)) { struct pan_image_block_size tile_size_px = pan_afrc_tile_size(format, modifier); @@ -369,11 +381,13 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props, row_stride_B = ALIGN_POT(row_stride_B, align_req_B); } - if (wsi_layout && !afbc && !afrc) { + if (wsi_layout && !afbc) { /* Explicit stride should be rejected by wsi_row_pitch_to_row_stride() * if it's too small. */ assert(wsi_row_stride_B >= row_stride_B); - row_stride_B = wsi_row_stride_B; + + if (!afrc || wsi_layout->strict) + row_stride_B = wsi_row_stride_B; } else if (linear) { /* Keep lines alignment on 64 byte for performance */ row_stride_B = ALIGN_POT(row_stride_B, 64); @@ -390,7 +404,14 @@ pan_image_layout_init(unsigned arch, const struct pan_image_props *props, /* Explicit stride should be rejected by wsi_row_pitch_to_row_stride() * if it's too small. */ assert(!wsi_layout || wsi_row_stride_B >= slice->row_stride_B); - slice->afbc.stride_sb = effective_width_el / block_size_el.width; + + if (wsi_layout && wsi_layout->strict) { + slice->row_stride_B = wsi_row_stride_B; + slice_one_size_B = (uint64_t)wsi_layout->row_pitch_B * effective_height_el; + } + + slice->afbc.stride_sb = + pan_afbc_stride_blocks(props->modifier, slice->row_stride_B); slice->afbc.nr_sblocks = slice->afbc.stride_sb * (effective_height_el / block_size_el.height); slice->afbc.header_size_B = diff --git a/src/panfrost/lib/pan_layout.h b/src/panfrost/lib/pan_layout.h index e148c8a4bb7..c47ad838e99 100644 --- a/src/panfrost/lib/pan_layout.h +++ b/src/panfrost/lib/pan_layout.h @@ -96,6 +96,7 @@ struct pan_image_layout { struct pan_image_wsi_layout { unsigned offset_B; unsigned row_pitch_B; + bool strict; }; /* diff --git a/src/panfrost/lib/tests/test-layout.cpp b/src/panfrost/lib/tests/test-layout.cpp index afbb26c4d77..17bce12cc79 100644 --- a/src/panfrost/lib/tests/test-layout.cpp +++ b/src/panfrost/lib/tests/test-layout.cpp @@ -227,6 +227,7 @@ row_stride_from_wsi_pitch(unsigned row_pitch_B, unsigned width_px, { const struct pan_image_wsi_layout wsi_l = { .row_pitch_B = row_pitch_B, + .strict = true, }; struct pan_image_props p = { .modifier = mod, @@ -254,9 +255,9 @@ TEST(WSI, FromWSILinear) row_stride_from_wsi_pitch(1920 * 4, 1920, PIPE_FORMAT_R8G8B8A8_UINT, DRM_FORMAT_MOD_LINEAR), 1920 * 4); - EXPECT_EQ(row_stride_from_wsi_pitch(53, 53, PIPE_FORMAT_R8_SNORM, + EXPECT_EQ(row_stride_from_wsi_pitch(64, 53, PIPE_FORMAT_R8_SNORM, DRM_FORMAT_MOD_LINEAR), - 53); + 64); EXPECT_EQ(row_stride_from_wsi_pitch(64, 32, PIPE_FORMAT_ETC2_RGB8, DRM_FORMAT_MOD_LINEAR), 64);