tu: Fix unaligned image_to_buffer on close to (1 << 14) width

The bottom right corner of the copy exceeded the maximum allowed
value in GRAS_A2D_DEST_BR.x

In order to fix this, we have to do a second copy per line of
the last texels.

Fixes asserts in:
 dEQP-GLES31.functional.copy_image.*

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36939>
This commit is contained in:
Danylo Piliaiev 2025-08-21 20:06:26 +02:00 committed by Marge Bot
parent 2e33098162
commit a288b77403

View file

@ -2600,7 +2600,8 @@ tu_copy_image_to_buffer(struct tu_cmd_buffer *cmd,
copy_compressed(src_image->vk.format, &offset, &extent, &dst_width, &dst_height);
uint32_t pitch = dst_width * util_format_get_blocksize(dst_format);
uint32_t block_size = util_format_get_blocksize(dst_format);
uint32_t pitch = dst_width * block_size;
uint32_t layer_size = pitch * dst_height;
handle_buffer_unaligned_store<CHIP>(cmd,
@ -2620,11 +2621,32 @@ tu_copy_image_to_buffer(struct tu_cmd_buffer *cmd,
uint64_t dst_va = vk_buffer_address(&dst_buffer->vk, info->bufferOffset) + layer_size * i;
if ((dst_va & 63) || (pitch & 63)) {
for (uint32_t y = 0; y < extent.height; y++) {
uint32_t x = (dst_va & 63) / util_format_get_blocksize(dst_format);
uint32_t x = (dst_va & 63) / block_size;
uint32_t excess_width = 0;
/* With VA aligning we can go over the maximum copy size
* and will have to do additional copy of the leftover.
*/
if (x + extent.width > MAX_VIEWPORT_SIZE) {
excess_width = x + extent.width - MAX_VIEWPORT_SIZE;
assert(excess_width < 64 / block_size);
}
uint32_t clamped_width = extent.width - excess_width;
ops->dst_buffer(cs, dst_format, dst_va & ~63, 0, src_format);
ops->coords(cmd, cs, (VkOffset2D) {x}, (VkOffset2D) {offset.x, offset.y + y},
(VkExtent2D) {extent.width, 1});
(VkExtent2D) {clamped_width, 1});
ops->run(cmd, cs);
if (excess_width) {
uint64_t dst_va_overflow = (dst_va + clamped_width * block_size);
assert((dst_va_overflow & 63) == 0);
ops->dst_buffer(cs, dst_format, dst_va_overflow, 0, src_format);
ops->coords(cmd, cs, (VkOffset2D) { 0 },
(VkOffset2D) { offset.x + clamped_width, offset.y + y },
(VkExtent2D) { excess_width, 1 });
ops->run(cmd, cs);
}
dst_va += pitch;
}
} else {