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(BindImageMemory);
|
||||||
WSI_GET_CB(BeginCommandBuffer);
|
WSI_GET_CB(BeginCommandBuffer);
|
||||||
WSI_GET_CB(CmdPipelineBarrier);
|
WSI_GET_CB(CmdPipelineBarrier);
|
||||||
|
WSI_GET_CB(CmdCopyImage);
|
||||||
WSI_GET_CB(CmdCopyImageToBuffer);
|
WSI_GET_CB(CmdCopyImageToBuffer);
|
||||||
WSI_GET_CB(CreateBuffer);
|
WSI_GET_CB(CreateBuffer);
|
||||||
WSI_GET_CB(CreateCommandPool);
|
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->FreeMemory(chain->device, image->memory, &chain->alloc);
|
||||||
wsi->DestroyImage(chain->device, image->image, &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->FreeMemory(chain->device, image->blit.memory, &chain->alloc);
|
||||||
wsi->DestroyBuffer(chain->device, image->blit.buffer, &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,
|
VkExternalMemoryHandleTypeFlags handle_types,
|
||||||
bool implicit_sync)
|
bool implicit_sync)
|
||||||
{
|
{
|
||||||
|
assert(chain->blit.type == WSI_SWAPCHAIN_BUFFER_BLIT);
|
||||||
|
|
||||||
const struct wsi_device *wsi = chain->wsi;
|
const struct wsi_device *wsi = chain->wsi;
|
||||||
VkResult result;
|
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);
|
wsi->BeginCommandBuffer(image->blit.cmd_buffers[i], &begin_info);
|
||||||
|
|
||||||
VkImageMemoryBarrier img_mem_barrier = {
|
VkImageMemoryBarrier img_mem_barriers[] = {
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
{
|
||||||
.pNext = NULL,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.srcAccessMask = 0,
|
.pNext = NULL,
|
||||||
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
.srcAccessMask = 0,
|
||||||
.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
|
||||||
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image->image,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.subresourceRange = {
|
.image = image->image,
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
.subresourceRange = {
|
||||||
.baseMipLevel = 0,
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
.levelCount = 1,
|
.baseMipLevel = 0,
|
||||||
.baseArrayLayer = 0,
|
.levelCount = 1,
|
||||||
.layerCount = 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],
|
wsi->CmdPipelineBarrier(image->blit.cmd_buffers[i],
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0,
|
0,
|
||||||
0, NULL,
|
0, NULL,
|
||||||
0, NULL,
|
0, NULL,
|
||||||
1, &img_mem_barrier);
|
1, img_mem_barriers);
|
||||||
|
|
||||||
struct VkBufferImageCopy buffer_image_copy = {
|
if (chain->blit.type == WSI_SWAPCHAIN_BUFFER_BLIT) {
|
||||||
.bufferOffset = 0,
|
struct VkBufferImageCopy buffer_image_copy = {
|
||||||
.bufferRowLength = info->linear_stride /
|
.bufferOffset = 0,
|
||||||
vk_format_get_blocksize(info->create.format),
|
.bufferRowLength = info->linear_stride /
|
||||||
.bufferImageHeight = 0,
|
vk_format_get_blocksize(info->create.format),
|
||||||
.imageSubresource = {
|
.bufferImageHeight = 0,
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
.imageSubresource = {
|
||||||
.mipLevel = 0,
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
.baseArrayLayer = 0,
|
.mipLevel = 0,
|
||||||
.layerCount = 1,
|
.baseArrayLayer = 0,
|
||||||
},
|
.layerCount = 1,
|
||||||
.imageOffset = { .x = 0, .y = 0, .z = 0 },
|
},
|
||||||
.imageExtent = info->create.extent,
|
.imageOffset = { .x = 0, .y = 0, .z = 0 },
|
||||||
};
|
.imageExtent = info->create.extent,
|
||||||
wsi->CmdCopyImageToBuffer(image->blit.cmd_buffers[i],
|
};
|
||||||
image->image,
|
wsi->CmdCopyImageToBuffer(image->blit.cmd_buffers[i],
|
||||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
image->image,
|
||||||
image->blit.buffer,
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
1, &buffer_image_copy);
|
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;
|
wsi->CmdCopyImage(image->blit.cmd_buffers[i],
|
||||||
img_mem_barrier.dstAccessMask = 0;
|
image->image,
|
||||||
img_mem_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
img_mem_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
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],
|
wsi->CmdPipelineBarrier(image->blit.cmd_buffers[i],
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||||
0,
|
0,
|
||||||
0, NULL,
|
0, NULL,
|
||||||
0, NULL,
|
0, NULL,
|
||||||
1, &img_mem_barrier);
|
img_mem_barrier_count, img_mem_barriers);
|
||||||
|
|
||||||
result = wsi->EndCommandBuffer(image->blit.cmd_buffers[i]);
|
result = wsi->EndCommandBuffer(image->blit.cmd_buffers[i]);
|
||||||
if (result != VK_SUCCESS)
|
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;
|
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
|
static VkResult
|
||||||
wsi_create_cpu_linear_image_mem(const struct wsi_swapchain *chain,
|
wsi_create_cpu_linear_image_mem(const struct wsi_swapchain *chain,
|
||||||
const struct wsi_image_info *info,
|
const struct wsi_image_info *info,
|
||||||
|
@@ -208,6 +208,7 @@ struct wsi_device {
|
|||||||
WSI_CB(BindImageMemory);
|
WSI_CB(BindImageMemory);
|
||||||
WSI_CB(BeginCommandBuffer);
|
WSI_CB(BeginCommandBuffer);
|
||||||
WSI_CB(CmdPipelineBarrier);
|
WSI_CB(CmdPipelineBarrier);
|
||||||
|
WSI_CB(CmdCopyImage);
|
||||||
WSI_CB(CmdCopyImageToBuffer);
|
WSI_CB(CmdCopyImageToBuffer);
|
||||||
WSI_CB(CreateBuffer);
|
WSI_CB(CreateBuffer);
|
||||||
WSI_CB(CreateCommandPool);
|
WSI_CB(CreateCommandPool);
|
||||||
|
@@ -104,6 +104,7 @@ struct wsi_image_info {
|
|||||||
enum wsi_swapchain_blit_type {
|
enum wsi_swapchain_blit_type {
|
||||||
WSI_SWAPCHAIN_NO_BLIT,
|
WSI_SWAPCHAIN_NO_BLIT,
|
||||||
WSI_SWAPCHAIN_BUFFER_BLIT,
|
WSI_SWAPCHAIN_BUFFER_BLIT,
|
||||||
|
WSI_SWAPCHAIN_IMAGE_BLIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wsi_image {
|
struct wsi_image {
|
||||||
@@ -112,6 +113,7 @@ struct wsi_image {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
VkBuffer buffer;
|
VkBuffer buffer;
|
||||||
|
VkImage image;
|
||||||
VkDeviceMemory memory;
|
VkDeviceMemory memory;
|
||||||
VkCommandBuffer *cmd_buffers;
|
VkCommandBuffer *cmd_buffers;
|
||||||
} blit;
|
} blit;
|
||||||
@@ -245,6 +247,10 @@ wsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain,
|
|||||||
uint32_t stride_align, uint32_t size_align,
|
uint32_t stride_align, uint32_t size_align,
|
||||||
struct wsi_image_info *info);
|
struct wsi_image_info *info);
|
||||||
|
|
||||||
|
void
|
||||||
|
wsi_configure_image_blit_image(UNUSED const struct wsi_swapchain *chain,
|
||||||
|
struct wsi_image_info *info);
|
||||||
|
|
||||||
VkResult
|
VkResult
|
||||||
wsi_configure_image(const struct wsi_swapchain *chain,
|
wsi_configure_image(const struct wsi_swapchain *chain,
|
||||||
const VkSwapchainCreateInfoKHR *pCreateInfo,
|
const VkSwapchainCreateInfoKHR *pCreateInfo,
|
||||||
|
Reference in New Issue
Block a user