From 9027793074fd88f662343668e41e28425bdbe97c Mon Sep 17 00:00:00 2001 From: squidbus <1249084-squidbus@users.noreply.gitlab.freedesktop.org> Date: Sat, 16 May 2026 21:33:51 -0700 Subject: [PATCH] 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 Part-of: --- src/kosmickrisp/vulkan/kk_cmd_copy.c | 48 +++++++++++++++++++--------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/kosmickrisp/vulkan/kk_cmd_copy.c b/src/kosmickrisp/vulkan/kk_cmd_copy.c index 8c51d5d8e2b..3ebb65c60bd 100644 --- a/src/kosmickrisp/vulkan/kk_cmd_copy.c +++ b/src/kosmickrisp/vulkan/kk_cmd_copy.c @@ -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(®ion->extent); struct mtl_size dst_size = vk_extent_3d_to_mtl_size(®ion->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, ®ion->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;