diff --git a/ext/vulkan/meson.build b/ext/vulkan/meson.build index a9b8542caa..25b16699b7 100644 --- a/ext/vulkan/meson.build +++ b/ext/vulkan/meson.build @@ -17,7 +17,6 @@ vulkan_sources = [ 'vksink.c', 'vkshader.c', 'vkswapper.c', - 'vktrash.c', 'vkupload.c', ] diff --git a/ext/vulkan/vkcolorconvert.c b/ext/vulkan/vkcolorconvert.c index bceaca3eb4..f617ee15e9 100644 --- a/ext/vulkan/vkcolorconvert.c +++ b/ext/vulkan/vkcolorconvert.c @@ -32,7 +32,6 @@ #include #include "vkcolorconvert.h" -#include "vktrash.h" #include "vkshader.h" #include "shaders/identity.vert.h" #include "shaders/swizzle.frag.h" @@ -1532,13 +1531,13 @@ gst_vulkan_color_convert_set_caps (GstBaseTransform * bt, GstCaps * in_caps, if (render->last_fence) { if (conv->descriptor_pool) - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref (render->last_fence), conv->descriptor_pool)); conv->descriptor_set = NULL; conv->descriptor_pool = NULL; if (conv->uniform) - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (render->last_fence), (GstMiniObject *) conv->uniform)); conv->uniform = NULL; @@ -1579,18 +1578,18 @@ gst_vulkan_color_convert_stop (GstBaseTransform * bt) if (render->device) { if (render->last_fence) { if (conv->descriptor_pool) - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref (render->last_fence), conv->descriptor_pool)); conv->descriptor_set = NULL; conv->descriptor_pool = NULL; if (conv->sampler) - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_sampler (gst_vulkan_fence_ref (render->last_fence), conv->sampler)); conv->sampler = NULL; if (conv->uniform) - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (render->last_fence), (GstMiniObject *) conv->uniform)); conv->uniform = NULL; @@ -1907,8 +1906,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, out_img_mems[i]->barrier.image_layout, 1, &blit, VK_FILTER_LINEAR); /* XXX: try to reuse this image later */ - render->trash_list = - g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (fence), (GstMiniObject *) render_img_mems[i])); } @@ -1918,11 +1916,10 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0) goto error; - render->trash_list = - g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_framebuffer (gst_vulkan_fence_ref (fence), framebuffer)); - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence), conv->cmd_pool, cmd)); diff --git a/ext/vulkan/vkdownload.c b/ext/vulkan/vkdownload.c index d07101e546..4ca0aebed0 100644 --- a/ext/vulkan/vkdownload.c +++ b/ext/vulkan/vkdownload.c @@ -32,7 +32,6 @@ #include #include "vkdownload.h" -#include "vktrash.h" GST_DEBUG_CATEGORY (gst_debug_vulkan_download); #define GST_CAT_DEFAULT gst_debug_vulkan_download @@ -86,7 +85,7 @@ struct ImageToRawDownload gboolean pool_active; GstVulkanCommandPool *cmd_pool; - GList *trash_list; + GstVulkanTrashList *trash_list; }; static gpointer @@ -95,6 +94,7 @@ _image_to_raw_new_impl (GstVulkanDownload * download) struct ImageToRawDownload *raw = g_new0 (struct ImageToRawDownload, 1); raw->download = download; + raw->trash_list = gst_vulkan_trash_fence_list_new (); return raw; } @@ -315,7 +315,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0) goto error; - raw->trash_list = g_list_prepend (raw->trash_list, + gst_vulkan_trash_list_add (raw->trash_list, gst_vulkan_trash_new_free_command_buffer (fence, raw->cmd_pool, cmd)); } @@ -323,7 +323,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) * Need to have the buffer gst_memory_map() wait for this fence before * allowing access */ gst_vulkan_trash_list_wait (raw->trash_list, -1); - raw->trash_list = NULL; + gst_vulkan_trash_list_gc (raw->trash_list); ret = GST_FLOW_OK; @@ -361,6 +361,9 @@ _image_to_raw_free (gpointer impl) raw->cmd_pool = NULL; } + gst_object_unref (raw->trash_list); + raw->trash_list = NULL; + g_free (impl); } diff --git a/ext/vulkan/vkfullscreenrender.c b/ext/vulkan/vkfullscreenrender.c index 9880685b3d..26cb56baaa 100644 --- a/ext/vulkan/vkfullscreenrender.c +++ b/ext/vulkan/vkfullscreenrender.c @@ -32,7 +32,6 @@ #include #include "vkimageidentity.h" -#include "vktrash.h" #include "vkshader.h" GST_DEBUG_CATEGORY (gst_debug_vulkan_full_screen_render); @@ -564,25 +563,25 @@ gst_vulkan_full_screen_render_set_caps (GstBaseTransform * bt, if (render->last_fence) { if (render->descriptor_set_layout) { - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_descriptor_set_layout (gst_vulkan_fence_ref (render->last_fence), render->descriptor_set_layout)); render->descriptor_set_layout = NULL; } if (render->pipeline_layout) { - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_pipeline_layout (gst_vulkan_fence_ref (render->last_fence), render->pipeline_layout)); render->pipeline_layout = NULL; } if (render->render_pass) { - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_render_pass (gst_vulkan_fence_ref (render->last_fence), render->render_pass)); render->render_pass = NULL; } if (render->graphics_pipeline) { - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_pipeline (gst_vulkan_fence_ref (render->last_fence), render->graphics_pipeline)); render->graphics_pipeline = NULL; @@ -757,6 +756,8 @@ gst_vulkan_full_screen_render_start (GstBaseTransform * bt) if (!_create_vertex_buffers (render)) return FALSE; + render->trash_list = gst_vulkan_trash_fence_list_new (); + return TRUE; } @@ -767,19 +768,19 @@ gst_vulkan_full_screen_render_stop (GstBaseTransform * bt) if (render->device) { if (render->last_fence) { - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_pipeline (gst_vulkan_fence_ref (render->last_fence), render->graphics_pipeline)); render->graphics_pipeline = NULL; - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_pipeline_layout (gst_vulkan_fence_ref (render->last_fence), render->pipeline_layout)); render->pipeline_layout = NULL; - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_render_pass (gst_vulkan_fence_ref (render->last_fence), render->render_pass)); render->render_pass = NULL; - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_descriptor_set_layout (gst_vulkan_fence_ref (render->last_fence), render->descriptor_set_layout)); render->descriptor_set_layout = NULL; @@ -806,6 +807,7 @@ gst_vulkan_full_screen_render_stop (GstBaseTransform * bt) if (!gst_vulkan_trash_list_wait (render->trash_list, -1)) GST_WARNING_OBJECT (render, "Failed to wait for all resources to be freed"); + gst_object_unref (render->trash_list); render->trash_list = NULL; if (render->vertices) @@ -914,7 +916,7 @@ gst_vulkan_full_screen_render_submit (GstVulkanFullScreenRender * render, if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0) goto error; - render->trash_list = gst_vulkan_trash_list_gc (render->trash_list); + gst_vulkan_trash_list_gc (render->trash_list); gst_vulkan_fence_unref (fence); diff --git a/ext/vulkan/vkfullscreenrender.h b/ext/vulkan/vkfullscreenrender.h index 2d90fefabf..9a61491e01 100644 --- a/ext/vulkan/vkfullscreenrender.h +++ b/ext/vulkan/vkfullscreenrender.h @@ -71,7 +71,7 @@ struct _GstVulkanFullScreenRender GstMemory *vertices; GstMemory *indices; - GList *trash_list; + GstVulkanTrashList *trash_list; GstVulkanFence *last_fence; }; diff --git a/ext/vulkan/vkimageidentity.c b/ext/vulkan/vkimageidentity.c index 2d666ba3d8..4bc49b7654 100644 --- a/ext/vulkan/vkimageidentity.c +++ b/ext/vulkan/vkimageidentity.c @@ -32,7 +32,6 @@ #include #include "vkimageidentity.h" -#include "vktrash.h" #include "vkshader.h" #include "shaders/identity.vert.h" #include "shaders/identity.frag.h" @@ -355,7 +354,7 @@ gst_vulkan_image_identity_set_caps (GstBaseTransform * bt, GstCaps * in_caps, return FALSE; if (render->last_fence) { - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref (render->last_fence), vk_identity->descriptor_pool)); vk_identity->descriptor_set = NULL; @@ -438,12 +437,12 @@ gst_vulkan_image_identity_stop (GstBaseTransform * bt) if (render->device) { if (render->last_fence) { - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref (render->last_fence), vk_identity->descriptor_pool)); vk_identity->descriptor_set = NULL; vk_identity->descriptor_pool = NULL; - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_sampler (gst_vulkan_fence_ref (render->last_fence), vk_identity->sampler)); vk_identity->sampler = NULL; @@ -658,11 +657,10 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf, if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0) goto error; - render->trash_list = - g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_framebuffer (gst_vulkan_fence_ref (fence), framebuffer)); - render->trash_list = g_list_prepend (render->trash_list, + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence), vk_identity->cmd_pool, cmd)); diff --git a/ext/vulkan/vkswapper.c b/ext/vulkan/vkswapper.c index cf12d4043d..684b583fb4 100644 --- a/ext/vulkan/vkswapper.c +++ b/ext/vulkan/vkswapper.c @@ -25,7 +25,6 @@ #include #include "vkswapper.h" -#include "vktrash.h" #define GST_CAT_DEFAULT gst_vulkan_swapper_debug GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); @@ -38,7 +37,7 @@ struct _GstVulkanSwapperPrivate { GMutex render_lock; - GList *trash_list; + GstVulkanTrashList *trash_list; /* source sizes accounting for all aspect ratios */ guint dar_width; @@ -435,6 +434,7 @@ gst_vulkan_swapper_finalize (GObject * object) 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"); + gst_object_unref (swapper->priv->trash_list); swapper->priv->trash_list = NULL; if (swapper->swap_chain_images) { @@ -497,6 +497,8 @@ gst_vulkan_swapper_init (GstVulkanSwapper * swapper) swapper->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; swapper->par_n = DEFAULT_PIXEL_ASPECT_RATIO_N; swapper->par_d = DEFAULT_PIXEL_ASPECT_RATIO_D; + + swapper->priv->trash_list = gst_vulkan_trash_fence_list_new (); } static void @@ -1064,8 +1066,7 @@ _render_buffer_unlocked (GstVulkanSwapper * swapper, guint32 swap_idx; VkResult err, present_err = VK_SUCCESS; - swapper->priv->trash_list = - gst_vulkan_trash_list_gc (swapper->priv->trash_list); + gst_vulkan_trash_list_gc (swapper->priv->trash_list); if (!buffer) { g_set_error (error, GST_VULKAN_ERROR, @@ -1147,10 +1148,10 @@ reacquire: 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_list_add (swapper->priv->trash_list, gst_vulkan_trash_new_free_command_buffer (gst_vulkan_fence_ref (fence), swapper->cmd_pool, cmd)); - swapper->priv->trash_list = g_list_prepend (swapper->priv->trash_list, + gst_vulkan_trash_list_add (swapper->priv->trash_list, gst_vulkan_trash_new_free_semaphore (fence, acquire_semaphore)); cmd = VK_NULL_HANDLE; @@ -1204,7 +1205,7 @@ reacquire: 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_list_add (swapper->priv->trash_list, gst_vulkan_trash_new_free_semaphore (fence, present_semaphore)); fence = NULL; } diff --git a/ext/vulkan/vkupload.c b/ext/vulkan/vkupload.c index b75aadfab4..af1996072b 100644 --- a/ext/vulkan/vkupload.c +++ b/ext/vulkan/vkupload.c @@ -32,7 +32,6 @@ #include #include "vkupload.h" -#include "vktrash.h" GST_DEBUG_CATEGORY (gst_debug_vulkan_upload); #define GST_CAT_DEFAULT gst_debug_vulkan_upload @@ -379,7 +378,7 @@ struct BufferToImageUpload gboolean pool_active; GstVulkanCommandPool *cmd_pool; - GList *trash_list; + GstVulkanTrashList *trash_list; }; static gpointer @@ -388,6 +387,7 @@ _buffer_to_image_new_impl (GstVulkanUpload * upload) struct BufferToImageUpload *raw = g_new0 (struct BufferToImageUpload, 1); raw->upload = upload; + raw->trash_list = gst_vulkan_trash_fence_list_new (); return raw; } @@ -608,11 +608,11 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0) goto error; - raw->trash_list = g_list_prepend (raw->trash_list, + gst_vulkan_trash_list_add (raw->trash_list, gst_vulkan_trash_new_free_command_buffer (fence, raw->cmd_pool, cmd)); } - raw->trash_list = gst_vulkan_trash_list_gc (raw->trash_list); + gst_vulkan_trash_list_gc (raw->trash_list); ret = GST_FLOW_OK; @@ -651,6 +651,7 @@ _buffer_to_image_free (gpointer impl) if (!gst_vulkan_trash_list_wait (raw->trash_list, -1)) GST_WARNING_OBJECT (raw->upload, "Failed to wait for all fences to complete " "before shutting down"); + gst_object_unref (raw->trash_list); raw->trash_list = NULL; g_free (impl); @@ -687,7 +688,7 @@ struct RawToImageUpload gboolean in_pool_active; GstVulkanCommandPool *cmd_pool; - GList *trash_list; + GstVulkanTrashList *trash_list; }; static gpointer @@ -696,6 +697,7 @@ _raw_to_image_new_impl (GstVulkanUpload * upload) struct RawToImageUpload *raw = g_new0 (struct RawToImageUpload, 1); raw->upload = upload; + raw->trash_list = gst_vulkan_trash_fence_list_new (); return raw; } @@ -982,11 +984,11 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0) goto error; - raw->trash_list = g_list_prepend (raw->trash_list, + gst_vulkan_trash_list_add (raw->trash_list, gst_vulkan_trash_new_free_command_buffer (fence, raw->cmd_pool, cmd)); } - raw->trash_list = gst_vulkan_trash_list_gc (raw->trash_list); + gst_vulkan_trash_list_gc (raw->trash_list); ret = GST_FLOW_OK; @@ -1037,6 +1039,7 @@ _raw_to_image_free (gpointer impl) if (!gst_vulkan_trash_list_wait (raw->trash_list, -1)) GST_WARNING_OBJECT (raw->upload, "Failed to wait for all fences to complete " "before shutting down"); + gst_object_unref (raw->trash_list); raw->trash_list = NULL; g_free (impl); diff --git a/ext/vulkan/vktrash.c b/gst-libs/gst/vulkan/gstvktrash.c similarity index 62% rename from ext/vulkan/vktrash.c rename to gst-libs/gst/vulkan/gstvktrash.c index 854d61b44b..777e6133ce 100644 --- a/ext/vulkan/vktrash.c +++ b/gst-libs/gst/vulkan/gstvktrash.c @@ -22,7 +22,7 @@ #include "config.h" #endif -#include "vktrash.h" +#include "gstvktrash.h" GST_DEBUG_CATEGORY (gst_debug_vulkan_trash); #define GST_CAT_DEFAULT gst_debug_vulkan_trash @@ -39,11 +39,12 @@ _init_debug (void) } } -void -gst_vulkan_trash_free (GstVulkanTrash * trash) +static void +gst_vulkan_trash_free (GstMiniObject * object) { - if (!trash) - return; + GstVulkanTrash *trash = (GstVulkanTrash *) object; + + g_warn_if_fail (gst_vulkan_fence_is_signaled (trash->fence)); GST_TRACE ("Freeing trash object %p with fence %" GST_PTR_FORMAT, trash, trash->fence); @@ -53,6 +54,17 @@ gst_vulkan_trash_free (GstVulkanTrash * trash) g_free (trash); } +/** + * gst_vulkan_trash_new: + * @fence: a #GstVulkanFence + * @notify: (scope async): a #GstVulkanTrashNotify + * @user_data: (closure notify): user data for @notify + * + * Create and return a new #GstVulkanTrash object that will stores a callback + * to call when @fence is signalled. + * + * Returns: (transfer full): a new #GstVulkanTrash + */ GstVulkanTrash * gst_vulkan_trash_new (GstVulkanFence * fence, GstVulkanTrashNotify notify, gpointer user_data) @@ -68,6 +80,8 @@ gst_vulkan_trash_new (GstVulkanFence * fence, GstVulkanTrashNotify notify, ret = g_new0 (GstVulkanTrash, 1); GST_TRACE ("Creating new trash object %p with fence %" GST_PTR_FORMAT " on device %" GST_PTR_FORMAT, ret, fence, fence->device); + gst_mini_object_init ((GstMiniObject *) ret, 0, gst_vulkan_trash_get_type (), + NULL, NULL, (GstMiniObjectFreeFunction) gst_vulkan_trash_free); ret->fence = fence; ret->notify = notify; ret->user_data = user_data; @@ -75,69 +89,6 @@ gst_vulkan_trash_new (GstVulkanFence * fence, GstVulkanTrashNotify notify, return ret; } -GList * -gst_vulkan_trash_list_gc (GList * trash_list) -{ - GList *l = trash_list; - - while (l) { - GstVulkanTrash *trash = l->data; - - if (gst_vulkan_fence_is_signaled (trash->fence)) { - GList *next = g_list_next (l); - GST_TRACE ("fence %" GST_PTR_FORMAT " has been signalled, notifying", - trash->fence); - trash->notify (trash->fence->device, trash->user_data); - gst_vulkan_trash_free (trash); - trash_list = g_list_delete_link (trash_list, l); - l = next; - } else { - l = g_list_next (l); - } - } - - return trash_list; -} - -gboolean -gst_vulkan_trash_list_wait (GList * trash_list, guint64 timeout) -{ - VkResult err = VK_SUCCESS; - guint i, n; - - /* remove all the previously signaled fences */ - trash_list = gst_vulkan_trash_list_gc (trash_list); - - n = g_list_length (trash_list); - if (n > 0) { - VkFence *fences; - GstVulkanDevice *device = NULL; - GList *l = NULL; - - fences = g_new0 (VkFence, n); - for (i = 0, l = trash_list; i < n; i++, l = g_list_next (l)) { - GstVulkanTrash *trash = l->data; - - if (device == NULL) - device = trash->fence->device; - - fences[i] = trash->fence->fence; - - /* only support waiting on fences from the same device */ - g_assert (device == trash->fence->device); - } - - GST_TRACE ("Waiting on %d fences with timeout %" GST_TIME_FORMAT, n, - GST_TIME_ARGS (timeout)); - err = vkWaitForFences (device->device, n, fences, TRUE, timeout); - g_free (fences); - - trash_list = gst_vulkan_trash_list_gc (trash_list); - } - - return err == VK_SUCCESS; -} - #define FREE_DESTROY_FUNC(func, type, type_name) \ static void \ G_PASTE(_free_,type_name) (GstVulkanDevice * device, type resource) \ @@ -258,3 +209,178 @@ gst_vulkan_trash_new_mini_object_unref (GstVulkanFence * fence, (GstVulkanTrashNotify) _trash_mini_object_unref, object); return trash; } + +G_DEFINE_TYPE (GstVulkanTrashList, gst_vulkan_trash_list, GST_TYPE_OBJECT); + +void +gst_vulkan_trash_list_gc (GstVulkanTrashList * trash_list) +{ + GstVulkanTrashListClass *trash_class; + g_return_if_fail (GST_IS_VULKAN_TRASH_LIST (trash_list)); + trash_class = GST_VULKAN_TRASH_LIST_GET_CLASS (trash_list); + g_return_if_fail (trash_class->gc_func != NULL); + + trash_class->gc_func (trash_list); +} + +gboolean +gst_vulkan_trash_list_add (GstVulkanTrashList * trash_list, + GstVulkanTrash * trash) +{ + GstVulkanTrashListClass *trash_class; + g_return_val_if_fail (GST_IS_VULKAN_TRASH_LIST (trash_list), FALSE); + trash_class = GST_VULKAN_TRASH_LIST_GET_CLASS (trash_list); + g_return_val_if_fail (trash_class->add_func != NULL, FALSE); + + return trash_class->add_func (trash_list, trash); +} + +gboolean +gst_vulkan_trash_list_wait (GstVulkanTrashList * trash_list, guint64 timeout) +{ + GstVulkanTrashListClass *trash_class; + g_return_val_if_fail (GST_IS_VULKAN_TRASH_LIST (trash_list), FALSE); + trash_class = GST_VULKAN_TRASH_LIST_GET_CLASS (trash_list); + g_return_val_if_fail (trash_class->wait_func != NULL, FALSE); + + return trash_class->wait_func (trash_list, timeout); +} + +static void +gst_vulkan_trash_list_class_init (GstVulkanTrashListClass * klass) +{ +} + +static void +gst_vulkan_trash_list_init (GstVulkanTrashList * trash_list) +{ +} + +typedef struct _GstVulkanTrashFenceList GstVulkanTrashFenceList; + +struct _GstVulkanTrashFenceList +{ + GstVulkanTrashList parent; + + GList *list; +}; + +G_DEFINE_TYPE (GstVulkanTrashFenceList, gst_vulkan_trash_fence_list, + GST_TYPE_VULKAN_TRASH_LIST); + +static void +gst_vulkan_trash_fence_list_gc (GstVulkanTrashList * trash_list) +{ + GstVulkanTrashFenceList *fence_list = (GstVulkanTrashFenceList *) trash_list; + GList *l = fence_list->list; + + while (l) { + GstVulkanTrash *trash = l->data; + + if (gst_vulkan_fence_is_signaled (trash->fence)) { + GList *next = g_list_next (l); + GST_TRACE ("fence %" GST_PTR_FORMAT " has been signalled, notifying", + trash->fence); + trash->notify (trash->fence->device, trash->user_data); + gst_vulkan_trash_unref (trash); + fence_list->list = g_list_delete_link (fence_list->list, l); + l = next; + } else { + l = g_list_next (l); + } + } +} + +static gboolean +gst_vulkan_trash_fence_list_wait (GstVulkanTrashList * trash_list, + guint64 timeout) +{ + GstVulkanTrashFenceList *fence_list = (GstVulkanTrashFenceList *) trash_list; + VkResult err = VK_SUCCESS; + guint i, n; + + /* remove all the previously signaled fences */ + gst_vulkan_trash_fence_list_gc (trash_list); + + n = g_list_length (fence_list->list); + if (n > 0) { + VkFence *fences; + GstVulkanDevice *device = NULL; + GList *l = NULL; + + fences = g_new0 (VkFence, n); + for (i = 0, l = fence_list->list; i < n; i++, l = g_list_next (l)) { + GstVulkanTrash *trash = l->data; + + if (device == NULL) + device = trash->fence->device; + + fences[i] = trash->fence->fence; + + /* only support waiting on fences from the same device */ + g_assert (device == trash->fence->device); + } + + GST_TRACE ("Waiting on %d fences with timeout %" GST_TIME_FORMAT, n, + GST_TIME_ARGS (timeout)); + err = vkWaitForFences (device->device, n, fences, TRUE, timeout); + g_free (fences); + + gst_vulkan_trash_fence_list_gc (trash_list); + } + + return err == VK_SUCCESS; +} + +static gboolean +gst_vulkan_trash_fence_list_add (GstVulkanTrashList * trash_list, + GstVulkanTrash * trash) +{ + GstVulkanTrashFenceList *fence_list = (GstVulkanTrashFenceList *) trash_list; + + g_return_val_if_fail (GST_MINI_OBJECT_TYPE (trash) == GST_TYPE_VULKAN_TRASH, + FALSE); + + /* XXX: do something better based on the actual fence */ + fence_list->list = g_list_prepend (fence_list->list, trash); + + return TRUE; +} + +static void +gst_vulkan_trash_fence_list_finalize (GObject * object) +{ + GstVulkanTrashList *trash_list = (GstVulkanTrashList *) object; + GstVulkanTrashFenceList *fence_list = (GstVulkanTrashFenceList *) object; + + gst_vulkan_trash_fence_list_gc (trash_list); + g_warn_if_fail (fence_list->list == NULL); + + G_OBJECT_CLASS (gst_vulkan_trash_fence_list_parent_class)->finalize (object); +} + +static void +gst_vulkan_trash_fence_list_class_init (GstVulkanTrashFenceListClass * klass) +{ + GstVulkanTrashListClass *trash_class = (GstVulkanTrashListClass *) klass; + GObjectClass *object_class = (GObjectClass *) klass; + + trash_class->add_func = gst_vulkan_trash_fence_list_add; + trash_class->gc_func = gst_vulkan_trash_fence_list_gc; + trash_class->wait_func = gst_vulkan_trash_fence_list_wait; + + object_class->finalize = gst_vulkan_trash_fence_list_finalize; +} + +static void +gst_vulkan_trash_fence_list_init (GstVulkanTrashFenceList * trash_list) +{ +} + +GstVulkanTrashList * +gst_vulkan_trash_fence_list_new (void) +{ + return g_object_new (gst_vulkan_trash_fence_list_get_type (), NULL); +} + +GST_DEFINE_MINI_OBJECT_TYPE (GstVulkanTrash, gst_vulkan_trash); diff --git a/ext/vulkan/vktrash.h b/gst-libs/gst/vulkan/gstvktrash.h similarity index 55% rename from ext/vulkan/vktrash.h rename to gst-libs/gst/vulkan/gstvktrash.h index cd84b371e1..c8253008d5 100644 --- a/ext/vulkan/vktrash.h +++ b/gst-libs/gst/vulkan/gstvktrash.h @@ -27,54 +27,145 @@ G_BEGIN_DECLS typedef void (*GstVulkanTrashNotify) (GstVulkanDevice * device, gpointer user_data); -typedef struct _GstVulkanTrash GstVulkanTrash; - struct _GstVulkanTrash { + GstMiniObject parent; + GstVulkanFence *fence; GstVulkanTrashNotify notify; gpointer user_data; }; +#define GST_TYPE_VULKAN_TRASH gst_vulkan_trash_get_type() +GST_VULKAN_API +GType gst_vulkan_trash_get_type (void); + +/** + * gst_vulkan_trash_ref: (skip) + * @trash: a #GstVulkanTrash. + * + * Increases the refcount of the given trash object by one. + * + * Returns: (transfer full): @trash + */ +static inline GstVulkanTrash* gst_vulkan_trash_ref(GstVulkanTrash* trash); +static inline GstVulkanTrash * +gst_vulkan_trash_ref (GstVulkanTrash * trash) +{ + return (GstVulkanTrash *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (trash)); +} + +/** + * gst_vulkan_trash_unref: (skip) + * @trash: (transfer full): a #GstVulkanTrash. + * + * Decreases the refcount of the trash object. If the refcount reaches 0, the + * trash will be freed. + */ +static inline void gst_vulkan_trash_unref(GstVulkanTrash* trash); +static inline void +gst_vulkan_trash_unref (GstVulkanTrash * trash) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (trash)); +} + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVulkanTrash, gst_vulkan_trash_unref) +#endif + +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new (GstVulkanFence * fence, GstVulkanTrashNotify notify, gpointer user_data); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_descriptor_pool (GstVulkanFence * fence, VkDescriptorPool descriptor_pool); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_descriptor_set_layout (GstVulkanFence * fence, VkDescriptorSetLayout descriptor_set_layout); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_framebuffer (GstVulkanFence * fence, VkFramebuffer framebuffer); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_pipeline (GstVulkanFence * fence, VkPipeline pipeline); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_pipeline_layout (GstVulkanFence * fence, VkPipelineLayout pipeline_layout); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_render_pass (GstVulkanFence * fence, VkRenderPass render_pass); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_sampler (GstVulkanFence * fence, VkSampler sampler); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_semaphore (GstVulkanFence * fence, VkSemaphore semaphore); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_command_buffer (GstVulkanFence * fence, GstVulkanCommandPool * parent, VkCommandBuffer command_buffer); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_free_descriptor_set (GstVulkanFence * fence, VkDescriptorPool parent, VkDescriptorSet descriptor_set); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_object_unref (GstVulkanFence * fence, GstObject * object); +GST_VULKAN_API GstVulkanTrash * gst_vulkan_trash_new_mini_object_unref (GstVulkanFence * fence, GstMiniObject * object); -void gst_vulkan_trash_free (GstVulkanTrash * trash); +#define GST_TYPE_VULKAN_TRASH_LIST gst_vulkan_trash_list_get_type() +GST_VULKAN_API +GType gst_vulkan_trash_list_get_type (void); +#define GST_VULKAN_TRASH_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VULKAN_TRASH_LIST,GstVulkanTrashList)) +#define GST_VULKAN_TRASH_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VULKAN_TRASH_LIST,GstVulkanTrashListClass)) +#define GST_VULKAN_TRASH_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_VULKAN_TRASH_LIST,GstVulkanTrashListClass)) +#define GST_IS_VULKAN_TRASH_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VULKAN_TRASH_LIST)) +#define GST_IS_VULKAN_TRASH_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VULKAN_TRASH_LIST)) -GList * gst_vulkan_trash_list_gc (GList * trash_list); -gboolean gst_vulkan_trash_list_wait (GList * trash_list, +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVulkanTrashList, gst_object_unref) +#endif + +struct _GstVulkanTrashList +{ + GstObject parent; +}; + +typedef void (*GstVulkanTrashListGC) (GstVulkanTrashList * trash_list); +typedef gboolean (*GstVulkanTrashListAdd) (GstVulkanTrashList * trash_list, GstVulkanTrash * trash); +typedef gboolean (*GstVulkanTrashListWait) (GstVulkanTrashList * trash_list, guint64 timeout); + +struct _GstVulkanTrashListClass +{ + GstObjectClass parent_class; + + GstVulkanTrashListAdd add_func; + GstVulkanTrashListGC gc_func; + GstVulkanTrashListWait wait_func; + + gpointer _padding[GST_PADDING]; +}; + +GST_VULKAN_API +void gst_vulkan_trash_list_gc (GstVulkanTrashList * trash_list); +GST_VULKAN_API +gboolean gst_vulkan_trash_list_wait (GstVulkanTrashList * trash_list, guint64 timeout); +GST_VULKAN_API +gboolean gst_vulkan_trash_list_add (GstVulkanTrashList * trash_list, + GstVulkanTrash * trash); + +GST_VULKAN_API +G_DECLARE_FINAL_TYPE (GstVulkanTrashFenceList, gst_vulkan_trash_fence_list, GST, VULKAN_TRASH_FENCE_LIST, GstVulkanTrashList); +GST_VULKAN_API +GstVulkanTrashList * gst_vulkan_trash_fence_list_new (void); G_END_DECLS diff --git a/gst-libs/gst/vulkan/meson.build b/gst-libs/gst/vulkan/meson.build index 1ada67e182..71dd579aef 100644 --- a/gst-libs/gst/vulkan/meson.build +++ b/gst-libs/gst/vulkan/meson.build @@ -17,6 +17,7 @@ vulkan_sources = [ 'gstvkinstance.c', 'gstvkmemory.c', 'gstvkqueue.c', + 'gstvktrash.c', 'gstvkutils.c', 'gstvkwindow.c', ] @@ -36,6 +37,7 @@ vulkan_headers = [ 'gstvkinstance.h', 'gstvkmemory.h', 'gstvkqueue.h', + 'gstvktrash.h', 'gstvkutils.h', 'gstvkwindow.h', 'vulkan-prelude.h', diff --git a/gst-libs/gst/vulkan/vulkan.h b/gst-libs/gst/vulkan/vulkan.h index 62f6828d3b..987de82c57 100644 --- a/gst-libs/gst/vulkan/vulkan.h +++ b/gst-libs/gst/vulkan/vulkan.h @@ -41,5 +41,6 @@ #include #include #include +#include #endif /* __GST_VULKAN_H__ */ diff --git a/gst-libs/gst/vulkan/vulkan_fwd.h b/gst-libs/gst/vulkan/vulkan_fwd.h index 19cdd1be23..dbb5ace018 100644 --- a/gst-libs/gst/vulkan/vulkan_fwd.h +++ b/gst-libs/gst/vulkan/vulkan_fwd.h @@ -74,6 +74,11 @@ typedef struct _GstVulkanBarrierMemoryInfo GstVulkanBarrierMemoryInfo; typedef struct _GstVulkanBarrierBufferInfo GstVulkanBarrierBufferInfo; typedef struct _GstVulkanBarrierImageInfo GstVulkanBarrierImageInfo; +typedef struct _GstVulkanTrashList GstVulkanTrashList; +typedef struct _GstVulkanTrashListClass GstVulkanTrashListClass; + +typedef struct _GstVulkanTrash GstVulkanTrash; + G_END_DECLS #endif /* __GST_VULKAN_FWD_H__ */