vkswapper: Use the trash list to free resources after they've been used

This allows further parallelism and removes a device wait from the end of
the render code.
This commit is contained in:
Matthew Waters 2016-09-01 20:04:08 +10:00
parent 0f800095e1
commit ea167c533e

View file

@ -41,6 +41,8 @@ G_DEFINE_TYPE_WITH_CODE (GstVulkanSwapper, gst_vulkan_swapper,
struct _GstVulkanSwapperPrivate
{
GMutex render_lock;
GList *trash_list;
};
static void _on_window_draw (GstVulkanWindow * window,
@ -333,6 +335,11 @@ gst_vulkan_swapper_finalize (GObject * object)
GstVulkanSwapper *swapper = GST_VULKAN_SWAPPER (object);
int i;
if (!gst_vulkan_trash_list_wait (swapper->priv->trash_list, -1))
GST_WARNING_OBJECT (swapper, "Failed to wait for all fences to complete "
"before shutting down");
swapper->priv->trash_list = NULL;
if (swapper->swap_chain_images) {
for (i = 0; i < swapper->n_swap_chain_images; i++) {
gst_memory_unref ((GstMemory *) swapper->swap_chain_images[i]);
@ -487,37 +494,21 @@ _swapper_set_image_layout_with_cmd (GstVulkanSwapper * swapper,
return TRUE;
}
static gboolean
_new_fence (GstVulkanDevice * device, VkFence * fence, GError ** error)
{
VkFenceCreateInfo fence_info;
VkResult err;
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.pNext = NULL;
fence_info.flags = 0;
err = vkCreateFence (device->device, &fence_info, NULL, fence);
if (gst_vulkan_error_to_g_error (err, error, "vkCreateFence") < 0)
return FALSE;
return TRUE;
}
static gboolean
_swapper_set_image_layout (GstVulkanSwapper * swapper,
GstVulkanImageMemory * image, VkImageLayout new_image_layout,
GError ** error)
{
VkCommandBuffer cmd;
VkFence fence;
VkCommandBuffer cmd = VK_NULL_HANDLE;
GstVulkanFence *fence = NULL;
VkResult err;
if (!gst_vulkan_device_create_cmd_buffer (swapper->device, &cmd, error))
return FALSE;
goto error;
if (!_new_fence (swapper->device, &fence, error))
return FALSE;
fence = gst_vulkan_fence_new (swapper->device, 0, error);
if (!fence)
goto error;
{
VkCommandBufferInheritanceInfo buf_inh = { 0, };
@ -539,16 +530,16 @@ _swapper_set_image_layout (GstVulkanSwapper * swapper,
err = vkBeginCommandBuffer (cmd, &cmd_buf_info);
if (gst_vulkan_error_to_g_error (err, error, "vkBeginCommandBuffer") < 0)
return FALSE;
goto error;
}
if (!_swapper_set_image_layout_with_cmd (swapper, cmd, image,
new_image_layout, error))
return FALSE;
goto error;
err = vkEndCommandBuffer (cmd);
if (gst_vulkan_error_to_g_error (err, error, "vkEndCommandBuffer") < 0)
return FALSE;
goto error;
{
VkSubmitInfo submit_info = { 0, };
@ -564,20 +555,23 @@ _swapper_set_image_layout (GstVulkanSwapper * swapper,
submit_info.signalSemaphoreCount = 0;
submit_info.pSignalSemaphores = NULL;
err = vkQueueSubmit (swapper->queue->queue, 1, &submit_info, fence);
err =
vkQueueSubmit (swapper->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence));
if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0)
return FALSE;
goto error;
}
err = vkWaitForFences (swapper->device->device, 1, &fence, TRUE, -1);
if (gst_vulkan_error_to_g_error (err, error, "vkWaitForFences") < 0)
return FALSE;
vkFreeCommandBuffers (swapper->device->device, swapper->device->cmd_pool, 1,
&cmd);
vkDestroyFence (swapper->device->device, fence, NULL);
swapper->priv->trash_list = g_list_prepend (swapper->priv->trash_list,
gst_vulkan_trash_new_free_command_buffer (fence, cmd));
fence = NULL;
return TRUE;
error:
if (fence)
gst_vulkan_fence_unref (fence);
return FALSE;
}
static gboolean
@ -645,8 +639,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps,
n_images_wanted = swapper->surf_props.maxImageCount;
}
if (swapper->
surf_props.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
if (swapper->surf_props.
supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
} else {
preTransform = swapper->surf_props.currentTransform;
@ -677,8 +671,8 @@ _allocate_swapchain (GstVulkanSwapper * swapper, GstCaps * caps,
"Incorrect usage flags available for the swap images");
return FALSE;
}
if ((swapper->surf_props.
supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
if ((swapper->
surf_props.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
!= 0) {
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
} else {
@ -796,16 +790,9 @@ gst_vulkan_swapper_set_caps (GstVulkanSwapper * swapper, GstCaps * caps,
return _swapchain_resize (swapper, error);
}
struct cmd_data
{
VkCommandBuffer cmd;
GDestroyNotify notify;
gpointer data;
};
static gboolean
_build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
GstBuffer * buffer, struct cmd_data *cmd_data, GError ** error)
GstBuffer * buffer, VkCommandBuffer * cmd_ret, GError ** error)
{
GstVulkanBufferMemory *buf_mem;
GstVulkanImageMemory *swap_mem;
@ -815,8 +802,6 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
g_return_val_if_fail (swap_idx < swapper->n_swap_chain_images, FALSE);
swap_mem = swapper->swap_chain_images[swap_idx];
cmd_data->notify = NULL;
if (!gst_vulkan_device_create_cmd_buffer (swapper->device, &cmd, error))
return FALSE;
@ -885,8 +870,7 @@ _build_render_buffer_cmd (GstVulkanSwapper * swapper, guint32 swap_idx,
if (gst_vulkan_error_to_g_error (err, error, "vkEndCommandBuffer") < 0)
return FALSE;
cmd_data->cmd = cmd;
cmd_data->notify = NULL;
*cmd_ret = cmd;
return TRUE;
}
@ -898,10 +882,14 @@ _render_buffer_unlocked (GstVulkanSwapper * swapper,
VkSemaphore acquire_semaphore = { 0, };
VkSemaphore present_semaphore = { 0, };
VkSemaphoreCreateInfo semaphore_info = { 0, };
GstVulkanFence *fence = NULL;
VkPresentInfoKHR present;
struct cmd_data cmd_data = { 0, };
VkCommandBuffer cmd = VK_NULL_HANDLE;
guint32 swap_idx;
VkResult err, present_err;
VkResult err, present_err = VK_SUCCESS;
swapper->priv->trash_list =
gst_vulkan_trash_list_gc (swapper->priv->trash_list);
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
semaphore_info.pNext = NULL;
@ -943,7 +931,7 @@ reacquire:
goto error;
}
if (!_build_render_buffer_cmd (swapper, swap_idx, buffer, &cmd_data, error))
if (!_build_render_buffer_cmd (swapper, swap_idx, buffer, &cmd, error))
goto error;
err = vkCreateSemaphore (swapper->device->device, &semaphore_info,
@ -961,14 +949,28 @@ reacquire:
submit_info.pWaitSemaphores = &acquire_semaphore;
submit_info.pWaitDstStageMask = &stages;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &cmd_data.cmd;
submit_info.pCommandBuffers = &cmd;
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &present_semaphore;
err = vkQueueSubmit (swapper->queue->queue, 1, &submit_info, NULL);
if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0) {
fence = gst_vulkan_fence_new (swapper->device, 0, error);
if (!fence)
goto error;
}
err =
vkQueueSubmit (swapper->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence));
if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0)
goto error;
swapper->priv->trash_list = g_list_prepend (swapper->priv->trash_list,
gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence),
cmd));
swapper->priv->trash_list = g_list_prepend (swapper->priv->trash_list,
gst_vulkan_trash_new_free_semaphore (fence, acquire_semaphore));
cmd = VK_NULL_HANDLE;
fence = NULL;
}
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@ -992,19 +994,28 @@ reacquire:
} else if (gst_vulkan_error_to_g_error (err, error, "vkQueuePresentKHR") < 0)
goto error;
err = vkDeviceWaitIdle (swapper->device->device);
if (gst_vulkan_error_to_g_error (err, error, "vkDeviceWaitIdle") < 0)
goto error;
{
VkSubmitInfo submit_info = { 0, };
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.pWaitDstStageMask = &stages;
fence = gst_vulkan_fence_new (swapper->device, 0, error);
if (!fence)
goto error;
err =
vkQueueSubmit (swapper->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence));
if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0)
goto error;
swapper->priv->trash_list = g_list_prepend (swapper->priv->trash_list,
gst_vulkan_trash_new_free_semaphore (fence, present_semaphore));
fence = NULL;
}
if (acquire_semaphore)
vkDestroySemaphore (swapper->device->device, acquire_semaphore, NULL);
if (present_semaphore)
vkDestroySemaphore (swapper->device->device, present_semaphore, NULL);
if (cmd_data.cmd)
vkFreeCommandBuffers (swapper->device->device, swapper->device->cmd_pool,
1, &cmd_data.cmd);
if (cmd_data.notify)
cmd_data.notify (cmd_data.data);
return TRUE;
error:
@ -1013,11 +1024,9 @@ error:
vkDestroySemaphore (swapper->device->device, acquire_semaphore, NULL);
if (present_semaphore)
vkDestroySemaphore (swapper->device->device, present_semaphore, NULL);
if (cmd_data.cmd)
if (cmd)
vkFreeCommandBuffers (swapper->device->device, swapper->device->cmd_pool,
1, &cmd_data.cmd);
if (cmd_data.notify)
cmd_data.notify (cmd_data.data);
1, &cmd);
return FALSE;
}
}