tu/a6xx: Fix unaligned buffer_to_image on close to (1 << 14) width

I'm not sure why exactly it didn't work because
TPL1_A2D_SRC_TEXTURE_SIZE seemingly has (1 << 15) width
limit. However tests have shown that it doesn't work out.

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:41:34 +02:00 committed by Marge Bot
parent a288b77403
commit 8faf76a754

View file

@ -2405,7 +2405,8 @@ tu_copy_buffer_to_image(struct tu_cmd_buffer *cmd,
copy_compressed(dst_image->vk.format, &offset, &extent, &src_width, &src_height);
uint32_t pitch = src_width * util_format_get_blocksize(src_format);
uint32_t block_size = util_format_get_blocksize(src_format);
uint32_t pitch = src_width * block_size;
uint32_t layer_size = src_height * pitch;
ops->setup(cmd, cs, src_format, dst_format,
@ -2423,12 +2424,35 @@ tu_copy_buffer_to_image(struct tu_cmd_buffer *cmd,
bool unaligned = (src_va & 63) || (pitch & 63);
if (!has_unaligned && unaligned) {
for (uint32_t y = 0; y < extent.height; y++) {
uint32_t x = (src_va & 63) / util_format_get_blocksize(src_format);
uint32_t x = (src_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->src_buffer(cmd, cs, src_format, src_va & ~63, pitch,
x + extent.width, 1, dst_format);
x + clamped_width, 1, dst_format);
ops->coords(cmd, cs, (VkOffset2D) {offset.x, offset.y + y}, (VkOffset2D) {x},
(VkExtent2D) {extent.width, 1});
(VkExtent2D) {clamped_width, 1});
ops->run(cmd, cs);
if (excess_width) {
uint64_t src_va_overflow =
(src_va + clamped_width * block_size);
assert((src_va_overflow & 63) == 0);
ops->src_buffer(cmd, cs, src_format, src_va_overflow & ~63,
pitch, excess_width, 1, dst_format);
ops->coords(
cmd, cs,
(VkOffset2D) { offset.x + clamped_width, offset.y + y },
(VkOffset2D) { 0 }, (VkExtent2D) { excess_width, 1 });
ops->run(cmd, cs);
}
src_va += pitch;
}
} else {