radv/meta: fix CmdCopyBufferToImage2() on compute queue with compressed HTILE

Only for partial copies because image stores don't decompress on writes
(ie. HTILE isn't updated by image stores).

Cc: mesa-stable
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39656>
This commit is contained in:
Samuel Pitoiset 2026-02-02 16:45:54 +01:00 committed by Marge Bot
parent e362011cca
commit 9f5a20abde

View file

@ -144,6 +144,40 @@ gfx_or_compute_copy_memory_to_image(struct radv_cmd_buffer *cmd_buffer, uint64_t
(use_compute ? RADV_META_SAVE_COMPUTE_PIPELINE : RADV_META_SAVE_GRAPHICS_PIPELINE) |
RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS);
if (use_compute) {
/* For partial copies, HTILE is decompressed before because image stores don't write the
* uncompressed DWORD to HTILE. And then it's needed to re-initialize HTILE to its
* uncompressed state after the copy.
*/
const bool is_partial_copy = region->imageOffset.x || region->imageOffset.y || region->imageOffset.z ||
region->imageExtent.width != image->vk.extent.width ||
region->imageExtent.height != image->vk.extent.height ||
region->imageExtent.depth != image->vk.extent.depth;
uint32_t queue_mask = radv_image_queue_family_mask(image, cmd_buffer->qf, cmd_buffer->qf);
if (radv_layout_is_htile_compressed(device, image, region->imageSubresource.mipLevel, layout, queue_mask) &&
is_partial_copy) {
radv_describe_barrier_start(cmd_buffer, RGP_BARRIER_UNKNOWN_REASON);
u_foreach_bit (i, region->imageSubresource.aspectMask) {
unsigned aspect_mask = 1u << i;
radv_expand_depth_stencil(
cmd_buffer, image,
&(VkImageSubresourceRange){
.aspectMask = aspect_mask,
.baseMipLevel = region->imageSubresource.mipLevel,
.levelCount = 1,
.baseArrayLayer = region->imageSubresource.baseArrayLayer,
.layerCount = vk_image_subresource_layer_count(&image->vk, &region->imageSubresource),
},
NULL);
}
radv_describe_barrier_end(cmd_buffer);
}
}
/**
* From the Vulkan 1.0.6 spec: 18.3 Copying Data Between Images
* extent is the size in texels of the source image to copy in width,
@ -222,6 +256,27 @@ gfx_or_compute_copy_memory_to_image(struct radv_cmd_buffer *cmd_buffer, uint64_t
slice_array++;
}
if (use_compute) {
/* Fixup HTILE after a copy on compute. */
uint32_t queue_mask = radv_image_queue_family_mask(image, cmd_buffer->qf, cmd_buffer->qf);
if (radv_layout_is_htile_compressed(device, image, region->imageSubresource.mipLevel, layout, queue_mask)) {
cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_INV_VCACHE;
VkImageSubresourceRange range = {
.aspectMask = region->imageSubresource.aspectMask,
.baseMipLevel = region->imageSubresource.mipLevel,
.levelCount = 1,
.baseArrayLayer = region->imageSubresource.baseArrayLayer,
.layerCount = vk_image_subresource_layer_count(&image->vk, &region->imageSubresource),
};
uint32_t htile_value = radv_get_htile_initial_value(device, image);
cmd_buffer->state.flush_bits |= radv_clear_htile(cmd_buffer, image, &range, htile_value, false);
}
}
radv_meta_restore(&saved_state, cmd_buffer);
}