From 12711939320e4fcd3a0d86af22da1042ad92035f Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 20 Feb 2020 14:29:22 +0200 Subject: [PATCH] vulkan/overlay: Add a workaround semaphore for application presenting without one When an application calls vkQueuePresent() on a different queue than the one we run our drawing on and it doesn't give a semaphore to wait on, let's insert our own semaphore so that we don't race the application's drawing. Signed-off-by: Lionel Landwerlin Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/2540 Tested-by: Marge Bot Part-of: --- src/vulkan/overlay-layer/overlay.cpp | 72 ++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/src/vulkan/overlay-layer/overlay.cpp b/src/vulkan/overlay-layer/overlay.cpp index 565f5884bb6..1ed1d2b02e7 100644 --- a/src/vulkan/overlay-layer/overlay.cpp +++ b/src/vulkan/overlay-layer/overlay.cpp @@ -125,6 +125,8 @@ struct overlay_draw { VkCommandBuffer command_buffer; + VkSemaphore cross_engine_semaphore; + VkSemaphore semaphore; VkFence fence; @@ -544,6 +546,8 @@ struct overlay_draw *get_overlay_draw(struct swapchain_data *data) VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, NULL, &draw->semaphore)); + VK_CHECK(device_data->vtable.CreateSemaphore(device_data->device, &sem_info, + NULL, &draw->cross_engine_semaphore)); list_addtail(&draw->link, &data->draws); @@ -1349,26 +1353,55 @@ static struct overlay_draw *render_swapchain_display(struct swapchain_data *data device_data->vtable.EndCommandBuffer(draw->command_buffer); - VkPipelineStageFlags *stages_wait = (VkPipelineStageFlags*) malloc(sizeof(VkPipelineStageFlags) * n_wait_semaphores); - for (unsigned i = 0; i < n_wait_semaphores; i++) - { - // wait in the fragment stage until the swapchain image is ready - stages_wait[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + /* When presenting on a different queue than where we're drawing the + * overlay *AND* when the application does not provide a semaphore to + * vkQueuePresent, insert our own cross engine synchronization + * semaphore. + */ + if (n_wait_semaphores == 0 && device_data->graphic_queue->queue != present_queue->queue) { + VkPipelineStageFlags stages_wait = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 0; + submit_info.pWaitDstStageMask = &stages_wait; + submit_info.waitSemaphoreCount = 0; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &draw->cross_engine_semaphore; + + device_data->vtable.QueueSubmit(present_queue->queue, 1, &submit_info, VK_NULL_HANDLE); + + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pWaitDstStageMask = &stages_wait; + submit_info.pCommandBuffers = &draw->command_buffer; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = &draw->cross_engine_semaphore; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &draw->semaphore; + + device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); + } else { + VkPipelineStageFlags *stages_wait = (VkPipelineStageFlags*) malloc(sizeof(VkPipelineStageFlags) * n_wait_semaphores); + for (unsigned i = 0; i < n_wait_semaphores; i++) + { + // wait in the fragment stage until the swapchain image is ready + stages_wait[i] = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &draw->command_buffer; + submit_info.pWaitDstStageMask = stages_wait; + submit_info.waitSemaphoreCount = n_wait_semaphores; + submit_info.pWaitSemaphores = wait_semaphores; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = &draw->semaphore; + + device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); + + free(stages_wait); } - - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &draw->command_buffer; - submit_info.pWaitDstStageMask = stages_wait; - submit_info.waitSemaphoreCount = n_wait_semaphores; - submit_info.pWaitSemaphores = wait_semaphores; - submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &draw->semaphore; - - device_data->vtable.QueueSubmit(device_data->graphic_queue->queue, 1, &submit_info, draw->fence); - - free(stages_wait); return draw; } @@ -1750,6 +1783,7 @@ static void shutdown_swapchain_data(struct swapchain_data *data) struct device_data *device_data = data->device; list_for_each_entry_safe(struct overlay_draw, draw, &data->draws, link) { + device_data->vtable.DestroySemaphore(device_data->device, draw->cross_engine_semaphore, NULL); device_data->vtable.DestroySemaphore(device_data->device, draw->semaphore, NULL); device_data->vtable.DestroyFence(device_data->device, draw->fence, NULL); device_data->vtable.DestroyBuffer(device_data->device, draw->vertex_buffer, NULL); -- 2.30.2