From: Samuel Pitoiset Date: Tue, 22 Sep 2020 08:40:51 +0000 (+0200) Subject: radv: add support for CmdResolveImage2KHR() X-Git-Tag: upstream/21.0.0~5155 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0401507b77db041cf1364dfd37973bf3bd2597e0;p=platform%2Fupstream%2Fmesa.git radv: add support for CmdResolveImage2KHR() Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Part-of: --- diff --git a/src/amd/vulkan/radv_meta.h b/src/amd/vulkan/radv_meta.h index f799467..aaf569c 100644 --- a/src/amd/vulkan/radv_meta.h +++ b/src/amd/vulkan/radv_meta.h @@ -219,24 +219,21 @@ void radv_meta_resolve_compute_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *dest_image, VkFormat dest_format, VkImageLayout dest_image_layout, - uint32_t region_count, - const VkImageResolve *regions); + const VkImageResolve2KHR *region); void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkImageLayout src_image_layout, struct radv_image *dest_image, VkImageLayout dest_image_layout, - uint32_t region_count, - const VkImageResolve *regions); + const VkImageResolve2KHR *region); void radv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer); void radv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkImageLayout src_image_layout, - uint32_t region_count, - const VkImageResolve *regions); + const VkImageResolve2KHR *region); uint32_t radv_clear_cmask(struct radv_cmd_buffer *cmd_buffer, struct radv_image *image, diff --git a/src/amd/vulkan/radv_meta_resolve.c b/src/amd/vulkan/radv_meta_resolve.c index 9d5a306..1318ff1 100644 --- a/src/amd/vulkan/radv_meta_resolve.c +++ b/src/amd/vulkan/radv_meta_resolve.c @@ -426,7 +426,7 @@ radv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, VkImageLayout src_image_layout, struct radv_image *dst_image, VkImageLayout dst_image_layout, - const VkImageResolve *region) + const VkImageResolve2KHR *region) { struct radv_device *device = cmd_buffer->device; struct radv_meta_saved_state saved_state; @@ -599,6 +599,47 @@ radv_meta_resolve_hardware_image(struct radv_cmd_buffer *cmd_buffer, radv_meta_restore(&saved_state, cmd_buffer); } +static void +resolve_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 VkImageResolve2KHR *region, + enum radv_resolve_method resolve_method) +{ + switch (resolve_method) { + case RESOLVE_HW: + radv_meta_resolve_hardware_image(cmd_buffer, + src_image, + src_image_layout, + dst_image, + dst_image_layout, + region); + break; + case RESOLVE_FRAGMENT: + radv_meta_resolve_fragment_image(cmd_buffer, + src_image, + src_image_layout, + dst_image, + dst_image_layout, + region); + break; + case RESOLVE_COMPUTE: + radv_meta_resolve_compute_image(cmd_buffer, + src_image, + src_image->vk_format, + src_image_layout, + dst_image, + dst_image->vk_format, + dst_image_layout, + region); + break; + default: + assert(!"Invalid resolve method selected"); + } +} + void radv_CmdResolveImage( VkCommandBuffer cmd_buffer_h, VkImage src_image_h, @@ -635,36 +676,59 @@ void radv_CmdResolveImage( dest_image_layout, false, cmd_buffer, &resolve_method); - switch (resolve_method) { - case RESOLVE_HW: - assert(region_count == 1); - radv_meta_resolve_hardware_image(cmd_buffer, - src_image, - src_image_layout, - dest_image, - dest_image_layout, - ®ions[0]); - break; - case RESOLVE_FRAGMENT: - radv_meta_resolve_fragment_image(cmd_buffer, - src_image, - src_image_layout, - dest_image, - dest_image_layout, - region_count, regions); - break; - case RESOLVE_COMPUTE: - radv_meta_resolve_compute_image(cmd_buffer, - src_image, - src_image->vk_format, - src_image_layout, - dest_image, - dest_image->vk_format, - dest_image_layout, - region_count, regions); - break; - default: - assert(!"Invalid resolve method selected"); + for (uint32_t r = 0; r < region_count; r++) { + VkImageResolve2KHR region = { + .sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR, + .srcSubresource = regions[r].srcSubresource, + .srcOffset = regions[r].srcOffset, + .dstSubresource = regions[r].dstSubresource, + .dstOffset = regions[r].dstOffset, + .extent = regions[r].extent, + }; + + resolve_image(cmd_buffer, src_image, src_image_layout, + dest_image, dest_image_layout, + ®ion, resolve_method); + } +} + +void radv_CmdResolveImage2KHR( + VkCommandBuffer commandBuffer, + const VkResolveImageInfo2KHR* pResolveImageInfo) +{ + RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer); + RADV_FROM_HANDLE(radv_image, src_image, pResolveImageInfo->srcImage); + RADV_FROM_HANDLE(radv_image, dst_image, pResolveImageInfo->dstImage); + VkImageLayout src_image_layout = pResolveImageInfo->srcImageLayout; + VkImageLayout dst_image_layout = pResolveImageInfo->dstImageLayout; + enum radv_resolve_method resolve_method = RESOLVE_HW; + /* we can use the hw resolve only for single full resolves */ + if (pResolveImageInfo->regionCount == 1) { + if (pResolveImageInfo->pRegions[0].srcOffset.x || + pResolveImageInfo->pRegions[0].srcOffset.y || + pResolveImageInfo->pRegions[0].srcOffset.z) + resolve_method = RESOLVE_COMPUTE; + if (pResolveImageInfo->pRegions[0].dstOffset.x || + pResolveImageInfo->pRegions[0].dstOffset.y || + pResolveImageInfo->pRegions[0].dstOffset.z) + resolve_method = RESOLVE_COMPUTE; + + if (pResolveImageInfo->pRegions[0].extent.width != src_image->info.width || + pResolveImageInfo->pRegions[0].extent.height != src_image->info.height || + pResolveImageInfo->pRegions[0].extent.depth != src_image->info.depth) + resolve_method = RESOLVE_COMPUTE; + } else + resolve_method = RESOLVE_COMPUTE; + + radv_pick_resolve_method_images(cmd_buffer->device, src_image, + src_image->vk_format, dst_image, + dst_image_layout, false, cmd_buffer, + &resolve_method); + + for (uint32_t r = 0; r < pResolveImageInfo->regionCount; r++) { + resolve_image(cmd_buffer, src_image, src_image_layout, + dst_image, dst_image_layout, + &pResolveImageInfo->pRegions[r], resolve_method); } } @@ -839,14 +903,15 @@ radv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer) struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; struct radv_image *src_image = src_iview->image; - VkImageResolve region = {}; + VkImageResolve2KHR region = {}; + region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR; region.srcSubresource.aspectMask = src_iview->aspect_mask; region.srcSubresource.mipLevel = 0; region.srcSubresource.baseArrayLayer = src_iview->base_layer; region.srcSubresource.layerCount = layer_count; radv_decompress_resolve_src(cmd_buffer, src_image, - src_att.layout, 1, ®ion); + src_att.layout, ®ion); } if (subpass->ds_resolve_attachment) { @@ -854,14 +919,15 @@ radv_decompress_resolve_subpass_src(struct radv_cmd_buffer *cmd_buffer) struct radv_image_view *src_iview = fb->attachments[src_att.attachment]; struct radv_image *src_image = src_iview->image; - VkImageResolve region = {}; + VkImageResolve2KHR region = {}; + region.sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR; region.srcSubresource.aspectMask = src_iview->aspect_mask; region.srcSubresource.mipLevel = 0; region.srcSubresource.baseArrayLayer = src_iview->base_layer; region.srcSubresource.layerCount = layer_count; radv_decompress_resolve_src(cmd_buffer, src_image, - src_att.layout, 1, ®ion); + src_att.layout, ®ion); } } @@ -886,48 +952,44 @@ void radv_decompress_resolve_src(struct radv_cmd_buffer *cmd_buffer, struct radv_image *src_image, VkImageLayout src_image_layout, - uint32_t region_count, - const VkImageResolve *regions) + const VkImageResolve2KHR *region) { - for (uint32_t r = 0; r < region_count; ++r) { - const VkImageResolve *region = ®ions[r]; - const uint32_t src_base_layer = - radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, - ®ion->srcOffset); - - VkImageMemoryBarrier barrier = {}; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.oldLayout = src_image_layout; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.image = radv_image_to_handle(src_image); - barrier.subresourceRange = (VkImageSubresourceRange) { - .aspectMask = region->srcSubresource.aspectMask, - .baseMipLevel = region->srcSubresource.mipLevel, - .levelCount = 1, - .baseArrayLayer = src_base_layer, - .layerCount = region->srcSubresource.layerCount, - }; + const uint32_t src_base_layer = + radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, + ®ion->srcOffset); - if (src_image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) { - /* If the depth/stencil image uses different sample - * locations, we need them during HTILE decompressions. - */ - struct radv_sample_locations_state *sample_locs = - radv_get_resolve_sample_locations(cmd_buffer); - - barrier.pNext = &(VkSampleLocationsInfoEXT) { - .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, - .sampleLocationsPerPixel = sample_locs->per_pixel, - .sampleLocationGridSize = sample_locs->grid_size, - .sampleLocationsCount = sample_locs->count, - .pSampleLocations = sample_locs->locations, - }; - } + VkImageMemoryBarrier barrier = {}; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.oldLayout = src_image_layout; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.image = radv_image_to_handle(src_image); + barrier.subresourceRange = (VkImageSubresourceRange) { + .aspectMask = region->srcSubresource.aspectMask, + .baseMipLevel = region->srcSubresource.mipLevel, + .levelCount = 1, + .baseArrayLayer = src_base_layer, + .layerCount = region->srcSubresource.layerCount, + }; - radv_CmdPipelineBarrier(radv_cmd_buffer_to_handle(cmd_buffer), - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - false, 0, NULL, 0, NULL, 1, &barrier); + if (src_image->flags & VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT) { + /* If the depth/stencil image uses different sample + * locations, we need them during HTILE decompressions. + */ + struct radv_sample_locations_state *sample_locs = + radv_get_resolve_sample_locations(cmd_buffer); + + barrier.pNext = &(VkSampleLocationsInfoEXT) { + .sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, + .sampleLocationsPerPixel = sample_locs->per_pixel, + .sampleLocationGridSize = sample_locs->grid_size, + .sampleLocationsCount = sample_locs->count, + .pSampleLocations = sample_locs->locations, + }; } + + radv_CmdPipelineBarrier(radv_cmd_buffer_to_handle(cmd_buffer), + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + false, 0, NULL, 0, NULL, 1, &barrier); } diff --git a/src/amd/vulkan/radv_meta_resolve_cs.c b/src/amd/vulkan/radv_meta_resolve_cs.c index e1e3077..a5b5c32 100644 --- a/src/amd/vulkan/radv_meta_resolve_cs.c +++ b/src/amd/vulkan/radv_meta_resolve_cs.c @@ -811,84 +811,80 @@ void radv_meta_resolve_compute_image(struct radv_cmd_buffer *cmd_buffer, struct radv_image *dest_image, VkFormat dest_format, VkImageLayout dest_image_layout, - uint32_t region_count, - const VkImageResolve *regions) + const VkImageResolve2KHR *region) { struct radv_meta_saved_state saved_state; radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, - region_count, regions); + region); radv_meta_save(&saved_state, cmd_buffer, RADV_META_SAVE_COMPUTE_PIPELINE | RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS); - for (uint32_t r = 0; r < region_count; ++r) { - const VkImageResolve *region = ®ions[r]; - - assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); - assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); - assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount); - - const uint32_t src_base_layer = - radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, - ®ion->srcOffset); - - const uint32_t dest_base_layer = - radv_meta_get_iview_layer(dest_image, ®ion->dstSubresource, - ®ion->dstOffset); - - const struct VkExtent3D extent = - radv_sanitize_image_extent(src_image->type, region->extent); - const struct VkOffset3D srcOffset = - radv_sanitize_image_offset(src_image->type, region->srcOffset); - const struct VkOffset3D dstOffset = - radv_sanitize_image_offset(dest_image->type, region->dstOffset); - - for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; - ++layer) { - - struct radv_image_view src_iview; - radv_image_view_init(&src_iview, cmd_buffer->device, - &(VkImageViewCreateInfo) { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = radv_image_to_handle(src_image), - .viewType = radv_meta_get_view_type(src_image), - .format = src_format, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = region->srcSubresource.mipLevel, - .levelCount = 1, - .baseArrayLayer = src_base_layer + layer, - .layerCount = 1, - }, - }, NULL); - - struct radv_image_view dest_iview; - radv_image_view_init(&dest_iview, cmd_buffer->device, - &(VkImageViewCreateInfo) { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = radv_image_to_handle(dest_image), - .viewType = radv_meta_get_view_type(dest_image), - .format = vk_to_non_srgb_format(dest_format), - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = region->dstSubresource.mipLevel, - .levelCount = 1, - .baseArrayLayer = dest_base_layer + layer, - .layerCount = 1, - }, - }, NULL); - - emit_resolve(cmd_buffer, - &src_iview, - &dest_iview, - &(VkOffset2D) {srcOffset.x, srcOffset.y }, - &(VkOffset2D) {dstOffset.x, dstOffset.y }, - &(VkExtent2D) {extent.width, extent.height }); - } + assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); + assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); + assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount); + + const uint32_t src_base_layer = + radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, + ®ion->srcOffset); + + const uint32_t dest_base_layer = + radv_meta_get_iview_layer(dest_image, ®ion->dstSubresource, + ®ion->dstOffset); + + const struct VkExtent3D extent = + radv_sanitize_image_extent(src_image->type, region->extent); + const struct VkOffset3D srcOffset = + radv_sanitize_image_offset(src_image->type, region->srcOffset); + const struct VkOffset3D dstOffset = + radv_sanitize_image_offset(dest_image->type, region->dstOffset); + + for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; + ++layer) { + + struct radv_image_view src_iview; + radv_image_view_init(&src_iview, cmd_buffer->device, + &(VkImageViewCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = radv_image_to_handle(src_image), + .viewType = radv_meta_get_view_type(src_image), + .format = src_format, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = region->srcSubresource.mipLevel, + .levelCount = 1, + .baseArrayLayer = src_base_layer + layer, + .layerCount = 1, + }, + }, NULL); + + struct radv_image_view dest_iview; + radv_image_view_init(&dest_iview, cmd_buffer->device, + &(VkImageViewCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = radv_image_to_handle(dest_image), + .viewType = radv_meta_get_view_type(dest_image), + .format = vk_to_non_srgb_format(dest_format), + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = region->dstSubresource.mipLevel, + .levelCount = 1, + .baseArrayLayer = dest_base_layer + layer, + .layerCount = 1, + }, + }, NULL); + + emit_resolve(cmd_buffer, + &src_iview, + &dest_iview, + &(VkOffset2D) {srcOffset.x, srcOffset.y }, + &(VkOffset2D) {dstOffset.x, dstOffset.y }, + &(VkExtent2D) {extent.width, extent.height }); } + radv_meta_restore(&saved_state, cmd_buffer); } @@ -924,7 +920,8 @@ radv_cmd_buffer_resolve_subpass_cs(struct radv_cmd_buffer *cmd_buffer) struct radv_image_view *src_iview = cmd_buffer->state.attachments[src_att.attachment].iview; struct radv_image_view *dst_iview = cmd_buffer->state.attachments[dst_att.attachment].iview; - VkImageResolve region = { + VkImageResolve2KHR region = { + .sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR, .extent = (VkExtent3D){ fb->width, fb->height, 0 }, .srcSubresource = (VkImageSubresourceLayers) { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, @@ -949,7 +946,7 @@ radv_cmd_buffer_resolve_subpass_cs(struct radv_cmd_buffer *cmd_buffer) dst_iview->image, dst_iview->vk_format, dst_att.layout, - 1, ®ion); + ®ion); } cmd_buffer->state.flush_bits |= RADV_CMD_FLAG_CS_PARTIAL_FLUSH | diff --git a/src/amd/vulkan/radv_meta_resolve_fs.c b/src/amd/vulkan/radv_meta_resolve_fs.c index 12ff91a..c60d5eb 100644 --- a/src/amd/vulkan/radv_meta_resolve_fs.c +++ b/src/amd/vulkan/radv_meta_resolve_fs.c @@ -1027,8 +1027,7 @@ void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, VkImageLayout src_image_layout, struct radv_image *dest_image, VkImageLayout dest_image_layout, - uint32_t region_count, - const VkImageResolve *regions) + const VkImageResolve2KHR *region) { struct radv_device *device = cmd_buffer->device; struct radv_meta_saved_state saved_state; @@ -1039,7 +1038,7 @@ void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, VkRenderPass rp; radv_decompress_resolve_src(cmd_buffer, src_image, src_image_layout, - region_count, regions); + region); if (!device->meta_state.resolve_fragment.rc[samples_log2].render_pass[fs_key][dst_layout]) { VkResult ret = create_resolve_pipeline(device, samples_log2, radv_fs_key_format_exemplars[fs_key]); @@ -1056,104 +1055,100 @@ void radv_meta_resolve_fragment_image(struct radv_cmd_buffer *cmd_buffer, RADV_META_SAVE_CONSTANTS | RADV_META_SAVE_DESCRIPTORS); - for (uint32_t r = 0; r < region_count; ++r) { - const VkImageResolve *region = ®ions[r]; - - assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); - assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); - assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount); - - const uint32_t src_base_layer = - radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, - ®ion->srcOffset); - - const uint32_t dest_base_layer = - radv_meta_get_iview_layer(dest_image, ®ion->dstSubresource, - ®ion->dstOffset); - - const struct VkExtent3D extent = - radv_sanitize_image_extent(src_image->type, region->extent); - const struct VkOffset3D srcOffset = - radv_sanitize_image_offset(src_image->type, region->srcOffset); - const struct VkOffset3D dstOffset = - radv_sanitize_image_offset(dest_image->type, region->dstOffset); - - for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; - ++layer) { - - struct radv_image_view src_iview; - radv_image_view_init(&src_iview, cmd_buffer->device, - &(VkImageViewCreateInfo) { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = radv_image_to_handle(src_image), - .viewType = radv_meta_get_view_type(src_image), - .format = src_image->vk_format, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = region->srcSubresource.mipLevel, - .levelCount = 1, - .baseArrayLayer = src_base_layer + layer, - .layerCount = 1, - }, - }, NULL); - - struct radv_image_view dest_iview; - radv_image_view_init(&dest_iview, cmd_buffer->device, - &(VkImageViewCreateInfo) { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = radv_image_to_handle(dest_image), - .viewType = radv_meta_get_view_type(dest_image), - .format = dest_image->vk_format, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = region->dstSubresource.mipLevel, - .levelCount = 1, - .baseArrayLayer = dest_base_layer + layer, - .layerCount = 1, - }, - }, NULL); - - - VkFramebuffer fb; - radv_CreateFramebuffer(radv_device_to_handle(cmd_buffer->device), - &(VkFramebufferCreateInfo) { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = (VkImageView[]) { - radv_image_view_to_handle(&dest_iview), - }, - .width = extent.width + dstOffset.x, - .height = extent.height + dstOffset.y, - .layers = 1 - }, &cmd_buffer->pool->alloc, &fb); - - radv_cmd_buffer_begin_render_pass(cmd_buffer, - &(VkRenderPassBeginInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = rp, - .framebuffer = fb, - .renderArea = { - .offset = { dstOffset.x, dstOffset.y, }, - .extent = { extent.width, extent.height }, - }, - .clearValueCount = 0, - .pClearValues = NULL, - }); - - radv_cmd_buffer_set_subpass(cmd_buffer, - &cmd_buffer->state.pass->subpasses[0]); - - emit_resolve(cmd_buffer, - &src_iview, - &dest_iview, - &(VkOffset2D) { srcOffset.x, srcOffset.y }, - &(VkOffset2D) { dstOffset.x, dstOffset.y }, - &(VkExtent2D) { extent.width, extent.height }); - - radv_cmd_buffer_end_render_pass(cmd_buffer); - - radv_DestroyFramebuffer(radv_device_to_handle(cmd_buffer->device), fb, &cmd_buffer->pool->alloc); - } + assert(region->srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); + assert(region->dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT); + assert(region->srcSubresource.layerCount == region->dstSubresource.layerCount); + + const uint32_t src_base_layer = + radv_meta_get_iview_layer(src_image, ®ion->srcSubresource, + ®ion->srcOffset); + + const uint32_t dest_base_layer = + radv_meta_get_iview_layer(dest_image, ®ion->dstSubresource, + ®ion->dstOffset); + + const struct VkExtent3D extent = + radv_sanitize_image_extent(src_image->type, region->extent); + const struct VkOffset3D srcOffset = + radv_sanitize_image_offset(src_image->type, region->srcOffset); + const struct VkOffset3D dstOffset = + radv_sanitize_image_offset(dest_image->type, region->dstOffset); + + for (uint32_t layer = 0; layer < region->srcSubresource.layerCount; + ++layer) { + + struct radv_image_view src_iview; + radv_image_view_init(&src_iview, cmd_buffer->device, + &(VkImageViewCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = radv_image_to_handle(src_image), + .viewType = radv_meta_get_view_type(src_image), + .format = src_image->vk_format, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = region->srcSubresource.mipLevel, + .levelCount = 1, + .baseArrayLayer = src_base_layer + layer, + .layerCount = 1, + }, + }, NULL); + + struct radv_image_view dest_iview; + radv_image_view_init(&dest_iview, cmd_buffer->device, + &(VkImageViewCreateInfo) { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .image = radv_image_to_handle(dest_image), + .viewType = radv_meta_get_view_type(dest_image), + .format = dest_image->vk_format, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = region->dstSubresource.mipLevel, + .levelCount = 1, + .baseArrayLayer = dest_base_layer + layer, + .layerCount = 1, + }, + }, NULL); + + + VkFramebuffer fb; + radv_CreateFramebuffer(radv_device_to_handle(cmd_buffer->device), + &(VkFramebufferCreateInfo) { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = (VkImageView[]) { + radv_image_view_to_handle(&dest_iview), + }, + .width = extent.width + dstOffset.x, + .height = extent.height + dstOffset.y, + .layers = 1 + }, &cmd_buffer->pool->alloc, &fb); + + radv_cmd_buffer_begin_render_pass(cmd_buffer, + &(VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = rp, + .framebuffer = fb, + .renderArea = { + .offset = { dstOffset.x, dstOffset.y, }, + .extent = { extent.width, extent.height }, + }, + .clearValueCount = 0, + .pClearValues = NULL, + }); + + radv_cmd_buffer_set_subpass(cmd_buffer, + &cmd_buffer->state.pass->subpasses[0]); + + emit_resolve(cmd_buffer, + &src_iview, + &dest_iview, + &(VkOffset2D) { srcOffset.x, srcOffset.y }, + &(VkOffset2D) { dstOffset.x, dstOffset.y }, + &(VkExtent2D) { extent.width, extent.height }); + + radv_cmd_buffer_end_render_pass(cmd_buffer); + + radv_DestroyFramebuffer(radv_device_to_handle(cmd_buffer->device), fb, &cmd_buffer->pool->alloc); } radv_meta_restore(&saved_state, cmd_buffer);