From ea167c533e04afe491800ea978e4f982dd5d724a Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 1 Sep 2016 20:04:08 +1000 Subject: [PATCH] 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. --- ext/vulkan/vkswapper.c | 155 ++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 73 deletions(-) diff --git a/ext/vulkan/vkswapper.c b/ext/vulkan/vkswapper.c index d528f0b620..75f86abc35 100644 --- a/ext/vulkan/vkswapper.c +++ b/ext/vulkan/vkswapper.c @@ -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; } }