2 * Copyright © 2016 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 #include "tu_private.h"
27 #include "adreno_common.xml.h"
28 #include "adreno_pm4.xml.h"
30 #include "vk_format.h"
37 * - compressed image formats (need to divide offset/extent)
38 * - Fix d24_unorm_s8_uint support & aspects
42 blit_control(enum a6xx_color_fmt fmt
)
44 unsigned blit_cntl
= 0xf00000;
45 blit_cntl
|= A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT(fmt
);
46 blit_cntl
|= A6XX_RB_2D_BLIT_CNTL_IFMT(tu6_rb_fmt_to_ifmt(fmt
));
50 static uint32_t tu6_sp_2d_src_format(VkFormat format
)
52 const struct vk_format_description
*desc
= vk_format_description(format
);
53 uint32_t reg
= 0xf000 | A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(tu6_get_native_format(format
)->rb
);
55 int channel
= vk_format_get_first_non_void_channel(format
);
57 /* TODO special format. */
60 if (desc
->channel
[channel
].normalized
) {
61 if (desc
->channel
[channel
].type
== VK_FORMAT_TYPE_SIGNED
)
62 reg
|= A6XX_SP_2D_SRC_FORMAT_SINT
;
63 reg
|= A6XX_SP_2D_SRC_FORMAT_NORM
;
64 } else if (desc
->channel
[channel
].pure_integer
) {
65 if (desc
->channel
[channel
].type
== VK_FORMAT_TYPE_SIGNED
)
66 reg
|= A6XX_SP_2D_SRC_FORMAT_SINT
;
68 reg
|= A6XX_SP_2D_SRC_FORMAT_UINT
;
74 tu_dma_prepare(struct tu_cmd_buffer
*cmdbuf
)
76 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 10);
78 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_EVENT_WRITE
, 1);
79 tu_cs_emit(&cmdbuf
->cs
, PC_CCU_INVALIDATE_COLOR
);
81 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_EVENT_WRITE
, 1);
82 tu_cs_emit(&cmdbuf
->cs
, LRZ_FLUSH
);
84 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_SKIP_IB2_ENABLE_GLOBAL
, 1);
85 tu_cs_emit(&cmdbuf
->cs
, 0x0);
87 tu_cs_emit_wfi(&cmdbuf
->cs
);
89 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_CCU_CNTL
, 1);
90 tu_cs_emit(&cmdbuf
->cs
, 0x10000000);
93 /* Always use UINT formats to avoid precision issues.
95 * Example failure it avoids:
96 * - dEQP-VK.api.copy_and_blit.core.image_to_image.all_formats.color.r16_unorm.r16_unorm.general_general
99 tu_canonical_copy_format(VkFormat format
)
101 switch (vk_format_get_blocksizebits(format
)) {
103 return VK_FORMAT_R8_UINT
;
105 return VK_FORMAT_R16_UINT
;
107 return VK_FORMAT_R32_UINT
;
109 return VK_FORMAT_R32G32_UINT
;
111 return VK_FORMAT_R32G32B32_UINT
;
113 return VK_FORMAT_R32G32B32A32_UINT
;
115 unreachable("unhandled format size");
120 tu_copy_buffer(struct tu_cmd_buffer
*cmdbuf
,
121 struct tu_bo
*src_bo
,
123 struct tu_bo
*dst_bo
,
127 const unsigned max_size_per_iter
= 0x4000 - 0x40;
128 const unsigned max_iterations
=
129 (size
+ max_size_per_iter
) / max_size_per_iter
;
131 tu_bo_list_add(&cmdbuf
->bo_list
, src_bo
, MSM_SUBMIT_BO_READ
);
132 tu_bo_list_add(&cmdbuf
->bo_list
, dst_bo
, MSM_SUBMIT_BO_WRITE
);
134 tu_dma_prepare(cmdbuf
);
136 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 21 + 48 * max_iterations
);
138 /* buffer copy setup */
139 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_SET_MARKER
, 1);
140 tu_cs_emit(&cmdbuf
->cs
, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE
));
142 const uint32_t blit_cntl
= blit_control(RB6_R8_UNORM
) | 0x20000000;
144 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_BLIT_CNTL
, 1);
145 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
147 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_BLIT_CNTL
, 1);
148 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
151 uint64_t src_va
= src_bo
->iova
+ src_offset
;
152 uint64_t dst_va
= dst_bo
->iova
+ dst_offset
;
154 unsigned src_shift
= src_va
& 0x3f;
155 unsigned dst_shift
= dst_va
& 0x3f;
156 unsigned max_shift
= MAX2(src_shift
, dst_shift
);
161 uint32_t size_todo
= MIN2(0x4000 - max_shift
, size
);
162 unsigned pitch
= (size_todo
+ max_shift
+ 63) & ~63;
167 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_PS_2D_SRC_INFO
, 13);
168 tu_cs_emit(&cmdbuf
->cs
,
169 A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(RB6_R8_UNORM
) |
170 A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_LINEAR
) |
171 A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX
) | 0x500000);
172 tu_cs_emit(&cmdbuf
->cs
,
173 A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_shift
+ size_todo
) |
174 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(1)); /* SP_PS_2D_SRC_SIZE */
175 tu_cs_emit_qw(&cmdbuf
->cs
, src_va
);
176 tu_cs_emit(&cmdbuf
->cs
, A6XX_SP_PS_2D_SRC_PITCH_PITCH(pitch
));
178 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
179 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
180 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
181 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
182 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
184 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
185 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
186 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
191 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_DST_INFO
, 9);
192 tu_cs_emit(&cmdbuf
->cs
, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(RB6_R8_UNORM
) |
193 A6XX_RB_2D_DST_INFO_TILE_MODE(TILE6_LINEAR
) |
194 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX
));
195 tu_cs_emit_qw(&cmdbuf
->cs
, dst_va
);
197 tu_cs_emit(&cmdbuf
->cs
, A6XX_RB_2D_DST_SIZE_PITCH(pitch
));
198 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
199 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
200 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
201 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
202 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
207 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_SRC_TL_X
, 4);
208 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_X_X(src_shift
));
209 tu_cs_emit(&cmdbuf
->cs
,
210 A6XX_GRAS_2D_SRC_BR_X_X(src_shift
+ size_todo
- 1));
211 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_Y_Y(0));
212 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_BR_Y_Y(0));
214 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_DST_TL
, 2);
215 tu_cs_emit(&cmdbuf
->cs
,
216 A6XX_GRAS_2D_DST_TL_X(dst_shift
) | A6XX_GRAS_2D_DST_TL_Y(0));
217 tu_cs_emit(&cmdbuf
->cs
,
218 A6XX_GRAS_2D_DST_BR_X(dst_shift
+ size_todo
- 1) |
219 A6XX_GRAS_2D_DST_BR_Y(0));
221 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_EVENT_WRITE
, 1);
222 tu_cs_emit(&cmdbuf
->cs
, 0x3f);
223 tu_cs_emit_wfi(&cmdbuf
->cs
);
225 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8C01
, 1);
226 tu_cs_emit(&cmdbuf
->cs
, 0);
228 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_2D_SRC_FORMAT
, 1);
229 tu_cs_emit(&cmdbuf
->cs
, 0xf180);
231 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
232 tu_cs_emit(&cmdbuf
->cs
, 0x01000000);
234 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_BLIT
, 1);
235 tu_cs_emit(&cmdbuf
->cs
, CP_BLIT_0_OP(BLIT_OP_SCALE
));
237 tu_cs_emit_wfi(&cmdbuf
->cs
);
239 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
240 tu_cs_emit(&cmdbuf
->cs
, 0);
242 src_offset
+= size_todo
;
243 dst_offset
+= size_todo
;
247 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, 0x1d, true);
248 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, FACENESS_FLUSH
, true);
249 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, CACHE_FLUSH_TS
, true);
253 tu_copy_buffer_to_image_step(struct tu_cmd_buffer
*cmdbuf
,
254 struct tu_buffer
*src_buffer
,
255 struct tu_image
*dst_image
,
256 const VkBufferImageCopy
*copy_info
,
261 const enum a6xx_color_fmt rb_fmt
= tu6_get_native_format(format
)->rb
;
263 uint64_t dst_va
= dst_image
->bo
->iova
+ dst_image
->bo_offset
+ dst_image
->layer_size
* layer
+ dst_image
->levels
[copy_info
->imageSubresource
.mipLevel
].offset
;
264 unsigned dst_pitch
= dst_image
->levels
[copy_info
->imageSubresource
.mipLevel
].pitch
*
265 vk_format_get_blocksize(format
);
268 unsigned src_offset
= 0;
269 if (copy_info
->imageExtent
.height
== 1) {
270 /* Can't find this in the spec, but not having it is sort of insane? */
271 assert(src_va
% vk_format_get_blocksize(format
) == 0);
273 src_offset
= (src_va
& 63) / vk_format_get_blocksize(format
);
276 src_pitch
= align((src_offset
+ copy_info
->imageExtent
.width
) * vk_format_get_blocksize(format
), 64);
278 unsigned src_pixel_stride
= copy_info
->bufferRowLength
279 ? copy_info
->bufferRowLength
280 : copy_info
->imageExtent
.width
;
281 src_pitch
= src_pixel_stride
* vk_format_get_blocksize(format
);
282 assert(!(src_pitch
& 63));
283 assert(!(src_va
& 63));
286 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 48);
291 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_PS_2D_SRC_INFO
, 13);
292 tu_cs_emit(&cmdbuf
->cs
, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt
) |
293 A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_LINEAR
) |
294 A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX
) |
296 tu_cs_emit(&cmdbuf
->cs
,
297 A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_offset
+ copy_info
->imageExtent
.width
) |
298 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
299 copy_info
->imageExtent
.height
)); /* SP_PS_2D_SRC_SIZE */
300 tu_cs_emit_qw(&cmdbuf
->cs
, src_va
);
301 tu_cs_emit(&cmdbuf
->cs
, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch
));
303 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
304 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
305 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
306 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
307 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
309 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
310 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
311 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
316 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_DST_INFO
, 9);
317 tu_cs_emit(&cmdbuf
->cs
,
318 A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt
) |
319 A6XX_RB_2D_DST_INFO_TILE_MODE(dst_image
->tile_mode
) |
320 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX
));
321 tu_cs_emit_qw(&cmdbuf
->cs
, dst_va
);
322 tu_cs_emit(&cmdbuf
->cs
, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch
));
323 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
324 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
325 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
326 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
327 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
329 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_SRC_TL_X
, 4);
330 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_X_X(src_offset
));
331 tu_cs_emit(&cmdbuf
->cs
,
332 A6XX_GRAS_2D_SRC_BR_X_X(src_offset
+ copy_info
->imageExtent
.width
- 1));
333 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_Y_Y(0));
334 tu_cs_emit(&cmdbuf
->cs
,
335 A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info
->imageExtent
.height
- 1));
337 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_DST_TL
, 2);
338 tu_cs_emit(&cmdbuf
->cs
,
339 A6XX_GRAS_2D_DST_TL_X(copy_info
->imageOffset
.x
) |
340 A6XX_GRAS_2D_DST_TL_Y(copy_info
->imageOffset
.y
));
341 tu_cs_emit(&cmdbuf
->cs
,
342 A6XX_GRAS_2D_DST_BR_X(copy_info
->imageOffset
.x
+
343 copy_info
->imageExtent
.width
- 1) |
344 A6XX_GRAS_2D_DST_BR_Y(copy_info
->imageOffset
.y
+
345 copy_info
->imageExtent
.height
- 1));
347 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_EVENT_WRITE
, 1);
348 tu_cs_emit(&cmdbuf
->cs
, 0x3f);
349 tu_cs_emit_wfi(&cmdbuf
->cs
);
351 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8C01
, 1);
352 tu_cs_emit(&cmdbuf
->cs
, 0);
354 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_2D_SRC_FORMAT
, 1);
355 tu_cs_emit(&cmdbuf
->cs
, tu6_sp_2d_src_format(format
));
357 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
358 tu_cs_emit(&cmdbuf
->cs
, 0x01000000);
360 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_BLIT
, 1);
361 tu_cs_emit(&cmdbuf
->cs
, CP_BLIT_0_OP(BLIT_OP_SCALE
));
363 tu_cs_emit_wfi(&cmdbuf
->cs
);
365 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
366 tu_cs_emit(&cmdbuf
->cs
, 0);
370 tu_copy_buffer_to_image(struct tu_cmd_buffer
*cmdbuf
,
371 struct tu_buffer
*src_buffer
,
372 struct tu_image
*dst_image
,
373 const VkBufferImageCopy
*copy_info
)
375 tu_bo_list_add(&cmdbuf
->bo_list
, src_buffer
->bo
, MSM_SUBMIT_BO_READ
);
376 tu_bo_list_add(&cmdbuf
->bo_list
, dst_image
->bo
, MSM_SUBMIT_BO_WRITE
);
379 tu_dma_prepare(cmdbuf
);
381 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 6);
383 /* buffer copy setup */
384 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_SET_MARKER
, 1);
385 tu_cs_emit(&cmdbuf
->cs
, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE
));
387 VkFormat format
= tu_canonical_copy_format(dst_image
->vk_format
);
388 const enum a6xx_color_fmt rb_fmt
= tu6_get_native_format(format
)->rb
;
390 const uint32_t blit_cntl
= blit_control(rb_fmt
) | 0x20000000;
392 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_BLIT_CNTL
, 1);
393 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
395 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_BLIT_CNTL
, 1);
396 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
398 unsigned src_pixel_stride
= copy_info
->bufferRowLength
399 ? copy_info
->bufferRowLength
400 : copy_info
->imageExtent
.width
;
401 unsigned cpp
= vk_format_get_blocksize(format
);
402 unsigned src_pitch
= src_pixel_stride
* cpp
;
404 for (unsigned layer_offset
= 0; layer_offset
< copy_info
->imageSubresource
.layerCount
; ++layer_offset
) {
405 unsigned layer
= copy_info
->imageSubresource
.baseArrayLayer
+ layer_offset
;
406 uint64_t src_va
= src_buffer
->bo
->iova
+ src_buffer
->bo_offset
+ copy_info
->bufferOffset
+ layer_offset
* copy_info
->bufferImageHeight
* src_pitch
;
408 if ((src_pitch
& 63) || (src_va
& 63)) {
409 /* Do a per line copy */
410 VkBufferImageCopy line_copy_info
= *copy_info
;
411 line_copy_info
.imageExtent
.height
= 1;
412 for (unsigned r
= 0; r
< copy_info
->imageExtent
.height
; ++r
) {
414 * if src_va is not aligned the line copy will need to adjust. Give it
417 unsigned max_width
= 16384 - (src_va
& 0x3f) ? 64 : 0;
418 line_copy_info
.imageOffset
.x
= copy_info
->imageOffset
.x
;
419 line_copy_info
.imageExtent
.width
= copy_info
->imageExtent
.width
;
421 for (unsigned c
= 0; c
< copy_info
->imageExtent
.width
; c
+= max_width
) {
422 tu_copy_buffer_to_image_step(cmdbuf
, src_buffer
, dst_image
, &line_copy_info
, format
, layer
, src_va
+ c
* cpp
);
424 line_copy_info
.imageOffset
.x
+= max_width
;
425 line_copy_info
.imageExtent
.width
-= max_width
;
428 line_copy_info
.imageOffset
.y
++;
432 tu_copy_buffer_to_image_step(cmdbuf
, src_buffer
, dst_image
, copy_info
, format
, layer
, src_va
);
436 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 15);
438 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, 0x1d, true);
439 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, FACENESS_FLUSH
, true);
440 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, CACHE_FLUSH_TS
, true);
444 tu_copy_image_to_buffer_step(struct tu_cmd_buffer
*cmdbuf
,
445 struct tu_image
*src_image
,
446 struct tu_buffer
*dst_buffer
,
447 const VkBufferImageCopy
*copy_info
,
452 const enum a6xx_color_fmt rb_fmt
= tu6_get_native_format(format
)->rb
;
454 uint64_t src_va
= src_image
->bo
->iova
+ src_image
->bo_offset
+ src_image
->layer_size
* layer
+ src_image
->levels
[copy_info
->imageSubresource
.mipLevel
].offset
;
455 unsigned src_pitch
= src_image
->levels
[copy_info
->imageSubresource
.mipLevel
].pitch
*
456 vk_format_get_blocksize(format
);
459 unsigned dst_offset
= 0;
460 if (copy_info
->imageExtent
.height
== 1) {
461 /* Can't find this in the spec, but not having it is sort of insane? */
462 assert(dst_va
% vk_format_get_blocksize(format
) == 0);
464 dst_offset
= (dst_va
& 63) / vk_format_get_blocksize(format
);
467 dst_pitch
= align((dst_offset
+ copy_info
->imageExtent
.width
) * vk_format_get_blocksize(format
), 64);
469 unsigned dst_pixel_stride
= copy_info
->bufferRowLength
470 ? copy_info
->bufferRowLength
471 : copy_info
->imageExtent
.width
;
472 dst_pitch
= dst_pixel_stride
* vk_format_get_blocksize(format
);
473 assert(!(dst_pitch
& 63));
474 assert(!(dst_va
& 63));
478 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 48);
483 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_PS_2D_SRC_INFO
, 13);
484 tu_cs_emit(&cmdbuf
->cs
,
485 A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt
) |
486 A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(src_image
->tile_mode
) |
487 A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX
) | 0x500000);
488 tu_cs_emit(&cmdbuf
->cs
,
489 A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_image
->extent
.width
) |
490 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
491 src_image
->extent
.height
)); /* SP_PS_2D_SRC_SIZE */
492 tu_cs_emit_qw(&cmdbuf
->cs
, src_va
);
493 tu_cs_emit(&cmdbuf
->cs
, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch
));
495 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
496 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
497 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
498 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
499 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
501 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
502 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
503 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
508 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_DST_INFO
, 9);
509 tu_cs_emit(&cmdbuf
->cs
, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt
) |
510 A6XX_RB_2D_DST_INFO_TILE_MODE(TILE6_LINEAR
) |
511 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX
));
512 tu_cs_emit_qw(&cmdbuf
->cs
, dst_va
);
513 tu_cs_emit(&cmdbuf
->cs
, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch
));
514 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
515 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
516 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
517 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
518 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
520 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_SRC_TL_X
, 4);
521 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_X_X(copy_info
->imageOffset
.x
));
522 tu_cs_emit(&cmdbuf
->cs
,
523 A6XX_GRAS_2D_SRC_BR_X_X(copy_info
->imageOffset
.x
+
524 copy_info
->imageExtent
.width
- 1));
525 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_Y_Y(copy_info
->imageOffset
.y
));
526 tu_cs_emit(&cmdbuf
->cs
,
527 A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info
->imageOffset
.y
+
528 copy_info
->imageExtent
.height
- 1));
530 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_DST_TL
, 2);
531 tu_cs_emit(&cmdbuf
->cs
,
532 A6XX_GRAS_2D_DST_TL_X(dst_offset
) | A6XX_GRAS_2D_DST_TL_Y(0));
533 tu_cs_emit(&cmdbuf
->cs
,
534 A6XX_GRAS_2D_DST_BR_X(dst_offset
+ copy_info
->imageExtent
.width
- 1) |
535 A6XX_GRAS_2D_DST_BR_Y(copy_info
->imageExtent
.height
- 1));
537 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_EVENT_WRITE
, 1);
538 tu_cs_emit(&cmdbuf
->cs
, 0x3f);
539 tu_cs_emit_wfi(&cmdbuf
->cs
);
541 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8C01
, 1);
542 tu_cs_emit(&cmdbuf
->cs
, 0);
544 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_2D_SRC_FORMAT
, 1);
545 tu_cs_emit(&cmdbuf
->cs
, tu6_sp_2d_src_format(format
));
547 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
548 tu_cs_emit(&cmdbuf
->cs
, 0x01000000);
550 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_BLIT
, 1);
551 tu_cs_emit(&cmdbuf
->cs
, CP_BLIT_0_OP(BLIT_OP_SCALE
));
553 tu_cs_emit_wfi(&cmdbuf
->cs
);
555 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
556 tu_cs_emit(&cmdbuf
->cs
, 0);
560 tu_copy_image_to_buffer(struct tu_cmd_buffer
*cmdbuf
,
561 struct tu_image
*src_image
,
562 struct tu_buffer
*dst_buffer
,
563 const VkBufferImageCopy
*copy_info
)
565 tu_bo_list_add(&cmdbuf
->bo_list
, src_image
->bo
, MSM_SUBMIT_BO_READ
);
566 tu_bo_list_add(&cmdbuf
->bo_list
, dst_buffer
->bo
, MSM_SUBMIT_BO_WRITE
);
569 tu_dma_prepare(cmdbuf
);
571 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 6);
573 /* buffer copy setup */
574 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_SET_MARKER
, 1);
575 tu_cs_emit(&cmdbuf
->cs
, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE
));
577 VkFormat format
= tu_canonical_copy_format(src_image
->vk_format
);
578 const enum a6xx_color_fmt rb_fmt
= tu6_get_native_format(format
)->rb
;
580 unsigned dst_pixel_stride
= copy_info
->bufferRowLength
581 ? copy_info
->bufferRowLength
582 : copy_info
->imageExtent
.width
;
583 unsigned cpp
= vk_format_get_blocksize(format
);
584 unsigned dst_pitch
= dst_pixel_stride
* cpp
;
587 const uint32_t blit_cntl
= blit_control(rb_fmt
) | 0x20000000;
589 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_BLIT_CNTL
, 1);
590 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
592 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_BLIT_CNTL
, 1);
593 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
595 for (unsigned layer_offset
= 0; layer_offset
< copy_info
->imageSubresource
.layerCount
; ++layer_offset
) {
596 unsigned layer
= copy_info
->imageSubresource
.baseArrayLayer
+ layer_offset
;
597 uint64_t dst_va
= dst_buffer
->bo
->iova
+ dst_buffer
->bo_offset
+ copy_info
->bufferOffset
+ layer_offset
* copy_info
->bufferImageHeight
* dst_pitch
;
599 if ((dst_pitch
& 63) || (dst_va
& 63)) {
600 /* Do a per line copy */
601 VkBufferImageCopy line_copy_info
= *copy_info
;
602 line_copy_info
.imageExtent
.height
= 1;
603 for (unsigned r
= 0; r
< copy_info
->imageExtent
.height
; ++r
) {
605 * if dst_va is not aligned the line copy will need to adjust. Give it
608 unsigned max_width
= 16384 - (dst_va
& 0x3f) ? 64 : 0;
609 line_copy_info
.imageOffset
.x
= copy_info
->imageOffset
.x
;
610 line_copy_info
.imageExtent
.width
= copy_info
->imageExtent
.width
;
612 for (unsigned c
= 0; c
< copy_info
->imageExtent
.width
; c
+= max_width
) {
613 tu_copy_image_to_buffer_step(cmdbuf
, src_image
, dst_buffer
, &line_copy_info
, format
, layer
, dst_va
+ c
* cpp
);
615 line_copy_info
.imageOffset
.x
+= max_width
;
616 line_copy_info
.imageExtent
.width
-= max_width
;
619 line_copy_info
.imageOffset
.y
++;
623 tu_copy_image_to_buffer_step(cmdbuf
, src_image
, dst_buffer
, copy_info
, format
, layer
, dst_va
);
627 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 15);
629 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, 0x1d, true);
630 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, FACENESS_FLUSH
, true);
631 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, CACHE_FLUSH_TS
, true);
635 tu_copy_image_to_image_step(struct tu_cmd_buffer
*cmdbuf
,
636 struct tu_image
*src_image
,
637 struct tu_image
*dst_image
,
638 const VkImageCopy
*copy_info
,
640 uint32_t layer_offset
)
642 const enum a6xx_color_fmt rb_fmt
= tu6_get_native_format(format
)->rb
;
645 copy_info
->srcSubresource
.baseArrayLayer
+ layer_offset
;
647 src_image
->bo
->iova
+ src_image
->bo_offset
+
648 src_image
->layer_size
* src_layer
+
649 src_image
->levels
[copy_info
->srcSubresource
.mipLevel
].offset
;
651 src_image
->levels
[copy_info
->srcSubresource
.mipLevel
].pitch
*
652 vk_format_get_blocksize(format
);
655 copy_info
->dstSubresource
.baseArrayLayer
+ layer_offset
;
657 dst_image
->bo
->iova
+ dst_image
->bo_offset
+
658 dst_image
->layer_size
* dst_layer
+
659 dst_image
->levels
[copy_info
->dstSubresource
.mipLevel
].offset
;
661 src_image
->levels
[copy_info
->dstSubresource
.mipLevel
].pitch
*
662 vk_format_get_blocksize(format
);
664 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 48);
669 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_PS_2D_SRC_INFO
, 13);
670 tu_cs_emit(&cmdbuf
->cs
,
671 A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt
) |
672 A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(src_image
->tile_mode
) |
673 A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX
) | 0x500000);
674 tu_cs_emit(&cmdbuf
->cs
,
675 A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_image
->extent
.width
) |
676 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
677 src_image
->extent
.height
)); /* SP_PS_2D_SRC_SIZE */
678 tu_cs_emit_qw(&cmdbuf
->cs
, src_va
);
679 tu_cs_emit(&cmdbuf
->cs
, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch
));
681 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
682 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
683 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
684 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
685 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
687 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
688 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
689 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
694 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_DST_INFO
, 9);
695 tu_cs_emit(&cmdbuf
->cs
,
696 A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt
) |
697 A6XX_RB_2D_DST_INFO_TILE_MODE(dst_image
->tile_mode
) |
698 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX
));
699 tu_cs_emit_qw(&cmdbuf
->cs
, dst_va
);
700 tu_cs_emit(&cmdbuf
->cs
, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch
));
701 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
702 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
703 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
704 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
705 tu_cs_emit(&cmdbuf
->cs
, 0x00000000);
707 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_SRC_TL_X
, 4);
708 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_X_X(copy_info
->srcOffset
.x
));
709 tu_cs_emit(&cmdbuf
->cs
,
710 A6XX_GRAS_2D_SRC_BR_X_X(copy_info
->srcOffset
.x
+
711 copy_info
->extent
.width
- 1));
712 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_SRC_TL_Y_Y(copy_info
->srcOffset
.y
));
713 tu_cs_emit(&cmdbuf
->cs
,
714 A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info
->srcOffset
.y
+
715 copy_info
->extent
.height
- 1));
717 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_DST_TL
, 2);
718 tu_cs_emit(&cmdbuf
->cs
, A6XX_GRAS_2D_DST_TL_X(copy_info
->dstOffset
.x
) |
719 A6XX_GRAS_2D_DST_TL_Y(copy_info
->dstOffset
.y
));
720 tu_cs_emit(&cmdbuf
->cs
,
721 A6XX_GRAS_2D_DST_BR_X(copy_info
->dstOffset
.x
+
722 copy_info
->extent
.width
- 1) |
723 A6XX_GRAS_2D_DST_BR_Y(copy_info
->dstOffset
.y
+
724 copy_info
->extent
.height
- 1));
726 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_EVENT_WRITE
, 1);
727 tu_cs_emit(&cmdbuf
->cs
, 0x3f);
728 tu_cs_emit_wfi(&cmdbuf
->cs
);
730 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8C01
, 1);
731 tu_cs_emit(&cmdbuf
->cs
, 0);
733 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_SP_2D_SRC_FORMAT
, 1);
734 tu_cs_emit(&cmdbuf
->cs
, tu6_sp_2d_src_format(format
));
736 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
737 tu_cs_emit(&cmdbuf
->cs
, 0x01000000);
739 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_BLIT
, 1);
740 tu_cs_emit(&cmdbuf
->cs
, CP_BLIT_0_OP(BLIT_OP_SCALE
));
742 tu_cs_emit_wfi(&cmdbuf
->cs
);
744 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_UNKNOWN_8E04
, 1);
745 tu_cs_emit(&cmdbuf
->cs
, 0);
749 tu_copy_image_to_image(struct tu_cmd_buffer
*cmdbuf
,
750 struct tu_image
*src_image
,
751 struct tu_image
*dst_image
,
752 const VkImageCopy
*copy_info
)
755 * - Handle 3D images.
756 * - In some cases where src and dst format are different this may
757 * have tiling implications. Not sure if things happen correctly
761 tu_bo_list_add(&cmdbuf
->bo_list
, src_image
->bo
, MSM_SUBMIT_BO_READ
);
762 tu_bo_list_add(&cmdbuf
->bo_list
, dst_image
->bo
, MSM_SUBMIT_BO_WRITE
);
765 tu_dma_prepare(cmdbuf
);
767 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 6);
769 /* buffer copy setup */
770 tu_cs_emit_pkt7(&cmdbuf
->cs
, CP_SET_MARKER
, 1);
771 tu_cs_emit(&cmdbuf
->cs
, A6XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE
));
773 VkFormat format
= tu_canonical_copy_format(src_image
->vk_format
);
774 const enum a6xx_color_fmt rb_fmt
= tu6_get_native_format(format
)->rb
;
775 const uint32_t blit_cntl
= blit_control(rb_fmt
) | 0x20000000;
777 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_RB_2D_BLIT_CNTL
, 1);
778 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
780 tu_cs_emit_pkt4(&cmdbuf
->cs
, REG_A6XX_GRAS_2D_BLIT_CNTL
, 1);
781 tu_cs_emit(&cmdbuf
->cs
, blit_cntl
);
783 for (unsigned layer_offset
= 0;
784 layer_offset
< copy_info
->srcSubresource
.layerCount
; ++layer_offset
) {
785 tu_copy_image_to_image_step(cmdbuf
, src_image
, dst_image
, copy_info
,
786 format
, layer_offset
);
789 tu_cs_reserve_space(cmdbuf
->device
, &cmdbuf
->cs
, 15);
791 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, 0x1d, true);
792 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, FACENESS_FLUSH
, true);
793 tu6_emit_event_write(cmdbuf
, &cmdbuf
->cs
, CACHE_FLUSH_TS
, true);
797 tu_CmdCopyBuffer(VkCommandBuffer commandBuffer
,
800 uint32_t regionCount
,
801 const VkBufferCopy
*pRegions
)
803 TU_FROM_HANDLE(tu_cmd_buffer
, cmdbuf
, commandBuffer
);
804 TU_FROM_HANDLE(tu_buffer
, src_buffer
, srcBuffer
);
805 TU_FROM_HANDLE(tu_buffer
, dst_buffer
, destBuffer
);
807 for (unsigned i
= 0; i
< regionCount
; ++i
) {
808 uint64_t src_offset
= src_buffer
->bo_offset
+ pRegions
[i
].srcOffset
;
809 uint64_t dst_offset
= dst_buffer
->bo_offset
+ pRegions
[i
].dstOffset
;
811 tu_copy_buffer(cmdbuf
, src_buffer
->bo
, src_offset
, dst_buffer
->bo
,
812 dst_offset
, pRegions
[i
].size
);
817 tu_CmdCopyBufferToImage(VkCommandBuffer commandBuffer
,
820 VkImageLayout destImageLayout
,
821 uint32_t regionCount
,
822 const VkBufferImageCopy
*pRegions
)
824 TU_FROM_HANDLE(tu_cmd_buffer
, cmd_buffer
, commandBuffer
);
825 TU_FROM_HANDLE(tu_image
, dest_image
, destImage
);
826 TU_FROM_HANDLE(tu_buffer
, src_buffer
, srcBuffer
);
828 for (unsigned i
= 0; i
< regionCount
; ++i
) {
829 tu_copy_buffer_to_image(cmd_buffer
, src_buffer
, dest_image
,
835 tu_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer
,
837 VkImageLayout srcImageLayout
,
839 uint32_t regionCount
,
840 const VkBufferImageCopy
*pRegions
)
842 TU_FROM_HANDLE(tu_cmd_buffer
, cmd_buffer
, commandBuffer
);
843 TU_FROM_HANDLE(tu_image
, src_image
, srcImage
);
844 TU_FROM_HANDLE(tu_buffer
, dst_buffer
, destBuffer
);
846 for (unsigned i
= 0; i
< regionCount
; ++i
) {
847 tu_copy_image_to_buffer(cmd_buffer
, src_image
, dst_buffer
,
853 tu_CmdCopyImage(VkCommandBuffer commandBuffer
,
855 VkImageLayout srcImageLayout
,
857 VkImageLayout destImageLayout
,
858 uint32_t regionCount
,
859 const VkImageCopy
*pRegions
)
861 TU_FROM_HANDLE(tu_cmd_buffer
, cmd_buffer
, commandBuffer
);
862 TU_FROM_HANDLE(tu_image
, src_image
, srcImage
);
863 TU_FROM_HANDLE(tu_image
, dest_image
, destImage
);
865 for (uint32_t i
= 0; i
< regionCount
; ++i
) {
866 tu_copy_image_to_image(cmd_buffer
, src_image
, dest_image
, pRegions
+ i
);