diff options
author | Italo Nicola <italonicola@collabora.com> | 2023-02-01 19:21:26 +0000 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2023-08-07 19:35:12 +0000 |
commit | bba74a84a96d97290411e93d8a32fd2d5e686d76 (patch) | |
tree | 8b1051001c527b9324207cd96e80c11c48e04fc5 | |
parent | c1ad78476d52085203d22596d1eb59521d43a5ce (diff) |
panfrost: mandate proper alignment requirement depending format and arch
v7+ mandates row_stride alignment to be equal to surface alignment.
AFBC surface alignment is always 16-bytes.
NV12/NV21 formats on v7+ have 16-byte surface alignment.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21109>
-rw-r--r-- | src/gallium/drivers/panfrost/pan_resource.c | 5 | ||||
-rw-r--r-- | src/panfrost/lib/pan_layout.c | 64 | ||||
-rw-r--r-- | src/panfrost/lib/pan_texture.h | 3 | ||||
-rw-r--r-- | src/panfrost/lib/tests/test-layout.cpp | 28 | ||||
-rw-r--r-- | src/panfrost/vulkan/panvk_image.c | 3 |
5 files changed, 85 insertions, 18 deletions
diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 24f7d216c61..a75d4532211 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -132,7 +132,8 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, .nr_slices = 1, }; - bool valid = pan_image_layout_init(&rsc->image.layout, &explicit_layout); + bool valid = + pan_image_layout_init(dev, &rsc->image.layout, &explicit_layout); if (!valid) { FREE(rsc); @@ -491,7 +492,7 @@ panfrost_resource_setup(struct panfrost_device *dev, .crc = panfrost_should_checksum(dev, pres), }; - ASSERTED bool valid = pan_image_layout_init(&pres->image.layout, NULL); + ASSERTED bool valid = pan_image_layout_init(dev, &pres->image.layout, NULL); assert(valid); } diff --git a/src/panfrost/lib/pan_layout.c b/src/panfrost/lib/pan_layout.c index b63b6e31c87..abe654e3205 100644 --- a/src/panfrost/lib/pan_layout.c +++ b/src/panfrost/lib/pan_layout.c @@ -184,6 +184,26 @@ pan_afbc_body_align(uint64_t modifier) return (modifier & AFBC_FORMAT_MOD_TILED) ? 4096 : 64; } +static inline unsigned +format_minimum_alignment(const struct panfrost_device *dev, + enum pipe_format format, bool afbc) +{ + if (afbc) + return 16; + + if (dev->arch < 7) + return 63; + + switch (format) { + /* For v7+, NV12 and NV21 have a looser alignment requirement of 16 bytes */ + case PIPE_FORMAT_R8_G8B8_420_UNORM: + case PIPE_FORMAT_G8_B8R8_420_UNORM: + return 16; + default: + return 64; + } +} + /* Computes sizes for checksumming, which is 8 bytes per 16x16 tile. * Checksumming is believed to be a CRC variant (CRC64 based on the size?). * This feature is also known as "transaction elimination". */ @@ -262,7 +282,8 @@ panfrost_texture_offset(const struct pan_image_layout *layout, unsigned level, } bool -pan_image_layout_init(struct pan_image_layout *layout, +pan_image_layout_init(const struct panfrost_device *dev, + struct pan_image_layout *layout, const struct pan_image_explicit_layout *explicit_layout) { /* Explicit stride only work with non-mipmap, non-array, single-sample @@ -274,9 +295,29 @@ pan_image_layout_init(struct pan_image_layout *layout, layout->crc)) return false; - /* Mandate 64 byte alignement */ - if (explicit_layout && (explicit_layout->offset & 63)) - return false; + bool afbc = drm_is_afbc(layout->modifier); + int align_req = format_minimum_alignment(dev, layout->format, afbc); + + /* Mandate alignment */ + if (explicit_layout) { + bool rejected = false; + + int align_mask = align_req - 1; + + if (dev->arch >= 7) { + rejected = ((explicit_layout->offset & align_mask) || + (explicit_layout->row_stride & align_mask)); + } else { + rejected = (explicit_layout->offset & align_mask); + } + + if (rejected) { + mesa_loge( + "panfrost: rejecting image due to unsupported offset or stride " + "alignment.\n"); + return false; + } + } unsigned fmt_blocksize = util_format_get_blocksize(layout->format); @@ -285,7 +326,6 @@ pan_image_layout_init(struct pan_image_layout *layout, assert(layout->depth == 1 || layout->nr_samples == 1); - bool afbc = drm_is_afbc(layout->modifier); bool linear = layout->modifier == DRM_FORMAT_MOD_LINEAR; bool is_3d = layout->dim == MALI_TEXTURE_DIMENSION_3D; @@ -323,10 +363,17 @@ pan_image_layout_init(struct pan_image_layout *layout, unsigned row_stride = fmt_blocksize * effective_width * block_size.height; + /* On v7+ row_stride and offset alignment requirement are equal */ + if (dev->arch >= 7) { + row_stride = ALIGN_POT(row_stride, align_req); + } + if (explicit_layout && !afbc) { /* Make sure the explicit stride is valid */ - if (explicit_layout->row_stride < row_stride) + if (explicit_layout->row_stride < row_stride) { + mesa_loge("panfrost: rejecting image due to invalid row stride.\n"); return false; + } row_stride = explicit_layout->row_stride; } else if (linear) { @@ -345,8 +392,11 @@ pan_image_layout_init(struct pan_image_layout *layout, ALIGN_POT(slice->row_stride * (effective_height / align_h), pan_afbc_body_align(layout->modifier)); - if (explicit_layout && explicit_layout->row_stride < slice->row_stride) + if (explicit_layout && + explicit_layout->row_stride < slice->row_stride) { + mesa_loge("panfrost: rejecting image due to invalid row stride.\n"); return false; + } /* AFBC body size */ slice->afbc.body_size = slice_one_size; diff --git a/src/panfrost/lib/pan_texture.h b/src/panfrost/lib/pan_texture.h index 75822668507..790e34dd1ef 100644 --- a/src/panfrost/lib/pan_texture.h +++ b/src/panfrost/lib/pan_texture.h @@ -287,7 +287,8 @@ struct pan_image_explicit_layout { }; bool -pan_image_layout_init(struct pan_image_layout *layout, +pan_image_layout_init(const struct panfrost_device *dev, + struct pan_image_layout *layout, const struct pan_image_explicit_layout *explicit_layout); unsigned panfrost_get_legacy_stride(const struct pan_image_layout *layout, diff --git a/src/panfrost/lib/tests/test-layout.cpp b/src/panfrost/lib/tests/test-layout.cpp index f47337a64f4..0628e0b2740 100644 --- a/src/panfrost/lib/tests/test-layout.cpp +++ b/src/panfrost/lib/tests/test-layout.cpp @@ -267,6 +267,8 @@ TEST(LegacyStride, FromLegacyAFBC) /* dEQP-GLES3.functional.texture.format.compressed.etc1_2d_pot */ TEST(Layout, ImplicitLayoutInterleavedETC2) { + struct panfrost_device dev = {0}; + struct pan_image_layout l = { .modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, .format = PIPE_FORMAT_ETC2_RGB8, @@ -280,7 +282,7 @@ TEST(Layout, ImplicitLayoutInterleavedETC2) unsigned offsets[9] = {0, 8192, 10240, 10752, 10880, 11008, 11136, 11264, 11392}; - ASSERT_TRUE(pan_image_layout_init(&l, NULL)); + ASSERT_TRUE(pan_image_layout_init(&dev, &l, NULL)); for (unsigned i = 0; i < 8; ++i) { unsigned size = (offsets[i + 1] - offsets[i]); @@ -295,6 +297,8 @@ TEST(Layout, ImplicitLayoutInterleavedETC2) TEST(Layout, ImplicitLayoutInterleavedASTC5x5) { + struct panfrost_device dev = {0}; + struct pan_image_layout l = { .modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, .format = PIPE_FORMAT_ASTC_5x5, @@ -305,7 +309,7 @@ TEST(Layout, ImplicitLayoutInterleavedASTC5x5) .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1}; - ASSERT_TRUE(pan_image_layout_init(&l, NULL)); + ASSERT_TRUE(pan_image_layout_init(&dev, &l, NULL)); /* The image is 50x50 pixels, with 5x5 blocks. So it is a 10x10 grid of ASTC * blocks. 4x4 tiles of ASTC blocks are u-interleaved, so we have to round up @@ -321,6 +325,8 @@ TEST(Layout, ImplicitLayoutInterleavedASTC5x5) TEST(Layout, ImplicitLayoutLinearASTC5x5) { + struct panfrost_device dev = {0}; + struct pan_image_layout l = {.modifier = DRM_FORMAT_MOD_LINEAR, .format = PIPE_FORMAT_ASTC_5x5, .width = 50, @@ -330,7 +336,7 @@ TEST(Layout, ImplicitLayoutLinearASTC5x5) .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1}; - ASSERT_TRUE(pan_image_layout_init(&l, NULL)); + ASSERT_TRUE(pan_image_layout_init(&dev, &l, NULL)); /* The image is 50x50 pixels, with 5x5 blocks. So it is a 10x10 grid of ASTC * blocks. Each ASTC block is 16 bytes, so the row stride is 160 bytes, @@ -346,6 +352,8 @@ TEST(Layout, ImplicitLayoutLinearASTC5x5) /* dEQP-GLES3.functional.texture.format.unsized.rgba_unsigned_byte_3d_pot */ TEST(AFBCLayout, Linear3D) { + struct panfrost_device dev = {0}; + uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE); @@ -358,7 +366,7 @@ TEST(AFBCLayout, Linear3D) .dim = MALI_TEXTURE_DIMENSION_3D, .nr_slices = 1}; - ASSERT_TRUE(pan_image_layout_init(&l, NULL)); + ASSERT_TRUE(pan_image_layout_init(&dev, &l, NULL)); /* AFBC Surface stride is bytes between consecutive surface headers, which is * the header size since this is a 3D texture. At superblock size 16x16, the @@ -384,6 +392,8 @@ TEST(AFBCLayout, Linear3D) TEST(AFBCLayout, Tiled16x16) { + struct panfrost_device dev = {0}; + uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE); @@ -397,7 +407,7 @@ TEST(AFBCLayout, Tiled16x16) .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1}; - ASSERT_TRUE(pan_image_layout_init(&l, NULL)); + ASSERT_TRUE(pan_image_layout_init(&dev, &l, NULL)); /* The image is 917x417. Superblocks are 16x16, so there are 58x27 * superblocks. Superblocks are grouped into 8x8 tiles, so there are 8x4 @@ -421,6 +431,8 @@ TEST(AFBCLayout, Tiled16x16) TEST(AFBCLayout, Linear16x16Minimal) { + struct panfrost_device dev = {0}; + uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE); @@ -433,7 +445,7 @@ TEST(AFBCLayout, Linear16x16Minimal) .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1}; - ASSERT_TRUE(pan_image_layout_init(&l, NULL)); + ASSERT_TRUE(pan_image_layout_init(&dev, &l, NULL)); /* Image is 1x1 to test for correct alignment everywhere. */ EXPECT_EQ(l.slices[0].offset, 0); @@ -446,6 +458,8 @@ TEST(AFBCLayout, Linear16x16Minimal) TEST(AFBCLayout, Tiled16x16Minimal) { + struct panfrost_device dev = {0}; + uint64_t modifier = DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SPARSE); @@ -459,7 +473,7 @@ TEST(AFBCLayout, Tiled16x16Minimal) .dim = MALI_TEXTURE_DIMENSION_2D, .nr_slices = 1}; - ASSERT_TRUE(pan_image_layout_init(&l, NULL)); + ASSERT_TRUE(pan_image_layout_init(&dev, &l, NULL)); /* Image is 1x1 to test for correct alignment everywhere. */ EXPECT_EQ(l.slices[0].offset, 0); diff --git a/src/panfrost/vulkan/panvk_image.c b/src/panfrost/vulkan/panvk_image.c index 5a1d3a60234..938eadf8918 100644 --- a/src/panfrost/vulkan/panvk_image.c +++ b/src/panfrost/vulkan/panvk_image.c @@ -70,6 +70,7 @@ panvk_image_create(VkDevice _device, const VkImageCreateInfo *pCreateInfo, uint64_t modifier, const VkSubresourceLayout *plane_layouts) { VK_FROM_HANDLE(panvk_device, device, _device); + const struct panfrost_device *pdev = &device->physical_device->pdev; struct panvk_image *image = NULL; image = vk_image_create(&device->vk, pCreateInfo, alloc, sizeof(*image)); @@ -88,7 +89,7 @@ panvk_image_create(VkDevice _device, const VkImageCreateInfo *pCreateInfo, .nr_slices = image->vk.mip_levels, }; - pan_image_layout_init(&image->pimage.layout, NULL); + pan_image_layout_init(pdev, &image->pimage.layout, NULL); *pImage = panvk_image_to_handle(image); return VK_SUCCESS; |