1 /*
2 * Copyright © 2016 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "radv_meta.h"
25 #include "radv_private.h"
26 #include "radv_sdma.h"
27 #include "vk_format.h"
28
29 static VkFormat
vk_format_for_size(int bs)30 vk_format_for_size(int bs)
31 {
32 switch (bs) {
33 case 1:
34 return VK_FORMAT_R8_UINT;
35 case 2:
36 return VK_FORMAT_R8G8_UINT;
37 case 4:
38 return VK_FORMAT_R8G8B8A8_UINT;
39 case 8:
40 return VK_FORMAT_R16G16B16A16_UINT;
41 case 12:
42 return VK_FORMAT_R32G32B32_UINT;
43 case 16:
44 return VK_FORMAT_R32G32B32A32_UINT;
45 default:
46 unreachable("Invalid format block size");
47 }
48 }
49
50 static struct radv_meta_blit2d_surf
blit_surf_for_image_level_layer(struct radv_image * image,VkImageLayout layout,const VkImageSubresourceLayers * subres,VkImageAspectFlags aspect_mask)51 blit_surf_for_image_level_layer(struct radv_image *image, VkImageLayout layout, const VkImageSubresourceLayers *subres,
52 VkImageAspectFlags aspect_mask)
53 {
54 VkFormat format = radv_get_aspect_format(image, aspect_mask);
55
56 if (!radv_dcc_enabled(image, subres->mipLevel) && !(radv_image_is_tc_compat_htile(image)))
57 format = vk_format_for_size(vk_format_get_blocksize(format));
58
59 format = vk_format_no_srgb(format);
60
61 return (struct radv_meta_blit2d_surf){
62 .format = format,
63 .bs = vk_format_get_blocksize(format),
64 .level = subres->mipLevel,
65 .layer = subres->baseArrayLayer,
66 .image = image,
67 .aspect_mask = aspect_mask,
68 .current_layout = layout,
69 };
70 }
71
72 static bool
alloc_transfer_temp_bo(struct radv_cmd_buffer * cmd_buffer)73 alloc_transfer_temp_bo(struct radv_cmd_buffer *cmd_buffer)
74 {
75 if (cmd_buffer->transfer.copy_temp)
76 return true;
77
78 const struct radv_device *const device = cmd_buffer->device;
79 const VkResult r = device->ws->buffer_create(device->ws, RADV_SDMA_TRANSFER_TEMP_BYTES, 4096, RADEON_DOMAIN_VRAM,
80 RADEON_FLAG_NO_CPU_ACCESS | RADEON_FLAG_NO_INTERPROCESS_SHARING,
81 RADV_BO_PRIORITY_SCRATCH, 0, &cmd_buffer->transfer.copy_temp);
82
83 if (r != VK_SUCCESS) {
84 vk_command_buffer_set_error(&cmd_buffer->vk, r);
85 return false;
86 }
87
88 radv_cs_add_buffer(device->ws, cmd_buffer->cs, cmd_buffer->transfer.copy_temp);
89 return true;
90 }
91
92 static void
transfer_copy_buffer_image(struct radv_cmd_buffer * cmd_buffer,struct radv_buffer * buffer,struct radv_image * image,const VkBufferImageCopy2 * region,bool to_image)93 transfer_copy_buffer_image(struct radv_cmd_buffer *cmd_buffer, struct radv_buffer *buffer, struct radv_image *image,
94 const VkBufferImageCopy2 *region, bool to_image)
95 {
96 const struct radv_device *device = cmd_buffer->device;
97 struct radeon_cmdbuf *cs = cmd_buffer->cs;
98 const VkImageAspectFlags aspect_mask = region->imageSubresource.aspectMask;
99 const unsigned binding_idx = image->disjoint ? radv_plane_from_aspect(aspect_mask) : 0;
100
101 radv_cs_add_buffer(device->ws, cs, image->bindings[binding_idx].bo);
102 radv_cs_add_buffer(device->ws, cs, buffer->bo);
103
104 struct radv_sdma_surf buf = radv_sdma_get_buf_surf(buffer, image, region, aspect_mask);
105 const struct radv_sdma_surf img =
106 radv_sdma_get_surf(device, image, region->imageSubresource, region->imageOffset, aspect_mask);
107 const VkExtent3D extent = radv_sdma_get_copy_extent(image, region->imageSubresource, region->imageExtent);
108
109 if (radv_sdma_use_unaligned_buffer_image_copy(device, &buf, &img, extent)) {
110 if (!alloc_transfer_temp_bo(cmd_buffer))
111 return;
112
113 radv_sdma_copy_buffer_image_unaligned(device, cs, &buf, &img, extent, cmd_buffer->transfer.copy_temp, to_image);
114 return;
115 }
116
117 radv_sdma_copy_buffer_image(device, cs, &buf, &img, extent, to_image);
118 }
119
120 static void
copy_buffer_to_image(struct radv_cmd_buffer * cmd_buffer,struct radv_buffer * buffer,struct radv_image * image,VkImageLayout layout,const VkBufferImageCopy2 * region)121 copy_buffer_to_image(struct radv_cmd_buffer *cmd_buffer, struct radv_buffer *buffer, struct radv_image *image,
122 VkImageLayout layout, const VkBufferImageCopy2 *region)
123 {
124 if (cmd_buffer->qf == RADV_QUEUE_TRANSFER) {
125 transfer_copy_buffer_image(cmd_buffer, buffer, image, region, true);
126 return;
127 }
128
129 struct radv_meta_saved_state saved_state;
130 bool cs;
131
132 /* The Vulkan 1.0 spec says "dstImage must have a sample count equal to
133 * VK_SAMPLE_COUNT_1_BIT."
134 */
135 assert(image->vk.samples == 1);
136
137 cs = cmd_buffer->qf == RADV_QUEUE_COMPUTE || !radv_image_is_renderable(cmd_buffer->device, image);
138
139 /* VK_EXT_conditional_rendering says that copy commands should not be
140 * affected by conditional rendering.
141 */
142 radv_meta_save(&saved_state, cmd_buffer,
143 (cs ? RADV_META_SAVE_COMPUTE_PIPELINE : RADV_META_SAVE_GRAPHICS_PIPELINE) | RADV_META_SAVE_CONSTANTS |
144 RADV_META_SAVE_DESCRIPTORS | RADV_META_SUSPEND_PREDICATING);
145
146 /**
147 * From the Vulkan 1.0.6 spec: 18.3 Copying Data Between Images
148 * extent is the size in texels of the source image to copy in width,
149 * height and depth. 1D images use only x and width. 2D images use x, y,
150 * width and height. 3D images use x, y, z, width, height and depth.
151 *
152 *
153 * Also, convert the offsets and extent from units of texels to units of
154 * blocks - which is the highest resolution accessible in this command.
155 */
156 const VkOffset3D img_offset_el = vk_image_offset_to_elements(&image->vk, region->imageOffset);
157
158 /* Start creating blit rect */
159 const VkExtent3D img_extent_el = vk_image_extent_to_elements(&image->vk, region->imageExtent);
160 struct radv_meta_blit2d_rect rect = {
161 .width = img_extent_el.width,
162 .height = img_extent_el.height,
163 };
164
165 /* Create blit surfaces */
166 struct radv_meta_blit2d_surf img_bsurf =
167 blit_surf_for_image_level_layer(image, layout, ®ion->imageSubresource, region->imageSubresource.aspectMask);
168
169 if (!radv_is_buffer_format_supported(img_bsurf.format, NULL)) {
170 uint32_t queue_mask = radv_image_queue_family_mask(image, cmd_buffer->qf, cmd_buffer->qf);
171 bool compressed =
172 radv_layout_dcc_compressed(cmd_buffer->device, image, region->imageSubresource.mipLevel, layout, queue_mask);
173 if (compressed) {
174 radv_describe_barrier_start(cmd_buffer, RGP_BARRIER_UNKNOWN_REASON);
175
176 radv_decompress_dcc(cmd_buffer, image,
177 &(VkImageSubresourceRange){
178 .aspectMask = region->imageSubresource.aspectMask,
179 .baseMipLevel = region->imageSubresource.mipLevel,
180 .levelCount = 1,
181 .baseArrayLayer = region->imageSubresource.baseArrayLayer,
182 .layerCount = vk_image_subresource_layer_count(&image->vk, ®ion->imageSubresource),
183 });
184 img_bsurf.disable_compression = true;
185
186 radv_describe_barrier_end(cmd_buffer);
187 }
188 img_bsurf.format = vk_format_for_size(vk_format_get_blocksize(img_bsurf.format));
189 }
190
191 const struct vk_image_buffer_layout buf_layout = vk_image_buffer_copy_layout(&image->vk, region);
192 struct radv_meta_blit2d_buffer buf_bsurf = {
193 .bs = img_bsurf.bs,
194 .format = img_bsurf.format,
195 .buffer = buffer,
196 .offset = region->bufferOffset,
197 .pitch = buf_layout.row_stride_B / buf_layout.element_size_B,
198 };
199
200 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
201 img_bsurf.layer = img_offset_el.z;
202 /* Loop through each 3D or array slice */
203 unsigned num_slices_3d = img_extent_el.depth;
204 unsigned num_slices_array = vk_image_subresource_layer_count(&image->vk, ®ion->imageSubresource);
205 unsigned slice_3d = 0;
206 unsigned slice_array = 0;
207 while (slice_3d < num_slices_3d && slice_array < num_slices_array) {
208
209 rect.dst_x = img_offset_el.x;
210 rect.dst_y = img_offset_el.y;
211
212 /* Perform Blit */
213 if (cs) {
214 radv_meta_buffer_to_image_cs(cmd_buffer, &buf_bsurf, &img_bsurf, 1, &rect);
215 } else {
216 radv_meta_blit2d(cmd_buffer, NULL, &buf_bsurf, &img_bsurf, 1, &rect);
217 }
218
219 /* Once we've done the blit, all of the actual information about
220 * the image is embedded in the command buffer so we can just
221 * increment the offset directly in the image effectively
222 * re-binding it to different backing memory.
223 */
224 buf_bsurf.offset += buf_layout.image_stride_B;
225 img_bsurf.layer++;
226 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
227 slice_3d++;
228 else
229 slice_array++;
230 }
231
232 radv_meta_restore(&saved_state, cmd_buffer);
233 }
234
235 VKAPI_ATTR void VKAPI_CALL
radv_CmdCopyBufferToImage2(VkCommandBuffer commandBuffer,const VkCopyBufferToImageInfo2 * pCopyBufferToImageInfo)236 radv_CmdCopyBufferToImage2(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2 *pCopyBufferToImageInfo)
237 {
238 RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
239 RADV_FROM_HANDLE(radv_buffer, src_buffer, pCopyBufferToImageInfo->srcBuffer);
240 RADV_FROM_HANDLE(radv_image, dst_image, pCopyBufferToImageInfo->dstImage);
241
242 for (unsigned r = 0; r < pCopyBufferToImageInfo->regionCount; r++) {
243 copy_buffer_to_image(cmd_buffer, src_buffer, dst_image, pCopyBufferToImageInfo->dstImageLayout,
244 &pCopyBufferToImageInfo->pRegions[r]);
245 }
246
247 if (radv_is_format_emulated(cmd_buffer->device->physical_device, dst_image->vk.format)) {
248 cmd_buffer->state.flush_bits |=
249 RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_PS_PARTIAL_FLUSH |
250 radv_src_access_flush(cmd_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, dst_image) |
251 radv_dst_access_flush(cmd_buffer, VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, dst_image);
252
253 const enum util_format_layout format_layout = vk_format_description(dst_image->vk.format)->layout;
254 for (unsigned r = 0; r < pCopyBufferToImageInfo->regionCount; r++) {
255 if (format_layout == UTIL_FORMAT_LAYOUT_ASTC) {
256 radv_meta_decode_astc(cmd_buffer, dst_image, pCopyBufferToImageInfo->dstImageLayout,
257 &pCopyBufferToImageInfo->pRegions[r].imageSubresource,
258 pCopyBufferToImageInfo->pRegions[r].imageOffset,
259 pCopyBufferToImageInfo->pRegions[r].imageExtent);
260 } else {
261 radv_meta_decode_etc(cmd_buffer, dst_image, pCopyBufferToImageInfo->dstImageLayout,
262 &pCopyBufferToImageInfo->pRegions[r].imageSubresource,
263 pCopyBufferToImageInfo->pRegions[r].imageOffset,
264 pCopyBufferToImageInfo->pRegions[r].imageExtent);
265 }
266 }
267 }
268 }
269
270 static void
copy_image_to_buffer(struct radv_cmd_buffer * cmd_buffer,struct radv_buffer * buffer,struct radv_image * image,VkImageLayout layout,const VkBufferImageCopy2 * region)271 copy_image_to_buffer(struct radv_cmd_buffer *cmd_buffer, struct radv_buffer *buffer, struct radv_image *image,
272 VkImageLayout layout, const VkBufferImageCopy2 *region)
273 {
274 struct radv_device *device = cmd_buffer->device;
275 if (cmd_buffer->qf == RADV_QUEUE_TRANSFER) {
276 transfer_copy_buffer_image(cmd_buffer, buffer, image, region, false);
277 return;
278 }
279
280 struct radv_meta_saved_state saved_state;
281
282 /* VK_EXT_conditional_rendering says that copy commands should not be
283 * affected by conditional rendering.
284 */
285 radv_meta_save(&saved_state, cmd_buffer,
286 RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS |
287 RADV_META_SUSPEND_PREDICATING);
288
289 /**
290 * From the Vulkan 1.0.6 spec: 18.3 Copying Data Between Images
291 * extent is the size in texels of the source image to copy in width,
292 * height and depth. 1D images use only x and width. 2D images use x, y,
293 * width and height. 3D images use x, y, z, width, height and depth.
294 *
295 *
296 * Also, convert the offsets and extent from units of texels to units of
297 * blocks - which is the highest resolution accessible in this command.
298 */
299 const VkOffset3D img_offset_el = vk_image_offset_to_elements(&image->vk, region->imageOffset);
300 const VkExtent3D bufferExtent = {
301 .width = region->bufferRowLength ? region->bufferRowLength : region->imageExtent.width,
302 .height = region->bufferImageHeight ? region->bufferImageHeight : region->imageExtent.height,
303 };
304 const VkExtent3D buf_extent_el = vk_image_extent_to_elements(&image->vk, bufferExtent);
305
306 /* Start creating blit rect */
307 const VkExtent3D img_extent_el = vk_image_extent_to_elements(&image->vk, region->imageExtent);
308 struct radv_meta_blit2d_rect rect = {
309 .width = img_extent_el.width,
310 .height = img_extent_el.height,
311 };
312
313 /* Create blit surfaces */
314 struct radv_meta_blit2d_surf img_info =
315 blit_surf_for_image_level_layer(image, layout, ®ion->imageSubresource, region->imageSubresource.aspectMask);
316
317 if (!radv_is_buffer_format_supported(img_info.format, NULL)) {
318 uint32_t queue_mask = radv_image_queue_family_mask(image, cmd_buffer->qf, cmd_buffer->qf);
319 bool compressed =
320 radv_layout_dcc_compressed(device, image, region->imageSubresource.mipLevel, layout, queue_mask);
321 if (compressed) {
322 radv_describe_barrier_start(cmd_buffer, RGP_BARRIER_UNKNOWN_REASON);
323
324 radv_decompress_dcc(cmd_buffer, image,
325 &(VkImageSubresourceRange){
326 .aspectMask = region->imageSubresource.aspectMask,
327 .baseMipLevel = region->imageSubresource.mipLevel,
328 .levelCount = 1,
329 .baseArrayLayer = region->imageSubresource.baseArrayLayer,
330 .layerCount = vk_image_subresource_layer_count(&image->vk, ®ion->imageSubresource),
331 });
332 img_info.disable_compression = true;
333
334 radv_describe_barrier_end(cmd_buffer);
335 }
336 img_info.format = vk_format_for_size(vk_format_get_blocksize(img_info.format));
337 }
338
339 struct radv_meta_blit2d_buffer buf_info = {
340 .bs = img_info.bs,
341 .format = img_info.format,
342 .buffer = buffer,
343 .offset = region->bufferOffset,
344 .pitch = buf_extent_el.width,
345 };
346
347 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
348 img_info.layer = img_offset_el.z;
349 /* Loop through each 3D or array slice */
350 unsigned num_slices_3d = img_extent_el.depth;
351 unsigned num_slices_array = vk_image_subresource_layer_count(&image->vk, ®ion->imageSubresource);
352 unsigned slice_3d = 0;
353 unsigned slice_array = 0;
354 while (slice_3d < num_slices_3d && slice_array < num_slices_array) {
355
356 rect.src_x = img_offset_el.x;
357 rect.src_y = img_offset_el.y;
358
359 /* Perform Blit */
360 radv_meta_image_to_buffer(cmd_buffer, &img_info, &buf_info, 1, &rect);
361
362 buf_info.offset += buf_extent_el.width * buf_extent_el.height * buf_info.bs;
363 img_info.layer++;
364 if (image->vk.image_type == VK_IMAGE_TYPE_3D)
365 slice_3d++;
366 else
367 slice_array++;
368 }
369
370 radv_meta_restore(&saved_state, cmd_buffer);
371 }
372
373 VKAPI_ATTR void VKAPI_CALL
radv_CmdCopyImageToBuffer2(VkCommandBuffer commandBuffer,const VkCopyImageToBufferInfo2 * pCopyImageToBufferInfo)374 radv_CmdCopyImageToBuffer2(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2 *pCopyImageToBufferInfo)
375 {
376 RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
377 RADV_FROM_HANDLE(radv_image, src_image, pCopyImageToBufferInfo->srcImage);
378 RADV_FROM_HANDLE(radv_buffer, dst_buffer, pCopyImageToBufferInfo->dstBuffer);
379
380 for (unsigned r = 0; r < pCopyImageToBufferInfo->regionCount; r++) {
381 copy_image_to_buffer(cmd_buffer, dst_buffer, src_image, pCopyImageToBufferInfo->srcImageLayout,
382 &pCopyImageToBufferInfo->pRegions[r]);
383 }
384 }
385
386 static void
transfer_copy_image(struct radv_cmd_buffer * cmd_buffer,struct radv_image * src_image,VkImageLayout src_image_layout,struct radv_image * dst_image,VkImageLayout dst_image_layout,const VkImageCopy2 * region)387 transfer_copy_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkImageLayout src_image_layout,
388 struct radv_image *dst_image, VkImageLayout dst_image_layout, const VkImageCopy2 *region)
389 {
390 const struct radv_device *device = cmd_buffer->device;
391 struct radeon_cmdbuf *cs = cmd_buffer->cs;
392 unsigned int dst_aspect_mask_remaining = region->dstSubresource.aspectMask;
393
394 u_foreach_bit (b, region->srcSubresource.aspectMask) {
395 const VkImageAspectFlags src_aspect_mask = BITFIELD_BIT(b);
396 const VkImageAspectFlags dst_aspect_mask = BITFIELD_BIT(u_bit_scan(&dst_aspect_mask_remaining));
397 const unsigned src_binding_idx = src_image->disjoint ? radv_plane_from_aspect(src_aspect_mask) : 0;
398 const unsigned dst_binding_idx = dst_image->disjoint ? radv_plane_from_aspect(dst_aspect_mask) : 0;
399
400 radv_cs_add_buffer(device->ws, cs, src_image->bindings[src_binding_idx].bo);
401 radv_cs_add_buffer(device->ws, cs, dst_image->bindings[dst_binding_idx].bo);
402
403 const struct radv_sdma_surf src =
404 radv_sdma_get_surf(device, src_image, region->srcSubresource, region->srcOffset, src_aspect_mask);
405 const struct radv_sdma_surf dst =
406 radv_sdma_get_surf(device, dst_image, region->dstSubresource, region->dstOffset, dst_aspect_mask);
407 const VkExtent3D extent = radv_sdma_get_copy_extent(src_image, region->srcSubresource, region->extent);
408
409 if (radv_sdma_use_t2t_scanline_copy(device, &src, &dst, extent)) {
410 if (!alloc_transfer_temp_bo(cmd_buffer))
411 return;
412
413 radv_sdma_copy_image_t2t_scanline(device, cs, &src, &dst, extent, cmd_buffer->transfer.copy_temp);
414 } else {
415 radv_sdma_copy_image(device, cs, &src, &dst, extent);
416 }
417 }
418 }
419
420 static void
copy_image(struct radv_cmd_buffer * cmd_buffer,struct radv_image * src_image,VkImageLayout src_image_layout,struct radv_image * dst_image,VkImageLayout dst_image_layout,const VkImageCopy2 * region)421 copy_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkImageLayout src_image_layout,
422 struct radv_image *dst_image, VkImageLayout dst_image_layout, const VkImageCopy2 *region)
423 {
424 if (cmd_buffer->qf == RADV_QUEUE_TRANSFER) {
425 transfer_copy_image(cmd_buffer, src_image, src_image_layout, dst_image, dst_image_layout, region);
426 return;
427 }
428
429 struct radv_meta_saved_state saved_state;
430 bool cs;
431
432 /* From the Vulkan 1.0 spec:
433 *
434 * vkCmdCopyImage can be used to copy image data between multisample images, but both images must have the same
435 * number of samples.
436 */
437 assert(src_image->vk.samples == dst_image->vk.samples);
438 /* From the Vulkan 1.3 spec:
439 *
440 * Multi-planar images can only be copied on a per-plane basis, and the subresources used in each region when
441 * copying to or from such images must specify only one plane, though different regions can specify different
442 * planes.
443 */
444 assert(src_image->plane_count == 1 || util_is_power_of_two_nonzero(region->srcSubresource.aspectMask));
445 assert(dst_image->plane_count == 1 || util_is_power_of_two_nonzero(region->dstSubresource.aspectMask));
446
447 cs = cmd_buffer->qf == RADV_QUEUE_COMPUTE || !radv_image_is_renderable(cmd_buffer->device, dst_image);
448
449 /* VK_EXT_conditional_rendering says that copy commands should not be
450 * affected by conditional rendering.
451 */
452 radv_meta_save(&saved_state, cmd_buffer,
453 (cs ? RADV_META_SAVE_COMPUTE_PIPELINE : RADV_META_SAVE_GRAPHICS_PIPELINE) | RADV_META_SAVE_CONSTANTS |
454 RADV_META_SAVE_DESCRIPTORS | RADV_META_SUSPEND_PREDICATING);
455
456 if (cs) {
457 /* For partial copies, HTILE should be decompressed before copying because the metadata is
458 * re-initialized to the uncompressed state after.
459 */
460 uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf, cmd_buffer->qf);
461
462 if (radv_layout_is_htile_compressed(cmd_buffer->device, dst_image, dst_image_layout, queue_mask) &&
463 (region->dstOffset.x || region->dstOffset.y || region->dstOffset.z ||
464 region->extent.width != dst_image->vk.extent.width || region->extent.height != dst_image->vk.extent.height ||
465 region->extent.depth != dst_image->vk.extent.depth)) {
466 radv_describe_barrier_start(cmd_buffer, RGP_BARRIER_UNKNOWN_REASON);
467
468 u_foreach_bit (i, region->dstSubresource.aspectMask) {
469 unsigned aspect_mask = 1u << i;
470 radv_expand_depth_stencil(
471 cmd_buffer, dst_image,
472 &(VkImageSubresourceRange){
473 .aspectMask = aspect_mask,
474 .baseMipLevel = region->dstSubresource.mipLevel,
475 .levelCount = 1,
476 .baseArrayLayer = region->dstSubresource.baseArrayLayer,
477 .layerCount = vk_image_subresource_layer_count(&dst_image->vk, ®ion->dstSubresource),
478 },
479 NULL);
480 }
481
482 radv_describe_barrier_end(cmd_buffer);
483 }
484 }
485
486 /* Create blit surfaces */
487 struct radv_meta_blit2d_surf b_src = blit_surf_for_image_level_layer(
488 src_image, src_image_layout, ®ion->srcSubresource, region->srcSubresource.aspectMask);
489
490 struct radv_meta_blit2d_surf b_dst = blit_surf_for_image_level_layer(
491 dst_image, dst_image_layout, ®ion->dstSubresource, region->dstSubresource.aspectMask);
492
493 uint32_t dst_queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf, cmd_buffer->qf);
494 bool dst_compressed = radv_layout_dcc_compressed(cmd_buffer->device, dst_image, region->dstSubresource.mipLevel,
495 dst_image_layout, dst_queue_mask);
496 uint32_t src_queue_mask = radv_image_queue_family_mask(src_image, cmd_buffer->qf, cmd_buffer->qf);
497 bool src_compressed = radv_layout_dcc_compressed(cmd_buffer->device, src_image, region->srcSubresource.mipLevel,
498 src_image_layout, src_queue_mask);
499 bool need_dcc_sign_reinterpret = false;
500
501 if (!src_compressed || (radv_dcc_formats_compatible(cmd_buffer->device->physical_device->rad_info.gfx_level,
502 b_src.format, b_dst.format, &need_dcc_sign_reinterpret) &&
503 !need_dcc_sign_reinterpret)) {
504 b_src.format = b_dst.format;
505 } else if (!dst_compressed) {
506 b_dst.format = b_src.format;
507 } else {
508 radv_describe_barrier_start(cmd_buffer, RGP_BARRIER_UNKNOWN_REASON);
509
510 radv_decompress_dcc(cmd_buffer, dst_image,
511 &(VkImageSubresourceRange){
512 .aspectMask = region->dstSubresource.aspectMask,
513 .baseMipLevel = region->dstSubresource.mipLevel,
514 .levelCount = 1,
515 .baseArrayLayer = region->dstSubresource.baseArrayLayer,
516 .layerCount = vk_image_subresource_layer_count(&dst_image->vk, ®ion->dstSubresource),
517 });
518 b_dst.format = b_src.format;
519 b_dst.disable_compression = true;
520
521 radv_describe_barrier_end(cmd_buffer);
522 }
523
524 /**
525 * From the Vulkan 1.0.6 spec: 18.4 Copying Data Between Buffers and Images
526 * imageExtent is the size in texels of the image to copy in width, height
527 * and depth. 1D images use only x and width. 2D images use x, y, width
528 * and height. 3D images use x, y, z, width, height and depth.
529 *
530 * Also, convert the offsets and extent from units of texels to units of
531 * blocks - which is the highest resolution accessible in this command.
532 */
533 const VkOffset3D dst_offset_el = vk_image_offset_to_elements(&dst_image->vk, region->dstOffset);
534 const VkOffset3D src_offset_el = vk_image_offset_to_elements(&src_image->vk, region->srcOffset);
535
536 /*
537 * From Vulkan 1.0.68, "Copying Data Between Images":
538 * "When copying between compressed and uncompressed formats
539 * the extent members represent the texel dimensions of the
540 * source image and not the destination."
541 * However, we must use the destination image type to avoid
542 * clamping depth when copying multiple layers of a 2D image to
543 * a 3D image.
544 */
545 const VkExtent3D img_extent_el = vk_image_extent_to_elements(&src_image->vk, region->extent);
546
547 /* Start creating blit rect */
548 struct radv_meta_blit2d_rect rect = {
549 .width = img_extent_el.width,
550 .height = img_extent_el.height,
551 };
552
553 unsigned num_slices = vk_image_subresource_layer_count(&src_image->vk, ®ion->srcSubresource);
554
555 if (src_image->vk.image_type == VK_IMAGE_TYPE_3D) {
556 b_src.layer = src_offset_el.z;
557 num_slices = img_extent_el.depth;
558 }
559
560 if (dst_image->vk.image_type == VK_IMAGE_TYPE_3D)
561 b_dst.layer = dst_offset_el.z;
562
563 for (unsigned slice = 0; slice < num_slices; slice++) {
564 /* Finish creating blit rect */
565 rect.dst_x = dst_offset_el.x;
566 rect.dst_y = dst_offset_el.y;
567 rect.src_x = src_offset_el.x;
568 rect.src_y = src_offset_el.y;
569
570 /* Perform Blit */
571 if (cs) {
572 radv_meta_image_to_image_cs(cmd_buffer, &b_src, &b_dst, 1, &rect);
573 } else {
574 if (radv_can_use_fmask_copy(cmd_buffer, b_src.image, b_dst.image, 1, &rect)) {
575 radv_fmask_copy(cmd_buffer, &b_src, &b_dst);
576 } else {
577 radv_meta_blit2d(cmd_buffer, &b_src, NULL, &b_dst, 1, &rect);
578 }
579 }
580
581 b_src.layer++;
582 b_dst.layer++;
583 }
584
585 if (cs) {
586 /* Fixup HTILE after a copy on compute. */
587 uint32_t queue_mask = radv_image_queue_family_mask(dst_image, cmd_buffer->qf, cmd_buffer->qf);
588
589 if (radv_layout_is_htile_compressed(cmd_buffer->device, dst_image, dst_image_layout, queue_mask)) {
590 cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_INV_VCACHE;
591
592 VkImageSubresourceRange range = {
593 .aspectMask = region->dstSubresource.aspectMask,
594 .baseMipLevel = region->dstSubresource.mipLevel,
595 .levelCount = 1,
596 .baseArrayLayer = region->dstSubresource.baseArrayLayer,
597 .layerCount = vk_image_subresource_layer_count(&dst_image->vk, ®ion->dstSubresource),
598 };
599
600 uint32_t htile_value = radv_get_htile_initial_value(cmd_buffer->device, dst_image);
601
602 cmd_buffer->state.flush_bits |= radv_clear_htile(cmd_buffer, dst_image, &range, htile_value);
603 }
604 }
605
606 radv_meta_restore(&saved_state, cmd_buffer);
607 }
608
609 VKAPI_ATTR void VKAPI_CALL
radv_CmdCopyImage2(VkCommandBuffer commandBuffer,const VkCopyImageInfo2 * pCopyImageInfo)610 radv_CmdCopyImage2(VkCommandBuffer commandBuffer, const VkCopyImageInfo2 *pCopyImageInfo)
611 {
612 RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
613 RADV_FROM_HANDLE(radv_image, src_image, pCopyImageInfo->srcImage);
614 RADV_FROM_HANDLE(radv_image, dst_image, pCopyImageInfo->dstImage);
615
616 for (unsigned r = 0; r < pCopyImageInfo->regionCount; r++) {
617 copy_image(cmd_buffer, src_image, pCopyImageInfo->srcImageLayout, dst_image, pCopyImageInfo->dstImageLayout,
618 &pCopyImageInfo->pRegions[r]);
619 }
620
621 if (radv_is_format_emulated(cmd_buffer->device->physical_device, dst_image->vk.format)) {
622 cmd_buffer->state.flush_bits |=
623 RADV_CMD_FLAG_CS_PARTIAL_FLUSH | RADV_CMD_FLAG_PS_PARTIAL_FLUSH |
624 radv_src_access_flush(cmd_buffer, VK_ACCESS_TRANSFER_WRITE_BIT, dst_image) |
625 radv_dst_access_flush(cmd_buffer, VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, dst_image);
626
627 const enum util_format_layout format_layout = vk_format_description(dst_image->vk.format)->layout;
628 for (unsigned r = 0; r < pCopyImageInfo->regionCount; r++) {
629 VkExtent3D dst_extent = pCopyImageInfo->pRegions[r].extent;
630 if (src_image->vk.format != dst_image->vk.format) {
631 dst_extent.width = dst_extent.width / vk_format_get_blockwidth(src_image->vk.format) *
632 vk_format_get_blockwidth(dst_image->vk.format);
633 dst_extent.height = dst_extent.height / vk_format_get_blockheight(src_image->vk.format) *
634 vk_format_get_blockheight(dst_image->vk.format);
635 }
636 if (format_layout == UTIL_FORMAT_LAYOUT_ASTC) {
637 radv_meta_decode_astc(cmd_buffer, dst_image, pCopyImageInfo->dstImageLayout,
638 &pCopyImageInfo->pRegions[r].dstSubresource, pCopyImageInfo->pRegions[r].dstOffset,
639 dst_extent);
640 } else {
641 radv_meta_decode_etc(cmd_buffer, dst_image, pCopyImageInfo->dstImageLayout,
642 &pCopyImageInfo->pRegions[r].dstSubresource, pCopyImageInfo->pRegions[r].dstOffset,
643 dst_extent);
644 }
645 }
646 }
647 }
648