kk: Fix image copies for depth/stencil<->color and differing subresources

The buffer copy path needs to account for depth/stencil aspect copies
to compatible color formats. It also must account for differing image
subresource ranges; for example the depth/stencil <-> color tests copy
from level 0 to level 3.

Reviewed-by: Aitor Camacho <aitor@lunarg.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41663>
This commit is contained in:
squidbus 2026-05-16 21:33:51 -07:00 committed by Marge Bot
parent 7033dee54f
commit 9027793074

View file

@ -160,21 +160,33 @@ copy_through_buffer(struct kk_cmd_buffer *cmd, struct kk_image *src,
{
struct kk_image_plane *src_plane = &src->planes[src_index];
struct kk_image_plane *dst_plane = &dst->planes[dst_index];
/* Handle depth/stencil for copies to/from compatible color formats */
enum pipe_format src_format = src_plane->layout.format.pipe;
enum mtl_blit_options src_options = MTL_BLIT_OPTION_NONE;
if (region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) {
src_format = util_format_get_depth_only(src_format);
src_options = MTL_BLIT_OPTION_DEPTH_FROM_DEPTH_STENCIL;
} else if (region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) {
src_format = PIPE_FORMAT_S8_UINT;
src_options = MTL_BLIT_OPTION_STENCIL_FROM_DEPTH_STENCIL;
}
enum pipe_format dst_format = dst_plane->layout.format.pipe;
enum mtl_blit_options dst_options = MTL_BLIT_OPTION_NONE;
if (region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) {
dst_format = util_format_get_depth_only(dst_format);
dst_options = MTL_BLIT_OPTION_DEPTH_FROM_DEPTH_STENCIL;
} else if (region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) {
dst_format = PIPE_FORMAT_S8_UINT;
dst_options = MTL_BLIT_OPTION_STENCIL_FROM_DEPTH_STENCIL;
}
bool is_src_compressed = util_format_is_compressed(src_format);
bool is_dst_compressed = util_format_is_compressed(dst_format);
/* We shouldn't do any depth/stencil through this path */
assert(!util_format_is_depth_or_stencil(src_format) ||
!util_format_is_depth_or_stencil(dst_format));
mtl_blit_encoder *blit = kk_blit_encoder(cmd);
uint32_t mip_level = region->srcSubresource.mipLevel;
const uint32_t mip_width = u_minify(src_plane->layout.width_px, mip_level);
const uint32_t mip_height = u_minify(src_plane->layout.height_px, mip_level);
const uint32_t stride_B = util_format_get_stride(src_format, mip_width);
const uint32_t size_2d_B =
util_format_get_2d_size(src_format, stride_B, mip_height);
const uint32_t buffer_stride_B =
util_format_get_stride(src_format, region->extent.width);
const uint32_t buffer_size_2d_B = util_format_get_2d_size(
@ -185,11 +197,9 @@ copy_through_buffer(struct kk_cmd_buffer *cmd, struct kk_image *src,
/* Metal requires this value to be 0 for 2D images, otherwise the number
* of bytes between each 2D image of a 3D texture */
info.mtl_data.buffer_2d_image_size_B =
src_plane->layout.depth_px == 1u ? 0u : size_2d_B;
src_plane->layout.depth_px == 1u ? 0u : buffer_size_2d_B;
info.mtl_data.buffer_stride_B = buffer_stride_B;
info.mtl_data.image_level = mip_level;
info.mtl_data.buffer = buffer;
info.mtl_data.options = MTL_BLIT_OPTION_NONE;
info.buffer_slice_size_B = buffer_size_2d_B;
struct mtl_size src_size = vk_extent_3d_to_mtl_size(&region->extent);
struct mtl_size dst_size = vk_extent_3d_to_mtl_size(&region->extent);
@ -212,18 +222,26 @@ copy_through_buffer(struct kk_cmd_buffer *cmd, struct kk_image *src,
/* Texture->Buffer->Texture */
// TODO_KOSMICKRISP We don't handle 3D to 2D array nor vice-versa in this
// path. Unsure if it's even needed, can compressed textures be 3D?
kk_foreach_slice(slice, src, srcSubresource)
{
for (uint32_t slice_idx = 0; slice_idx <
vk_image_subresource_layer_count(&src->vk, &region->srcSubresource);
++slice_idx) {
info.mtl_data.image = src_plane->mtl_handle;
info.mtl_data.image_size = src_size;
info.mtl_data.image_origin = src_origin;
info.mtl_data.image_slice = slice;
info.mtl_data.image_slice =
region->srcSubresource.baseArrayLayer + slice_idx;
info.mtl_data.image_level = region->srcSubresource.mipLevel;
info.mtl_data.buffer_offset_B = buffer_offset;
info.mtl_data.options = src_options;
mtl_copy_from_texture_to_buffer(blit, &info.mtl_data);
info.mtl_data.image = dst_plane->mtl_handle;
info.mtl_data.image_size = dst_size;
info.mtl_data.image_origin = dst_origin;
info.mtl_data.image_slice =
region->dstSubresource.baseArrayLayer + slice_idx;
info.mtl_data.image_level = region->dstSubresource.mipLevel;
info.mtl_data.options = dst_options;
mtl_copy_from_buffer_to_texture(blit, &info.mtl_data);
buffer_offset += info.buffer_slice_size_B;