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);