diff options
author | Matthew Waters <matthew@centricular.com> | 2019-11-27 00:25:16 +1100 |
---|---|---|
committer | GStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2019-11-28 23:27:21 +0000 |
commit | 24d096597b6073c314b56a511d366ccde746a8fd (patch) | |
tree | 5da6e030d3f2c9b15614ac9aa1efe4f61994b8e1 | |
parent | 5177c24a7eb59b28022a696d483f540fe489f221 (diff) | |
download | gstreamer-plugins-bad-24d096597b6073c314b56a511d366ccde746a8fd.tar.gz |
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.
24 files changed, 767 insertions, 208 deletions
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 <matthew@centricular.com> - * - * 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 <gst/gst.h> - -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 <gst/vulkan/gstvkqueue.h> +#include <gst/vulkan/gstvkhandlepool.h> #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/gstvkqueue.h> +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, @@ -192,6 +198,24 @@ gst_vulkan_device_class_init (GstVulkanDeviceClass * device_class) } 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) { GstVulkanDevice *device = GST_VULKAN_DEVICE (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 <gst/vulkan/vulkan.h> +#include <gst/vulkan/gstvkhandlepool.h> G_BEGIN_DECLS @@ -37,15 +37,18 @@ 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); GST_VULKAN_API @@ -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; + + /* <private> */ + 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 <matthew@centricular.com> + * + * 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 <matthew@centricular.com> + * + * 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 <gst/gst.h> + +#include <gst/vulkan/vulkan_fwd.h> +#include <gst/vulkan/gstvkapi.h> + +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; + + /* <protected> */ + GPtrArray *outstanding; + GPtrArray *available; + + /* <private> */ + 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; + + /* <private> */ + 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 <gst/vulkan/gstvkdescriptorset.h> #include <gst/vulkan/gstvkdescriptorpool.h> #include <gst/vulkan/gstvkhandle.h> +#include <gst/vulkan/gstvkhandlepool.h> #include <gst/vulkan/gstvktrash.h> #include <gst/vulkan/gstvkswapper.h> 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, |