radv: cleanup selecting the hardware resolve path
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6813>
diff --git a/src/amd/vulkan/radv_meta_resolve.c b/src/amd/vulkan/radv_meta_resolve.c
index 0a03e62..9d5a306 100644
--- a/src/amd/vulkan/radv_meta_resolve.c
+++ b/src/amd/vulkan/radv_meta_resolve.c
@@ -420,6 +420,185 @@
return result;
}
+static void
+radv_meta_resolve_hardware_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 VkImageResolve *region)
+{
+ struct radv_device *device = cmd_buffer->device;
+ struct radv_meta_saved_state saved_state;
+
+ radv_meta_save(&saved_state, cmd_buffer,
+ RADV_META_SAVE_GRAPHICS_PIPELINE);
+
+ assert(src_image->info.samples > 1);
+ if (src_image->info.samples <= 1) {
+ /* this causes GPU hangs if we get past here */
+ fprintf(stderr, "radv: Illegal resolve operation (src not multisampled), will hang GPU.");
+ return;
+ }
+ assert(dst_image->info.samples == 1);
+
+ if (src_image->info.array_size > 1)
+ radv_finishme("vkCmdResolveImage: multisample array images");
+
+ unsigned fs_key = radv_format_meta_fs_key(dst_image->vk_format);
+
+ /* From the Vulkan 1.0 spec:
+ *
+ * - The aspectMask member of srcSubresource and dstSubresource must
+ * only contain VK_IMAGE_ASPECT_COLOR_BIT
+ *
+ * - The layerCount member of srcSubresource and dstSubresource must
+ * match
+ */
+ 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 dst_base_layer =
+ radv_meta_get_iview_layer(dst_image, ®ion->dstSubresource,
+ ®ion->dstOffset);
+
+ /**
+ * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
+ *
+ * extent is the size in texels of the source image to resolve in width,
+ * height and depth. 1D images use only x and width. 2D images use x, y,
+ * width and height. 3D images use x, y, z, width, height and depth.
+ *
+ * srcOffset and dstOffset select the initial x, y, and z offsets in
+ * texels of the sub-regions of the source and destination image data.
+ * extent is the size in texels of the source image to resolve in width,
+ * height and depth. 1D images use only x and width. 2D images use x, y,
+ * width and height. 3D images use x, y, z, width, height and depth.
+ */
+ const struct VkExtent3D extent =
+ radv_sanitize_image_extent(src_image->type, region->extent);
+ const struct VkOffset3D dstOffset =
+ radv_sanitize_image_offset(dst_image->type, region->dstOffset);
+
+ if (radv_dcc_enabled(dst_image, region->dstSubresource.mipLevel)) {
+ VkImageSubresourceRange range = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = region->dstSubresource.mipLevel,
+ .levelCount = 1,
+ .baseArrayLayer = dst_base_layer,
+ .layerCount = region->dstSubresource.layerCount,
+ };
+
+ radv_initialize_dcc(cmd_buffer, dst_image, &range, 0xffffffff);
+ }
+
+ for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
+ ++layer) {
+
+ VkResult ret = build_resolve_pipeline(device, fs_key);
+ if (ret != VK_SUCCESS) {
+ cmd_buffer->record_result = ret;
+ break;
+ }
+
+ 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 dst_iview;
+ radv_image_view_init(&dst_iview, cmd_buffer->device,
+ &(VkImageViewCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ .image = radv_image_to_handle(dst_image),
+ .viewType = radv_meta_get_view_type(dst_image),
+ .format = dst_image->vk_format,
+ .subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+ .baseMipLevel = region->dstSubresource.mipLevel,
+ .levelCount = 1,
+ .baseArrayLayer = dst_base_layer + layer,
+ .layerCount = 1,
+ },
+ }, NULL);
+
+ VkFramebuffer fb_h;
+ radv_CreateFramebuffer(radv_device_to_handle(device),
+ &(VkFramebufferCreateInfo) {
+ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ .attachmentCount = 2,
+ .pAttachments = (VkImageView[]) {
+ radv_image_view_to_handle(&src_iview),
+ radv_image_view_to_handle(&dst_iview),
+ },
+ .width = radv_minify(dst_image->info.width,
+ region->dstSubresource.mipLevel),
+ .height = radv_minify(dst_image->info.height,
+ region->dstSubresource.mipLevel),
+ .layers = 1
+ },
+ &cmd_buffer->pool->alloc,
+ &fb_h);
+
+ radv_cmd_buffer_begin_render_pass(cmd_buffer,
+ &(VkRenderPassBeginInfo) {
+ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ .renderPass = device->meta_state.resolve.pass[fs_key],
+ .framebuffer = fb_h,
+ .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,
+ dst_iview.vk_format,
+ &(VkOffset2D) {
+ .x = dstOffset.x,
+ .y = dstOffset.y,
+ },
+ &(VkExtent2D) {
+ .width = extent.width,
+ .height = extent.height,
+ });
+
+ radv_cmd_buffer_end_render_pass(cmd_buffer);
+
+ radv_DestroyFramebuffer(radv_device_to_handle(device),
+ fb_h, &cmd_buffer->pool->alloc);
+ }
+
+ radv_meta_restore(&saved_state, cmd_buffer);
+}
+
void radv_CmdResolveImage(
VkCommandBuffer cmd_buffer_h,
VkImage src_image_h,
@@ -432,9 +611,6 @@
RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, cmd_buffer_h);
RADV_FROM_HANDLE(radv_image, src_image, src_image_h);
RADV_FROM_HANDLE(radv_image, dest_image, dest_image_h);
- struct radv_device *device = cmd_buffer->device;
- struct radv_meta_saved_state saved_state;
- VkDevice device_h = radv_device_to_handle(device);
enum radv_resolve_method resolve_method = RESOLVE_HW;
/* we can use the hw resolve only for single full resolves */
if (region_count == 1) {
@@ -459,17 +635,25 @@
dest_image_layout, false, cmd_buffer,
&resolve_method);
- if (resolve_method == RESOLVE_FRAGMENT) {
+ 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);
- return;
- }
-
- if (resolve_method == RESOLVE_COMPUTE) {
+ break;
+ case RESOLVE_COMPUTE:
radv_meta_resolve_compute_image(cmd_buffer,
src_image,
src_image->vk_format,
@@ -478,178 +662,10 @@
dest_image->vk_format,
dest_image_layout,
region_count, regions);
- return;
+ break;
+ default:
+ assert(!"Invalid resolve method selected");
}
-
- radv_meta_save(&saved_state, cmd_buffer,
- RADV_META_SAVE_GRAPHICS_PIPELINE);
-
- assert(src_image->info.samples > 1);
- if (src_image->info.samples <= 1) {
- /* this causes GPU hangs if we get past here */
- fprintf(stderr, "radv: Illegal resolve operation (src not multisampled), will hang GPU.");
- return;
- }
- assert(dest_image->info.samples == 1);
-
- if (src_image->info.array_size > 1)
- radv_finishme("vkCmdResolveImage: multisample array images");
-
- unsigned fs_key = radv_format_meta_fs_key(dest_image->vk_format);
- for (uint32_t r = 0; r < region_count; ++r) {
- const VkImageResolve *region = ®ions[r];
-
- /* From the Vulkan 1.0 spec:
- *
- * - The aspectMask member of srcSubresource and dstSubresource must
- * only contain VK_IMAGE_ASPECT_COLOR_BIT
- *
- * - The layerCount member of srcSubresource and dstSubresource must
- * match
- */
- 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);
-
- /**
- * From Vulkan 1.0.6 spec: 18.6 Resolving Multisample Images
- *
- * extent is the size in texels of the source image to resolve in width,
- * height and depth. 1D images use only x and width. 2D images use x, y,
- * width and height. 3D images use x, y, z, width, height and depth.
- *
- * srcOffset and dstOffset select the initial x, y, and z offsets in
- * texels of the sub-regions of the source and destination image data.
- * extent is the size in texels of the source image to resolve in width,
- * height and depth. 1D images use only x and width. 2D images use x, y,
- * width and height. 3D images use x, y, z, width, height and depth.
- */
- const struct VkExtent3D extent =
- radv_sanitize_image_extent(src_image->type, region->extent);
- const struct VkOffset3D dstOffset =
- radv_sanitize_image_offset(dest_image->type, region->dstOffset);
-
- if (radv_dcc_enabled(dest_image, region->dstSubresource.mipLevel)) {
- VkImageSubresourceRange range = {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = region->dstSubresource.mipLevel,
- .levelCount = 1,
- .baseArrayLayer = dest_base_layer,
- .layerCount = region->dstSubresource.layerCount,
- };
-
- radv_initialize_dcc(cmd_buffer, dest_image, &range, 0xffffffff);
- }
-
- for (uint32_t layer = 0; layer < region->srcSubresource.layerCount;
- ++layer) {
-
- VkResult ret = build_resolve_pipeline(device, fs_key);
- if (ret != VK_SUCCESS) {
- cmd_buffer->record_result = ret;
- break;
- }
-
- 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 = src_image_h,
- .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 = dest_image_h,
- .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_h;
- radv_CreateFramebuffer(device_h,
- &(VkFramebufferCreateInfo) {
- .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- .attachmentCount = 2,
- .pAttachments = (VkImageView[]) {
- radv_image_view_to_handle(&src_iview),
- radv_image_view_to_handle(&dest_iview),
- },
- .width = radv_minify(dest_image->info.width,
- region->dstSubresource.mipLevel),
- .height = radv_minify(dest_image->info.height,
- region->dstSubresource.mipLevel),
- .layers = 1
- },
- &cmd_buffer->pool->alloc,
- &fb_h);
-
- radv_cmd_buffer_begin_render_pass(cmd_buffer,
- &(VkRenderPassBeginInfo) {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
- .renderPass = device->meta_state.resolve.pass[fs_key],
- .framebuffer = fb_h,
- .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,
- dest_iview.vk_format,
- &(VkOffset2D) {
- .x = dstOffset.x,
- .y = dstOffset.y,
- },
- &(VkExtent2D) {
- .width = extent.width,
- .height = extent.height,
- });
-
- radv_cmd_buffer_end_render_pass(cmd_buffer);
-
- radv_DestroyFramebuffer(device_h, fb_h,
- &cmd_buffer->pool->alloc);
- }
- }
-
- radv_meta_restore(&saved_state, cmd_buffer);
}
/**