From 749265da0db945d0d84faa6226a59669e84a7994 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Fri, 16 May 2025 15:59:05 -0700 Subject: [PATCH] vulkan/wsi: split cmd record for img2buf blit and img2img blit There's no behavior change, but to prepare for the next img2buf blit improvement, except adding asserts to make clear of the existing blit code paths. v2: use switch with unreachable default per @gfxstrand has suggested Reviewed-by: Faith Ekstrand Part-of: --- src/vulkan/wsi/wsi_common.c | 292 ++++++++++++++++++++++-------------- 1 file changed, 179 insertions(+), 113 deletions(-) diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c index 4fa9991caab..6689b323ac0 100644 --- a/src/vulkan/wsi/wsi_common.c +++ b/src/vulkan/wsi/wsi_common.c @@ -1919,6 +1919,169 @@ wsi_label_cmd_buffer(const struct wsi_device *wsi, VkDevice device, VkCommandBuf wsi->SetDebugUtilsObjectNameEXT(device, &name_info); } +static void +wsi_cmd_blit_image_to_buffer(VkCommandBuffer cmd_buffer, + const struct wsi_device *wsi, + const struct wsi_image_info *info, + struct wsi_image *image) +{ + assert(info->image_type == WSI_IMAGE_TYPE_CPU || + info->image_type == WSI_IMAGE_TYPE_DRM); + + VkImageMemoryBarrier img_mem_barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = NULL, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image->image, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + wsi->CmdPipelineBarrier(cmd_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, NULL, + 0, NULL, + 1, &img_mem_barrier); + + struct VkBufferImageCopy buffer_image_copy = { + .bufferOffset = 0, + .bufferRowLength = info->linear_stride / + vk_format_get_blocksize(info->create.format), + .bufferImageHeight = 0, + .imageSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .imageOffset = { .x = 0, .y = 0, .z = 0 }, + .imageExtent = info->create.extent, + }; + wsi->CmdCopyImageToBuffer(cmd_buffer, + image->image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image->blit.buffer, + 1, &buffer_image_copy); + + img_mem_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + img_mem_barrier.dstAccessMask = 0; + img_mem_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + img_mem_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + wsi->CmdPipelineBarrier(cmd_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, NULL, + 0, NULL, + 1, &img_mem_barrier); +} + +static void +wsi_cmd_blit_image_to_image(VkCommandBuffer cmd_buffer, + const struct wsi_device *wsi, + const struct wsi_image_info *info, + struct wsi_image *image) +{ + assert(info->image_type == WSI_IMAGE_TYPE_DXGI); + + VkImageMemoryBarrier img_mem_barriers[2] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = NULL, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image->image, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = NULL, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image->blit.image, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }, + }; + wsi->CmdPipelineBarrier(cmd_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, NULL, + 0, NULL, + 2, img_mem_barriers); + + const struct VkImageCopy image_copy = { + .srcSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .srcOffset = { .x = 0, .y = 0, .z = 0 }, + .dstSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .dstOffset = { .x = 0, .y = 0, .z = 0 }, + .extent = info->create.extent, + }; + wsi->CmdCopyImage(cmd_buffer, + image->image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image->blit.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &image_copy); + + img_mem_barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + img_mem_barriers[0].dstAccessMask = 0; + img_mem_barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + img_mem_barriers[0].newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + img_mem_barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + img_mem_barriers[1].dstAccessMask = 0; + img_mem_barriers[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + img_mem_barriers[1].newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + wsi->CmdPipelineBarrier(cmd_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, NULL, + 0, NULL, + 2, img_mem_barriers); +} + VkResult wsi_finish_create_blit_context(const struct wsi_swapchain *chain, const struct wsi_image_info *info, @@ -1947,130 +2110,33 @@ wsi_finish_create_blit_context(const struct wsi_swapchain *chain, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1, }; + VkCommandBuffer cmd_buffer; result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info, - &image->blit.cmd_buffers[i]); + &cmd_buffer); if (result != VK_SUCCESS) return result; - wsi_label_cmd_buffer(wsi, chain->device, image->blit.cmd_buffers[i], "wsi blit"); + image->blit.cmd_buffers[i] = cmd_buffer; + + wsi_label_cmd_buffer(wsi, chain->device, cmd_buffer, "wsi blit"); const VkCommandBufferBeginInfo begin_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, }; - wsi->BeginCommandBuffer(image->blit.cmd_buffers[i], &begin_info); + wsi->BeginCommandBuffer(cmd_buffer, &begin_info); - VkImageMemoryBarrier img_mem_barriers[] = { - { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = NULL, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, - .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image->image, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }, - { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = NULL, - .srcAccessMask = 0, - .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image->blit.image, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }, - }; - uint32_t img_mem_barrier_count = - chain->blit.type == WSI_SWAPCHAIN_BUFFER_BLIT ? 1 : 2; - wsi->CmdPipelineBarrier(image->blit.cmd_buffers[i], - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, - 0, NULL, - 0, NULL, - img_mem_barrier_count, img_mem_barriers); - - if (chain->blit.type == WSI_SWAPCHAIN_BUFFER_BLIT) { - struct VkBufferImageCopy buffer_image_copy = { - .bufferOffset = 0, - .bufferRowLength = info->linear_stride / - vk_format_get_blocksize(info->create.format), - .bufferImageHeight = 0, - .imageSubresource = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .imageOffset = { .x = 0, .y = 0, .z = 0 }, - .imageExtent = info->create.extent, - }; - wsi->CmdCopyImageToBuffer(image->blit.cmd_buffers[i], - image->image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image->blit.buffer, - 1, &buffer_image_copy); - } else { - struct VkImageCopy image_copy = { - .srcSubresource = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .srcOffset = { .x = 0, .y = 0, .z = 0 }, - .dstSubresource = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .dstOffset = { .x = 0, .y = 0, .z = 0 }, - .extent = info->create.extent, - }; - - wsi->CmdCopyImage(image->blit.cmd_buffers[i], - image->image, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image->blit.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &image_copy); + switch (chain->blit.type) { + case WSI_SWAPCHAIN_BUFFER_BLIT: + wsi_cmd_blit_image_to_buffer(cmd_buffer, wsi, info, image); + break; + case WSI_SWAPCHAIN_IMAGE_BLIT: + wsi_cmd_blit_image_to_image(cmd_buffer, wsi, info, image); + break; + default: + unreachable("Invalid wsi_swapchain_blit_type"); } - img_mem_barriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - img_mem_barriers[0].dstAccessMask = 0; - img_mem_barriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - img_mem_barriers[0].newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - img_mem_barriers[1].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - img_mem_barriers[1].dstAccessMask = 0; - img_mem_barriers[1].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - img_mem_barriers[1].newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - wsi->CmdPipelineBarrier(image->blit.cmd_buffers[i], - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, NULL, - 0, NULL, - img_mem_barrier_count, img_mem_barriers); - - result = wsi->EndCommandBuffer(image->blit.cmd_buffers[i]); + result = wsi->EndCommandBuffer(cmd_buffer); if (result != VK_SUCCESS) return result; }