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