vkswapper: fix up display synchronization

Use the semaphores in the correct place, before and after the submission for
acquiring and presenting the swapchain buffer.

Waiting on the fence that only signals the command buffer completion rather than
the completion of the presentation is racy with the destruction of the vulkan
buffers associated with that image.  Wait on the device to be idle instead after
presenting.
This commit is contained in:
Matthew Waters 2016-05-05 23:18:11 +10:00
parent 267588fb5e
commit 77f6e253e1

View file

@ -454,6 +454,7 @@ gst_vulkan_swapper_get_supported_caps (GstVulkanSwapper * swapper,
gst_structure_set_value (s, "format", &list); gst_structure_set_value (s, "format", &list);
g_value_unset (&list); g_value_unset (&list);
} }
{ {
guint32 max_dim = swapper->device->gpu_props.limits.maxImageDimension2D; guint32 max_dim = swapper->device->gpu_props.limits.maxImageDimension2D;
@ -798,7 +799,6 @@ gst_vulkan_swapper_set_caps (GstVulkanSwapper * swapper, GstCaps * caps,
struct cmd_data struct cmd_data
{ {
VkCommandBuffer cmd; VkCommandBuffer cmd;
VkFence fence;
GDestroyNotify notify; GDestroyNotify notify;
gpointer data; gpointer data;
}; };
@ -888,10 +888,6 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
cmd_data->cmd = cmd; cmd_data->cmd = cmd;
cmd_data->notify = NULL; cmd_data->notify = NULL;
if (!_new_fence (swapper->device, &cmd_data->fence, error)) {
return FALSE;
}
return TRUE; return TRUE;
} }
@ -899,7 +895,8 @@ static gboolean
_render_buffer_unlocked (GstVulkanSwapper * swapper, _render_buffer_unlocked (GstVulkanSwapper * swapper,
GstBuffer * buffer, GError ** error) GstBuffer * buffer, GError ** error)
{ {
VkSemaphore semaphore = { 0, }; VkSemaphore acquire_semaphore = { 0, };
VkSemaphore present_semaphore = { 0, };
VkSemaphoreCreateInfo semaphore_info = { 0, }; VkSemaphoreCreateInfo semaphore_info = { 0, };
VkPresentInfoKHR present; VkPresentInfoKHR present;
struct cmd_data cmd_data = { 0, }; struct cmd_data cmd_data = { 0, };
@ -926,18 +923,18 @@ _render_buffer_unlocked (GstVulkanSwapper * swapper,
reacquire: reacquire:
err = vkCreateSemaphore (swapper->device->device, &semaphore_info, err = vkCreateSemaphore (swapper->device->device, &semaphore_info,
NULL, &semaphore); NULL, &acquire_semaphore);
if (gst_vulkan_error_to_g_error (err, error, "vkCreateSemaphore") < 0) if (gst_vulkan_error_to_g_error (err, error, "vkCreateSemaphore") < 0)
goto error; goto error;
err = err =
swapper->AcquireNextImageKHR (swapper->device->device, swapper->AcquireNextImageKHR (swapper->device->device,
swapper->swap_chain, -1, semaphore, VK_NULL_HANDLE, &swap_idx); swapper->swap_chain, -1, acquire_semaphore, VK_NULL_HANDLE, &swap_idx);
/* TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR */ /* TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR */
if (err == VK_ERROR_OUT_OF_DATE_KHR) { if (err == VK_ERROR_OUT_OF_DATE_KHR) {
GST_DEBUG_OBJECT (swapper, "out of date frame acquired"); GST_DEBUG_OBJECT (swapper, "out of date frame acquired");
vkDestroySemaphore (swapper->device->device, semaphore, NULL); vkDestroySemaphore (swapper->device->device, acquire_semaphore, NULL);
if (!_swapchain_resize (swapper, error)) if (!_swapchain_resize (swapper, error))
goto error; goto error;
goto reacquire; goto reacquire;
@ -949,6 +946,11 @@ reacquire:
if (!_build_render_buffer_cmd (swapper, swap_idx, buffer, &cmd_data, error)) if (!_build_render_buffer_cmd (swapper, swap_idx, buffer, &cmd_data, error))
goto error; goto error;
err = vkCreateSemaphore (swapper->device->device, &semaphore_info,
NULL, &present_semaphore);
if (gst_vulkan_error_to_g_error (err, error, "vkCreateSemaphore") < 0)
goto error;
{ {
VkSubmitInfo submit_info = { 0, }; VkSubmitInfo submit_info = { 0, };
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; VkPipelineStageFlags stages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
@ -956,24 +958,23 @@ reacquire:
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pNext = NULL; submit_info.pNext = NULL;
submit_info.waitSemaphoreCount = 1; submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &semaphore; submit_info.pWaitSemaphores = &acquire_semaphore;
submit_info.pWaitDstStageMask = &stages; submit_info.pWaitDstStageMask = &stages;
submit_info.commandBufferCount = 1; submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &cmd_data.cmd; submit_info.pCommandBuffers = &cmd_data.cmd;
submit_info.signalSemaphoreCount = 0; submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = NULL; submit_info.pSignalSemaphores = &present_semaphore;
err = err = vkQueueSubmit (swapper->queue->queue, 1, &submit_info, NULL);
vkQueueSubmit (swapper->queue->queue, 1, &submit_info, cmd_data.fence);
if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0) { if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0) {
return FALSE; goto error;
} }
} }
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present.pNext = NULL; present.pNext = NULL;
present.waitSemaphoreCount = 0; present.waitSemaphoreCount = 1;
present.pWaitSemaphores = NULL; present.pWaitSemaphores = &present_semaphore;
present.swapchainCount = 1; present.swapchainCount = 1;
present.pSwapchains = &swapper->swap_chain; present.pSwapchains = &swapper->swap_chain;
present.pImageIndices = &swap_idx; present.pImageIndices = &swap_idx;
@ -988,30 +989,30 @@ reacquire:
} else if (gst_vulkan_error_to_g_error (err, error, "vkQueuePresentKHR") < 0) } else if (gst_vulkan_error_to_g_error (err, error, "vkQueuePresentKHR") < 0)
goto error; goto error;
err = vkWaitForFences (swapper->device->device, 1, &cmd_data.fence, TRUE, -1); err = vkDeviceWaitIdle (swapper->device->device);
if (gst_vulkan_error_to_g_error (err, error, "vkWaitForFences") < 0) if (gst_vulkan_error_to_g_error (err, error, "vkDeviceWaitIdle") < 0)
goto error; goto error;
if (semaphore) if (acquire_semaphore)
vkDestroySemaphore (swapper->device->device, semaphore, NULL); vkDestroySemaphore (swapper->device->device, acquire_semaphore, NULL);
if (present_semaphore)
vkDestroySemaphore (swapper->device->device, present_semaphore, NULL);
if (cmd_data.cmd) if (cmd_data.cmd)
vkFreeCommandBuffers (swapper->device->device, swapper->device->cmd_pool, vkFreeCommandBuffers (swapper->device->device, swapper->device->cmd_pool,
1, &cmd_data.cmd); 1, &cmd_data.cmd);
if (cmd_data.fence)
vkDestroyFence (swapper->device->device, cmd_data.fence, NULL);
if (cmd_data.notify) if (cmd_data.notify)
cmd_data.notify (cmd_data.data); cmd_data.notify (cmd_data.data);
return TRUE; return TRUE;
error: error:
{ {
if (semaphore) if (acquire_semaphore)
vkDestroySemaphore (swapper->device->device, semaphore, NULL); vkDestroySemaphore (swapper->device->device, acquire_semaphore, NULL);
if (present_semaphore)
vkDestroySemaphore (swapper->device->device, present_semaphore, NULL);
if (cmd_data.cmd) if (cmd_data.cmd)
vkFreeCommandBuffers (swapper->device->device, swapper->device->cmd_pool, vkFreeCommandBuffers (swapper->device->device, swapper->device->cmd_pool,
1, &cmd_data.cmd); 1, &cmd_data.cmd);
if (cmd_data.fence)
vkDestroyFence (swapper->device->device, cmd_data.fence, NULL);
if (cmd_data.notify) if (cmd_data.notify)
cmd_data.notify (cmd_data.data); cmd_data.notify (cmd_data.data);
return FALSE; return FALSE;