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