From fa6704a523edf7c0da62df1734d9aa54141e4ed4 Mon Sep 17 00:00:00 2001 From: Ella Stanforth Date: Tue, 27 Jan 2026 14:11:50 +0000 Subject: [PATCH] pvr: add multiplanar format support Reviewed-by: Simon Perretta Part-of: --- src/imagination/vulkan/pvr_arch_cmd_buffer.c | 35 ++++--- src/imagination/vulkan/pvr_arch_image.c | 24 +++-- src/imagination/vulkan/pvr_device.c | 2 +- src/imagination/vulkan/pvr_image.c | 99 +++++++++++++++----- src/imagination/vulkan/pvr_image.h | 84 ++++++++++++++++- src/imagination/vulkan/rogue/pvr_blit.c | 95 ++++++++++++++----- 6 files changed, 261 insertions(+), 78 deletions(-) diff --git a/src/imagination/vulkan/pvr_arch_cmd_buffer.c b/src/imagination/vulkan/pvr_arch_cmd_buffer.c index fd5e3dc983b..8e3f6b06c97 100644 --- a/src/imagination/vulkan/pvr_arch_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_arch_cmd_buffer.c @@ -685,6 +685,7 @@ static VkResult pvr_setup_texture_state_words( uint32_t view_index) { const struct pvr_image *image = vk_to_pvr_image(image_view->vk.image); + const struct pvr_image_plane *plane = pvr_single_plane_const(image); struct pvr_texture_state_info info = { .format = image_view->vk.format, .mem_layout = image->memlayout, @@ -695,8 +696,8 @@ static VkResult pvr_setup_texture_state_words( .extent = image_view->vk.extent, .mip_levels = 1, .sample_count = image_view->vk.image->samples, - .stride = image->physical_extent.width, - .offset = image->layer_size * view_index, + .stride = plane->physical_extent.width, + .offset = plane->layer_size * view_index, .addr = image->dev_addr, }; const uint8_t *const swizzle = pvr_get_format_swizzle(info.format); @@ -1106,7 +1107,8 @@ static void pvr_setup_pbe_state( uint32_t view_index) { const struct pvr_image *image = pvr_image_view_get_image(iview); - uint32_t level_pitch = image->mip_levels[iview->vk.base_mip_level].pitch; + const struct pvr_image_plane *plane = pvr_single_plane_const(image); + uint32_t level_pitch = plane->mip_levels[iview->vk.base_mip_level].pitch; struct pvr_pbe_surf_params surface_params; struct pvr_pbe_render_params render_params; @@ -1147,13 +1149,13 @@ static void pvr_setup_pbe_state( */ surface_params.addr = PVR_DEV_ADDR_OFFSET( image->vma->dev_addr, - image->layer_size * view_index + - image->mip_levels[iview->vk.base_mip_level].offset); + plane->layer_size * view_index + + plane->mip_levels[iview->vk.base_mip_level].offset); if (!iview->vk.storage.z_slice_offset) { surface_params.addr = PVR_DEV_ADDR_OFFSET(surface_params.addr, - iview->vk.base_array_layer * image->layer_size); + iview->vk.base_array_layer * plane->layer_size); } surface_params.mem_layout = image->memlayout; @@ -1288,13 +1290,15 @@ static bool pvr_sub_cmd_gfx_requires_ds_subtile_alignment( { const struct pvr_image *const ds_image = pvr_image_view_get_image(job->ds.iview); + const struct pvr_image_plane *const ds_plane = + pvr_single_plane_const(ds_image); uint32_t zls_tile_size_x; uint32_t zls_tile_size_y; rogue_get_zls_tile_size_xy(dev_info, &zls_tile_size_x, &zls_tile_size_y); - if (ds_image->physical_extent.width >= zls_tile_size_x && - ds_image->physical_extent.height >= zls_tile_size_y) { + if (ds_plane->physical_extent.width >= zls_tile_size_x && + ds_plane->physical_extent.height >= zls_tile_size_y) { return false; } @@ -1325,6 +1329,8 @@ pvr_sub_cmd_gfx_align_ds_subtiles(struct pvr_cmd_buffer *const cmd_buffer, container_of(gfx_sub_cmd, struct pvr_sub_cmd, gfx); struct pvr_ds_attachment *const ds = &gfx_sub_cmd->job.ds; const struct pvr_image *const ds_image = pvr_image_view_get_image(ds->iview); + const struct pvr_image_plane *const ds_plane = + pvr_single_plane_const(ds_image); const VkFormat copy_format = pvr_get_raw_copy_format(ds_image->vk.format); struct pvr_suballoc_bo *buffer; @@ -1354,9 +1360,9 @@ pvr_sub_cmd_gfx_align_ds_subtiles(struct pvr_cmd_buffer *const cmd_buffer, &scale.height); rounded_size = (VkExtent2D){ - .width = ALIGN_POT(ds_image->physical_extent.width, zls_tile_size.width), + .width = ALIGN_POT(ds_plane->physical_extent.width, zls_tile_size.width), .height = - ALIGN_POT(ds_image->physical_extent.height, zls_tile_size.height), + ALIGN_POT(ds_plane->physical_extent.height, zls_tile_size.height), }; buffer_layer_size = vk_format_get_blocksize(ds_image->vk.format) * @@ -1767,13 +1773,14 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, struct pvr_image_view *ds_iview = render_pass_info->attachments[hw_render->ds_attach_idx]; const struct pvr_image *ds_image = pvr_image_view_get_image(ds_iview); + const struct pvr_image_plane *ds_plane = pvr_single_plane_const(ds_image); job->has_depth_attachment = vk_format_has_depth(ds_image->vk.format); job->has_stencil_attachment = vk_format_has_stencil(ds_image->vk.format); if (job->has_depth_attachment || job->has_stencil_attachment) { uint32_t level_pitch = - ds_image->mip_levels[ds_iview->vk.base_mip_level].pitch; + ds_plane->mip_levels[ds_iview->vk.base_mip_level].pitch; const bool render_area_is_tile_aligned = pvr_is_render_area_tile_aligned(cmd_buffer, ds_iview); bool store_was_optimised_out = false; @@ -1787,12 +1794,12 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, pvr_stride_from_pitch(level_pitch, ds_iview->vk.format); job->ds.height = ds_iview->vk.extent.height; job->ds.physical_extent = (VkExtent2D){ - .width = u_minify(ds_image->physical_extent.width, + .width = u_minify(ds_plane->physical_extent.width, ds_iview->vk.base_mip_level), - .height = u_minify(ds_image->physical_extent.height, + .height = u_minify(ds_plane->physical_extent.height, ds_iview->vk.base_mip_level), }; - job->ds.layer_size = ds_image->layer_size; + job->ds.layer_size = ds_plane->layer_size; job->ds_clear_value = default_ds_clear_value; diff --git a/src/imagination/vulkan/pvr_arch_image.c b/src/imagination/vulkan/pvr_arch_image.c index 3283ec9b586..5ba025f601d 100644 --- a/src/imagination/vulkan/pvr_arch_image.c +++ b/src/imagination/vulkan/pvr_arch_image.c @@ -19,6 +19,7 @@ #include "pvr_tex_state.h" static void pvr_adjust_non_compressed_view(const struct pvr_image *image, + const struct pvr_image_plane *plane, struct pvr_texture_state_info *info) { const uint32_t base_level = info->base_level; @@ -37,7 +38,7 @@ static void pvr_adjust_non_compressed_view(const struct pvr_image *image, info->extent.height = u_minify(info->extent.height, base_level); info->extent.depth = u_minify(info->extent.depth, base_level); info->extent = vk_image_extent_to_elements(&image->vk, info->extent); - info->offset += image->mip_levels[base_level].offset; + info->offset += plane->mip_levels[base_level].offset; info->base_level = 0; } @@ -62,6 +63,17 @@ VkResult PVR_PER_ARCH(CreateImageView)(VkDevice _device, return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); image = pvr_image_view_get_image(iview); + const struct pvr_image_plane *plane; + + const struct vk_format_ycbcr_info *ycbcr_image = + vk_format_get_ycbcr_info(image->vk.format); + const struct vk_format_ycbcr_info *ycbcr_iview = + vk_format_get_ycbcr_info(iview->vk.format); + if (ycbcr_image && !ycbcr_iview) { + plane = pvr_plane_from_aspect_const(image, iview->vk.aspects); + } else { + plane = &image->planes[0]; + } if (image->vk.image_type == VK_IMAGE_TYPE_3D && (iview->vk.view_type == VK_IMAGE_VIEW_TYPE_2D_ARRAY || @@ -77,9 +89,9 @@ VkResult PVR_PER_ARCH(CreateImageView)(VkDevice _device, info.is_cube = (info.type == VK_IMAGE_VIEW_TYPE_CUBE || info.type == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY); info.array_size = iview->vk.layer_count; - info.offset = iview->vk.base_array_layer * image->layer_size; + info.offset = iview->vk.base_array_layer * plane->layer_size; info.mipmaps_present = (image->vk.mip_levels > 1) ? true : false; - info.stride = image->physical_extent.width; + info.stride = plane->physical_extent.width; info.tex_state_type = PVR_TEXTURE_STATE_SAMPLE; info.mem_layout = image->memlayout; info.flags = 0; @@ -87,14 +99,14 @@ VkResult PVR_PER_ARCH(CreateImageView)(VkDevice _device, info.addr = image->dev_addr; info.format = pCreateInfo->format; - info.layer_size = image->layer_size; + info.layer_size = plane->layer_size; if (image->vk.create_flags & VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT) { info.offset = 0; info.z_slice = iview->vk.base_array_layer; } - pvr_adjust_non_compressed_view(image, &info); + pvr_adjust_non_compressed_view(image, plane, &info); vk_component_mapping_to_pipe_swizzle(iview->vk.swizzle, input_swizzle); @@ -155,7 +167,7 @@ VkResult PVR_PER_ARCH(CreateImageView)(VkDevice _device, info.mip_levels = 1; info.mipmaps_present = false; - info.stride = u_minify(image->physical_extent.width, info.base_level); + info.stride = u_minify(plane->physical_extent.width, info.base_level); info.base_level = 0; info.tex_state_type = PVR_TEXTURE_STATE_ATTACHMENT; diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 26bf808797b..b8bb8bf539d 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -1037,7 +1037,7 @@ void pvr_GetImageMemoryRequirements2(VkDevice _device, */ pMemoryRequirements->memoryRequirements.alignment = image->alignment; pMemoryRequirements->memoryRequirements.size = - align64(image->size, image->alignment); + align64(image->total_size, image->alignment); pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types; vk_foreach_struct (ext, pMemoryRequirements->pNext) { diff --git a/src/imagination/vulkan/pvr_image.c b/src/imagination/vulkan/pvr_image.c index 09458aad3f6..eea7de6e4dd 100644 --- a/src/imagination/vulkan/pvr_image.c +++ b/src/imagination/vulkan/pvr_image.c @@ -64,60 +64,88 @@ static void pvr_image_init_memlayout(struct pvr_image *image) } } -static void pvr_image_init_physical_extent(struct pvr_image *image, - unsigned pbe_stride_align) +static void pvr_image_plane_init_physical_extent( + struct pvr_image *image, + unsigned pbe_stride_align, + const struct vk_format_ycbcr_info *ycbcr_info, + uint8_t i) { - assert(image->memlayout != PVR_MEMLAYOUT_UNDEFINED); - + struct pvr_image_plane *plane = &image->planes[i]; /* clang-format off */ if (image->vk.mip_levels > 1 || image->memlayout == PVR_MEMLAYOUT_TWIDDLED || image->memlayout == PVR_MEMLAYOUT_3DTWIDDLED) { /* clang-format on */ - image->physical_extent.width = + plane->physical_extent.width = util_next_power_of_two(image->vk.extent.width); - image->physical_extent.height = + plane->physical_extent.height = util_next_power_of_two(image->vk.extent.height); - image->physical_extent.depth = + plane->physical_extent.depth = util_next_power_of_two(image->vk.extent.depth); } else { assert(image->memlayout == PVR_MEMLAYOUT_LINEAR); - image->physical_extent = image->vk.extent; + plane->physical_extent = image->vk.extent; /* If the image is being rendered to (written by the PBE) make sure the * width is aligned correctly. */ if (image->vk.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)) { - image->physical_extent.width = - align(image->physical_extent.width, pbe_stride_align); + plane->physical_extent.width = + align(plane->physical_extent.width, pbe_stride_align); } } + + if (ycbcr_info) { + plane->physical_extent.width /= + ycbcr_info->planes[i].denominator_scales[0]; + plane->physical_extent.height /= + ycbcr_info->planes[i].denominator_scales[1]; + } } -static void pvr_image_setup_mip_levels(struct pvr_image *image) +static void pvr_image_init_physical_extent(struct pvr_image *image, + unsigned pbe_stride_align) { + assert(image->memlayout != PVR_MEMLAYOUT_UNDEFINED); + + const struct vk_format_ycbcr_info *ycbcr_info = + vk_format_get_ycbcr_info(image->vk.format); + + for (uint8_t plane = 0; plane < image->plane_count; plane++) { + pvr_image_plane_init_physical_extent(image, + pbe_stride_align, + ycbcr_info, + plane); + } +} + +static void pvr_image_plane_setup_mip_levels(struct pvr_image *image, uint8_t i) +{ + struct pvr_image_plane *plane = &image->planes[i]; + VkFormat plane_format = vk_format_get_plane_format(image->vk.format, i); + const uint32_t extent_alignment = image->vk.image_type == VK_IMAGE_TYPE_3D ? 4 : 1; - const unsigned int cpp = vk_format_get_blocksize(image->vk.format); + const unsigned int cpp = vk_format_get_blocksize(plane_format); VkExtent3D extent = - vk_image_extent_to_elements(&image->vk, image->physical_extent); + vk_image_extent_to_elements(&image->vk, plane->physical_extent); - assert(image->vk.mip_levels <= ARRAY_SIZE(image->mip_levels)); + assert(image->vk.mip_levels <= ARRAY_SIZE(plane->mip_levels)); - image->layer_size = 0; + plane->layer_size = 0; for (uint32_t i = 0; i < image->vk.mip_levels; i++) { - struct pvr_mip_level *mip_level = &image->mip_levels[i]; + struct pvr_mip_level *mip_level = &plane->mip_levels[i]; mip_level->pitch = cpp * align(extent.width, extent_alignment); mip_level->height_pitch = align(extent.height, extent_alignment); mip_level->size = image->vk.samples * mip_level->pitch * mip_level->height_pitch * align(extent.depth, extent_alignment); - mip_level->offset = image->layer_size; + mip_level->offset = plane->layer_size; - image->layer_size += mip_level->size; + plane->layer_size += mip_level->size; extent.height = u_minify(extent.height, 1); extent.width = u_minify(extent.width, 1); @@ -132,7 +160,7 @@ static void pvr_image_setup_mip_levels(struct pvr_image *image) const uint32_t height_pitch = align(extent.height, extent_alignment); const uint32_t pitch = cpp * align(extent.width, extent_alignment); - image->layer_size += image->vk.samples * pitch * height_pitch * + plane->layer_size += image->vk.samples * pitch * height_pitch * align(extent.depth, extent_alignment); extent.height = u_minify(extent.height, 1); @@ -147,9 +175,23 @@ static void pvr_image_setup_mip_levels(struct pvr_image *image) * requirement comes from. */ if (image->vk.array_layers > 1) - image->layer_size = align64(image->layer_size, image->alignment); + plane->layer_size = align64(plane->layer_size, image->alignment); - image->size = image->layer_size * image->vk.array_layers; + plane->size = plane->layer_size * image->vk.array_layers; +} + +static void pvr_image_setup_mip_levels(struct pvr_image *image) +{ + VkDeviceSize offset = 0; + for (uint8_t plane = 0; plane < image->plane_count; plane++) { + pvr_image_plane_setup_mip_levels(image, plane); + + offset = align(offset, image->alignment); + image->planes[plane].offset = offset; + offset += image->planes[plane].size; + } + + image->total_size = offset; } static unsigned get_pbe_stride_align(const struct pvr_device_info *dev_info); @@ -178,6 +220,8 @@ VkResult pvr_CreateImage(VkDevice _device, */ image->alignment = 4096U; + image->plane_count = vk_format_get_plane_count(image->vk.format); + unsigned pbe_stride_align = get_pbe_stride_align(&device->pdevice->dev_info); /* Initialize the image using the saved information from pCreateInfo */ @@ -270,7 +314,7 @@ VkResult pvr_BindImageMemory2(VkDevice _device, result = pvr_bind_memory(device, mem, offset, - image->size, + image->total_size, image->alignment, &image->vma, &image->dev_addr); @@ -292,17 +336,20 @@ void pvr_get_image_subresource_layout(const struct pvr_image *image, const VkImageSubresource *subresource, VkSubresourceLayout *layout) { + const struct pvr_image_plane *plane = + pvr_plane_from_aspect_const(image, subresource->aspectMask); const struct pvr_mip_level *mip_level = - &image->mip_levels[subresource->mipLevel]; + &plane->mip_levels[subresource->mipLevel]; pvr_assert(subresource->mipLevel < image->vk.mip_levels); pvr_assert(subresource->arrayLayer < image->vk.array_layers); - layout->offset = - subresource->arrayLayer * image->layer_size + mip_level->offset; + layout->offset = plane->offset + + subresource->arrayLayer * plane->layer_size + + mip_level->offset; layout->rowPitch = mip_level->pitch; layout->depthPitch = mip_level->pitch * mip_level->height_pitch; - layout->arrayPitch = image->layer_size; + layout->arrayPitch = plane->layer_size; layout->size = mip_level->size; } diff --git a/src/imagination/vulkan/pvr_image.h b/src/imagination/vulkan/pvr_image.h index d9ea48f5d51..a7ea605fe3d 100644 --- a/src/imagination/vulkan/pvr_image.h +++ b/src/imagination/vulkan/pvr_image.h @@ -21,6 +21,8 @@ #include "pvr_common.h" #include "pvr_types.h" +#define PVR_MAX_PLANE_COUNT 3 + struct pvr_mip_level { /* Offset of the mip level in bytes */ uint32_t offset; @@ -35,6 +37,17 @@ struct pvr_mip_level { uint32_t height_pitch; }; +struct pvr_image_plane { + /* Derived and other state */ + VkExtent3D physical_extent; + + VkDeviceSize layer_size; + VkDeviceSize size; + VkDeviceSize offset; + + struct pvr_mip_level mip_levels[14]; +}; + struct pvr_image { struct vk_image vk; @@ -44,17 +57,78 @@ struct pvr_image { /* Device address the image is mapped to in device virtual address space */ pvr_dev_addr_t dev_addr; - /* Derived and other state */ - VkExtent3D physical_extent; enum pvr_memlayout memlayout; - VkDeviceSize layer_size; - VkDeviceSize size; VkDeviceSize alignment; + VkDeviceSize total_size; - struct pvr_mip_level mip_levels[14]; + uint8_t plane_count; + struct pvr_image_plane planes[PVR_MAX_PLANE_COUNT]; }; +/* Gets the first plane and asserts we only have one plane. For use in areas + * where we never want to deal with multiplanar images. + */ +static inline struct pvr_image_plane *pvr_single_plane(struct pvr_image *image) +{ + assert(image->plane_count == 1); + return &image->planes[0]; +} + +static inline const struct pvr_image_plane * +pvr_single_plane_const(const struct pvr_image *image) +{ + assert(image->plane_count == 1); + return &image->planes[0]; +} + +static inline struct pvr_image_plane * +pvr_plane_from_aspect(struct pvr_image *image, VkImageAspectFlags aspect) +{ + switch (aspect) { + case VK_IMAGE_ASPECT_COLOR_BIT: + case VK_IMAGE_ASPECT_DEPTH_BIT: + case VK_IMAGE_ASPECT_STENCIL_BIT: + case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT: + return pvr_single_plane(image); + case VK_IMAGE_ASPECT_PLANE_0_BIT: + case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT: + return &image->planes[0]; + case VK_IMAGE_ASPECT_PLANE_1_BIT: + case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT: + return &image->planes[1]; + case VK_IMAGE_ASPECT_PLANE_2_BIT: + case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT: + return &image->planes[2]; + default: + UNREACHABLE("invalid image aspect"); + } +} + +static inline const struct pvr_image_plane * +pvr_plane_from_aspect_const(const struct pvr_image *image, + VkImageAspectFlags aspect) +{ + switch (aspect) { + case VK_IMAGE_ASPECT_COLOR_BIT: + case VK_IMAGE_ASPECT_DEPTH_BIT: + case VK_IMAGE_ASPECT_STENCIL_BIT: + case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT: + return pvr_single_plane_const(image); + case VK_IMAGE_ASPECT_PLANE_0_BIT: + case VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT: + return &image->planes[0]; + case VK_IMAGE_ASPECT_PLANE_1_BIT: + case VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT: + return &image->planes[1]; + case VK_IMAGE_ASPECT_PLANE_2_BIT: + case VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT: + return &image->planes[2]; + default: + UNREACHABLE("invalid image aspect"); + } +} + struct pvr_image_view { struct vk_image_view vk; diff --git a/src/imagination/vulkan/rogue/pvr_blit.c b/src/imagination/vulkan/rogue/pvr_blit.c index 61afdd22eae..91bdeb00593 100644 --- a/src/imagination/vulkan/rogue/pvr_blit.c +++ b/src/imagination/vulkan/rogue/pvr_blit.c @@ -166,9 +166,33 @@ static void pvr_setup_transfer_surface(struct pvr_device *device, VkFormat format, VkImageAspectFlags aspect_mask) { - const uint32_t height = MAX2(image->vk.extent.height >> mip_level, 1U); - const uint32_t width = MAX2(image->vk.extent.width >> mip_level, 1U); - enum pipe_format image_pformat = vk_format_to_pipe_format(image->vk.format); + uint8_t plane; + switch (aspect_mask) { + case VK_IMAGE_ASPECT_PLANE_1_BIT: + plane = 1; + break; + case VK_IMAGE_ASPECT_PLANE_2_BIT: + plane = 2; + break; + default: + plane = 0; + break; + }; + + const uint32_t height = + MAX2(vk_format_get_plane_height(image->vk.format, + plane, + image->vk.extent.height) >> + mip_level, + 1U); + const uint32_t width = + MAX2(vk_format_get_plane_width(image->vk.format, + plane, + image->vk.extent.width) >> + mip_level, + 1U); + enum pipe_format image_pformat = vk_format_to_pipe_format( + vk_format_get_plane_aspect_format(image->vk.format, aspect_mask)); enum pipe_format pformat = vk_format_to_pipe_format(format); const VkImageSubresource sub_resource = { .aspectMask = aspect_mask, @@ -376,7 +400,9 @@ void pvr_rogue_CmdBlitImage2(VkCommandBuffer commandBuffer, ®ion->srcOffsets[0], &src_extent, initial_depth_offset, - src->vk.format, + vk_format_get_plane_aspect_format( + src->vk.format, + region->srcSubresource.aspectMask), region->srcSubresource.aspectMask); pvr_setup_transfer_surface(device, @@ -388,7 +414,9 @@ void pvr_rogue_CmdBlitImage2(VkCommandBuffer commandBuffer, &dst_offset, &dst_extent, min_dst_z, - dst->vk.format, + vk_format_get_plane_aspect_format( + dst->vk.format, + region->dstSubresource.aspectMask), region->dstSubresource.aspectMask); for (uint32_t dst_z = min_dst_z; dst_z < max_dst_z; dst_z++) { @@ -504,8 +532,12 @@ pvr_copy_or_resolve_image_region(struct pvr_cmd_buffer *cmd_buffer, const VkImageCopy2 *region, struct pvr_transfer_cmd *ds_transfer_cmd) { - enum pipe_format src_pformat = vk_format_to_pipe_format(src->vk.format); - enum pipe_format dst_pformat = vk_format_to_pipe_format(dst->vk.format); + enum pipe_format src_pformat = vk_format_to_pipe_format( + vk_format_get_plane_aspect_format(src->vk.format, + region->srcSubresource.aspectMask)); + enum pipe_format dst_pformat = vk_format_to_pipe_format( + vk_format_get_plane_aspect_format(dst->vk.format, + region->dstSubresource.aspectMask)); bool src_block_compressed = util_format_is_compressed(src_pformat); bool dst_block_compressed = util_format_is_compressed(dst_pformat); VkExtent3D src_extent; @@ -566,12 +598,16 @@ pvr_copy_or_resolve_image_region(struct pvr_cmd_buffer *cmd_buffer, if (src->vk.samples > dst->vk.samples) { /* Resolve op needs to know the actual format. */ - dst_format = dst->vk.format; + dst_format = + vk_format_get_plane_aspect_format(dst->vk.format, + region->dstSubresource.aspectMask); } else { /* We don't care what format dst is as it's guaranteed to be size * compatible with src. */ - dst_format = pvr_get_raw_copy_format(src->vk.format); + dst_format = pvr_get_raw_copy_format( + vk_format_get_plane_aspect_format(src->vk.format, + region->srcSubresource.aspectMask)); } src_format = dst_format; @@ -872,7 +908,9 @@ pvr_copy_buffer_to_image_region_format(struct pvr_cmd_buffer *const cmd_buffer, buffer_dev_addr, buffer_offset, src_format, - image->vk.format, + vk_format_get_plane_aspect_format( + image->vk.format, + region->imageSubresource.aspectMask), region->imageExtent.width, region->imageExtent.height, row_length_in_texels); @@ -938,7 +976,8 @@ pvr_copy_buffer_to_image_region(struct pvr_cmd_buffer *const cmd_buffer, dst_format = image->vk.format; } else { - src_format = pvr_get_raw_copy_format(image->vk.format); + src_format = pvr_get_raw_copy_format( + vk_format_get_plane_aspect_format(image->vk.format, aspect_mask)); dst_format = src_format; } @@ -980,7 +1019,9 @@ pvr_copy_image_to_buffer_region_format(struct pvr_cmd_buffer *const cmd_buffer, const VkFormat src_format, const VkFormat dst_format) { - enum pipe_format pformat = vk_format_to_pipe_format(image->vk.format); + enum pipe_format pformat = vk_format_to_pipe_format( + vk_format_get_plane_aspect_format(image->vk.format, + region->imageSubresource.aspectMask)); struct pvr_transfer_cmd_surface dst_surface = { 0 }; VkImageSubresource sub_resource; uint32_t buffer_image_height; @@ -1010,15 +1051,17 @@ pvr_copy_image_to_buffer_region_format(struct pvr_cmd_buffer *const cmd_buffer, max_depth_slice = region->imageExtent.depth + region->imageOffset.z; - pvr_setup_buffer_surface(&dst_surface, - &dst_rect, - buffer_dev_addr, - region->bufferOffset, - dst_format, - image->vk.format, - buffer_row_length, - buffer_image_height, - buffer_row_length); + pvr_setup_buffer_surface( + &dst_surface, + &dst_rect, + buffer_dev_addr, + region->bufferOffset, + dst_format, + vk_format_get_plane_aspect_format(image->vk.format, + region->imageSubresource.aspectMask), + buffer_row_length, + buffer_image_height, + buffer_row_length); dst_rect.extent.width = region->imageExtent.width; dst_rect.extent.height = region->imageExtent.height; @@ -1110,7 +1153,8 @@ pvr_copy_image_to_buffer_region(struct pvr_cmd_buffer *const cmd_buffer, { const VkImageAspectFlags aspect_mask = region->imageSubresource.aspectMask; - VkFormat src_format = pvr_get_copy_format(image->vk.format); + VkFormat src_format = pvr_get_copy_format( + vk_format_get_plane_aspect_format(image->vk.format, aspect_mask)); VkFormat dst_format; /* From the Vulkan spec: @@ -1119,10 +1163,10 @@ pvr_copy_image_to_buffer_region(struct pvr_cmd_buffer *const cmd_buffer, */ assert(image->vk.samples == VK_SAMPLE_COUNT_1_BIT); - /* Color and depth aspect copies can nearly all be done using an appropriate + /* All but stencil aspect copies can nearly all be done using an appropriate * raw format. */ - if (aspect_mask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)) { + if (aspect_mask & (~VK_IMAGE_ASPECT_STENCIL_BIT)) { if (src_format == VK_FORMAT_D32_SFLOAT_S8_UINT) { dst_format = VK_FORMAT_D32_SFLOAT; } else { @@ -1138,8 +1182,7 @@ pvr_copy_image_to_buffer_region(struct pvr_cmd_buffer *const cmd_buffer, */ dst_format = VK_FORMAT_S8_UINT; } else { - /* YUV Planes require specific formats. */ - dst_format = src_format; + UNREACHABLE(""); } return pvr_copy_image_to_buffer_region_format(cmd_buffer,