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 <jenatali@microsoft.com> Reviewed-by: Daniel Stone <daniels@collabora.com> Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16200>
This commit is contained in:

committed by
Marge Bot

parent
65e4873d82
commit
2975a7f453
@@ -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);
|
||||
1, img_mem_barriers);
|
||||
|
||||
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);
|
||||
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,
|
||||
};
|
||||
|
||||
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->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,
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user