From 2975a7f453a03907827bbb8b38ea1394f052d045 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 27 Apr 2022 18:25:34 +0200 Subject: [PATCH] vulkan/wsi: Add support for image -> image blits The win32 swapchain can be backed by a DXGI swapchain, but such swapchains are incompatible with STORAGE images (AKA UNORDERED_ACCESS usage in DXGI). So, we need to allocate an intermediate image that will serve as a render-target, and copy this image to the WSI image when QueuePresent() is called. That's pretty similar to what we do for the buffer blit case, except the image -> buffer copy is replaced by an image -> image copy. Reviewed-by: Jesse Natalie Reviewed-by: Daniel Stone Reviewed-by: Jason Ekstrand Part-of: --- src/vulkan/wsi/wsi_common.c | 152 ++++++++++++++++++++++++++---------- src/vulkan/wsi/wsi_common.h | 1 + src/vulkan/wsi/wsi_common_private.h | 6 ++ 3 files changed, 116 insertions(+), 43 deletions(-) diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c index a6fbc01..fecc517 100644 --- a/src/vulkan/wsi/wsi_common.c +++ b/src/vulkan/wsi/wsi_common.c @@ -146,6 +146,7 @@ wsi_device_init(struct wsi_device *wsi, WSI_GET_CB(BindImageMemory); WSI_GET_CB(BeginCommandBuffer); WSI_GET_CB(CmdPipelineBarrier); + WSI_GET_CB(CmdCopyImage); WSI_GET_CB(CmdCopyImageToBuffer); WSI_GET_CB(CreateBuffer); WSI_GET_CB(CreateCommandPool); @@ -693,6 +694,7 @@ wsi_destroy_image(const struct wsi_swapchain *chain, wsi->FreeMemory(chain->device, image->memory, &chain->alloc); wsi->DestroyImage(chain->device, image->image, &chain->alloc); + wsi->DestroyImage(chain->device, image->blit.image, &chain->alloc); wsi->FreeMemory(chain->device, image->blit.memory, &chain->alloc); wsi->DestroyBuffer(chain->device, image->blit.buffer, &chain->alloc); } @@ -1533,6 +1535,8 @@ wsi_create_buffer_blit_context(const struct wsi_swapchain *chain, VkExternalMemoryHandleTypeFlags handle_types, bool implicit_sync) { + assert(chain->blit.type == WSI_SWAPCHAIN_BUFFER_BLIT); + const struct wsi_device *wsi = chain->wsi; VkResult result; @@ -1671,63 +1675,116 @@ wsi_finish_create_blit_context(const struct wsi_swapchain *chain, }; wsi->BeginCommandBuffer(image->blit.cmd_buffers[i], &begin_info); - 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, + 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, - 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(image->blit.cmd_buffers[i], - 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; + 1, 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); + } + + 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, - 1, &img_mem_barrier); + img_mem_barrier_count, img_mem_barriers); result = wsi->EndCommandBuffer(image->blit.cmd_buffers[i]); if (result != VK_SUCCESS) @@ -1768,6 +1825,15 @@ wsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain, info->finish_create = wsi_finish_create_blit_context; } +void +wsi_configure_image_blit_image(UNUSED const struct wsi_swapchain *chain, + struct wsi_image_info *info) +{ + info->create.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + info->wsi.blit_src = true; + info->finish_create = wsi_finish_create_blit_context; +} + static VkResult wsi_create_cpu_linear_image_mem(const struct wsi_swapchain *chain, const struct wsi_image_info *info, diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h index 369e6ab..22e4313 100644 --- a/src/vulkan/wsi/wsi_common.h +++ b/src/vulkan/wsi/wsi_common.h @@ -208,6 +208,7 @@ struct wsi_device { WSI_CB(BindImageMemory); WSI_CB(BeginCommandBuffer); WSI_CB(CmdPipelineBarrier); + WSI_CB(CmdCopyImage); WSI_CB(CmdCopyImageToBuffer); WSI_CB(CreateBuffer); WSI_CB(CreateCommandPool); diff --git a/src/vulkan/wsi/wsi_common_private.h b/src/vulkan/wsi/wsi_common_private.h index 6cc4421..a4de215 100644 --- a/src/vulkan/wsi/wsi_common_private.h +++ b/src/vulkan/wsi/wsi_common_private.h @@ -104,6 +104,7 @@ struct wsi_image_info { enum wsi_swapchain_blit_type { WSI_SWAPCHAIN_NO_BLIT, WSI_SWAPCHAIN_BUFFER_BLIT, + WSI_SWAPCHAIN_IMAGE_BLIT, }; struct wsi_image { @@ -112,6 +113,7 @@ struct wsi_image { struct { VkBuffer buffer; + VkImage image; VkDeviceMemory memory; VkCommandBuffer *cmd_buffers; } blit; @@ -245,6 +247,10 @@ wsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain, uint32_t stride_align, uint32_t size_align, struct wsi_image_info *info); +void +wsi_configure_image_blit_image(UNUSED const struct wsi_swapchain *chain, + struct wsi_image_info *info); + VkResult wsi_configure_image(const struct wsi_swapchain *chain, const VkSwapchainCreateInfoKHR *pCreateInfo, -- 2.7.4