From 24d096597b6073c314b56a511d366ccde746a8fd Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Wed, 27 Nov 2019 00:25:16 +1100 Subject: vulkan: implement caching and reuse of a couple of vulkan resources Includes a new GstVulkanHandlePool base class for pooling different resources togther. The descriptor cache object is ported to GstVulkanHandlePool with the exact same functionality. A new GstVulkanFenceCache is also implemented for caching fences which is used internally by GstVulkanDevice for creating or reusing fences. The existing GstVulkanTrashFenceList object now caches trash objects. --- ext/vulkan/vkcolorconvert.c | 14 +- ext/vulkan/vkdownload.c | 5 +- ext/vulkan/vkfullscreenquad.c | 58 +++--- ext/vulkan/vkupload.c | 10 +- ext/vulkan/vkviewconvert.c | 8 +- gst-libs/gst/vulkan/gstvkdescriptorcache-private.h | 33 ---- gst-libs/gst/vulkan/gstvkdescriptorcache.c | 141 +++++++-------- gst-libs/gst/vulkan/gstvkdescriptorcache.h | 5 +- gst-libs/gst/vulkan/gstvkdescriptorpool.h | 4 +- gst-libs/gst/vulkan/gstvkdescriptorset.c | 4 +- gst-libs/gst/vulkan/gstvkdevice.c | 39 +++++ gst-libs/gst/vulkan/gstvkdevice.h | 4 + gst-libs/gst/vulkan/gstvkfence.c | 130 +++++++++++++- gst-libs/gst/vulkan/gstvkfence.h | 33 +++- gst-libs/gst/vulkan/gstvkhandlepool.c | 194 +++++++++++++++++++++ gst-libs/gst/vulkan/gstvkhandlepool.h | 74 ++++++++ gst-libs/gst/vulkan/gstvkswapper.c | 4 +- gst-libs/gst/vulkan/gstvktrash.c | 161 ++++++++++++----- gst-libs/gst/vulkan/gstvktrash.h | 43 ++++- gst-libs/gst/vulkan/meson.build | 2 + gst-libs/gst/vulkan/vulkan.h | 1 + gst-libs/gst/vulkan/vulkan_fwd.h | 6 + meson.build | 1 + meson_options.txt | 1 + 24 files changed, 767 insertions(+), 208 deletions(-) delete mode 100644 gst-libs/gst/vulkan/gstvkdescriptorcache-private.h create mode 100644 gst-libs/gst/vulkan/gstvkhandlepool.c create mode 100644 gst-libs/gst/vulkan/gstvkhandlepool.h diff --git a/ext/vulkan/vkcolorconvert.c b/ext/vulkan/vkcolorconvert.c index 0ff0e0dd1..9e14a8a3e 100644 --- a/ext/vulkan/vkcolorconvert.c +++ b/ext/vulkan/vkcolorconvert.c @@ -1209,7 +1209,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, VkResult err; int i; - fence = gst_vulkan_fence_new (vfilter->device, 0, &error); + fence = gst_vulkan_device_create_fence (vfilter->device, &error); if (!fence) goto error; @@ -1226,7 +1226,8 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, in_img_views[i] = get_or_create_image_view ((GstVulkanImageMemory *) img_mem); gst_vulkan_trash_list_add (conv->quad->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (conv->quad->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) in_img_views[i])); } @@ -1280,7 +1281,8 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, gst_memory_ref ((GstMemory *) render_img_mems[i])); } gst_vulkan_trash_list_add (conv->quad->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (conv->quad->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) render_buf)); } else { render_buf = outbuf; @@ -1296,7 +1298,8 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, render_img_views[i] = get_or_create_image_view ((GstVulkanImageMemory *) img_mem); gst_vulkan_trash_list_add (conv->quad->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (conv->quad->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) render_img_views[i])); } } @@ -1445,7 +1448,8 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, /* XXX: try to reuse this image later */ gst_vulkan_trash_list_add (conv->quad->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (conv->quad->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) render_img_mems[i])); } } diff --git a/ext/vulkan/vkdownload.c b/ext/vulkan/vkdownload.c index 897cd1f5a..1bb64b877 100644 --- a/ext/vulkan/vkdownload.c +++ b/ext/vulkan/vkdownload.c @@ -307,7 +307,7 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) }; /* *INDENT-ON* */ - fence = gst_vulkan_fence_new (raw->download->device, 0, &error); + fence = gst_vulkan_device_create_fence (raw->download->device, &error); if (!fence) goto error; @@ -320,7 +320,8 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) goto error; gst_vulkan_trash_list_add (raw->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (raw->trash_list, fence, + gst_vulkan_trash_mini_object_unref, GST_MINI_OBJECT_CAST (cmd_buf))); gst_vulkan_fence_unref (fence); } diff --git a/ext/vulkan/vkfullscreenquad.c b/ext/vulkan/vkfullscreenquad.c index 00f11c14e..4f35c6159 100644 --- a/ext/vulkan/vkfullscreenquad.c +++ b/ext/vulkan/vkfullscreenquad.c @@ -627,7 +627,8 @@ clear_descriptor_set (GstVulkanFullScreenQuad * self) if (self->descriptor_set) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) self->descriptor_set)); self->descriptor_set = NULL; @@ -642,7 +643,8 @@ clear_framebuffer (GstVulkanFullScreenQuad * self) if (self->framebuffer) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) self->framebuffer)); self->framebuffer = NULL; @@ -657,8 +659,8 @@ clear_command_pool (GstVulkanFullScreenQuad * self) if (self->cmd_pool) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_object_unref (last_fence, - (GstObject *) self->cmd_pool)); + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_object_unref, (GstObject *) self->cmd_pool)); self->cmd_pool = NULL; gst_vulkan_fence_unref (last_fence); @@ -672,7 +674,8 @@ clear_sampler (GstVulkanFullScreenQuad * self) if (self->sampler) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) self->sampler)); self->sampler = NULL; @@ -687,7 +690,8 @@ clear_descriptor_cache (GstVulkanFullScreenQuad * self) if (self->descriptor_cache) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_object_unref, (GstObject *) self->descriptor_cache)); self->descriptor_cache = NULL; @@ -703,14 +707,14 @@ clear_shaders (GstVulkanFullScreenQuad * self) if (priv->vert) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, - (GstMiniObject *) priv->vert)); + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) priv->vert)); priv->vert = NULL; if (priv->frag) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, - (GstMiniObject *) priv->frag)); + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) priv->frag)); priv->frag = NULL; gst_vulkan_fence_unref (last_fence); @@ -725,7 +729,8 @@ clear_uniform_data (GstVulkanFullScreenQuad * self) if (priv->uniforms) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) priv->uniforms)); priv->uniforms = NULL; priv->uniform_size = 0; @@ -741,22 +746,26 @@ destroy_pipeline (GstVulkanFullScreenQuad * self) if (self->render_pass) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) self->render_pass)); self->render_pass = NULL; if (self->pipeline_layout) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) self->pipeline_layout)); self->pipeline_layout = NULL; if (self->graphics_pipeline) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) self->graphics_pipeline)); self->graphics_pipeline = NULL; if (self->descriptor_set_layout) gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (last_fence, + gst_vulkan_trash_list_acquire (self->trash_list, last_fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) self->descriptor_set_layout)); self->descriptor_set_layout = NULL; @@ -985,7 +994,7 @@ gst_vulkan_full_screen_quad_draw (GstVulkanFullScreenQuad * self, g_return_val_if_fail (GST_IS_VULKAN_FULL_SCREEN_QUAD (self), FALSE); - fence = gst_vulkan_fence_new (self->queue->device, 0, error); + fence = gst_vulkan_device_create_fence (self->queue->device, error); if (!fence) goto error; @@ -1073,7 +1082,8 @@ gst_vulkan_full_screen_quad_prepare_draw (GstVulkanFullScreenQuad * self, } in_views[i] = get_or_create_image_view (img_mem); gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (self->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) in_views[i])); } if (!(self->descriptor_set = @@ -1091,7 +1101,8 @@ gst_vulkan_full_screen_quad_prepare_draw (GstVulkanFullScreenQuad * self, } out_views[i] = get_or_create_image_view (img_mem); gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (self->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) out_views[i])); } if (!create_framebuffer (self, out_views, error)) @@ -1145,8 +1156,8 @@ gst_vulkan_full_screen_quad_fill_command_buffer (GstVulkanFullScreenQuad * self, } in_views[i] = get_or_create_image_view (img_mem); gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, - (GstMiniObject *) in_views[i])); + gst_vulkan_trash_list_acquire (self->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) in_views[i])); } for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->out_info); i++) { GstVulkanImageMemory *img_mem = peek_image_from_buffer (priv->outbuf, i); @@ -1157,7 +1168,8 @@ gst_vulkan_full_screen_quad_fill_command_buffer (GstVulkanFullScreenQuad * self, } out_views[i] = get_or_create_image_view (img_mem); gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (self->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) out_views[i])); } @@ -1309,8 +1321,8 @@ gst_vulkan_full_screen_quad_submit (GstVulkanFullScreenQuad * self, } gst_vulkan_trash_list_add (self->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, - GST_MINI_OBJECT_CAST (cmd))); + gst_vulkan_trash_list_acquire (self->trash_list, fence, + gst_vulkan_trash_mini_object_unref, GST_MINI_OBJECT_CAST (cmd))); gst_vulkan_trash_list_gc (self->trash_list); diff --git a/ext/vulkan/vkupload.c b/ext/vulkan/vkupload.c index 7edf64d37..0f2a6e9d5 100644 --- a/ext/vulkan/vkupload.c +++ b/ext/vulkan/vkupload.c @@ -599,7 +599,7 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) }; /* *INDENT-ON* */ - fence = gst_vulkan_fence_new (raw->upload->device, 0, &error); + fence = gst_vulkan_device_create_fence (raw->upload->device, &error); if (!fence) goto error; @@ -610,7 +610,8 @@ _buffer_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) goto error; gst_vulkan_trash_list_add (raw->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (raw->trash_list, fence, + gst_vulkan_trash_mini_object_unref, GST_MINI_OBJECT_CAST (cmd_buf))); gst_vulkan_fence_unref (fence); } @@ -983,7 +984,7 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) }; /* *INDENT-ON* */ - fence = gst_vulkan_fence_new (raw->upload->device, 0, &error); + fence = gst_vulkan_device_create_fence (raw->upload->device, &error); if (!fence) goto error; @@ -996,7 +997,8 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf) goto error; gst_vulkan_trash_list_add (raw->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (raw->trash_list, fence, + gst_vulkan_trash_mini_object_unref, GST_MINI_OBJECT_CAST (cmd_buf))); gst_vulkan_fence_unref (fence); } diff --git a/ext/vulkan/vkviewconvert.c b/ext/vulkan/vkviewconvert.c index 8f58325fe..c37b6d2ae 100644 --- a/ext/vulkan/vkviewconvert.c +++ b/ext/vulkan/vkviewconvert.c @@ -1915,7 +1915,7 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, &error)) goto error; - fence = gst_vulkan_fence_new (vfilter->device, 0, &error); + fence = gst_vulkan_device_create_fence (vfilter->device, &error); if (!fence) goto error; @@ -1929,7 +1929,8 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, in_img_views[i] = get_or_create_image_view ((GstVulkanImageMemory *) img_mem); gst_vulkan_trash_list_add (conv->quad->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (conv->quad->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) in_img_views[i])); } for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&conv->quad->out_info); i++) { @@ -1941,7 +1942,8 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, } out_img_views[i] = get_or_create_image_view ((GstVulkanImageMemory *) mem); gst_vulkan_trash_list_add (conv->quad->trash_list, - gst_vulkan_trash_new_mini_object_unref (fence, + gst_vulkan_trash_list_acquire (conv->quad->trash_list, fence, + gst_vulkan_trash_mini_object_unref, (GstMiniObject *) out_img_views[i])); } diff --git a/gst-libs/gst/vulkan/gstvkdescriptorcache-private.h b/gst-libs/gst/vulkan/gstvkdescriptorcache-private.h deleted file mode 100644 index 9c0d50b7e..000000000 --- a/gst-libs/gst/vulkan/gstvkdescriptorcache-private.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2019 Matthew Waters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_VULKAN_DESCRIPTOR_CACHE_PRIVATE_H__ -#define __GST_VULKAN_DESCRIPTOR_CACHE_PRIVATE_H__ - -#include - -G_BEGIN_DECLS - -void gst_vulkan_descriptor_cache_release_set (GstVulkanDescriptorCache * cache, - GstVulkanDescriptorSet * set); - -G_END_DECLS - -#endif /* __GST_VULKAN_COMMAND_POOL_PRIVATE_H__ */ diff --git a/gst-libs/gst/vulkan/gstvkdescriptorcache.c b/gst-libs/gst/vulkan/gstvkdescriptorcache.c index a2dff8a5b..c90156f4e 100644 --- a/gst-libs/gst/vulkan/gstvkdescriptorcache.c +++ b/gst-libs/gst/vulkan/gstvkdescriptorcache.c @@ -23,7 +23,6 @@ #endif #include "gstvkdescriptorcache.h" -#include "gstvkdescriptorcache-private.h" /** * SECTION:vkdescriptorcache @@ -41,42 +40,14 @@ struct _GstVulkanDescriptorCachePrivate { guint n_layouts; GstVulkanHandle **layouts; - - GQueue *available; - gsize outstanding; }; #define parent_class gst_vulkan_descriptor_cache_parent_class G_DEFINE_TYPE_WITH_CODE (GstVulkanDescriptorCache, gst_vulkan_descriptor_cache, - GST_TYPE_OBJECT, G_ADD_PRIVATE (GstVulkanDescriptorCache); + GST_TYPE_VULKAN_HANDLE_POOL, G_ADD_PRIVATE (GstVulkanDescriptorCache); GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "vulkancommandcache", 0, "Vulkan Command Cache")); -static void gst_vulkan_descriptor_cache_finalize (GObject * object); - -static void -gst_vulkan_descriptor_cache_init (GstVulkanDescriptorCache * cache) -{ - GstVulkanDescriptorCachePrivate *priv = GET_PRIV (cache); - - priv->available = g_queue_new (); -} - -static void -gst_vulkan_descriptor_cache_class_init (GstVulkanDescriptorCacheClass * - device_class) -{ - GObjectClass *gobject_class = (GObjectClass *) device_class; - - gobject_class->finalize = gst_vulkan_descriptor_cache_finalize; -} - -static void -do_free_set (GstVulkanHandle * handle) -{ - gst_vulkan_handle_unref (handle); -} - static void gst_vulkan_descriptor_cache_finalize (GObject * object) { @@ -84,17 +55,10 @@ gst_vulkan_descriptor_cache_finalize (GObject * object) GstVulkanDescriptorCachePrivate *priv = GET_PRIV (cache); guint i; - if (priv->outstanding > 0) - g_critical - ("Destroying a Vulkan descriptor cache that has outstanding descriptors!"); - for (i = 0; i < priv->n_layouts; i++) gst_vulkan_handle_unref (priv->layouts[i]); g_free (priv->layouts); - g_queue_free_full (priv->available, (GDestroyNotify) do_free_set); - priv->available = NULL; - gst_clear_object (&cache->pool); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -114,6 +78,7 @@ GstVulkanDescriptorCache * gst_vulkan_descriptor_cache_new (GstVulkanDescriptorPool * pool, guint n_layouts, GstVulkanHandle ** layouts) { + GstVulkanHandlePool *handle_pool; GstVulkanDescriptorCache *ret; GstVulkanDescriptorCachePrivate *priv; guint i; @@ -129,11 +94,61 @@ gst_vulkan_descriptor_cache_new (GstVulkanDescriptorPool * pool, for (i = 0; i < n_layouts; i++) priv->layouts[i] = gst_vulkan_handle_ref (layouts[i]); + handle_pool = GST_VULKAN_HANDLE_POOL (ret); + handle_pool->device = gst_object_ref (pool->device); + gst_object_ref_sink (ret); return ret; } +static gpointer +gst_vulkan_descriptor_cache_acquire_impl (GstVulkanHandlePool * pool, + GError ** error) +{ + GstVulkanDescriptorSet *set; + + if ((set = + GST_VULKAN_HANDLE_POOL_CLASS (parent_class)->acquire (pool, error))) + set->cache = gst_object_ref (pool); + + return set; +} + +static gpointer +gst_vulkan_descriptor_cache_alloc_impl (GstVulkanHandlePool * pool, + GError ** error) +{ + GstVulkanDescriptorCache *desc = GST_VULKAN_DESCRIPTOR_CACHE (pool); + GstVulkanDescriptorCachePrivate *priv = GET_PRIV (desc); + + return gst_vulkan_descriptor_pool_create (desc->pool, priv->n_layouts, + priv->layouts, error); +} + +static void +gst_vulkan_descriptor_cache_release_impl (GstVulkanHandlePool * pool, + gpointer handle) +{ + GstVulkanDescriptorSet *set = handle; + + GST_VULKAN_HANDLE_POOL_CLASS (parent_class)->release (pool, handle); + + /* decrease the refcount that the set had to us */ + gst_clear_object (&set->cache); +} + +static void +gst_vulkan_descriptor_cache_free_impl (GstVulkanHandlePool * pool, + gpointer handle) +{ + GstVulkanDescriptorSet *set = handle; + + GST_VULKAN_HANDLE_POOL_CLASS (parent_class)->free (pool, handle); + + gst_vulkan_descriptor_set_unref (set); +} + /** * gst_vulkan_descriptor_cache_acquire: * @cache: a #GstVulkanDescriptorCache @@ -147,47 +162,25 @@ GstVulkanDescriptorSet * gst_vulkan_descriptor_cache_acquire (GstVulkanDescriptorCache * cache, GError ** error) { - GstVulkanDescriptorSet *set = NULL; - GstVulkanDescriptorCachePrivate *priv; - - g_return_val_if_fail (GST_IS_VULKAN_DESCRIPTOR_CACHE (cache), NULL); - - priv = GET_PRIV (cache); - - GST_OBJECT_LOCK (cache); - set = g_queue_pop_head (priv->available); - GST_OBJECT_UNLOCK (cache); - - if (!set) - set = gst_vulkan_descriptor_pool_create (cache->pool, priv->n_layouts, - priv->layouts, error); - if (!set) - return NULL; - - GST_OBJECT_LOCK (cache); - priv->outstanding++; - GST_OBJECT_UNLOCK (cache); - - set->cache = gst_object_ref (cache); - return set; + return gst_vulkan_handle_pool_acquire (GST_VULKAN_HANDLE_POOL_CAST (cache), + error); } -void -gst_vulkan_descriptor_cache_release_set (GstVulkanDescriptorCache * cache, - GstVulkanDescriptorSet * set) +static void +gst_vulkan_descriptor_cache_init (GstVulkanDescriptorCache * cache) { - GstVulkanDescriptorCachePrivate *priv; - - g_return_if_fail (GST_IS_VULKAN_DESCRIPTOR_CACHE (cache)); - g_return_if_fail (set != NULL); +} - priv = GET_PRIV (cache); +static void +gst_vulkan_descriptor_cache_class_init (GstVulkanDescriptorCacheClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstVulkanHandlePoolClass *handle_class = (GstVulkanHandlePoolClass *) klass; - GST_OBJECT_LOCK (cache); - g_queue_push_tail (priv->available, set); - priv->outstanding--; - GST_OBJECT_UNLOCK (cache); + gobject_class->finalize = gst_vulkan_descriptor_cache_finalize; - /* decrease the refcount that the set had to us */ - gst_clear_object (&set->cache); + handle_class->acquire = gst_vulkan_descriptor_cache_acquire_impl; + handle_class->alloc = gst_vulkan_descriptor_cache_alloc_impl; + handle_class->release = gst_vulkan_descriptor_cache_release_impl; + handle_class->free = gst_vulkan_descriptor_cache_free_impl; } diff --git a/gst-libs/gst/vulkan/gstvkdescriptorcache.h b/gst-libs/gst/vulkan/gstvkdescriptorcache.h index 02d9a6765..b6e9bfc9c 100644 --- a/gst-libs/gst/vulkan/gstvkdescriptorcache.h +++ b/gst-libs/gst/vulkan/gstvkdescriptorcache.h @@ -22,6 +22,7 @@ #define __GST_VULKAN_DESCRIPTOR_CACHE_H__ #include +#include #define GST_TYPE_VULKAN_DESCRIPTOR_CACHE (gst_vulkan_descriptor_cache_get_type()) #define GST_VULKAN_DESCRIPTOR_CACHE(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_VULKAN_DESCRIPTOR_CACHE, GstVulkanDescriptorCache)) @@ -34,14 +35,14 @@ GType gst_vulkan_descriptor_cache_get_type (void); struct _GstVulkanDescriptorCache { - GstObject parent; + GstVulkanHandlePool parent; GstVulkanDescriptorPool *pool; }; struct _GstVulkanDescriptorCacheClass { - GstObjectClass parent_class; + GstVulkanHandlePoolClass parent_class; }; GST_VULKAN_API diff --git a/gst-libs/gst/vulkan/gstvkdescriptorpool.h b/gst-libs/gst/vulkan/gstvkdescriptorpool.h index b2e684026..868a7e1d7 100644 --- a/gst-libs/gst/vulkan/gstvkdescriptorpool.h +++ b/gst-libs/gst/vulkan/gstvkdescriptorpool.h @@ -23,14 +23,14 @@ #include +GST_VULKAN_API +GType gst_vulkan_descriptor_pool_get_type (void); #define GST_TYPE_VULKAN_DESCRIPTOR_POOL (gst_vulkan_descriptor_pool_get_type()) #define GST_VULKAN_DESCRIPTOR_POOL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_VULKAN_DESCRIPTOR_POOL, GstVulkanDescriptorPool)) #define GST_VULKAN_DESCRIPTOR_POOL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GST_TYPE_VULKAN_DESCRIPTOR_POOL, GstVulkanDescriptorPoolClass)) #define GST_IS_VULKAN_DESCRIPTOR_POOL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_VULKAN_DESCRIPTOR_POOL)) #define GST_IS_VULKAN_DESCRIPTOR_POOL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_VULKAN_DESCRIPTOR_POOL)) #define GST_VULKAN_DESCRIPTOR_POOL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_VULKAN_DESCRIPTOR_POOL, GstVulkanDescriptorPoolClass)) -GST_VULKAN_API -GType gst_vulkan_descriptor_pool_get_type (void); struct _GstVulkanDescriptorPool { diff --git a/gst-libs/gst/vulkan/gstvkdescriptorset.c b/gst-libs/gst/vulkan/gstvkdescriptorset.c index a2adacc02..7b335779d 100644 --- a/gst-libs/gst/vulkan/gstvkdescriptorset.c +++ b/gst-libs/gst/vulkan/gstvkdescriptorset.c @@ -32,11 +32,13 @@ #include "gstvkdescriptorset.h" #include "gstvkdescriptorpool.h" #include "gstvkdescriptorcache.h" -#include "gstvkdescriptorcache-private.h" #define GST_CAT_DEFAULT gst_debug_vulkan_descriptor_set GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); +#define gst_vulkan_descriptor_cache_release_set(c,s) \ + gst_vulkan_handle_pool_release (GST_VULKAN_HANDLE_POOL_CAST (c), s); + static void init_debug (void) { diff --git a/gst-libs/gst/vulkan/gstvkdevice.c b/gst-libs/gst/vulkan/gstvkdevice.c index b71216233..dd6c34559 100644 --- a/gst-libs/gst/vulkan/gstvkdevice.c +++ b/gst-libs/gst/vulkan/gstvkdevice.c @@ -49,6 +49,7 @@ enum PROP_PHYSICAL_DEVICE, }; +static void gst_vulkan_device_dispose (GObject * object); static void gst_vulkan_device_finalize (GObject * object); struct _GstVulkanDevicePrivate @@ -56,6 +57,8 @@ struct _GstVulkanDevicePrivate gboolean opened; guint queue_family_id; guint n_queues; + + GstVulkanFenceCache *fence_cache; }; static void @@ -168,6 +171,8 @@ gst_vulkan_device_constructed (GObject * object) GstVulkanDevice *device = GST_VULKAN_DEVICE (object); g_object_get (device->physical_device, "instance", &device->instance, NULL); + + G_OBJECT_CLASS (parent_class)->constructed (object); } static void @@ -178,6 +183,7 @@ gst_vulkan_device_class_init (GstVulkanDeviceClass * device_class) gobject_class->set_property = gst_vulkan_device_set_property; gobject_class->get_property = gst_vulkan_device_get_property; gobject_class->finalize = gst_vulkan_device_finalize; + gobject_class->dispose = gst_vulkan_device_dispose; gobject_class->constructed = gst_vulkan_device_constructed; g_object_class_install_property (gobject_class, PROP_INSTANCE, @@ -191,6 +197,24 @@ gst_vulkan_device_class_init (GstVulkanDeviceClass * device_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } +static void +gst_vulkan_device_dispose (GObject * object) +{ + GstVulkanDevice *device = GST_VULKAN_DEVICE (object); + GstVulkanDevicePrivate *priv = GET_PRIV (device); + + if (priv->fence_cache) { + /* clear any outstanding fences */ + g_object_run_dispose (G_OBJECT (priv->fence_cache)); + + /* don't double free this device */ + priv->fence_cache->parent.device = NULL; + } + gst_clear_object (&priv->fence_cache); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + static void gst_vulkan_device_finalize (GObject * object) { @@ -305,6 +329,10 @@ gst_vulkan_device_open (GstVulkanDevice * device, GError ** error) } } + priv->fence_cache = gst_vulkan_fence_cache_new (device); + /* avoid reference loops between us and the fence cache */ + gst_object_unref (device); + priv->opened = TRUE; GST_OBJECT_UNLOCK (device); return TRUE; @@ -590,3 +618,14 @@ gst_vulkan_device_run_context_query (GstElement * element, return FALSE; } + +GstVulkanFence * +gst_vulkan_device_create_fence (GstVulkanDevice * device, GError ** error) +{ + GstVulkanDevicePrivate *priv; + + g_return_val_if_fail (GST_IS_VULKAN_DEVICE (device), NULL); + priv = GET_PRIV (device); + + return gst_vulkan_fence_cache_acquire (priv->fence_cache, error); +} diff --git a/gst-libs/gst/vulkan/gstvkdevice.h b/gst-libs/gst/vulkan/gstvkdevice.h index 567b2874f..1614f98f3 100644 --- a/gst-libs/gst/vulkan/gstvkdevice.h +++ b/gst-libs/gst/vulkan/gstvkdevice.h @@ -91,6 +91,10 @@ GST_VULKAN_API gboolean gst_vulkan_device_run_context_query (GstElement * element, GstVulkanDevice ** device); +GST_VULKAN_API +GstVulkanFence * gst_vulkan_device_create_fence (GstVulkanDevice * device, + GError ** error); + G_END_DECLS #endif /* __GST_VULKAN_DEVICE_H__ */ diff --git a/gst-libs/gst/vulkan/gstvkfence.c b/gst-libs/gst/vulkan/gstvkfence.c index 8e4ffaf6b..a624b9bcb 100644 --- a/gst-libs/gst/vulkan/gstvkfence.c +++ b/gst-libs/gst/vulkan/gstvkfence.c @@ -23,6 +23,7 @@ #endif #include "gstvkfence.h" +#include "gstvkdevice.h" /** * SECTION:vkfence @@ -36,6 +37,8 @@ GST_DEBUG_CATEGORY (gst_debug_vulkan_fence); #define GST_CAT_DEFAULT gst_debug_vulkan_fence +#define gst_vulkan_fence_cache_release(c,f) gst_vulkan_handle_pool_release(GST_VULKAN_HANDLE_POOL (c), f) + static void _init_debug (void) { @@ -48,6 +51,23 @@ _init_debug (void) } } +static gboolean +gst_vulkan_fence_dispose (GstVulkanFence * fence) +{ + GstVulkanFenceCache *cache; + + /* no pool, do free */ + if ((cache = fence->cache) == NULL) + return TRUE; + + /* keep the buffer alive */ + gst_vulkan_fence_ref (fence); + /* return the buffer to the cache */ + gst_vulkan_fence_cache_release (cache, fence); + + return FALSE; +} + static void gst_vulkan_fence_free (GstVulkanFence * fence) { @@ -59,7 +79,7 @@ gst_vulkan_fence_free (GstVulkanFence * fence) if (fence->fence) vkDestroyFence (fence->device->device, fence->fence, NULL); - gst_object_unref (fence->device); + gst_clear_object (&fence->device); g_free (fence); } @@ -67,7 +87,6 @@ gst_vulkan_fence_free (GstVulkanFence * fence) /** * gst_vulkan_fence_new: * @device: the parent #GstVulkanDevice - * @flags: set of flags to create the fence with * @error: a #GError for the failure condition * * Returns: whether a new #GstVulkanFence or %NULL on error @@ -75,8 +94,7 @@ gst_vulkan_fence_free (GstVulkanFence * fence) * Since: 1.18 */ GstVulkanFence * -gst_vulkan_fence_new (GstVulkanDevice * device, VkFenceCreateFlags flags, - GError ** error) +gst_vulkan_fence_new (GstVulkanDevice * device, GError ** error) { VkFenceCreateInfo fence_info = { 0, }; GstVulkanFence *fence; @@ -92,7 +110,7 @@ gst_vulkan_fence_new (GstVulkanDevice * device, VkFenceCreateFlags flags, fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fence_info.pNext = NULL; - fence_info.flags = flags; + fence_info.flags = 0; err = vkCreateFence (device->device, &fence_info, NULL, &fence->fence); if (gst_vulkan_error_to_g_error (err, error, "vkCreateFence") < 0) { @@ -102,7 +120,8 @@ gst_vulkan_fence_new (GstVulkanDevice * device, VkFenceCreateFlags flags, } gst_mini_object_init (GST_MINI_OBJECT_CAST (fence), 0, GST_TYPE_VULKAN_FENCE, - NULL, NULL, (GstMiniObjectFreeFunction) gst_vulkan_fence_free); + NULL, (GstMiniObjectDisposeFunction) gst_vulkan_fence_dispose, + (GstMiniObjectFreeFunction) gst_vulkan_fence_free); return fence; } @@ -152,4 +171,103 @@ gst_vulkan_fence_is_signaled (GstVulkanFence * fence) return vkGetFenceStatus (fence->device->device, fence->fence) == VK_SUCCESS; } +void +gst_vulkan_fence_reset (GstVulkanFence * fence) +{ + g_return_if_fail (fence != NULL); + + if (!fence->fence) + return; + + GST_TRACE ("resetting fence %p", fence); + vkResetFences (fence->device->device, 1, &fence->fence); +} + GST_DEFINE_MINI_OBJECT_TYPE (GstVulkanFence, gst_vulkan_fence); + +#define parent_class gst_vulkan_fence_cache_parent_class +G_DEFINE_TYPE_WITH_CODE (GstVulkanFenceCache, gst_vulkan_fence_cache, + GST_TYPE_VULKAN_HANDLE_POOL, _init_debug ()); + +GstVulkanFenceCache * +gst_vulkan_fence_cache_new (GstVulkanDevice * device) +{ + GstVulkanFenceCache *ret; + GstVulkanHandlePool *pool; + + g_return_val_if_fail (GST_IS_VULKAN_DEVICE (device), NULL); + + ret = g_object_new (GST_TYPE_VULKAN_FENCE_CACHE, NULL); + + pool = GST_VULKAN_HANDLE_POOL (ret); + pool->device = gst_object_ref (device); + + gst_object_ref_sink (ret); + + return ret; +} + +static gpointer +gst_vulkan_fence_cache_alloc (GstVulkanHandlePool * pool, GError ** error) +{ + return gst_vulkan_fence_new (pool->device, error); +} + +static gpointer +gst_vulkan_fence_cache_acquire_impl (GstVulkanHandlePool * pool, + GError ** error) +{ + GstVulkanFence *fence; + + if ((fence = + GST_VULKAN_HANDLE_POOL_CLASS (parent_class)->acquire (pool, error))) { + fence->cache = gst_object_ref (pool); + if (!fence->device) + fence->device = gst_object_ref (pool->device); + } + + return fence; +} + +static void +gst_vulkan_fence_cache_release_impl (GstVulkanHandlePool * pool, + gpointer handle) +{ + GstVulkanFence *fence = handle; + + gst_vulkan_fence_reset (fence); + + GST_VULKAN_HANDLE_POOL_CLASS (parent_class)->release (pool, handle); + + if (fence) { + gst_clear_object (&fence->cache); + gst_clear_object (&fence->device); + } +} + +static void +gst_vulkan_fence_cache_free (GstVulkanHandlePool * pool, gpointer handle) +{ + GstVulkanFence *fence = handle; + + if (!fence->device) + fence->device = gst_object_ref (pool->device); + + gst_vulkan_fence_unref (handle); +} + +static void +gst_vulkan_fence_cache_init (GstVulkanFenceCache * cache) +{ +} + +static void +gst_vulkan_fence_cache_class_init (GstVulkanFenceCacheClass * klass) +{ + GstVulkanHandlePoolClass *handle_class = (GstVulkanHandlePoolClass *) klass; + + handle_class->acquire = gst_vulkan_fence_cache_acquire_impl; + handle_class->alloc = gst_vulkan_fence_cache_alloc; + handle_class->release = gst_vulkan_fence_cache_release_impl; + handle_class->free = gst_vulkan_fence_cache_free; +} diff --git a/gst-libs/gst/vulkan/gstvkfence.h b/gst-libs/gst/vulkan/gstvkfence.h index a395bf68d..069eb1dda 100644 --- a/gst-libs/gst/vulkan/gstvkfence.h +++ b/gst-libs/gst/vulkan/gstvkfence.h @@ -21,7 +21,7 @@ #ifndef __GST_VULKAN_FENCE_H__ #define __GST_VULKAN_FENCE_H__ -#include +#include G_BEGIN_DECLS @@ -37,14 +37,17 @@ struct _GstVulkanFence GstMiniObject parent; GstVulkanDevice *device; + GstVulkanFenceCache *cache; VkFence fence; }; GST_VULKAN_API GstVulkanFence * gst_vulkan_fence_new (GstVulkanDevice * device, - VkFenceCreateFlags flags, GError ** error); +GST_VULKAN_API +void gst_vulkan_fence_reset (GstVulkanFence * fence); + GST_VULKAN_API GstVulkanFence * gst_vulkan_fence_new_always_signalled (GstVulkanDevice *device); @@ -63,6 +66,32 @@ gst_vulkan_fence_unref (GstVulkanFence * fence) gst_mini_object_unref (GST_MINI_OBJECT_CAST (fence)); } +GST_VULKAN_API +GType gst_vulkan_fence_cache_get_type (void); +#define GST_TYPE_VULKAN_FENCE_CACHE (gst_vulkan_fence_cache_get_type()) +#define GST_VULKAN_FENCE_CACHE(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_TYPE_VULKAN_FENCE_CACHE, GstVulkanFenceCache)) +#define GST_VULKAN_FENCE_CACHE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GST_TYPE_VULKAN_FENCE_CACHE, GstVulkanFenceCacheClass)) +#define GST_IS_VULKAN_FENCE_CACHE(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_VULKAN_FENCE_CACHE)) +#define GST_IS_VULKAN_FENCE_CACHE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_VULKAN_FENCE_CACHE)) +#define GST_VULKAN_FENCE_CACHE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_VULKAN_FENCE_CACHE, GstVulkanFenceCacheClass)) + +struct _GstVulkanFenceCache +{ + GstVulkanHandlePool parent; + + /* */ + gpointer _reserved [GST_PADDING]; +}; + +struct _GstVulkanFenceCacheClass +{ + GstVulkanHandlePoolClass parent_class; +}; + +GstVulkanFenceCache * gst_vulkan_fence_cache_new (GstVulkanDevice * device); + +#define gst_vulkan_fence_cache_acquire(o,e) (GstVulkanFence *) gst_vulkan_handle_pool_acquire (GST_VULKAN_HANDLE_POOL (o),e); + G_END_DECLS #endif /* __GST_VULKAN_FENCE_H__ */ diff --git a/gst-libs/gst/vulkan/gstvkhandlepool.c b/gst-libs/gst/vulkan/gstvkhandlepool.c new file mode 100644 index 000000000..22cc975aa --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkhandlepool.c @@ -0,0 +1,194 @@ +/* + * GStreamer + * Copyright (C) 2019 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +/** + * SECTION:vulkanhandlepool + * @title: vulkanhandlepool + * + * #GstVulkanHandlePool holds a number of handles that are pooled together. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvkhandlepool.h" +#include "gstvkdevice.h" + +#define GST_VULKAN_HANDLE_POOL_LARGE_OUTSTANDING 1024 + +#define GST_CAT_DEFAULT gst_debug_vulkan_handle_pool +GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); + +#define parent_class gst_vulkan_handle_pool_parent_class +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstVulkanHandlePool, gst_vulkan_handle_pool, + GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, + "vulkanhandlepool", 0, "Vulkan handle pool")); + +static gpointer +gst_vulkan_handle_pool_default_alloc (GstVulkanHandlePool * pool, + GError ** error) +{ + return NULL; +} + +static gpointer +gst_vulkan_handle_pool_default_acquire (GstVulkanHandlePool * pool, + GError ** error) +{ + gpointer ret; + + GST_OBJECT_LOCK (pool); + if (pool->available->len > 0) { + ret = g_ptr_array_remove_index_fast (pool->available, 0); + } else { + ret = gst_vulkan_handle_pool_alloc (pool, error); + } + + if (ret) { + g_ptr_array_add (pool->outstanding, ret); + +#if defined(GST_ENABLE_EXTRA_CHECKS) + if (pool->outstanding->len > GST_VULKAN_HANDLE_POOL_LARGE_OUTSTANDING) + g_critical ("%s: There are a large number of handles outstanding! " + "This usually means there is a reference counting issue somewhere.", + GST_OBJECT_NAME (pool)); +#endif + } + GST_OBJECT_UNLOCK (pool); + + return ret; +} + +static void +gst_vulkan_handle_pool_default_release (GstVulkanHandlePool * pool, + gpointer handle) +{ + GST_OBJECT_LOCK (pool); + if (!g_ptr_array_remove_fast (pool->outstanding, handle)) { + g_warning ("%s: Attempt was made to release a handle (%p) that does not " + "belong to us", GST_OBJECT_NAME (pool), handle); + GST_OBJECT_UNLOCK (pool); + return; + } + + g_ptr_array_add (pool->available, handle); + GST_OBJECT_UNLOCK (pool); +} + +static void +gst_vulkan_handle_pool_default_free (GstVulkanHandlePool * pool, + gpointer handle) +{ +} + +static void +do_free_handle (gpointer handle, GstVulkanHandlePool * pool) +{ + GstVulkanHandlePoolClass *klass = GST_VULKAN_HANDLE_POOL_GET_CLASS (pool); + klass->free (pool, handle); +} + +static void +gst_vulkan_handle_pool_dispose (GObject * object) +{ + GstVulkanHandlePool *pool = GST_VULKAN_HANDLE_POOL (object); + + if (pool->outstanding) { + g_warn_if_fail (pool->outstanding->len <= 0); + g_ptr_array_unref (pool->outstanding); + } + pool->outstanding = NULL; + + if (pool->available) { + g_ptr_array_foreach (pool->available, (GFunc) do_free_handle, pool); + g_ptr_array_unref (pool->available); + } + pool->available = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_vulkan_handle_pool_finalize (GObject * object) +{ + GstVulkanHandlePool *pool = GST_VULKAN_HANDLE_POOL (object); + + gst_clear_object (&pool->device); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_vulkan_handle_pool_init (GstVulkanHandlePool * handle) +{ + handle->outstanding = g_ptr_array_new (); + handle->available = g_ptr_array_new (); +} + +static void +gst_vulkan_handle_pool_class_init (GstVulkanHandlePoolClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gst_vulkan_handle_pool_dispose; + gobject_class->finalize = gst_vulkan_handle_pool_finalize; + + klass->alloc = gst_vulkan_handle_pool_default_alloc; + klass->acquire = gst_vulkan_handle_pool_default_acquire; + klass->release = gst_vulkan_handle_pool_default_release; + klass->free = gst_vulkan_handle_pool_default_free; +} + +gpointer +gst_vulkan_handle_pool_alloc (GstVulkanHandlePool * pool, GError ** error) +{ + GstVulkanHandlePoolClass *klass; + + g_return_val_if_fail (GST_IS_VULKAN_HANDLE_POOL (pool), NULL); + klass = GST_VULKAN_HANDLE_POOL_GET_CLASS (pool); + g_return_val_if_fail (klass->alloc != NULL, NULL); + + return klass->alloc (pool, error); +} + +gpointer +gst_vulkan_handle_pool_acquire (GstVulkanHandlePool * pool, GError ** error) +{ + GstVulkanHandlePoolClass *klass; + + g_return_val_if_fail (GST_IS_VULKAN_HANDLE_POOL (pool), NULL); + klass = GST_VULKAN_HANDLE_POOL_GET_CLASS (pool); + g_return_val_if_fail (klass->acquire != NULL, NULL); + + return klass->acquire (pool, error); +} + +void +gst_vulkan_handle_pool_release (GstVulkanHandlePool * pool, gpointer handle) +{ + GstVulkanHandlePoolClass *klass; + + g_return_if_fail (GST_IS_VULKAN_HANDLE_POOL (pool)); + klass = GST_VULKAN_HANDLE_POOL_GET_CLASS (pool); + g_return_if_fail (klass->release != NULL); + + klass->release (pool, handle); +} diff --git a/gst-libs/gst/vulkan/gstvkhandlepool.h b/gst-libs/gst/vulkan/gstvkhandlepool.h new file mode 100644 index 000000000..a3acde310 --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkhandlepool.h @@ -0,0 +1,74 @@ +/* + * GStreamer + * Copyright (C) 2019 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_VULKAN_HANDLE_POOL_H__ +#define __GST_VULKAN_HANDLE_POOL_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +GST_VULKAN_API +GType gst_vulkan_handle_pool_get_type (void); +#define GST_TYPE_VULKAN_HANDLE_POOL (gst_vulkan_handle_pool_get_type()) +#define GST_VULKAN_HANDLE_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VULKAN_HANDLE_POOL,GstVulkanHandlePool)) +#define GST_VULKAN_HANDLE_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VULKAN_HANDLE_POOL,GstVulkanHandlePoolClass)) +#define GST_IS_VULKAN_HANDLE_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VULKAN_HANDLE_POOL)) +#define GST_IS_VULKAN_HANDLE_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VULKAN_HANDLE_POOL)) +#define GST_VULKAN_HANDLE_POOL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_VULKAN_HANDLE_POOL, GstVulkanHandlePoolClass)) +#define GST_VULKAN_HANDLE_POOL_CAST(o) ((GstVulkanHandlePool *) o) + +struct _GstVulkanHandlePool +{ + GstObject parent; + + GstVulkanDevice *device; + + /* */ + GPtrArray *outstanding; + GPtrArray *available; + + /* */ + gpointer _padding[GST_PADDING]; +}; + +struct _GstVulkanHandlePoolClass +{ + GstObjectClass parent; + + gpointer (*alloc) (GstVulkanHandlePool * pool, GError ** error); + gpointer (*acquire) (GstVulkanHandlePool * pool, GError ** error); + void (*release) (GstVulkanHandlePool * pool, gpointer handle); + void (*free) (GstVulkanHandlePool * pool, gpointer handle); +}; + +GST_VULKAN_API +gpointer gst_vulkan_handle_pool_alloc (GstVulkanHandlePool * pool, GError ** error); +GST_VULKAN_API +gpointer gst_vulkan_handle_pool_acquire (GstVulkanHandlePool * pool, GError ** error); +GST_VULKAN_API +void gst_vulkan_handle_pool_release (GstVulkanHandlePool * pool, gpointer handle); + +G_END_DECLS + +#endif /* _GST_VULKAN_HANDLE_H_ */ diff --git a/gst-libs/gst/vulkan/gstvkswapper.c b/gst-libs/gst/vulkan/gstvkswapper.c index 3000bb093..92198190b 100644 --- a/gst-libs/gst/vulkan/gstvkswapper.c +++ b/gst-libs/gst/vulkan/gstvkswapper.c @@ -1264,7 +1264,7 @@ reacquire: }; /* *INDENT-ON* */ - fence = gst_vulkan_fence_new (swapper->device, 0, error); + fence = gst_vulkan_device_create_fence (swapper->device, error); if (!fence) goto error; @@ -1324,7 +1324,7 @@ reacquire: }; /* *INDENT-ON* */ - fence = gst_vulkan_fence_new (swapper->device, 0, error); + fence = gst_vulkan_device_create_fence (swapper->device, error); if (!fence) goto error; diff --git a/gst-libs/gst/vulkan/gstvktrash.c b/gst-libs/gst/vulkan/gstvktrash.c index f911d16c8..abce93c1f 100644 --- a/gst-libs/gst/vulkan/gstvktrash.c +++ b/gst-libs/gst/vulkan/gstvktrash.c @@ -28,6 +28,9 @@ GST_DEBUG_CATEGORY (gst_debug_vulkan_trash); #define GST_CAT_DEFAULT gst_debug_vulkan_trash +#define gst_vulkan_trash_release(c,t) \ + gst_vulkan_handle_pool_release (GST_VULKAN_HANDLE_POOL_CAST (c), t); + static void _init_debug (void) { @@ -40,21 +43,68 @@ _init_debug (void) } } +static gboolean +gst_vulkan_trash_dispose (GstVulkanTrash * trash) +{ + GstVulkanTrashList *cache; + + /* no pool, do free */ + if ((cache = trash->cache) == NULL) + return TRUE; + + /* keep the buffer alive */ + gst_vulkan_trash_ref (trash); + /* return the buffer to the pool */ + gst_vulkan_trash_release (cache, trash); + + return FALSE; +} + +static void +gst_vulkan_trash_deinit (GstVulkanTrash * trash) +{ + if (trash->fence) { + g_warn_if_fail (gst_vulkan_fence_is_signaled (trash->fence)); + gst_vulkan_fence_unref (trash->fence); + trash->fence = NULL; + } + + trash->notify = NULL; + trash->user_data = NULL; +} + static void gst_vulkan_trash_free (GstMiniObject * object) { 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); - gst_vulkan_fence_unref (trash->fence); + gst_vulkan_trash_deinit (trash); g_free (trash); } +static void +gst_vulkan_trash_init (GstVulkanTrash * trash, GstVulkanFence * fence, + GstVulkanTrashNotify notify, gpointer user_data) +{ + g_return_if_fail (fence != NULL); + g_return_if_fail (GST_IS_VULKAN_DEVICE (fence->device)); + g_return_if_fail (notify != NULL); + + gst_mini_object_init ((GstMiniObject *) trash, 0, + gst_vulkan_trash_get_type (), NULL, + (GstMiniObjectDisposeFunction) gst_vulkan_trash_dispose, + (GstMiniObjectFreeFunction) gst_vulkan_trash_free); + GST_TRACE ("Initializing trash object %p with fence %" GST_PTR_FORMAT + " on device %" GST_PTR_FORMAT, trash, fence, fence->device); + trash->fence = gst_vulkan_fence_ref (fence); + trash->notify = notify; + trash->user_data = user_data; +} + /** * gst_vulkan_trash_new: * @fence: a #GstVulkanFence @@ -81,11 +131,7 @@ 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 = gst_vulkan_fence_ref (fence); - ret->notify = notify; - ret->user_data = user_data; + gst_vulkan_trash_init (ret, fence, notify, user_data); return ret; } @@ -160,40 +206,21 @@ G_PASTE(gst_vulkan_trash_new_free_,type_name) (GstVulkanFence * fence, \ return trash; \ } -static void -_trash_object_unref (GstVulkanDevice * device, GstObject * object) -{ - gst_object_unref (object); -} - -GstVulkanTrash * -gst_vulkan_trash_new_object_unref (GstVulkanFence * fence, GstObject * object) -{ - GstVulkanTrash *trash; - g_return_val_if_fail (GST_IS_OBJECT (object), NULL); - trash = gst_vulkan_trash_new (fence, - (GstVulkanTrashNotify) _trash_object_unref, object); - return trash; -} - -static void -_trash_mini_object_unref (GstVulkanDevice * device, GstMiniObject * object) +void +gst_vulkan_trash_object_unref (GstVulkanDevice * device, gpointer user_data) { - gst_mini_object_unref (object); + gst_object_unref ((GstObject *) user_data); } -GstVulkanTrash * -gst_vulkan_trash_new_mini_object_unref (GstVulkanFence * fence, - GstMiniObject * object) +void +gst_vulkan_trash_mini_object_unref (GstVulkanDevice * device, + gpointer user_data) { - GstVulkanTrash *trash; - g_return_val_if_fail (object != NULL, NULL); - trash = gst_vulkan_trash_new (fence, - (GstVulkanTrashNotify) _trash_mini_object_unref, object); - return trash; + gst_mini_object_unref ((GstMiniObject *) user_data); } -G_DEFINE_TYPE (GstVulkanTrashList, gst_vulkan_trash_list, GST_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE (GstVulkanTrashList, gst_vulkan_trash_list, + GST_TYPE_VULKAN_HANDLE_POOL, _init_debug ()); void gst_vulkan_trash_list_gc (GstVulkanTrashList * trash_list) @@ -229,9 +256,42 @@ gst_vulkan_trash_list_wait (GstVulkanTrashList * trash_list, guint64 timeout) return trash_class->wait_func (trash_list, timeout); } +static gpointer +gst_vulkan_trash_list_alloc_impl (GstVulkanHandlePool * pool, GError ** error) +{ + return g_new0 (GstVulkanTrash, 1); +} + +static void +gst_vulkan_trash_list_release_impl (GstVulkanHandlePool * pool, gpointer handle) +{ + GstVulkanTrash *trash = handle; + + GST_TRACE_OBJECT (pool, "reset trash object %p", trash); + + gst_vulkan_trash_deinit (trash); + gst_clear_object (&trash->cache); + + GST_VULKAN_HANDLE_POOL_CLASS (gst_vulkan_trash_list_parent_class)->release + (pool, handle); +} + +static void +gst_vulkan_trash_list_free_impl (GstVulkanHandlePool * pool, gpointer handle) +{ + GstVulkanTrash *trash = handle; + + gst_vulkan_trash_unref (trash); +} + static void gst_vulkan_trash_list_class_init (GstVulkanTrashListClass * klass) { + GstVulkanHandlePoolClass *pool_class = (GstVulkanHandlePoolClass *) klass; + + pool_class->alloc = gst_vulkan_trash_list_alloc_impl; + pool_class->release = gst_vulkan_trash_list_release_impl; + pool_class->free = gst_vulkan_trash_list_free_impl; } static void @@ -239,6 +299,27 @@ gst_vulkan_trash_list_init (GstVulkanTrashList * trash_list) { } +GstVulkanTrash * +gst_vulkan_trash_list_acquire (GstVulkanTrashList * trash_list, + GstVulkanFence * fence, GstVulkanTrashNotify notify, gpointer user_data) +{ + GstVulkanHandlePool *pool = GST_VULKAN_HANDLE_POOL (trash_list); + GstVulkanHandlePoolClass *pool_class; + GstVulkanTrash *trash; + + g_return_val_if_fail (GST_IS_VULKAN_TRASH_LIST (trash_list), NULL); + + pool_class = GST_VULKAN_HANDLE_POOL_GET_CLASS (trash_list); + + trash = pool_class->acquire (pool, NULL); + gst_vulkan_trash_init (trash, fence, notify, user_data); + trash->cache = gst_object_ref (trash_list); + + GST_TRACE_OBJECT (trash_list, "acquired trash object %p", trash); + + return trash; +} + typedef struct _GstVulkanTrashFenceList GstVulkanTrashFenceList; struct _GstVulkanTrashFenceList @@ -262,8 +343,8 @@ gst_vulkan_trash_fence_list_gc (GstVulkanTrashList * trash_list) 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); + GST_TRACE_OBJECT (fence_list, "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); @@ -304,8 +385,8 @@ gst_vulkan_trash_fence_list_wait (GstVulkanTrashList * trash_list, g_assert (device == trash->fence->device); } - GST_TRACE ("Waiting on %d fences with timeout %" GST_TIME_FORMAT, n, - GST_TIME_ARGS (timeout)); + GST_TRACE_OBJECT (trash_list, "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); diff --git a/gst-libs/gst/vulkan/gstvktrash.h b/gst-libs/gst/vulkan/gstvktrash.h index d00902224..29e2b5542 100644 --- a/gst-libs/gst/vulkan/gstvktrash.h +++ b/gst-libs/gst/vulkan/gstvktrash.h @@ -31,10 +31,15 @@ struct _GstVulkanTrash { GstMiniObject parent; + GstVulkanTrashList *cache; + GstVulkanFence *fence; GstVulkanTrashNotify notify; gpointer user_data; + + /* */ + gpointer _padding[GST_PADDING]; }; #define GST_TYPE_VULKAN_TRASH gst_vulkan_trash_get_type() @@ -79,18 +84,33 @@ GstVulkanTrash * gst_vulkan_trash_new (GstVulkanFe GstVulkanTrashNotify notify, gpointer user_data); GST_VULKAN_API -GstVulkanTrash * gst_vulkan_trash_new_free_semaphore (GstVulkanFence * fence, - VkSemaphore semaphore); +void gst_vulkan_trash_mini_object_unref (GstVulkanDevice * device, + gpointer user_data); GST_VULKAN_API -GstVulkanTrash * gst_vulkan_trash_new_object_unref (GstVulkanFence * fence, - GstObject * object); +void gst_vulkan_trash_object_unref (GstVulkanDevice * device, + gpointer user_data); GST_VULKAN_API -GstVulkanTrash * gst_vulkan_trash_new_mini_object_unref (GstVulkanFence * fence, - GstMiniObject * object); +GstVulkanTrash * gst_vulkan_trash_new_free_semaphore (GstVulkanFence * fence, + VkSemaphore semaphore); + +static inline GstVulkanTrash * +gst_vulkan_trash_new_object_unref (GstVulkanFence * fence, GstObject * object) +{ + g_return_val_if_fail (GST_IS_OBJECT (object), NULL); + return gst_vulkan_trash_new (fence, + (GstVulkanTrashNotify) gst_vulkan_trash_object_unref, (gpointer) object); +} + +static inline GstVulkanTrash * +gst_vulkan_trash_new_mini_object_unref (GstVulkanFence * fence, GstMiniObject * object) +{ + return gst_vulkan_trash_new (fence, + (GstVulkanTrashNotify) gst_vulkan_trash_mini_object_unref, (gpointer) object); +} -#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_TYPE_VULKAN_TRASH_LIST gst_vulkan_trash_list_get_type() #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)) @@ -103,7 +123,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVulkanTrashList, gst_object_unref) struct _GstVulkanTrashList { - GstObject parent; + GstVulkanHandlePool parent; }; typedef void (*GstVulkanTrashListGC) (GstVulkanTrashList * trash_list); @@ -112,7 +132,7 @@ typedef gboolean (*GstVulkanTrashListWait) (GstVulkanTrashList * trash_list struct _GstVulkanTrashListClass { - GstObjectClass parent_class; + GstVulkanHandlePoolClass parent_class; GstVulkanTrashListAdd add_func; GstVulkanTrashListGC gc_func; @@ -129,6 +149,11 @@ gboolean gst_vulkan_trash_list_wait (GstVulkanTr GST_VULKAN_API gboolean gst_vulkan_trash_list_add (GstVulkanTrashList * trash_list, GstVulkanTrash * trash); +GST_VULKAN_API +GstVulkanTrash * gst_vulkan_trash_list_acquire (GstVulkanTrashList * trash_list, + GstVulkanFence * fence, + GstVulkanTrashNotify notify, + gpointer user_data); GST_VULKAN_API G_DECLARE_FINAL_TYPE (GstVulkanTrashFenceList, gst_vulkan_trash_fence_list, GST, VULKAN_TRASH_FENCE_LIST, GstVulkanTrashList); diff --git a/gst-libs/gst/vulkan/meson.build b/gst-libs/gst/vulkan/meson.build index 2878566b1..8b3268ef6 100644 --- a/gst-libs/gst/vulkan/meson.build +++ b/gst-libs/gst/vulkan/meson.build @@ -18,6 +18,7 @@ vulkan_sources = [ 'gstvkfence.c', 'gstvkformat.c', 'gstvkhandle.c', + 'gstvkhandlepool.c', 'gstvkimagememory.c', 'gstvkimagebufferpool.c', 'gstvkimageview.c', @@ -49,6 +50,7 @@ vulkan_headers = [ 'gstvkfence.h', 'gstvkformat.h', 'gstvkhandle.h', + 'gstvkhandlepool.h', 'gstvkimagememory.h', 'gstvkimagebufferpool.h', 'gstvkimageview.h', diff --git a/gst-libs/gst/vulkan/vulkan.h b/gst-libs/gst/vulkan/vulkan.h index 013379304..bdf10f445 100644 --- a/gst-libs/gst/vulkan/vulkan.h +++ b/gst-libs/gst/vulkan/vulkan.h @@ -50,6 +50,7 @@ #include #include #include +#include #include #include diff --git a/gst-libs/gst/vulkan/vulkan_fwd.h b/gst-libs/gst/vulkan/vulkan_fwd.h index c542cccf5..f489fc3a7 100644 --- a/gst-libs/gst/vulkan/vulkan_fwd.h +++ b/gst-libs/gst/vulkan/vulkan_fwd.h @@ -69,6 +69,9 @@ typedef struct _GstVulkanWindowPrivate GstVulkanWindowPrivate; typedef struct _GstVulkanFence GstVulkanFence; +typedef struct _GstVulkanFenceCache GstVulkanFenceCache; +typedef struct _GstVulkanFenceCacheClass GstVulkanFenceCacheClass; + typedef struct _GstVulkanMemory GstVulkanMemory; typedef struct _GstVulkanMemoryAllocator GstVulkanMemoryAllocator; typedef struct _GstVulkanMemoryAllocatorClass GstVulkanMemoryAllocatorClass; @@ -83,6 +86,9 @@ typedef struct _GstVulkanBufferPoolPrivate GstVulkanBufferPoolPrivate; typedef struct _GstVulkanHandle GstVulkanHandle; +typedef struct _GstVulkanHandlePool GstVulkanHandlePool; +typedef struct _GstVulkanHandlePoolClass GstVulkanHandlePoolClass; + typedef struct _GstVulkanImageMemory GstVulkanImageMemory; typedef struct _GstVulkanImageMemoryAllocator GstVulkanImageMemoryAllocator; typedef struct _GstVulkanImageMemoryAllocatorClass GstVulkanImageMemoryAllocatorClass; diff --git a/meson.build b/meson.build index 6eabbf1bc..2432f879b 100644 --- a/meson.build +++ b/meson.build @@ -377,6 +377,7 @@ else message('Orc Compiler not found or disabled, will use backup C code') cdata.set('DISABLE_ORC', 1) endif +cdata.set('GST_ENABLE_EXTRA_CHECKS', get_option('extra-checks')) gnustl_dep = declare_dependency() if host_system == 'android' diff --git a/meson_options.txt b/meson_options.txt index b64c1ce78..0bcb5c04c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -181,6 +181,7 @@ option('glib-asserts', type : 'feature', value : 'enabled', yield : true, description: 'Enable GLib assertion (auto = enabled for development, disabled for stable releases)') option('glib-checks', type : 'feature', value : 'enabled', yield : true, description: 'Enable GLib checks such as API guards (auto = enabled for development, disabled for stable releases)') +option('extra-checks', type : 'boolean', value : true, description : 'Enable extra runtime checks') # Common options option('package-name', type : 'string', yield : true, -- cgit v1.2.1