From 8168ca3d3ea67c74b8b9fe629aafac5d49cccaa1 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 6 May 2026 16:12:05 +0100 Subject: [PATCH] vulkan-renderer: Fix external-queue sync in repaint When we're performing a queue-family ownership transfer to a foreign device, we need to transition to GENERAL (because we have no PRESENT_SRC when we're operating on dmabufs) from the colour attachment stage before display reads, and we need to transition back to OPTIMAL before the colour attachment stage. As external queues have no stage ordering, we use BOTTOM_OF_PIPE to indicate that we want to synchronise against everything the external queue may do. For the internal queue though, we don't need to serialise vertex/tiler work against the layout transition for the colour buffer, just the work which requires access to the colour attachment. Signed-off-by: Daniel Stone --- libweston/renderer-vulkan/vulkan-renderer.c | 40 ++++++--------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/libweston/renderer-vulkan/vulkan-renderer.c b/libweston/renderer-vulkan/vulkan-renderer.c index 76523b985..f6938f9c1 100644 --- a/libweston/renderer-vulkan/vulkan-renderer.c +++ b/libweston/renderer-vulkan/vulkan-renderer.c @@ -405,30 +405,6 @@ static const struct vulkan_extension_table vulkan_device_ext_table[] = { }, }; -static void -transfer_image_queue_family(VkCommandBuffer cmd_buffer, VkImage image, - uint32_t src_index, uint32_t dst_index) -{ - const VkImageMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .srcAccessMask = 0, - .dstAccessMask = 0, - .image = image, - .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .subresourceRange.layerCount = 1, - .subresourceRange.levelCount = 1, - .srcQueueFamilyIndex = src_index, - .dstQueueFamilyIndex = dst_index, - }; - - vkCmdPipelineBarrier(cmd_buffer, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - 0, 0, NULL, 0, NULL, 1, &barrier); -} - static void transition_image_layout(VkCommandBuffer cmd_buffer, VkImage image, VkImageLayout old_layout, VkImageLayout new_layout, @@ -2493,9 +2469,11 @@ vulkan_renderer_repaint_output(struct weston_output *output, if (rb->dmabuf) { // Transfer ownership of the dmabuf to Vulkan assert(vulkan_device_has(vr, EXTENSION_EXT_QUEUE_FAMILY_FOREIGN)); - transfer_image_queue_family(cmd_buffer, im->image, - VK_QUEUE_FAMILY_FOREIGN_EXT, - vr->queue_family); + transition_image_layout(cmd_buffer, im->image, + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_MEMORY_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_QUEUE_FAMILY_FOREIGN_EXT, vr->queue_family); } const struct weston_size *fb = &vo->fb_size; @@ -2536,9 +2514,11 @@ vulkan_renderer_repaint_output(struct weston_output *output, if (rb->dmabuf) { // Transfer ownership of the dmabuf to DRM assert(vulkan_device_has(vr, EXTENSION_EXT_QUEUE_FAMILY_FOREIGN)); - transfer_image_queue_family(cmd_buffer, im->image, - vr->queue_family, - VK_QUEUE_FAMILY_FOREIGN_EXT); + transition_image_layout(cmd_buffer, im->image, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + vr->queue_family, VK_QUEUE_FAMILY_FOREIGN_EXT); } result = vkEndCommandBuffer(cmd_buffer);