diff --git a/src/amd/vulkan/meta/radv_meta_copy.c b/src/amd/vulkan/meta/radv_meta_copy.c index 41ea870f4a3..91f61a491e3 100644 --- a/src/amd/vulkan/meta/radv_meta_copy.c +++ b/src/amd/vulkan/meta/radv_meta_copy.c @@ -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, ®ion->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, ®ion->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); }