1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2016 Intel Corporation
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21b8e80941Smrg * DEALINGS IN THE SOFTWARE.
22b8e80941Smrg */
23b8e80941Smrg
24b8e80941Smrg#include "tu_private.h"
25b8e80941Smrg
26b8e80941Smrg#include "a6xx.xml.h"
27b8e80941Smrg#include "adreno_common.xml.h"
28b8e80941Smrg#include "adreno_pm4.xml.h"
29b8e80941Smrg
30b8e80941Smrg#include "vk_format.h"
31b8e80941Smrg
32b8e80941Smrg#include "tu_cs.h"
33b8e80941Smrg
34b8e80941Smrg/*
35b8e80941Smrg * TODO:
36b8e80941Smrg *   - image -> image copies
37b8e80941Smrg *   - 3D textures
38b8e80941Smrg *   - compressed image formats (need to divide offset/extent)
39b8e80941Smrg */
40b8e80941Smrg
41b8e80941Smrgstatic uint32_t
42b8e80941Smrgblit_control(enum a6xx_color_fmt fmt)
43b8e80941Smrg{
44b8e80941Smrg   unsigned blit_cntl = 0xf00000;
45b8e80941Smrg   blit_cntl |= A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT(fmt);
46b8e80941Smrg   blit_cntl |= A6XX_RB_2D_BLIT_CNTL_IFMT(tu6_rb_fmt_to_ifmt(fmt));
47b8e80941Smrg   return blit_cntl;
48b8e80941Smrg}
49b8e80941Smrg
50b8e80941Smrgstatic uint32_t tu6_sp_2d_src_format(VkFormat format)
51b8e80941Smrg{
52b8e80941Smrg   const struct vk_format_description *desc = vk_format_description(format);
53b8e80941Smrg   uint32_t reg = 0xf000 | A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(tu6_get_native_format(format)->rb);
54b8e80941Smrg
55b8e80941Smrg   int channel = vk_format_get_first_non_void_channel(format);
56b8e80941Smrg   if (channel < 0) {
57b8e80941Smrg      /* TODO special format. */
58b8e80941Smrg      return reg;
59b8e80941Smrg   }
60b8e80941Smrg   if (desc->channel[channel].normalized) {
61b8e80941Smrg      if (desc->channel[channel].type == VK_FORMAT_TYPE_SIGNED)
62b8e80941Smrg         reg |= A6XX_SP_2D_SRC_FORMAT_SINT;
63b8e80941Smrg      reg |= A6XX_SP_2D_SRC_FORMAT_NORM;
64b8e80941Smrg   } else if (desc->channel[channel].pure_integer) {
65b8e80941Smrg      if (desc->channel[channel].type == VK_FORMAT_TYPE_SIGNED)
66b8e80941Smrg         reg |= A6XX_SP_2D_SRC_FORMAT_SINT;
67b8e80941Smrg      else
68b8e80941Smrg         reg |= A6XX_SP_2D_SRC_FORMAT_UINT;
69b8e80941Smrg   }
70b8e80941Smrg   return reg;
71b8e80941Smrg}
72b8e80941Smrg
73b8e80941Smrgstatic void
74b8e80941Smrgtu_dma_prepare(struct tu_cmd_buffer *cmdbuf)
75b8e80941Smrg{
76b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 10);
77b8e80941Smrg
78b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
79b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, PC_CCU_INVALIDATE_COLOR);
80b8e80941Smrg
81b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
82b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, LRZ_FLUSH);
83b8e80941Smrg
84b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_SKIP_IB2_ENABLE_GLOBAL, 1);
85b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x0);
86b8e80941Smrg
87b8e80941Smrg   tu_cs_emit_wfi(&cmdbuf->cs);
88b8e80941Smrg
89b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_CCU_CNTL, 1);
90b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x10000000);
91b8e80941Smrg}
92b8e80941Smrg
93b8e80941Smrgstatic void
94b8e80941Smrgtu_copy_buffer(struct tu_cmd_buffer *cmdbuf,
95b8e80941Smrg               struct tu_bo *src_bo,
96b8e80941Smrg               uint64_t src_offset,
97b8e80941Smrg               struct tu_bo *dst_bo,
98b8e80941Smrg               uint64_t dst_offset,
99b8e80941Smrg               uint64_t size)
100b8e80941Smrg{
101b8e80941Smrg   const unsigned max_size_per_iter = 0x4000 - 0x40;
102b8e80941Smrg   const unsigned max_iterations =
103b8e80941Smrg      (size + max_size_per_iter) / max_size_per_iter;
104b8e80941Smrg
105b8e80941Smrg   tu_bo_list_add(&cmdbuf->bo_list, src_bo, MSM_SUBMIT_BO_READ);
106b8e80941Smrg   tu_bo_list_add(&cmdbuf->bo_list, dst_bo, MSM_SUBMIT_BO_WRITE);
107b8e80941Smrg
108b8e80941Smrg   tu_dma_prepare(cmdbuf);
109b8e80941Smrg
110b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 21 + 48 * max_iterations);
111b8e80941Smrg
112b8e80941Smrg   /* buffer copy setup */
113b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
114b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A2XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
115b8e80941Smrg
116b8e80941Smrg   const uint32_t blit_cntl = blit_control(RB6_R8_UNORM) | 0x20000000;
117b8e80941Smrg
118b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
119b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, blit_cntl);
120b8e80941Smrg
121b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
122b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, blit_cntl);
123b8e80941Smrg
124b8e80941Smrg   for (; size;) {
125b8e80941Smrg      uint64_t src_va = src_bo->iova + src_offset;
126b8e80941Smrg      uint64_t dst_va = dst_bo->iova + dst_offset;
127b8e80941Smrg
128b8e80941Smrg      unsigned src_shift = src_va & 0x3f;
129b8e80941Smrg      unsigned dst_shift = dst_va & 0x3f;
130b8e80941Smrg      unsigned max_shift = MAX2(src_shift, dst_shift);
131b8e80941Smrg
132b8e80941Smrg      src_va -= src_shift;
133b8e80941Smrg      dst_va -= dst_shift;
134b8e80941Smrg
135b8e80941Smrg      uint32_t size_todo = MIN2(0x4000 - max_shift, size);
136b8e80941Smrg      unsigned pitch = (size_todo + max_shift + 63) & ~63;
137b8e80941Smrg
138b8e80941Smrg      /*
139b8e80941Smrg       * Emit source:
140b8e80941Smrg       */
141b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
142b8e80941Smrg      tu_cs_emit(&cmdbuf->cs,
143b8e80941Smrg                 A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(RB6_R8_UNORM) |
144b8e80941Smrg                    A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_LINEAR) |
145b8e80941Smrg                    A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) | 0x500000);
146b8e80941Smrg      tu_cs_emit(&cmdbuf->cs,
147b8e80941Smrg                 A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_shift + size_todo) |
148b8e80941Smrg                    A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(1)); /* SP_PS_2D_SRC_SIZE */
149b8e80941Smrg      tu_cs_emit_qw(&cmdbuf->cs, src_va);
150b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_PITCH_PITCH(pitch));
151b8e80941Smrg
152b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
153b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
154b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
155b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
156b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
157b8e80941Smrg
158b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
159b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
160b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
161b8e80941Smrg
162b8e80941Smrg      /*
163b8e80941Smrg       * Emit destination:
164b8e80941Smrg       */
165b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_DST_INFO, 9);
166b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(RB6_R8_UNORM) |
167b8e80941Smrg                                 A6XX_RB_2D_DST_INFO_TILE_MODE(TILE6_LINEAR) |
168b8e80941Smrg                                 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
169b8e80941Smrg      tu_cs_emit_qw(&cmdbuf->cs, dst_va);
170b8e80941Smrg
171b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_SIZE_PITCH(pitch));
172b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
173b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
174b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
175b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
176b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x00000000);
177b8e80941Smrg
178b8e80941Smrg      /*
179b8e80941Smrg       * Blit command:
180b8e80941Smrg       */
181b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
182b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_X_X(src_shift));
183b8e80941Smrg      tu_cs_emit(&cmdbuf->cs,
184b8e80941Smrg                 A6XX_GRAS_2D_SRC_BR_X_X(src_shift + size_todo - 1));
185b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_Y_Y(0));
186b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_BR_Y_Y(0));
187b8e80941Smrg
188b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_DST_TL, 2);
189b8e80941Smrg      tu_cs_emit(&cmdbuf->cs,
190b8e80941Smrg                 A6XX_GRAS_2D_DST_TL_X(dst_shift) | A6XX_GRAS_2D_DST_TL_Y(0));
191b8e80941Smrg      tu_cs_emit(&cmdbuf->cs,
192b8e80941Smrg                 A6XX_GRAS_2D_DST_BR_X(dst_shift + size_todo - 1) |
193b8e80941Smrg                    A6XX_GRAS_2D_DST_BR_Y(0));
194b8e80941Smrg
195b8e80941Smrg      tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
196b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x3f);
197b8e80941Smrg      tu_cs_emit_wfi(&cmdbuf->cs);
198b8e80941Smrg
199b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
200b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0);
201b8e80941Smrg
202b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
203b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0xf180);
204b8e80941Smrg
205b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
206b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0x01000000);
207b8e80941Smrg
208b8e80941Smrg      tu_cs_emit_pkt7(&cmdbuf->cs, CP_BLIT, 1);
209b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
210b8e80941Smrg
211b8e80941Smrg      tu_cs_emit_wfi(&cmdbuf->cs);
212b8e80941Smrg
213b8e80941Smrg      tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
214b8e80941Smrg      tu_cs_emit(&cmdbuf->cs, 0);
215b8e80941Smrg
216b8e80941Smrg      src_offset += size_todo;
217b8e80941Smrg      dst_offset += size_todo;
218b8e80941Smrg      size -= size_todo;
219b8e80941Smrg   }
220b8e80941Smrg
221b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
222b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
223b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
224b8e80941Smrg}
225b8e80941Smrg
226b8e80941Smrgstatic void
227b8e80941Smrgtu_copy_buffer_to_image_step(struct tu_cmd_buffer *cmdbuf,
228b8e80941Smrg                             struct tu_buffer *src_buffer,
229b8e80941Smrg                             struct tu_image *dst_image,
230b8e80941Smrg                             const VkBufferImageCopy *copy_info,
231b8e80941Smrg                             VkFormat format,
232b8e80941Smrg                             uint32_t layer,
233b8e80941Smrg                             uint64_t src_va)
234b8e80941Smrg{
235b8e80941Smrg   const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
236b8e80941Smrg
237b8e80941Smrg   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;
238b8e80941Smrg   unsigned dst_pitch = dst_image->levels[copy_info->imageSubresource.mipLevel].pitch *
239b8e80941Smrg                        vk_format_get_blocksize(format);
240b8e80941Smrg
241b8e80941Smrg   unsigned src_pitch;
242b8e80941Smrg   unsigned src_offset = 0;
243b8e80941Smrg   if (copy_info->imageExtent.height == 1) {
244b8e80941Smrg      /* Can't find this in the spec, but not having it is sort of insane? */
245b8e80941Smrg      assert(src_va % vk_format_get_blocksize(format) == 0);
246b8e80941Smrg
247b8e80941Smrg      src_offset = (src_va & 63) / vk_format_get_blocksize(format);
248b8e80941Smrg      src_va &= ~63;
249b8e80941Smrg
250b8e80941Smrg      src_pitch = align((src_offset + copy_info->imageExtent.width) * vk_format_get_blocksize(format), 64);
251b8e80941Smrg   } else {
252b8e80941Smrg      unsigned src_pixel_stride = copy_info->bufferRowLength
253b8e80941Smrg                                  ? copy_info->bufferRowLength
254b8e80941Smrg                                  : copy_info->imageExtent.width;
255b8e80941Smrg      src_pitch = src_pixel_stride * vk_format_get_blocksize(format);
256b8e80941Smrg      assert(!(src_pitch & 63));
257b8e80941Smrg      assert(!(src_va & 63));
258b8e80941Smrg   }
259b8e80941Smrg
260b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 48);
261b8e80941Smrg
262b8e80941Smrg   /*
263b8e80941Smrg    * Emit source:
264b8e80941Smrg    */
265b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
266b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt) |
267b8e80941Smrg                              A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(TILE6_LINEAR) |
268b8e80941Smrg                              A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) |
269b8e80941Smrg                              0x500000);
270b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
271b8e80941Smrg              A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_offset + copy_info->imageExtent.width) |
272b8e80941Smrg                 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
273b8e80941Smrg                    copy_info->imageExtent.height)); /* SP_PS_2D_SRC_SIZE */
274b8e80941Smrg   tu_cs_emit_qw(&cmdbuf->cs, src_va);
275b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch));
276b8e80941Smrg
277b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
278b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
279b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
280b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
281b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
282b8e80941Smrg
283b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
284b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
285b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
286b8e80941Smrg
287b8e80941Smrg   /*
288b8e80941Smrg    * Emit destination:
289b8e80941Smrg    */
290b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_DST_INFO, 9);
291b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
292b8e80941Smrg              A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt) |
293b8e80941Smrg                 A6XX_RB_2D_DST_INFO_TILE_MODE(dst_image->tile_mode) |
294b8e80941Smrg                 A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
295b8e80941Smrg   tu_cs_emit_qw(&cmdbuf->cs, dst_va);
296b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch));
297b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
298b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
299b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
300b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
301b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
302b8e80941Smrg
303b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
304b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_X_X(src_offset));
305b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
306b8e80941Smrg              A6XX_GRAS_2D_SRC_BR_X_X(src_offset + copy_info->imageExtent.width - 1));
307b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_Y_Y(0));
308b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
309b8e80941Smrg              A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info->imageExtent.height - 1));
310b8e80941Smrg
311b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_DST_TL, 2);
312b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
313b8e80941Smrg              A6XX_GRAS_2D_DST_TL_X(copy_info->imageOffset.x) |
314b8e80941Smrg                 A6XX_GRAS_2D_DST_TL_Y(copy_info->imageOffset.y));
315b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
316b8e80941Smrg              A6XX_GRAS_2D_DST_BR_X(copy_info->imageOffset.x +
317b8e80941Smrg                                    copy_info->imageExtent.width - 1) |
318b8e80941Smrg                 A6XX_GRAS_2D_DST_BR_Y(copy_info->imageOffset.y +
319b8e80941Smrg                                       copy_info->imageExtent.height - 1));
320b8e80941Smrg
321b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
322b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x3f);
323b8e80941Smrg   tu_cs_emit_wfi(&cmdbuf->cs);
324b8e80941Smrg
325b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
326b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0);
327b8e80941Smrg
328b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
329b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, tu6_sp_2d_src_format(format));
330b8e80941Smrg
331b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
332b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x01000000);
333b8e80941Smrg
334b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_BLIT, 1);
335b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
336b8e80941Smrg
337b8e80941Smrg   tu_cs_emit_wfi(&cmdbuf->cs);
338b8e80941Smrg
339b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
340b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0);
341b8e80941Smrg}
342b8e80941Smrg
343b8e80941Smrgstatic void
344b8e80941Smrgtu_copy_buffer_to_image(struct tu_cmd_buffer *cmdbuf,
345b8e80941Smrg                        struct tu_buffer *src_buffer,
346b8e80941Smrg                        struct tu_image *dst_image,
347b8e80941Smrg                        const VkBufferImageCopy *copy_info)
348b8e80941Smrg{
349b8e80941Smrg   tu_bo_list_add(&cmdbuf->bo_list, src_buffer->bo, MSM_SUBMIT_BO_READ);
350b8e80941Smrg   tu_bo_list_add(&cmdbuf->bo_list, dst_image->bo, MSM_SUBMIT_BO_WRITE);
351b8e80941Smrg
352b8e80941Smrg   /* general setup */
353b8e80941Smrg   tu_dma_prepare(cmdbuf);
354b8e80941Smrg
355b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 6);
356b8e80941Smrg
357b8e80941Smrg   /* buffer copy setup */
358b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
359b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A2XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
360b8e80941Smrg
361b8e80941Smrg   VkFormat format = dst_image->vk_format;
362b8e80941Smrg   const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
363b8e80941Smrg
364b8e80941Smrg   const uint32_t blit_cntl = blit_control(rb_fmt) | 0x20000000;
365b8e80941Smrg
366b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
367b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, blit_cntl);
368b8e80941Smrg
369b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
370b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, blit_cntl);
371b8e80941Smrg
372b8e80941Smrg   unsigned src_pixel_stride = copy_info->bufferRowLength
373b8e80941Smrg                                  ? copy_info->bufferRowLength
374b8e80941Smrg                                  : copy_info->imageExtent.width;
375b8e80941Smrg   unsigned cpp = vk_format_get_blocksize(format);
376b8e80941Smrg   unsigned src_pitch = src_pixel_stride * cpp;
377b8e80941Smrg
378b8e80941Smrg   for (unsigned layer_offset = 0; layer_offset < copy_info->imageSubresource.layerCount; ++layer_offset) {
379b8e80941Smrg      unsigned layer = copy_info->imageSubresource.baseArrayLayer + layer_offset;
380b8e80941Smrg      uint64_t src_va = src_buffer->bo->iova + src_buffer->bo_offset + copy_info->bufferOffset + layer_offset * copy_info->bufferImageHeight * src_pitch;
381b8e80941Smrg
382b8e80941Smrg      if ((src_pitch & 63) || (src_va & 63)) {
383b8e80941Smrg         /* Do a per line copy */
384b8e80941Smrg         VkBufferImageCopy line_copy_info = *copy_info;
385b8e80941Smrg         line_copy_info.imageExtent.height = 1;
386b8e80941Smrg         for (unsigned r = 0; r < copy_info->imageExtent.height; ++r) {
387b8e80941Smrg            /*
388b8e80941Smrg             * if src_va is not aligned the line copy will need to adjust. Give it
389b8e80941Smrg             * room to do so.
390b8e80941Smrg             */
391b8e80941Smrg            unsigned max_width = 16384 - (src_va & 0x3f) ? 64 : 0;
392b8e80941Smrg            line_copy_info.imageOffset.x = copy_info->imageOffset.x;
393b8e80941Smrg            line_copy_info.imageExtent.width = copy_info->imageExtent.width;
394b8e80941Smrg
395b8e80941Smrg            for (unsigned c = 0; c < copy_info->imageExtent.width; c += max_width) {
396b8e80941Smrg               tu_copy_buffer_to_image_step(cmdbuf, src_buffer, dst_image, &line_copy_info, format, layer, src_va + c * cpp);
397b8e80941Smrg
398b8e80941Smrg               line_copy_info.imageOffset.x += max_width;
399b8e80941Smrg               line_copy_info.imageExtent.width -= max_width;
400b8e80941Smrg            }
401b8e80941Smrg
402b8e80941Smrg            line_copy_info.imageOffset.y++;
403b8e80941Smrg            src_va += src_pitch;
404b8e80941Smrg         }
405b8e80941Smrg      } else {
406b8e80941Smrg         tu_copy_buffer_to_image_step(cmdbuf, src_buffer, dst_image, copy_info, format, layer, src_va);
407b8e80941Smrg      }
408b8e80941Smrg   }
409b8e80941Smrg
410b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 15);
411b8e80941Smrg
412b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
413b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
414b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
415b8e80941Smrg}
416b8e80941Smrg
417b8e80941Smrgstatic void
418b8e80941Smrgtu_copy_image_to_buffer_step(struct tu_cmd_buffer *cmdbuf,
419b8e80941Smrg                             struct tu_image *src_image,
420b8e80941Smrg                             struct tu_buffer *dst_buffer,
421b8e80941Smrg                             const VkBufferImageCopy *copy_info,
422b8e80941Smrg                             VkFormat format,
423b8e80941Smrg                             uint32_t layer,
424b8e80941Smrg                             uint64_t dst_va)
425b8e80941Smrg{
426b8e80941Smrg   const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
427b8e80941Smrg
428b8e80941Smrg   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;
429b8e80941Smrg   unsigned src_pitch = src_image->levels[copy_info->imageSubresource.mipLevel].pitch *
430b8e80941Smrg                        vk_format_get_blocksize(format);
431b8e80941Smrg
432b8e80941Smrg   unsigned dst_pitch;
433b8e80941Smrg   unsigned dst_offset = 0;
434b8e80941Smrg   if (copy_info->imageExtent.height == 1) {
435b8e80941Smrg      /* Can't find this in the spec, but not having it is sort of insane? */
436b8e80941Smrg      assert(dst_va % vk_format_get_blocksize(format) == 0);
437b8e80941Smrg
438b8e80941Smrg      dst_offset = (dst_va & 63) / vk_format_get_blocksize(format);
439b8e80941Smrg      dst_va &= ~63;
440b8e80941Smrg
441b8e80941Smrg      dst_pitch = align((dst_offset + copy_info->imageExtent.width) * vk_format_get_blocksize(format), 64);
442b8e80941Smrg   } else {
443b8e80941Smrg      unsigned dst_pixel_stride = copy_info->bufferRowLength
444b8e80941Smrg                                  ? copy_info->bufferRowLength
445b8e80941Smrg                                  : copy_info->imageExtent.width;
446b8e80941Smrg      dst_pitch = dst_pixel_stride * vk_format_get_blocksize(format);
447b8e80941Smrg      assert(!(dst_pitch & 63));
448b8e80941Smrg      assert(!(dst_va & 63));
449b8e80941Smrg   }
450b8e80941Smrg
451b8e80941Smrg
452b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 48);
453b8e80941Smrg
454b8e80941Smrg   /*
455b8e80941Smrg    * Emit source:
456b8e80941Smrg    */
457b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_PS_2D_SRC_INFO, 13);
458b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
459b8e80941Smrg              A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(rb_fmt) |
460b8e80941Smrg                 A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(src_image->tile_mode) |
461b8e80941Smrg                 A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(WZYX) | 0x500000);
462b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
463b8e80941Smrg              A6XX_SP_PS_2D_SRC_SIZE_WIDTH(src_image->extent.width) |
464b8e80941Smrg                 A6XX_SP_PS_2D_SRC_SIZE_HEIGHT(
465b8e80941Smrg                    src_image->extent.height)); /* SP_PS_2D_SRC_SIZE */
466b8e80941Smrg   tu_cs_emit_qw(&cmdbuf->cs, src_va);
467b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_SP_PS_2D_SRC_PITCH_PITCH(src_pitch));
468b8e80941Smrg
469b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
470b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
471b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
472b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
473b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
474b8e80941Smrg
475b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
476b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
477b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
478b8e80941Smrg
479b8e80941Smrg   /*
480b8e80941Smrg    * Emit destination:
481b8e80941Smrg    */
482b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_DST_INFO, 9);
483b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_INFO_COLOR_FORMAT(rb_fmt) |
484b8e80941Smrg                              A6XX_RB_2D_DST_INFO_TILE_MODE(TILE6_LINEAR) |
485b8e80941Smrg                              A6XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX));
486b8e80941Smrg   tu_cs_emit_qw(&cmdbuf->cs, dst_va);
487b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_RB_2D_DST_SIZE_PITCH(dst_pitch));
488b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
489b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
490b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
491b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
492b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x00000000);
493b8e80941Smrg
494b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_SRC_TL_X, 4);
495b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_X_X(copy_info->imageOffset.x));
496b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
497b8e80941Smrg              A6XX_GRAS_2D_SRC_BR_X_X(copy_info->imageOffset.x +
498b8e80941Smrg                                      copy_info->imageExtent.width - 1));
499b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A6XX_GRAS_2D_SRC_TL_Y_Y(copy_info->imageOffset.y));
500b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
501b8e80941Smrg              A6XX_GRAS_2D_SRC_BR_Y_Y(copy_info->imageOffset.y +
502b8e80941Smrg                                      copy_info->imageExtent.height - 1));
503b8e80941Smrg
504b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_DST_TL, 2);
505b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
506b8e80941Smrg              A6XX_GRAS_2D_DST_TL_X(dst_offset) | A6XX_GRAS_2D_DST_TL_Y(0));
507b8e80941Smrg   tu_cs_emit(&cmdbuf->cs,
508b8e80941Smrg              A6XX_GRAS_2D_DST_BR_X(dst_offset + copy_info->imageExtent.width - 1) |
509b8e80941Smrg                 A6XX_GRAS_2D_DST_BR_Y(copy_info->imageExtent.height - 1));
510b8e80941Smrg
511b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_EVENT_WRITE, 1);
512b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x3f);
513b8e80941Smrg   tu_cs_emit_wfi(&cmdbuf->cs);
514b8e80941Smrg
515b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8C01, 1);
516b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0);
517b8e80941Smrg
518b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_SP_2D_SRC_FORMAT, 1);
519b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, tu6_sp_2d_src_format(format));
520b8e80941Smrg
521b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
522b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0x01000000);
523b8e80941Smrg
524b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_BLIT, 1);
525b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, CP_BLIT_0_OP(BLIT_OP_SCALE));
526b8e80941Smrg
527b8e80941Smrg   tu_cs_emit_wfi(&cmdbuf->cs);
528b8e80941Smrg
529b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_UNKNOWN_8E04, 1);
530b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, 0);
531b8e80941Smrg}
532b8e80941Smrg
533b8e80941Smrgstatic void
534b8e80941Smrgtu_copy_image_to_buffer(struct tu_cmd_buffer *cmdbuf,
535b8e80941Smrg                        struct tu_image *src_image,
536b8e80941Smrg                        struct tu_buffer *dst_buffer,
537b8e80941Smrg                        const VkBufferImageCopy *copy_info)
538b8e80941Smrg{
539b8e80941Smrg   tu_bo_list_add(&cmdbuf->bo_list, src_image->bo, MSM_SUBMIT_BO_READ);
540b8e80941Smrg   tu_bo_list_add(&cmdbuf->bo_list, dst_buffer->bo, MSM_SUBMIT_BO_WRITE);
541b8e80941Smrg
542b8e80941Smrg   /* general setup */
543b8e80941Smrg   tu_dma_prepare(cmdbuf);
544b8e80941Smrg
545b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 6);
546b8e80941Smrg
547b8e80941Smrg   /* buffer copy setup */
548b8e80941Smrg   tu_cs_emit_pkt7(&cmdbuf->cs, CP_SET_MARKER, 1);
549b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, A2XX_CP_SET_MARKER_0_MODE(RM6_BLIT2DSCALE));
550b8e80941Smrg
551b8e80941Smrg   VkFormat format = src_image->vk_format;
552b8e80941Smrg   const enum a6xx_color_fmt rb_fmt = tu6_get_native_format(format)->rb;
553b8e80941Smrg
554b8e80941Smrg   unsigned dst_pixel_stride = copy_info->bufferRowLength
555b8e80941Smrg                                  ? copy_info->bufferRowLength
556b8e80941Smrg                                  : copy_info->imageExtent.width;
557b8e80941Smrg   unsigned cpp = vk_format_get_blocksize(format);
558b8e80941Smrg   unsigned dst_pitch = dst_pixel_stride * cpp;
559b8e80941Smrg
560b8e80941Smrg
561b8e80941Smrg   const uint32_t blit_cntl = blit_control(rb_fmt) | 0x20000000;
562b8e80941Smrg
563b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_RB_2D_BLIT_CNTL, 1);
564b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, blit_cntl);
565b8e80941Smrg
566b8e80941Smrg   tu_cs_emit_pkt4(&cmdbuf->cs, REG_A6XX_GRAS_2D_BLIT_CNTL, 1);
567b8e80941Smrg   tu_cs_emit(&cmdbuf->cs, blit_cntl);
568b8e80941Smrg
569b8e80941Smrg   for (unsigned layer_offset = 0; layer_offset < copy_info->imageSubresource.layerCount; ++layer_offset) {
570b8e80941Smrg       unsigned layer = copy_info->imageSubresource.baseArrayLayer + layer_offset;
571b8e80941Smrg       uint64_t dst_va = dst_buffer->bo->iova + dst_buffer->bo_offset + copy_info->bufferOffset + layer_offset * copy_info->bufferImageHeight * dst_pitch;
572b8e80941Smrg
573b8e80941Smrg       if ((dst_pitch & 63) || (dst_va & 63)) {
574b8e80941Smrg         /* Do a per line copy */
575b8e80941Smrg         VkBufferImageCopy line_copy_info = *copy_info;
576b8e80941Smrg         line_copy_info.imageExtent.height = 1;
577b8e80941Smrg         for (unsigned r = 0; r < copy_info->imageExtent.height; ++r) {
578b8e80941Smrg            /*
579b8e80941Smrg             * if dst_va is not aligned the line copy will need to adjust. Give it
580b8e80941Smrg             * room to do so.
581b8e80941Smrg             */
582b8e80941Smrg            unsigned max_width = 16384 - (dst_va & 0x3f) ? 64 : 0;
583b8e80941Smrg            line_copy_info.imageOffset.x = copy_info->imageOffset.x;
584b8e80941Smrg            line_copy_info.imageExtent.width = copy_info->imageExtent.width;
585b8e80941Smrg
586b8e80941Smrg            for (unsigned c = 0; c < copy_info->imageExtent.width; c += max_width) {
587b8e80941Smrg               tu_copy_image_to_buffer_step(cmdbuf, src_image, dst_buffer, &line_copy_info, format, layer, dst_va + c * cpp);
588b8e80941Smrg
589b8e80941Smrg               line_copy_info.imageOffset.x += max_width;
590b8e80941Smrg               line_copy_info.imageExtent.width -= max_width;
591b8e80941Smrg            }
592b8e80941Smrg
593b8e80941Smrg            line_copy_info.imageOffset.y++;
594b8e80941Smrg            dst_va += dst_pitch;
595b8e80941Smrg         }
596b8e80941Smrg      } else {
597b8e80941Smrg         tu_copy_image_to_buffer_step(cmdbuf, src_image, dst_buffer, copy_info, format, layer, dst_va);
598b8e80941Smrg      }
599b8e80941Smrg   }
600b8e80941Smrg
601b8e80941Smrg   tu_cs_reserve_space(cmdbuf->device, &cmdbuf->cs, 15);
602b8e80941Smrg
603b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, 0x1d, true);
604b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, FACENESS_FLUSH, true);
605b8e80941Smrg   tu6_emit_event_write(cmdbuf, &cmdbuf->cs, CACHE_FLUSH_TS, true);
606b8e80941Smrg}
607b8e80941Smrg
608b8e80941Smrgvoid
609b8e80941Smrgtu_CmdCopyBuffer(VkCommandBuffer commandBuffer,
610b8e80941Smrg                 VkBuffer srcBuffer,
611b8e80941Smrg                 VkBuffer destBuffer,
612b8e80941Smrg                 uint32_t regionCount,
613b8e80941Smrg                 const VkBufferCopy *pRegions)
614b8e80941Smrg{
615b8e80941Smrg   TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, commandBuffer);
616b8e80941Smrg   TU_FROM_HANDLE(tu_buffer, src_buffer, srcBuffer);
617b8e80941Smrg   TU_FROM_HANDLE(tu_buffer, dst_buffer, destBuffer);
618b8e80941Smrg
619b8e80941Smrg   for (unsigned i = 0; i < regionCount; ++i) {
620b8e80941Smrg      uint64_t src_offset = src_buffer->bo_offset + pRegions[i].srcOffset;
621b8e80941Smrg      uint64_t dst_offset = dst_buffer->bo_offset + pRegions[i].dstOffset;
622b8e80941Smrg
623b8e80941Smrg      tu_copy_buffer(cmdbuf, src_buffer->bo, src_offset, dst_buffer->bo,
624b8e80941Smrg                     dst_offset, pRegions[i].size);
625b8e80941Smrg   }
626b8e80941Smrg}
627b8e80941Smrg
628b8e80941Smrgvoid
629b8e80941Smrgtu_CmdCopyBufferToImage(VkCommandBuffer commandBuffer,
630b8e80941Smrg                        VkBuffer srcBuffer,
631b8e80941Smrg                        VkImage destImage,
632b8e80941Smrg                        VkImageLayout destImageLayout,
633b8e80941Smrg                        uint32_t regionCount,
634b8e80941Smrg                        const VkBufferImageCopy *pRegions)
635b8e80941Smrg{
636b8e80941Smrg   TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
637b8e80941Smrg   TU_FROM_HANDLE(tu_image, dest_image, destImage);
638b8e80941Smrg   TU_FROM_HANDLE(tu_buffer, src_buffer, srcBuffer);
639b8e80941Smrg
640b8e80941Smrg   for (unsigned i = 0; i < regionCount; ++i) {
641b8e80941Smrg      tu_copy_buffer_to_image(cmd_buffer, src_buffer, dest_image,
642b8e80941Smrg                              pRegions + i);
643b8e80941Smrg   }
644b8e80941Smrg}
645b8e80941Smrg
646b8e80941Smrgvoid
647b8e80941Smrgtu_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
648b8e80941Smrg                        VkImage srcImage,
649b8e80941Smrg                        VkImageLayout srcImageLayout,
650b8e80941Smrg                        VkBuffer destBuffer,
651b8e80941Smrg                        uint32_t regionCount,
652b8e80941Smrg                        const VkBufferImageCopy *pRegions)
653b8e80941Smrg{
654b8e80941Smrg   TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
655b8e80941Smrg   TU_FROM_HANDLE(tu_image, src_image, srcImage);
656b8e80941Smrg   TU_FROM_HANDLE(tu_buffer, dst_buffer, destBuffer);
657b8e80941Smrg
658b8e80941Smrg   for (unsigned i = 0; i < regionCount; ++i) {
659b8e80941Smrg      tu_copy_image_to_buffer(cmd_buffer, src_image, dst_buffer,
660b8e80941Smrg                              pRegions + i);
661b8e80941Smrg   }
662b8e80941Smrg}
663b8e80941Smrg
664b8e80941Smrgstatic void
665b8e80941Smrgmeta_copy_image(struct tu_cmd_buffer *cmd_buffer,
666b8e80941Smrg                struct tu_image *src_image,
667b8e80941Smrg                VkImageLayout src_image_layout,
668b8e80941Smrg                struct tu_image *dest_image,
669b8e80941Smrg                VkImageLayout dest_image_layout,
670b8e80941Smrg                uint32_t regionCount,
671b8e80941Smrg                const VkImageCopy *pRegions)
672b8e80941Smrg{
673b8e80941Smrg}
674b8e80941Smrg
675b8e80941Smrgvoid
676b8e80941Smrgtu_CmdCopyImage(VkCommandBuffer commandBuffer,
677b8e80941Smrg                VkImage srcImage,
678b8e80941Smrg                VkImageLayout srcImageLayout,
679b8e80941Smrg                VkImage destImage,
680b8e80941Smrg                VkImageLayout destImageLayout,
681b8e80941Smrg                uint32_t regionCount,
682b8e80941Smrg                const VkImageCopy *pRegions)
683b8e80941Smrg{
684b8e80941Smrg   TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
685b8e80941Smrg   TU_FROM_HANDLE(tu_image, src_image, srcImage);
686b8e80941Smrg   TU_FROM_HANDLE(tu_image, dest_image, destImage);
687b8e80941Smrg
688b8e80941Smrg   meta_copy_image(cmd_buffer, src_image, srcImageLayout, dest_image,
689b8e80941Smrg                   destImageLayout, regionCount, pRegions);
690b8e80941Smrg}
691