panvk: fix imported external multi-planar image support

This change and the prior preparations have fixed the false assumption
of ordered image planes for external multi-planar image (YV12 has the
chroma planes swapped to map to the Vulkan format). We no longer need to
use plane data size to advance plane offset. The code paths for
subresource reporting, memroy reporting and memory binding are now
consistent across native disjoint/non-disjoint and imported external
images no matter single-planar or multi-planar.

Test:
- No regressions in dEQP-VK.ycbcr.*
- NV12 camera preview works on Android
- YV12 video playback works on Android
- Android graphics cts passing
  - BasicVulkanGpuTest
  - MediaVulkanGpuTest
  - CameraVulkanGpuTest

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35299>
This commit is contained in:
Yiwei Zhang
2025-06-02 14:26:36 -07:00
committed by Marge Bot
parent a9006ebde0
commit 69b458fdd7
2 changed files with 27 additions and 31 deletions
-4
View File
@@ -31,10 +31,6 @@ struct pan_image_slice_layout {
* Doing so allows us to use a single code path to correctly:
* - report image subres layout and memory requirement
* - bind image memory
*
* XXX However, for native non-disjoint multi-planar images in panvk, this
* offset_B is currently relative to the planar plane offset instead of base
* bo offset. To be fixed in the follow up.
*/
unsigned offset_B;
+27 -27
View File
@@ -208,6 +208,16 @@ panvk_image_type_to_mali_tex_dim(VkImageType type)
}
}
static bool
is_disjoint(const struct panvk_image *image)
{
assert((image->plane_count > 1 &&
image->vk.format != VK_FORMAT_D32_SFLOAT_S8_UINT) ||
(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) ||
!(image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT));
return image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT;
}
static void
panvk_image_init_layouts(struct panvk_image *image,
const VkImageCreateInfo *pCreateInfo)
@@ -229,6 +239,9 @@ panvk_image_init_layouts(struct panvk_image *image,
if (image->vk.format == VK_FORMAT_D32_SFLOAT_S8_UINT)
image->plane_count = 2;
struct pan_image_layout_constraints plane_layout = {
.offset_B = 0,
};
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
VkFormat format;
@@ -237,7 +250,6 @@ panvk_image_init_layouts(struct panvk_image *image,
else
format = vk_format_get_plane_format(image->vk.format, plane);
struct pan_image_layout_constraints plane_layout;
if (explicit_info) {
plane_layout = (struct pan_image_layout_constraints){
.offset_B = explicit_info->pPlaneLayouts[plane].offset,
@@ -265,8 +277,10 @@ panvk_image_init_layouts(struct panvk_image *image,
};
pan_image_layout_init(arch, &image->planes[plane].image.props, 0,
explicit_info ? &plane_layout : NULL,
&image->planes[plane].plane.layout);
&plane_layout, &image->planes[plane].plane.layout);
if (!is_disjoint(image) && !explicit_info)
plane_layout.offset_B += image->planes[plane].plane.layout.data_size_B;
}
}
@@ -330,21 +344,14 @@ static uint64_t
panvk_image_get_total_size(const struct panvk_image *image)
{
uint64_t size = 0;
for (uint8_t plane = 0; plane < image->plane_count; plane++)
size += image->planes[plane].plane.layout.data_size_B;
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
const struct pan_image_layout *layout =
&image->planes[plane].plane.layout;
size = MAX2(size, layout->slices[0].offset_B + layout->data_size_B);
}
return size;
}
static bool
is_disjoint(const struct panvk_image *image)
{
assert((image->plane_count > 1 &&
image->vk.format != VK_FORMAT_D32_SFLOAT_S8_UINT) ||
(image->vk.create_flags & VK_IMAGE_CREATE_ALIAS_BIT) ||
!(image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT));
return image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT;
}
static void
panvk_image_init(struct panvk_image *image,
const VkImageCreateInfo *pCreateInfo)
@@ -425,14 +432,8 @@ get_image_subresource_layout(const struct panvk_image *image,
const struct pan_image_slice_layout *slice_layout =
&image->planes[plane].plane.layout.slices[subres->mipLevel];
uint64_t base_offset = 0;
if (!is_disjoint(image)) {
for (uint8_t plane_idx = 0; plane_idx < plane; plane_idx++)
base_offset += image->planes[plane_idx].plane.layout.data_size_B;
}
layout->offset =
base_offset + slice_layout->offset_B +
slice_layout->offset_B +
(subres->arrayLayer * image->planes[plane].plane.layout.array_stride_B);
layout->size = slice_layout->size_B;
layout->rowPitch = slice_layout->row_stride_B;
@@ -595,20 +596,19 @@ panvk_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
assert(mem);
image->bo = mem->bo;
uint64_t offset = pBindInfos[i].memoryOffset;
if (is_disjoint(image)) {
const VkBindImagePlaneMemoryInfo *plane_info =
vk_find_struct_const(pBindInfos[i].pNext,
BIND_IMAGE_PLANE_MEMORY_INFO);
uint8_t plane =
const uint8_t plane =
panvk_plane_index(image->vk.format, plane_info->planeAspect);
panvk_image_plane_bind(&image->planes[plane], image->bo,
mem->addr.dev, offset);
mem->addr.dev, pBindInfos[i].memoryOffset);
} else {
for (unsigned plane = 0; plane < image->plane_count; plane++) {
panvk_image_plane_bind(&image->planes[plane], image->bo,
mem->addr.dev, offset);
offset += image->planes[plane].plane.layout.data_size_B;
mem->addr.dev,
pBindInfos[i].memoryOffset);
}
}
}