From 5d072e0e73e9dd466e849e5e61c469c00173f73a Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 3 Dec 2024 15:10:32 +0100 Subject: [PATCH] radv: fix stencil only copies of depth/stencil images with SDMA This was broken for two reasons: - the number of bytes per element should be 1 (8-bit for stencil) - the base offset should be adjusted for the stencil Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/radv_sdma.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/amd/vulkan/radv_sdma.c b/src/amd/vulkan/radv_sdma.c index 240159584d3..10a421132ae 100644 --- a/src/amd/vulkan/radv_sdma.c +++ b/src/amd/vulkan/radv_sdma.c @@ -154,6 +154,16 @@ radv_sdma_get_chunked_copy_info(const struct radv_device *const device, const st return r; } +static uint32_t +radv_sdma_get_bpe(const struct radv_image *const image, VkImageAspectFlags aspect_mask) +{ + const unsigned plane_idx = radv_plane_from_aspect(aspect_mask); + const struct radeon_surf *surf = &image->planes[plane_idx].surface; + const bool is_stencil_only = aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT; + + return is_stencil_only ? 1 : surf->bpe; +} + struct radv_sdma_surf radv_sdma_get_buf_surf(const struct radv_buffer *const buffer, const struct radv_image *const image, const VkBufferImageCopy2 *const region, const VkImageAspectFlags aspect_mask) @@ -166,11 +176,13 @@ radv_sdma_get_buf_surf(const struct radv_buffer *const buffer, const struct radv const unsigned plane_idx = radv_plane_from_aspect(region->imageSubresource.aspectMask); const struct radeon_surf *surf = &image->planes[plane_idx].surface; + const uint32_t bpe = radv_sdma_get_bpe(image, region->imageSubresource.aspectMask); + const struct radv_sdma_surf info = { .va = radv_buffer_get_va(buffer->bo) + buffer->offset + region->bufferOffset, .pitch = pitch, .slice_pitch = slice_pitch, - .bpp = surf->bpe, + .bpp = bpe, .blk_w = surf->blk_w, .blk_h = surf->blk_h, .is_linear = true, @@ -211,7 +223,8 @@ radv_sdma_get_tiled_info_dword(const struct radv_device *const device, const str const struct radeon_surf *const surf, const VkImageSubresourceLayers subresource) { const struct radv_physical_device *pdev = radv_device_physical(device); - const uint32_t element_size = util_logbase2(surf->bpe); + const uint32_t bpe = radv_sdma_get_bpe(image, subresource.aspectMask); + const uint32_t element_size = util_logbase2(bpe); const uint32_t swizzle_mode = surf->has_stencil ? surf->u.gfx9.zs.stencil_swizzle_mode : surf->u.gfx9.swizzle_mode; uint32_t info = element_size | swizzle_mode << 3; const enum sdma_version ver = pdev->info.sdma_ip_version; @@ -263,6 +276,7 @@ radv_sdma_get_surf(const struct radv_device *const device, const struct radv_ima const unsigned binding_idx = image->disjoint ? plane_idx : 0; const struct radeon_surf *const surf = &image->planes[plane_idx].surface; const uint64_t va = radv_image_get_va(image, binding_idx); + const uint32_t bpe = radv_sdma_get_bpe(image, aspect_mask); struct radv_sdma_surf info = { .extent = { @@ -276,7 +290,7 @@ radv_sdma_get_surf(const struct radv_device *const device, const struct radv_ima .y = offset.y, .z = image->vk.image_type == VK_IMAGE_TYPE_3D ? offset.z : subresource.baseArrayLayer, }, - .bpp = surf->bpe, + .bpp = bpe, .blk_w = surf->blk_w, .blk_h = surf->blk_h, .mip_levels = image->vk.mip_levels, @@ -285,15 +299,19 @@ radv_sdma_get_surf(const struct radv_device *const device, const struct radv_ima .is_3d = surf->u.gfx9.resource_type == RADEON_RESOURCE_3D, }; + const uint64_t surf_offset = + (aspect_mask == VK_IMAGE_ASPECT_STENCIL_BIT) ? surf->u.gfx9.zs.stencil_offset : surf->u.gfx9.surf_offset; + if (surf->is_linear) { - info.va = va + surf->u.gfx9.surf_offset + surf->u.gfx9.offset[subresource.mipLevel]; + info.va = va + surf_offset + surf->u.gfx9.offset[subresource.mipLevel]; info.pitch = surf->u.gfx9.pitch[subresource.mipLevel]; - info.slice_pitch = surf->blk_w * surf->blk_h * surf->u.gfx9.surf_slice_size / surf->bpe; + info.slice_pitch = surf->blk_w * surf->blk_h * surf->u.gfx9.surf_slice_size / bpe; } else { /* 1D resources should be linear. */ assert(surf->u.gfx9.resource_type != RADEON_RESOURCE_1D); - info.va = (va + surf->u.gfx9.surf_offset) | surf->tile_swizzle << 8; + info.va = (va + surf_offset) | surf->tile_swizzle << 8; + info.info_dword = radv_sdma_get_tiled_info_dword(device, image, surf, subresource); info.header_dword = radv_sdma_get_tiled_header_dword(device, image, subresource);