v3dv: handle pPlaneLayouts in VkImageDrmFormatModifierExplicitCreateInfoEXT

We have been ignoring these completely until now. V3D isn't very flexible
regarding image layouts anyway, so for the most part we require that
whatever the user puts here matches exactly what the driver would compute
while setting up the slices. The only exceptions are plane offsets which
and array strides.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9742
Tested-by: Roman Stratiienko <r.stratiienko@gmail.com>
Reviewed-by: Roman Stratiienko <r.stratiienko@gmail.com>
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25074>
This commit is contained in:
Iago Toral Quiroga
2023-09-05 12:41:21 +02:00
committed by Marge Bot
parent 717fbda536
commit 31eaeb8274

View File

@@ -91,13 +91,12 @@ v3d_get_dimension_mpad(uint32_t dimension, uint32_t level, uint32_t block_dimens
return u_minify(padded_dim, level - 1);
}
static void
static bool
v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
uint32_t plane_offset)
uint32_t plane_offset,
const VkSubresourceLayout *plane_layouts)
{
assert(image->planes[plane].cpp > 0);
/* Texture Base Address needs to be 64-byte aligned */
assert(plane_offset % 64 == 0);
uint32_t width = image->planes[plane].width;
uint32_t height = image->planes[plane].height;
@@ -136,7 +135,20 @@ v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
assert(depth > 0);
assert(image->vk.mip_levels >= 1);
uint32_t offset = plane_offset;
/* Texture Base Address needs to be 64-byte aligned. If we have an explicit
* plane layout we will return false to fail image creation with appropriate
* error code.
*/
uint32_t offset;
if (plane_layouts) {
offset = plane_layouts[plane].offset;
if (offset % 64 != 0)
return false;
} else {
offset = plane_offset;
}
assert(plane_offset % 64 == 0);
for (int32_t i = image->vk.mip_levels - 1; i >= 0; i--) {
struct v3d_resource_slice *slice = &image->planes[plane].slices[i];
@@ -209,6 +221,18 @@ v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
slice->offset = offset;
slice->stride = level_width * image->planes[plane].cpp;
/* We assume that rowPitch in the plane layout refers to level 0 */
if (plane_layouts && i == 0) {
if (plane_layouts[plane].rowPitch < slice->stride)
return false;
if (plane_layouts[plane].rowPitch % image->planes[plane].cpp)
return false;
if (image->tiled && (plane_layouts[plane].rowPitch % (4 * uif_block_w)))
return false;
slice->stride = plane_layouts[plane].rowPitch;
}
slice->padded_height = level_height;
if (slice->tiling == V3D_TILING_UIF_NO_XOR ||
slice->tiling == V3D_TILING_UIF_XOR) {
@@ -252,7 +276,8 @@ v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
image->planes[plane].alignment = 4096;
} else {
image->planes[plane].alignment =
(image->vk.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) ? 64 : image->planes[plane].cpp;
(image->vk.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) ?
64 : image->planes[plane].cpp;
}
uint32_t align_offset =
@@ -273,15 +298,36 @@ v3d_setup_plane_slices(struct v3dv_image *image, uint8_t plane,
image->planes[plane].cube_map_stride =
align(image->planes[plane].slices[0].offset +
image->planes[plane].slices[0].size, 64);
if (plane_layouts && image->vk.array_layers > 1) {
if (plane_layouts[plane].arrayPitch % 64 != 0)
return false;
if (plane_layouts[plane].arrayPitch <
image->planes[plane].cube_map_stride) {
return false;
}
image->planes[plane].cube_map_stride = plane_layouts[plane].arrayPitch;
}
image->planes[plane].size += image->planes[plane].cube_map_stride *
(image->vk.array_layers - 1);
} else {
image->planes[plane].cube_map_stride = image->planes[plane].slices[0].size;
if (plane_layouts) {
/* We assume that depthPitch in the plane layout refers to level 0 */
if (plane_layouts[plane].depthPitch !=
image->planes[plane].slices[0].size) {
return false;
}
}
}
return true;
}
static void
v3d_setup_slices(struct v3dv_image *image, bool disjoint)
static bool
v3d_setup_slices(struct v3dv_image *image, bool disjoint,
const VkSubresourceLayout *plane_layouts)
{
if (disjoint && image->plane_count == 1)
disjoint = false;
@@ -289,11 +335,15 @@ v3d_setup_slices(struct v3dv_image *image, bool disjoint)
uint32_t offset = 0;
for (uint8_t plane = 0; plane < image->plane_count; plane++) {
offset = disjoint ? 0 : offset;
v3d_setup_plane_slices(image, plane, offset);
if (!v3d_setup_plane_slices(image, plane, offset, plane_layouts)) {
assert(plane_layouts);
return false;
}
offset += align(image->planes[plane].size, 64);
}
image->non_disjoint_size = disjoint ? 0 : offset;
return true;
}
uint32_t
@@ -326,11 +376,13 @@ v3dv_image_init(struct v3dv_device *device,
*/
VkImageTiling tiling = pCreateInfo->tiling;
uint64_t modifier = DRM_FORMAT_MOD_INVALID;
const VkImageDrmFormatModifierListCreateInfoEXT *mod_info = NULL;
const VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod_info = NULL;
if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
const VkImageDrmFormatModifierListCreateInfoEXT *mod_info =
mod_info =
vk_find_struct_const(pCreateInfo->pNext,
IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
const VkImageDrmFormatModifierExplicitCreateInfoEXT *explicit_mod_info =
explicit_mod_info =
vk_find_struct_const(pCreateInfo->pNext,
IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT);
assert(mod_info || explicit_mod_info);
@@ -387,6 +439,8 @@ v3dv_image_init(struct v3dv_device *device,
image->format = format;
image->plane_count = vk_format_get_plane_count(pCreateInfo->format);
assert(!explicit_mod_info ||
image->plane_count == explicit_mod_info->drmFormatModifierPlaneCount);
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(image->vk.format);
@@ -423,7 +477,13 @@ v3dv_image_init(struct v3dv_device *device,
image->vk.create_flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
bool disjoint = image->vk.create_flags & VK_IMAGE_CREATE_DISJOINT_BIT;
v3d_setup_slices(image, disjoint);
bool ok =
v3d_setup_slices(image, disjoint,
explicit_mod_info ? explicit_mod_info->pPlaneLayouts : NULL);
if (!ok) {
assert(explicit_mod_info);
return VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT;
}
#ifdef ANDROID
if (native_buffer != NULL) {