From 32b3387ae6a4e28934c83b357fd95df2fe9103b4 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Wed, 6 Nov 2019 22:19:42 +1100 Subject: [PATCH] vulkan: implement proper descriptor set handling The major functionality gain this provides is proper reference counting for a descriptor set. Overall this allows us to create descriptor sets when they are needed (or reused from a cache) without violating any of vulkan's object synchronisation requirements. As there are a fixed number of sets available in a pool, the number of descriptors in elements is currently hardcoded to 32. This can be extended in a future change to create pools on the fly if that limit is ever overrun. --- ext/vulkan/vkcolorconvert.c | 133 ++++++------ ext/vulkan/vkcolorconvert.h | 5 +- ext/vulkan/vkfullscreenrender.c | 24 ++- ext/vulkan/vkfullscreenrender.h | 2 +- ext/vulkan/vkimageidentity.c | 93 ++++----- ext/vulkan/vkimageidentity.h | 3 +- ext/vulkan/vkviewconvert.c | 105 +++++----- ext/vulkan/vkviewconvert.h | 3 +- gst-libs/gst/vulkan/gstvkdescriptorcache-private.h | 33 +++ gst-libs/gst/vulkan/gstvkdescriptorcache.c | 193 +++++++++++++++++ gst-libs/gst/vulkan/gstvkdescriptorcache.h | 56 +++++ gst-libs/gst/vulkan/gstvkdescriptorpool.c | 231 +++++++++++++++++++++ gst-libs/gst/vulkan/gstvkdescriptorpool.h | 65 ++++++ gst-libs/gst/vulkan/gstvkdescriptorset.c | 136 ++++++++++++ gst-libs/gst/vulkan/gstvkdescriptorset.h | 113 ++++++++++ gst-libs/gst/vulkan/meson.build | 6 + gst-libs/gst/vulkan/vulkan.h | 3 + gst-libs/gst/vulkan/vulkan_fwd.h | 12 ++ 18 files changed, 1024 insertions(+), 192 deletions(-) create mode 100644 gst-libs/gst/vulkan/gstvkdescriptorcache-private.h create mode 100644 gst-libs/gst/vulkan/gstvkdescriptorcache.c create mode 100644 gst-libs/gst/vulkan/gstvkdescriptorcache.h create mode 100644 gst-libs/gst/vulkan/gstvkdescriptorpool.c create mode 100644 gst-libs/gst/vulkan/gstvkdescriptorpool.h create mode 100644 gst-libs/gst/vulkan/gstvkdescriptorset.c create mode 100644 gst-libs/gst/vulkan/gstvkdescriptorset.h diff --git a/ext/vulkan/vkcolorconvert.c b/ext/vulkan/vkcolorconvert.c index 4668132..02699b9 100644 --- a/ext/vulkan/vkcolorconvert.c +++ b/ext/vulkan/vkcolorconvert.c @@ -48,7 +48,7 @@ GST_DEBUG_CATEGORY (gst_debug_vulkan_color_convert); #define GST_CAT_DEFAULT gst_debug_vulkan_color_convert -#define N_SHADER_INFO (8*16) +#define N_SHADER_INFO (8*4*4) static shader_info shader_infos[N_SHADER_INFO]; #define PUSH_CONSTANT_RANGE_NULL_INIT (VkPushConstantRange) { \ @@ -494,9 +494,27 @@ convert_info_new (GstVideoInfo * in_info, GstVideoInfo * out_info) return conv; } +static GstVulkanDescriptorSet * +_create_descriptor_set (GstVulkanColorConvert * conv) +{ + GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + GstVulkanDescriptorSet *ret; + GError *error = NULL; + + ret = gst_vulkan_descriptor_cache_acquire (conv->descriptor_pool, &error); + if (!ret) { + GST_ERROR_OBJECT (render, "Failed to create framebuffer: %s", + error->message); + g_clear_error (&error); + return NULL; + } + + return ret; +} + static void -update_descriptor_set (GstVulkanColorConvert * conv, VkImageView * views, - guint n_views) +update_descriptor_set (GstVulkanColorConvert * conv, + VkDescriptorSet descriptor_set, VkImageView * views, guint n_views) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); VkDescriptorBufferInfo buffer_info; @@ -518,7 +536,7 @@ update_descriptor_set (GstVulkanColorConvert * conv, VkImageView * views, writes[i] = (VkWriteDescriptorSet) { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = NULL, - .dstSet = conv->descriptor_set, + .dstSet = descriptor_set, .dstBinding = i, .dstArrayElement = 0, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -537,7 +555,7 @@ update_descriptor_set (GstVulkanColorConvert * conv, VkImageView * views, writes[i] = (VkWriteDescriptorSet) { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = NULL, - .dstSet = conv->descriptor_set, + .dstSet = descriptor_set, .dstBinding = i, .dstArrayElement = 0, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, @@ -703,9 +721,11 @@ calculate_reorder_indexes (GstVideoFormat in_format, static gboolean swizzle_rgb_update_command_state (GstVulkanColorConvert * conv, VkCommandBuffer cmd, shader_info * sinfo, - GstVulkanImageView ** in_views, GstVulkanImageView ** out_views) + GstVulkanImageView ** in_views, GstVulkanImageView ** out_views, + GstVulkanFence * fence) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + GstVulkanDescriptorSet *descriptor_set; gint reorder[8]; calculate_reorder_indexes (GST_VIDEO_INFO_FORMAT (&render->in_info), @@ -715,9 +735,14 @@ swizzle_rgb_update_command_state (GstVulkanColorConvert * conv, vkCmdPushConstants (cmd, render->pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (reorder), (const void *) reorder); - update_descriptor_set (conv, &in_views[0]->view, 1); + descriptor_set = _create_descriptor_set (conv); + update_descriptor_set (conv, descriptor_set->set, &in_views[0]->view, 1); vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - render->pipeline_layout, 0, 1, &conv->descriptor_set, 0, NULL); + render->pipeline_layout, 0, 1, &descriptor_set->set, 0, NULL); + + gst_vulkan_trash_list_add (render->trash_list, + gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref + (fence), (GstMiniObject *) descriptor_set)); return TRUE; } @@ -742,16 +767,17 @@ struct YUVUpdateData static gboolean yuv_to_rgb_update_command_state (GstVulkanColorConvert * conv, VkCommandBuffer cmd, shader_info * sinfo, GstVulkanImageView ** in_views, - GstVulkanImageView ** out_views) + GstVulkanImageView ** out_views, GstVulkanFence * fence) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + VkImageView views[GST_VIDEO_MAX_PLANES]; + GstVulkanDescriptorSet *descriptor_set; + int i; if (!GPOINTER_TO_INT (sinfo->user_data)) { struct YUVUpdateData data; ConvertInfo *conv_info; GstMapInfo map_info; - VkImageView views[GST_VIDEO_MAX_PLANES]; - int i; calculate_reorder_indexes (GST_VIDEO_INFO_FORMAT (&render->in_info), in_views, GST_VIDEO_INFO_FORMAT (&render->out_info), @@ -773,15 +799,20 @@ yuv_to_rgb_update_command_state (GstVulkanColorConvert * conv, memcpy (map_info.data, &data, sizeof (data)); gst_memory_unmap (conv->uniform, &map_info); - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&render->in_info); i++) - views[i] = in_views[i]->view; - - update_descriptor_set (conv, views, - GST_VIDEO_INFO_N_PLANES (&render->in_info)); sinfo->user_data = GINT_TO_POINTER (1); } + + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&render->in_info); i++) + views[i] = in_views[i]->view; + descriptor_set = _create_descriptor_set (conv); + update_descriptor_set (conv, descriptor_set->set, views, + GST_VIDEO_INFO_N_PLANES (&render->in_info)); vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - render->pipeline_layout, 0, 1, &conv->descriptor_set, 0, NULL); + render->pipeline_layout, 0, 1, &descriptor_set->set, 0, NULL); + + gst_vulkan_trash_list_add (render->trash_list, + gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref + (fence), (GstMiniObject *) descriptor_set)); return TRUE; } @@ -1402,32 +1433,36 @@ gst_vulkan_color_convert_start (GstBaseTransform * bt) return TRUE; } -static VkDescriptorPool +static GstVulkanDescriptorCache * _create_descriptor_pool (GstVulkanColorConvert * conv) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + gsize max_sets = 32; /* FIXME: don't hardcode this! */ /* *INDENT-OFF* */ VkDescriptorPoolSize pool_sizes[] = { { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = GST_VIDEO_INFO_N_PLANES (&render->in_info), + .descriptorCount = max_sets * GST_VIDEO_INFO_N_PLANES (&render->in_info), }, { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1 + .descriptorCount = max_sets }, }; VkDescriptorPoolCreateInfo pool_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .pNext = NULL, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, .poolSizeCount = G_N_ELEMENTS (pool_sizes), .pPoolSizes = pool_sizes, - .maxSets = 1 + .maxSets = max_sets }; /* *INDENT-ON* */ VkDescriptorPool pool; + GstVulkanDescriptorPool *ret; + GstVulkanDescriptorCache *cache; GError *error = NULL; VkResult err; @@ -1440,38 +1475,12 @@ _create_descriptor_pool (GstVulkanColorConvert * conv) return VK_NULL_HANDLE; } - return pool; -} + ret = gst_vulkan_descriptor_pool_new_wrapped (render->device, pool, max_sets); + cache = + gst_vulkan_descriptor_cache_new (ret, 1, &render->descriptor_set_layout); + gst_object_unref (ret); -static VkDescriptorSet -_create_descriptor_set (GstVulkanColorConvert * conv) -{ - GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); - - /* *INDENT-OFF* */ - VkDescriptorSetAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pNext = NULL, - .descriptorPool = conv->descriptor_pool, - .descriptorSetCount = 1, - .pSetLayouts = &render->descriptor_set_layout - }; - /* *INDENT-ON* */ - VkDescriptorSet descriptor; - GError *error = NULL; - VkResult err; - - err = - vkAllocateDescriptorSets (render->device->device, &alloc_info, - &descriptor); - if (gst_vulkan_error_to_g_error (err, &error, "vkAllocateDescriptorSets") < 0) { - GST_ERROR_OBJECT (conv, "Failed to allocate descriptor: %s", - error->message); - g_clear_error (&error); - return VK_NULL_HANDLE; - } - - return descriptor; + return cache; } static gboolean @@ -1501,8 +1510,6 @@ gst_vulkan_color_convert_set_caps (GstBaseTransform * bt, GstCaps * in_caps, GstVulkanFence *last_fence; int i; - conv->current_shader = NULL; - if (!gst_video_info_from_caps (&in_info, in_caps)) return FALSE; if (!gst_video_info_from_caps (&out_info, out_caps)) @@ -1539,10 +1546,9 @@ gst_vulkan_color_convert_set_caps (GstBaseTransform * bt, GstCaps * in_caps, if (conv->descriptor_pool) gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref - (last_fence), conv->descriptor_pool)); - conv->descriptor_set = VK_NULL_HANDLE; - conv->descriptor_pool = VK_NULL_HANDLE; + gst_vulkan_trash_new_object_unref (gst_vulkan_fence_ref + (last_fence), (GstObject *) conv->descriptor_pool)); + conv->descriptor_pool = NULL; if (conv->uniform) gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref @@ -1557,8 +1563,6 @@ gst_vulkan_color_convert_set_caps (GstBaseTransform * bt, GstCaps * in_caps, if (!(conv->descriptor_pool = _create_descriptor_pool (conv))) return FALSE; - if (!(conv->descriptor_set = _create_descriptor_set (conv))) - return FALSE; if (!_create_uniform_buffer (conv)) return FALSE; @@ -1582,10 +1586,9 @@ gst_vulkan_color_convert_stop (GstBaseTransform * bt) if (conv->descriptor_pool) gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref - (last_fence), conv->descriptor_pool)); - conv->descriptor_set = VK_NULL_HANDLE; - conv->descriptor_pool = VK_NULL_HANDLE; + gst_vulkan_trash_new_object_unref (gst_vulkan_fence_ref + (last_fence), (GstObject *) conv->descriptor_pool)); + conv->descriptor_pool = NULL; if (conv->sampler) gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_sampler (gst_vulkan_fence_ref @@ -1818,7 +1821,7 @@ gst_vulkan_color_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, } conv->current_shader->cmd_state_update (conv, cmd_buf->cmd, - conv->current_shader, in_img_views, render_img_views); + conv->current_shader, in_img_views, render_img_views, fence); if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd_buf->cmd, framebuffer)) { g_set_error (&error, GST_VULKAN_ERROR, GST_VULKAN_FAILED, diff --git a/ext/vulkan/vkcolorconvert.h b/ext/vulkan/vkcolorconvert.h index b39e01b..227dc39 100644 --- a/ext/vulkan/vkcolorconvert.h +++ b/ext/vulkan/vkcolorconvert.h @@ -41,7 +41,7 @@ typedef struct _GstVulkanColorConvertClass GstVulkanColorConvertClass; typedef struct _shader_info shader_info; -typedef gboolean (*CommandStateUpdate) (GstVulkanColorConvert * conv, VkCommandBuffer cmd, shader_info * sinfo, GstVulkanImageView ** src_views, GstVulkanImageView ** dest_views); +typedef gboolean (*CommandStateUpdate) (GstVulkanColorConvert * conv, VkCommandBuffer cmd, shader_info * sinfo, GstVulkanImageView ** src_views, GstVulkanImageView ** dest_views, GstVulkanFence * fence); struct _shader_info { @@ -63,8 +63,7 @@ struct _GstVulkanColorConvert GstVulkanCommandPool *cmd_pool; VkSampler sampler; - VkDescriptorPool descriptor_pool; - VkDescriptorSet descriptor_set; + GstVulkanDescriptorCache *descriptor_pool; VkShaderModule vert_module; VkShaderModule frag_module; diff --git a/ext/vulkan/vkfullscreenrender.c b/ext/vulkan/vkfullscreenrender.c index 5cc14ee..f554f8c 100644 --- a/ext/vulkan/vkfullscreenrender.c +++ b/ext/vulkan/vkfullscreenrender.c @@ -445,7 +445,7 @@ _create_pipeline_layout (GstVulkanFullScreenRender * render) .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pNext = NULL, .setLayoutCount = 1, - .pSetLayouts = &render->descriptor_set_layout, + .pSetLayouts = (VkDescriptorSetLayout *) &render->descriptor_set_layout->handle, .pushConstantRangeCount = n_constants, .pPushConstantRanges = constants, }; @@ -514,7 +514,7 @@ _create_render_pass (GstVulkanFullScreenRender * render) return render_pass; } -static VkDescriptorSetLayout +static GstVulkanHandle * _create_descriptor_set_layout (GstVulkanFullScreenRender * render) { GstVulkanFullScreenRenderClass *render_class = @@ -532,6 +532,7 @@ _create_descriptor_set_layout (GstVulkanFullScreenRender * render) }; /* *INDENT-ON* */ VkDescriptorSetLayout descriptor_set_layout; + GstVulkanHandle *ret; VkResult err; GError *error = NULL; @@ -546,7 +547,12 @@ _create_descriptor_set_layout (GstVulkanFullScreenRender * render) return VK_NULL_HANDLE; } - return descriptor_set_layout; + ret = gst_vulkan_handle_new_wrapped (render->device, + GST_VULKAN_HANDLE_TYPE_DESCRIPTOR_SET_LAYOUT, + (GstVulkanHandleTypedef) descriptor_set_layout, + gst_vulkan_handle_free_descriptor_set_layout, NULL); + + return ret; } static gboolean @@ -571,9 +577,9 @@ gst_vulkan_full_screen_render_set_caps (GstBaseTransform * bt, if (render->descriptor_set_layout) { gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_set_layout (gst_vulkan_fence_ref - (last_fence), render->descriptor_set_layout)); - render->descriptor_set_layout = VK_NULL_HANDLE; + gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref + (last_fence), (GstMiniObject *) render->descriptor_set_layout)); + render->descriptor_set_layout = NULL; } if (render->pipeline_layout) { gst_vulkan_trash_list_add (render->trash_list, @@ -774,9 +780,9 @@ gst_vulkan_full_screen_render_stop (GstBaseTransform * bt) (last_fence), render->render_pass)); render->render_pass = VK_NULL_HANDLE; gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_set_layout (gst_vulkan_fence_ref - (last_fence), render->descriptor_set_layout)); - render->descriptor_set_layout = VK_NULL_HANDLE; + gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref + (last_fence), (GstMiniObject *) render->descriptor_set_layout)); + render->descriptor_set_layout = NULL; gst_vulkan_fence_unref (last_fence); diff --git a/ext/vulkan/vkfullscreenrender.h b/ext/vulkan/vkfullscreenrender.h index 9a61491..1e01812 100644 --- a/ext/vulkan/vkfullscreenrender.h +++ b/ext/vulkan/vkfullscreenrender.h @@ -66,7 +66,7 @@ struct _GstVulkanFullScreenRender VkRenderPass render_pass; VkPipelineLayout pipeline_layout; VkPipeline graphics_pipeline; - VkDescriptorSetLayout descriptor_set_layout; + GstVulkanHandle *descriptor_set_layout; GstMemory *vertices; GstMemory *indices; diff --git a/ext/vulkan/vkimageidentity.c b/ext/vulkan/vkimageidentity.c index e7f700c..3354bad 100644 --- a/ext/vulkan/vkimageidentity.c +++ b/ext/vulkan/vkimageidentity.c @@ -276,16 +276,17 @@ static VkAttachmentDescription return color_attachments; } -static VkDescriptorPool +static GstVulkanDescriptorCache * _create_descriptor_pool (GstVulkanImageIdentity * vk_identity) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (vk_identity); + guint max_sets = 32; /* FIXME: Don't hardcode this! */ /* *INDENT-OFF* */ VkDescriptorPoolSize pool_sizes = { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1 + .descriptorCount = max_sets }; VkDescriptorPoolCreateInfo pool_info = { @@ -293,10 +294,12 @@ _create_descriptor_pool (GstVulkanImageIdentity * vk_identity) .pNext = NULL, .poolSizeCount = 1, .pPoolSizes = &pool_sizes, - .maxSets = 1 + .maxSets = max_sets }; /* *INDENT-ON* */ VkDescriptorPool pool; + GstVulkanDescriptorPool *ret; + GstVulkanDescriptorCache *cache; GError *error = NULL; VkResult err; @@ -306,42 +309,15 @@ _create_descriptor_pool (GstVulkanImageIdentity * vk_identity) GST_ERROR_OBJECT (render, "Failed to create descriptor pool: %s", error->message); g_clear_error (&error); - return VK_NULL_HANDLE; + return NULL; } - return pool; -} - -static VkDescriptorSet -_create_descriptor_set (GstVulkanImageIdentity * vk_identity) -{ - GstVulkanFullScreenRender *render = - GST_VULKAN_FULL_SCREEN_RENDER (vk_identity); - - /* *INDENT-OFF* */ - VkDescriptorSetAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pNext = NULL, - .descriptorPool = vk_identity->descriptor_pool, - .descriptorSetCount = 1, - .pSetLayouts = &render->descriptor_set_layout - }; - /* *INDENT-ON* */ - VkDescriptorSet descriptor; - GError *error = NULL; - VkResult err; - - err = - vkAllocateDescriptorSets (render->device->device, &alloc_info, - &descriptor); - if (gst_vulkan_error_to_g_error (err, &error, "vkAllocateDescriptorSets") < 0) { - GST_ERROR_OBJECT (vk_identity, "Failed to allocate descriptor: %s", - error->message); - g_clear_error (&error); - return VK_NULL_HANDLE; - } + ret = gst_vulkan_descriptor_pool_new_wrapped (render->device, pool, max_sets); + cache = + gst_vulkan_descriptor_cache_new (ret, 1, &render->descriptor_set_layout); + gst_object_unref (ret); - return descriptor; + return cache; } static gboolean @@ -361,18 +337,16 @@ gst_vulkan_image_identity_set_caps (GstBaseTransform * bt, GstCaps * in_caps, else last_fence = gst_vulkan_fence_new_always_signalled (render->device); - gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref - (last_fence), vk_identity->descriptor_pool)); - vk_identity->descriptor_set = VK_NULL_HANDLE; - vk_identity->descriptor_pool = VK_NULL_HANDLE; + if (vk_identity->descriptor_pool) + gst_vulkan_trash_list_add (render->trash_list, + gst_vulkan_trash_new_object_unref (gst_vulkan_fence_ref + (last_fence), (GstObject *) vk_identity->descriptor_pool)); + vk_identity->descriptor_pool = NULL; gst_vulkan_fence_unref (last_fence); if (!(vk_identity->descriptor_pool = _create_descriptor_pool (vk_identity))) return FALSE; - if (!(vk_identity->descriptor_set = _create_descriptor_set (vk_identity))) - return FALSE; return TRUE; } @@ -446,15 +420,13 @@ gst_vulkan_image_identity_stop (GstBaseTransform * bt) else last_fence = gst_vulkan_fence_new_always_signalled (render->device); - if (vk_identity->descriptor_pool) - gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref - (render->last_fence), vk_identity->descriptor_pool)); - vk_identity->descriptor_pool = VK_NULL_HANDLE; - if (vk_identity->sampler) - gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_sampler (gst_vulkan_fence_ref - (render->last_fence), vk_identity->sampler)); + gst_vulkan_trash_list_add (render->trash_list, + gst_vulkan_trash_new_object_unref (gst_vulkan_fence_ref + (last_fence), (GstObject *) vk_identity->descriptor_pool)); + vk_identity->descriptor_pool = NULL; + gst_vulkan_trash_list_add (render->trash_list, + gst_vulkan_trash_new_free_sampler (gst_vulkan_fence_ref + (last_fence), vk_identity->sampler)); vk_identity->sampler = VK_NULL_HANDLE; gst_vulkan_fence_unref (last_fence); @@ -468,7 +440,8 @@ gst_vulkan_image_identity_stop (GstBaseTransform * bt) } static void -update_descriptor_set (GstVulkanImageIdentity * vk_identity, VkImageView view) +update_descriptor_set (GstVulkanImageIdentity * vk_identity, + VkDescriptorSet set, VkImageView view) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (vk_identity); @@ -483,7 +456,7 @@ update_descriptor_set (GstVulkanImageIdentity * vk_identity, VkImageView view) VkWriteDescriptorSet writes = { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = NULL, - .dstSet = vk_identity->descriptor_set, + .dstSet = set, .dstBinding = 0, .dstArrayElement = 0, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -541,6 +514,7 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf, GstVulkanImageMemory *in_img_mem, *out_img_mem; GstVulkanImageView *in_img_view, *out_img_view; GstVulkanFence *fence = NULL; + GstVulkanDescriptorSet *set; GstMemory *in_mem, *out_mem; VkFramebuffer framebuffer; GstVulkanCommandBuffer *cmd_buf; @@ -579,8 +553,12 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf, if (!(vk_identity->cmd_pool = gst_vulkan_queue_create_command_pool (render->queue, &error))) goto error; - update_descriptor_set (vk_identity, in_img_view->view); } + if (!(set = + gst_vulkan_descriptor_cache_acquire (vk_identity->descriptor_pool, + &error))) + goto error; + update_descriptor_set (vk_identity, set->set, in_img_view->view); if (!(cmd_buf = gst_vulkan_command_pool_create (vk_identity->cmd_pool, &error))) @@ -666,7 +644,7 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf, } vkCmdBindDescriptorSets (cmd_buf->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - render->pipeline_layout, 0, 1, &vk_identity->descriptor_set, 0, NULL); + render->pipeline_layout, 0, 1, &set->set, 0, NULL); if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd_buf->cmd, framebuffer)) goto unlock_error; @@ -677,6 +655,9 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf, goto error; gst_vulkan_trash_list_add (render->trash_list, + gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref (fence), + GST_MINI_OBJECT_CAST (set))); + gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_framebuffer (gst_vulkan_fence_ref (fence), framebuffer)); gst_vulkan_trash_list_add (render->trash_list, diff --git a/ext/vulkan/vkimageidentity.h b/ext/vulkan/vkimageidentity.h index 2856ae4..5ab1de4 100644 --- a/ext/vulkan/vkimageidentity.h +++ b/ext/vulkan/vkimageidentity.h @@ -44,8 +44,7 @@ struct _GstVulkanImageIdentity GstVulkanCommandPool *cmd_pool; VkSampler sampler; - VkDescriptorPool descriptor_pool; - VkDescriptorSet descriptor_set; + GstVulkanDescriptorCache *descriptor_pool; VkDescriptorSetLayoutBinding sampler_layout_binding; VkDescriptorSetLayoutCreateInfo layout_info; diff --git a/ext/vulkan/vkviewconvert.c b/ext/vulkan/vkviewconvert.c index 37efda3..cd1d64e 100644 --- a/ext/vulkan/vkviewconvert.c +++ b/ext/vulkan/vkviewconvert.c @@ -292,8 +292,8 @@ calculate_reorder_indexes (GstVideoFormat in_format, } static void -update_descriptor_set (GstVulkanViewConvert * conv, VkImageView * views, - guint n_views) +update_descriptor_set (GstVulkanViewConvert * conv, + VkDescriptorSet descriptor_set, VkImageView * views, guint n_views) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); VkDescriptorBufferInfo buffer_info; @@ -315,7 +315,7 @@ update_descriptor_set (GstVulkanViewConvert * conv, VkImageView * views, writes[i] = (VkWriteDescriptorSet) { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = NULL, - .dstSet = conv->descriptor_set, + .dstSet = descriptor_set, .dstBinding = i, .dstArrayElement = 0, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -333,7 +333,7 @@ update_descriptor_set (GstVulkanViewConvert * conv, VkImageView * views, writes[i] = (VkWriteDescriptorSet) { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = NULL, - .dstSet = conv->descriptor_set, + .dstSet = descriptor_set, .dstBinding = i, .dstArrayElement = 0, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, @@ -487,12 +487,31 @@ _update_uniform (GstVulkanViewConvert * conv, GstVulkanImageView ** in_views, return TRUE; } +static GstVulkanDescriptorSet * +_create_descriptor_set (GstVulkanViewConvert * conv) +{ + GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + GstVulkanDescriptorSet *ret; + GError *error = NULL; + + ret = gst_vulkan_descriptor_cache_acquire (conv->descriptor_pool, &error); + if (!ret) { + GST_ERROR_OBJECT (render, "Failed to create framebuffer: %s", + error->message); + g_clear_error (&error); + return NULL; + } + + return ret; +} + static gboolean view_convert_update_command_state (GstVulkanViewConvert * conv, VkCommandBuffer cmd, GstVulkanImageView ** in_views, - GstVulkanImageView ** out_views) + GstVulkanImageView ** out_views, GstVulkanFence * fence) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + GstVulkanDescriptorSet *set; VkImageView views[GST_VIDEO_MAX_PLANES]; int i; @@ -504,12 +523,17 @@ view_convert_update_command_state (GstVulkanViewConvert * conv, if (!conv->descriptor_up_to_date) { if (!_update_uniform (conv, in_views, out_views, views)) return FALSE; - update_descriptor_set (conv, views, - GST_VIDEO_INFO_N_PLANES (&render->in_info) * 2); } + set = _create_descriptor_set (conv); + update_descriptor_set (conv, set->set, views, + GST_VIDEO_INFO_N_PLANES (&render->in_info) * 2); vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - render->pipeline_layout, 0, 1, &conv->descriptor_set, 0, NULL); + render->pipeline_layout, 0, 1, &set->set, 0, NULL); + + gst_vulkan_trash_list_add (render->trash_list, + gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref + (fence), (GstMiniObject *) set)); return TRUE; } @@ -2012,20 +2036,21 @@ gst_vulkan_view_convert_start (GstBaseTransform * bt) return TRUE; } -static VkDescriptorPool +static GstVulkanDescriptorCache * _create_descriptor_pool (GstVulkanViewConvert * conv) { GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + guint max_sets = 32; /* FIXME: don't hardcode this! */ /* *INDENT-OFF* */ VkDescriptorPoolSize pool_sizes[] = { { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = GST_VIDEO_INFO_N_PLANES (&render->in_info) * 2, + .descriptorCount = max_sets * GST_VIDEO_INFO_N_PLANES (&render->in_info) * 2, }, { .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1 + .descriptorCount = max_sets }, }; @@ -2034,10 +2059,12 @@ _create_descriptor_pool (GstVulkanViewConvert * conv) .pNext = NULL, .poolSizeCount = G_N_ELEMENTS (pool_sizes), .pPoolSizes = pool_sizes, - .maxSets = 1 + .maxSets = max_sets }; /* *INDENT-ON* */ VkDescriptorPool pool; + GstVulkanDescriptorPool *ret; + GstVulkanDescriptorCache *cache; GError *error = NULL; VkResult err; @@ -2050,38 +2077,12 @@ _create_descriptor_pool (GstVulkanViewConvert * conv) return VK_NULL_HANDLE; } - return pool; -} - -static VkDescriptorSet -_create_descriptor_set (GstVulkanViewConvert * conv) -{ - GstVulkanFullScreenRender *render = GST_VULKAN_FULL_SCREEN_RENDER (conv); + ret = gst_vulkan_descriptor_pool_new_wrapped (render->device, pool, 32); + cache = + gst_vulkan_descriptor_cache_new (ret, 1, &render->descriptor_set_layout); + gst_object_unref (ret); - /* *INDENT-OFF* */ - VkDescriptorSetAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pNext = NULL, - .descriptorPool = conv->descriptor_pool, - .descriptorSetCount = 1, - .pSetLayouts = &render->descriptor_set_layout - }; - /* *INDENT-ON* */ - VkDescriptorSet descriptor; - GError *error = NULL; - VkResult err; - - err = - vkAllocateDescriptorSets (render->device->device, &alloc_info, - &descriptor); - if (gst_vulkan_error_to_g_error (err, &error, "vkAllocateDescriptorSets") < 0) { - GST_ERROR_OBJECT (conv, "Failed to allocate descriptor: %s", - error->message); - g_clear_error (&error); - return VK_NULL_HANDLE; - } - - return descriptor; + return cache; } static gboolean @@ -2114,10 +2115,9 @@ gst_vulkan_view_convert_set_caps (GstBaseTransform * bt, GstCaps * in_caps, if (conv->descriptor_pool) gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref - (last_fence), conv->descriptor_pool)); - conv->descriptor_set = VK_NULL_HANDLE; - conv->descriptor_pool = VK_NULL_HANDLE; + gst_vulkan_trash_new_object_unref (gst_vulkan_fence_ref + (last_fence), (GstObject *) conv->descriptor_pool)); + conv->descriptor_pool = NULL; if (conv->uniform) gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_mini_object_unref (gst_vulkan_fence_ref @@ -2132,8 +2132,6 @@ gst_vulkan_view_convert_set_caps (GstBaseTransform * bt, GstCaps * in_caps, if (!(conv->descriptor_pool = _create_descriptor_pool (conv))) return FALSE; - if (!(conv->descriptor_set = _create_descriptor_set (conv))) - return FALSE; if (!_create_uniform_buffer (conv)) return FALSE; @@ -2159,10 +2157,9 @@ gst_vulkan_view_convert_stop (GstBaseTransform * bt) if (conv->descriptor_pool) gst_vulkan_trash_list_add (render->trash_list, - gst_vulkan_trash_new_free_descriptor_pool (gst_vulkan_fence_ref - (last_fence), conv->descriptor_pool)); - conv->descriptor_set = VK_NULL_HANDLE; - conv->descriptor_pool = VK_NULL_HANDLE; + gst_vulkan_trash_new_object_unref (gst_vulkan_fence_ref + (last_fence), (GstObject *) conv->descriptor_pool)); + conv->descriptor_pool = NULL; if (conv->sampler) gst_vulkan_trash_list_add (render->trash_list, gst_vulkan_trash_new_free_sampler (gst_vulkan_fence_ref @@ -2370,7 +2367,7 @@ gst_vulkan_view_convert_transform (GstBaseTransform * bt, GstBuffer * inbuf, } view_convert_update_command_state (conv, cmd_buf->cmd, in_img_views, - out_img_views); + out_img_views, fence); if (!gst_vulkan_full_screen_render_fill_command_buffer (render, cmd_buf->cmd, framebuffer)) { diff --git a/ext/vulkan/vkviewconvert.h b/ext/vulkan/vkviewconvert.h index 370d89d..d95808c 100644 --- a/ext/vulkan/vkviewconvert.h +++ b/ext/vulkan/vkviewconvert.h @@ -51,8 +51,7 @@ struct _GstVulkanViewConvert GstVulkanCommandPool *cmd_pool; VkSampler sampler; - VkDescriptorPool descriptor_pool; - VkDescriptorSet descriptor_set; + GstVulkanDescriptorCache *descriptor_pool; VkShaderModule vert_module; VkShaderModule frag_module; diff --git a/gst-libs/gst/vulkan/gstvkdescriptorcache-private.h b/gst-libs/gst/vulkan/gstvkdescriptorcache-private.h new file mode 100644 index 0000000..9c0d50b --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkdescriptorcache-private.h @@ -0,0 +1,33 @@ +/* + * 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 new file mode 100644 index 0000000..fe50556 --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkdescriptorcache.c @@ -0,0 +1,193 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvkdescriptorcache.h" +#include "gstvkdescriptorcache-private.h" + +/** + * SECTION:vkdescriptorcache + * @title: GstVulkanDescriptorCache + * @short_description: Vulkan descriptor cache + * @see_also: #GstVulkanDevice + */ + +#define GET_PRIV(cache) G_TYPE_INSTANCE_GET_PRIVATE(cache, GST_TYPE_VULKAN_DESCRIPTOR_CACHE, GstVulkanDescriptorCachePrivate) + +#define GST_CAT_DEFAULT gst_vulkan_descriptor_cache_debug +GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); + +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_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) +{ + GstVulkanDescriptorCache *cache = GST_VULKAN_DESCRIPTOR_CACHE (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); +} + +/** + * gst_vulkan_descriptor_cache_new: + * @pool: a #GstVulkanDescriptorPool + * @n_layouts: number of @layouts + * @layouts: list of #GstVulkanHandle containing descriptor set layouts + * + * Returns: (transfer full): a new #GstVulkanDescriptorCache + * + * Since: 1.18 + */ +GstVulkanDescriptorCache * +gst_vulkan_descriptor_cache_new (GstVulkanDescriptorPool * pool, + guint n_layouts, GstVulkanHandle ** layouts) +{ + GstVulkanDescriptorCache *ret; + GstVulkanDescriptorCachePrivate *priv; + guint i; + + g_return_val_if_fail (GST_IS_VULKAN_DESCRIPTOR_POOL (pool), NULL); + + ret = g_object_new (GST_TYPE_VULKAN_DESCRIPTOR_CACHE, NULL); + ret->pool = gst_object_ref (pool); + + priv = GET_PRIV (ret); + priv->n_layouts = n_layouts; + priv->layouts = g_new0 (GstVulkanHandle *, n_layouts); + for (i = 0; i < n_layouts; i++) + priv->layouts[i] = gst_vulkan_handle_ref (layouts[i]); + + gst_object_ref_sink (ret); + + return ret; +} + +/** + * gst_vulkan_descriptor_cache_acquire: + * @cache: a #GstVulkanDescriptorCache + * @error: a #GError + * + * Returns: a new #GstVulkanDescriptorSet + * + * Since: 1.18 + */ +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; +} + +void +gst_vulkan_descriptor_cache_release_set (GstVulkanDescriptorCache * cache, + GstVulkanDescriptorSet * set) +{ + GstVulkanDescriptorCachePrivate *priv; + + g_return_if_fail (GST_IS_VULKAN_DESCRIPTOR_CACHE (cache)); + g_return_if_fail (set != NULL); + + priv = GET_PRIV (cache); + + GST_OBJECT_LOCK (cache); + g_queue_push_tail (priv->available, set); + priv->outstanding--; + GST_OBJECT_UNLOCK (cache); + + /* decrease the refcount that the set had to us */ + gst_clear_object (&set->cache); +} diff --git a/gst-libs/gst/vulkan/gstvkdescriptorcache.h b/gst-libs/gst/vulkan/gstvkdescriptorcache.h new file mode 100644 index 0000000..02d9a67 --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkdescriptorcache.h @@ -0,0 +1,56 @@ +/* + * 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_H__ +#define __GST_VULKAN_DESCRIPTOR_CACHE_H__ + +#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)) +#define GST_VULKAN_DESCRIPTOR_CACHE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GST_TYPE_VULKAN_DESCRIPTOR_CACHE, GstVulkanDescriptorCacheClass)) +#define GST_IS_VULKAN_DESCRIPTOR_CACHE(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_TYPE_VULKAN_DESCRIPTOR_CACHE)) +#define GST_IS_VULKAN_DESCRIPTOR_CACHE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_TYPE_VULKAN_DESCRIPTOR_CACHE)) +#define GST_VULKAN_DESCRIPTOR_CACHE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_TYPE_VULKAN_DESCRIPTOR_CACHE, GstVulkanDescriptorCacheClass)) +GST_VULKAN_API +GType gst_vulkan_descriptor_cache_get_type (void); + +struct _GstVulkanDescriptorCache +{ + GstObject parent; + + GstVulkanDescriptorPool *pool; +}; + +struct _GstVulkanDescriptorCacheClass +{ + GstObjectClass parent_class; +}; + +GST_VULKAN_API +GstVulkanDescriptorCache * gst_vulkan_descriptor_cache_new (GstVulkanDescriptorPool * pool, + guint n_layouts, + GstVulkanHandle ** layouts); + +GST_VULKAN_API +GstVulkanDescriptorSet * gst_vulkan_descriptor_cache_acquire (GstVulkanDescriptorCache * cache, + GError ** error); + +#endif /* __GST_VULKAN_DESCRIPTOR_CACHE_H__ */ diff --git a/gst-libs/gst/vulkan/gstvkdescriptorpool.c b/gst-libs/gst/vulkan/gstvkdescriptorpool.c new file mode 100644 index 0000000..1964bd5 --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkdescriptorpool.c @@ -0,0 +1,231 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvkdescriptorpool.h" + +/** + * SECTION:vkdescriptorpool + * @title: GstVulkanDescriptorPool + * @short_description: Vulkan descriptor pool + * @see_also: #GstVulkanDevice + */ + +#define GET_PRIV(pool) G_TYPE_INSTANCE_GET_PRIVATE(pool, GST_TYPE_VULKAN_DESCRIPTOR_POOL, GstVulkanDescriptorPoolPrivate) + +#define GST_CAT_DEFAULT gst_vulkan_descriptor_pool_debug +GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); + +struct _GstVulkanDescriptorPoolPrivate +{ + gsize max_sets; + gsize outstanding; +}; + +#define parent_class gst_vulkan_descriptor_pool_parent_class +G_DEFINE_TYPE_WITH_CODE (GstVulkanDescriptorPool, gst_vulkan_descriptor_pool, + GST_TYPE_OBJECT, G_ADD_PRIVATE (GstVulkanDescriptorPool); + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, + "vulkancommandpool", 0, "Vulkan Command Pool")); + +static void gst_vulkan_descriptor_pool_finalize (GObject * object); + +static void +gst_vulkan_descriptor_pool_init (GstVulkanDescriptorPool * pool) +{ +} + +static void +gst_vulkan_descriptor_pool_class_init (GstVulkanDescriptorPoolClass * + device_class) +{ + GObjectClass *gobject_class = (GObjectClass *) device_class; + + gobject_class->finalize = gst_vulkan_descriptor_pool_finalize; +} + +static void +gst_vulkan_descriptor_pool_finalize (GObject * object) +{ + GstVulkanDescriptorPool *pool = GST_VULKAN_DESCRIPTOR_POOL (object); + GstVulkanDescriptorPoolPrivate *priv = GET_PRIV (pool); + +#if 0 + /* FIXME: track these correctly */ + if (priv->outstanding > 0) + g_critical + ("Destroying a Vulkan descriptor pool that has outstanding descriptors!"); +#endif + + if (pool->pool) + vkDestroyDescriptorPool (pool->device->device, pool->pool, NULL); + pool->pool = VK_NULL_HANDLE; + + gst_clear_object (&pool->device); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/** + * gst_vulkan_descriptor_pool_new_wrapped: + * @device: a #GstVulkanDevice + * @pool: (transfer full): a #VkDescriptorPool + * + * Returns: (transfer full): a new #GstVulkanDescriptorPool + * + * Since: 1.18 + */ +GstVulkanDescriptorPool * +gst_vulkan_descriptor_pool_new_wrapped (GstVulkanDevice * device, + VkDescriptorPool pool, gsize max_sets) +{ + GstVulkanDescriptorPool *ret; + GstVulkanDescriptorPoolPrivate *priv; + + g_return_val_if_fail (GST_IS_VULKAN_DEVICE (device), NULL); + g_return_val_if_fail (pool != VK_NULL_HANDLE, NULL); + g_return_val_if_fail (max_sets > 0, NULL); + + ret = g_object_new (GST_TYPE_VULKAN_DESCRIPTOR_POOL, NULL); + ret->device = gst_object_ref (device); + ret->pool = pool; + + priv = GET_PRIV (ret); + priv->max_sets = max_sets; + + gst_object_ref_sink (ret); + + return ret; +} + +/** + * gst_vulkan_descriptor_pool_get_device + * @pool: a #GstVulkanDescriptorPool + * + * Returns: (transfer full): the parent #GstVulkanDevice for this descriptor pool + * + * Since: 1.18 + */ +GstVulkanDevice * +gst_vulkan_descriptor_pool_get_device (GstVulkanDescriptorPool * pool) +{ + g_return_val_if_fail (GST_IS_VULKAN_DESCRIPTOR_POOL (pool), NULL); + + return pool->device ? gst_object_ref (pool->device) : NULL; +} + +/** + * gst_vulkan_descriptor_pool_get_max_sets: + * @pool: a #GstVulkanDescriptorPool + * + * Returns: the maximum number of sets allocatable from @pool + */ +gsize +gst_vulkan_descriptor_pool_get_max_sets (GstVulkanDescriptorPool * pool) +{ + GstVulkanDescriptorPoolPrivate *priv; + + g_return_val_if_fail (GST_IS_VULKAN_DESCRIPTOR_POOL (pool), 0); + + priv = GET_PRIV (pool); + + return priv->max_sets; +} + +static GstVulkanDescriptorSet * +descriptor_set_alloc (GstVulkanDescriptorPool * pool, guint n_layouts, + GstVulkanHandle ** layouts, GError ** error) +{ + VkDescriptorSetLayout *vk_layouts; + VkDescriptorSetAllocateInfo alloc_info; + GstVulkanDescriptorSet *set; + VkDescriptorSet descriptor; + VkResult err; + guint i; + + vk_layouts = g_alloca (n_layouts * sizeof (VkDescriptorSetLayout)); + for (i = 0; i < n_layouts; i++) + vk_layouts[i] = (VkDescriptorSetLayout) layouts[i]->handle; + + /* *INDENT-OFF* */ + alloc_info = (VkDescriptorSetAllocateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .pNext = NULL, + .descriptorPool = pool->pool, + .descriptorSetCount = n_layouts, + .pSetLayouts = vk_layouts + }; + /* *INDENT-ON* */ + + err = + vkAllocateDescriptorSets (pool->device->device, &alloc_info, &descriptor); + if (gst_vulkan_error_to_g_error (err, error, "vkAllocateDescriptorSets") < 0) + return NULL; + + set = + gst_vulkan_descriptor_set_new_wrapped (pool, descriptor, n_layouts, + layouts); + GST_LOG_OBJECT (pool, "created descriptor set %p", set); + + return set; +} + +/** + * gst_vulkan_descriptor_pool_create: + * @pool: a #GstVulkanDescriptorPool + * @error: a #GError + * + * Returns: a new #GstVulkanDescriptorSet + * + * Since: 1.18 + */ +GstVulkanDescriptorSet * +gst_vulkan_descriptor_pool_create (GstVulkanDescriptorPool * pool, + guint n_layouts, GstVulkanHandle ** layouts, GError ** error) +{ + GstVulkanDescriptorSet *cmd = NULL; + GstVulkanDescriptorPoolPrivate *priv; + + g_return_val_if_fail (GST_IS_VULKAN_DESCRIPTOR_POOL (pool), NULL); + g_return_val_if_fail (n_layouts > 0, NULL); + g_return_val_if_fail (layouts != NULL, NULL); + + priv = GET_PRIV (pool); + + GST_OBJECT_LOCK (pool); + priv->outstanding++; + if (priv->outstanding >= priv->max_sets) { + g_warning ("%s: Attempt was made to allocate more descriptor sets than are " + "available", GST_OBJECT_NAME (pool)); + priv->outstanding--; + GST_OBJECT_UNLOCK (pool); + return NULL; + } + GST_OBJECT_UNLOCK (pool); + + cmd = descriptor_set_alloc (pool, n_layouts, layouts, error); + if (!cmd) + return NULL; + + return cmd; +} diff --git a/gst-libs/gst/vulkan/gstvkdescriptorpool.h b/gst-libs/gst/vulkan/gstvkdescriptorpool.h new file mode 100644 index 0000000..b2e6840 --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkdescriptorpool.h @@ -0,0 +1,65 @@ +/* + * 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_POOL_H__ +#define __GST_VULKAN_DESCRIPTOR_POOL_H__ + +#include + +#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 +{ + GstObject parent; + + GstVulkanDevice *device; + + VkDescriptorPool pool; /* hides a pointer */ +}; + +struct _GstVulkanDescriptorPoolClass +{ + GstObjectClass parent_class; +}; + +GST_VULKAN_API +GstVulkanDescriptorPool * gst_vulkan_descriptor_pool_new_wrapped (GstVulkanDevice * device, + VkDescriptorPool pool, + gsize max_sets); + +GST_VULKAN_API +GstVulkanDevice * gst_vulkan_descriptor_pool_get_device (GstVulkanDescriptorPool * pool); + +GST_VULKAN_API +GstVulkanDescriptorSet * gst_vulkan_descriptor_pool_create (GstVulkanDescriptorPool * pool, + guint n_layouts, + GstVulkanHandle **layouts, + GError ** error); +GST_VULKAN_API +gsize gst_vulkan_descriptor_pool_get_max_sets (GstVulkanDescriptorPool * pool); + +#endif /* __GST_VULKAN_DESCRIPTOR_POOL_H__ */ diff --git a/gst-libs/gst/vulkan/gstvkdescriptorset.c b/gst-libs/gst/vulkan/gstvkdescriptorset.c new file mode 100644 index 0000000..a2adacc --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkdescriptorset.c @@ -0,0 +1,136 @@ +/* + * 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:vulkandescriptorset + * @title: vulkandescriptorset + * + * vulkandescriptorset holds information about a descriptor set. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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); + +static void +init_debug (void) +{ + static volatile gsize _init = 0; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "vulkandescriptorset", 0, + "Vulkan descriptor set"); + g_once_init_leave (&_init, 1); + } +} + +static gboolean +gst_vulkan_descriptor_set_dispose (GstVulkanDescriptorSet * set) +{ + GstVulkanDescriptorCache *cache; + + /* no pool, do free */ + if ((cache = set->cache) == NULL) + return TRUE; + + /* keep the buffer alive */ + gst_vulkan_descriptor_set_ref (set); + /* return the buffer to the pool */ + gst_vulkan_descriptor_cache_release_set (cache, set); + + return FALSE; +} + +static void +gst_vulkan_descriptor_set_free (GstVulkanDescriptorSet * set) +{ + guint i; + + g_assert (set->cache == NULL); + + GST_TRACE ("Freeing %p", set); + + for (i = 0; i < set->n_layouts; i++) + gst_vulkan_handle_unref (set->layouts[i]); + g_free (set->layouts); + + vkFreeDescriptorSets (set->pool->device->device, set->pool->pool, 1, + &set->set); + + gst_clear_object (&set->pool); + + g_free (set); +} + +static void +gst_vulkan_descriptor_set_init (GstVulkanDescriptorSet * set, + GstVulkanDescriptorPool * pool, VkDescriptorSet desc_set, guint n_layouts, + GstVulkanHandle ** layouts) +{ + guint i; + + set->pool = gst_object_ref (pool); + set->set = desc_set; + set->n_layouts = n_layouts; + set->layouts = g_new0 (GstVulkanHandle *, n_layouts); + for (i = 0; i < n_layouts; i++) + set->layouts[i] = gst_vulkan_handle_ref (layouts[i]); + + init_debug (); + + GST_TRACE ("new %p", set); + + gst_mini_object_init (&set->parent, 0, GST_TYPE_VULKAN_DESCRIPTOR_SET, + NULL, (GstMiniObjectDisposeFunction) gst_vulkan_descriptor_set_dispose, + (GstMiniObjectFreeFunction) gst_vulkan_descriptor_set_free); +} + +/** + * gst_vulkan_descriptor_set_new_wrapped: + * @set: a VkDescriptorSet + * + * Returns: (transfer full): a new #GstVulkanDescriptorSet + */ +GstVulkanDescriptorSet * +gst_vulkan_descriptor_set_new_wrapped (GstVulkanDescriptorPool * pool, + VkDescriptorSet set, guint n_layouts, GstVulkanHandle ** layouts) +{ + GstVulkanDescriptorSet *ret; + + g_return_val_if_fail (GST_IS_VULKAN_DESCRIPTOR_POOL (pool), NULL); + g_return_val_if_fail (set != VK_NULL_HANDLE, NULL); + g_return_val_if_fail (n_layouts > 0, NULL); + g_return_val_if_fail (layouts != NULL, NULL); + + ret = g_new0 (GstVulkanDescriptorSet, 1); + gst_vulkan_descriptor_set_init (ret, pool, set, n_layouts, layouts); + + return ret; +} + +GST_DEFINE_MINI_OBJECT_TYPE (GstVulkanDescriptorSet, gst_vulkan_descriptor_set); diff --git a/gst-libs/gst/vulkan/gstvkdescriptorset.h b/gst-libs/gst/vulkan/gstvkdescriptorset.h new file mode 100644 index 0000000..8f10f00 --- /dev/null +++ b/gst-libs/gst/vulkan/gstvkdescriptorset.h @@ -0,0 +1,113 @@ +/* + * 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_SET_H__ +#define __GST_VULKAN_DESCRIPTOR_SET_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +GST_VULKAN_API +GType gst_vulkan_descriptor_set_get_type (void); +#define GST_TYPE_VULKAN_DESCRIPTOR_SET (gst_vulkan_descriptor_set_get_type ()) + +typedef struct _GstVulkanDescriptorSet GstVulkanDescriptorSet; + +struct _GstVulkanDescriptorSet +{ + GstMiniObject parent; + + VkDescriptorSet set; + + /* */ + GstVulkanDescriptorPool *pool; + GstVulkanDescriptorCache *cache; + + guint n_layouts; + GstVulkanHandle **layouts; + + GMutex lock; +}; + +/** + * gst_vulkan_descriptor_set_ref: (skip) + * @set: a #GstVulkanDescriptorSet. + * + * Increases the refcount of the given buffer by one. + * + * Returns: (transfer full): @buf + */ +static inline GstVulkanDescriptorSet* gst_vulkan_descriptor_set_ref(GstVulkanDescriptorSet* set); +static inline GstVulkanDescriptorSet * +gst_vulkan_descriptor_set_ref (GstVulkanDescriptorSet * set) +{ + return (GstVulkanDescriptorSet *) gst_mini_object_ref (GST_MINI_OBJECT_CAST (set)); +} + +/** + * gst_vulkan_descriptor_set_unref: (skip) + * @set: (transfer full): a #GstVulkanDescriptorSet. + * + * Decreases the refcount of the buffer. If the refcount reaches 0, the buffer + * will be freed. + */ +static inline void gst_vulkan_descriptor_set_unref(GstVulkanDescriptorSet* set); +static inline void +gst_vulkan_descriptor_set_unref (GstVulkanDescriptorSet * set) +{ + gst_mini_object_unref (GST_MINI_OBJECT_CAST (set)); +} + +/** + * gst_clear_vulkan_descriptor_set: (skip) + * @set_ptr: a pointer to a #GstVulkanDescriptorSet reference + * + * Clears a reference to a #GstVulkanDescriptorSet. + * + * @buf_ptr must not be %NULL. + * + * If the reference is %NULL then this function does nothing. Otherwise, the + * reference count of the descriptor set is decreased and the pointer is set + * to %NULL. + * + * Since: 1.16 + */ +static inline void +gst_clear_vulkan_descriptor_set (GstVulkanDescriptorSet ** set_ptr) +{ + gst_clear_mini_object ((GstMiniObject **) set_ptr); +} + +#define gst_vulkan_descriptor_set_lock(set) g_mutex_lock (&((set)->lock)) +#define gst_vulkan_descriptor_set_unlock(set) g_mutex_unlock (&((set)->lock)) + +GST_VULKAN_API +GstVulkanDescriptorSet * gst_vulkan_descriptor_set_new_wrapped (GstVulkanDescriptorPool * pool, + VkDescriptorSet set, + guint n_layouts, + GstVulkanHandle ** layouts); + +G_END_DECLS + +#endif /* _GST_VULKAN_DESCRIPTOR_SET_H_ */ diff --git a/gst-libs/gst/vulkan/meson.build b/gst-libs/gst/vulkan/meson.build index 22906b4..ca6809d 100644 --- a/gst-libs/gst/vulkan/meson.build +++ b/gst-libs/gst/vulkan/meson.build @@ -8,6 +8,9 @@ vulkan_sources = [ 'gstvkbufferpool.c', 'gstvkcommandbuffer.c', 'gstvkcommandpool.c', + 'gstvkdescriptorcache.c', + 'gstvkdescriptorset.c', + 'gstvkdescriptorpool.c', 'gstvkdevice.c', 'gstvkdebug.c', 'gstvkdisplay.c', @@ -35,6 +38,9 @@ vulkan_headers = [ 'gstvkbufferpool.h', 'gstvkcommandbuffer.h', 'gstvkcommandpool.h', + 'gstvkdescriptorcache.h', + 'gstvkdescriptorset.h', + 'gstvkdescriptorpool.h', 'gstvkdebug.h', 'gstvkdevice.h', 'gstvkdisplay.h', diff --git a/gst-libs/gst/vulkan/vulkan.h b/gst-libs/gst/vulkan/vulkan.h index 30fec89..d123714 100644 --- a/gst-libs/gst/vulkan/vulkan.h +++ b/gst-libs/gst/vulkan/vulkan.h @@ -45,6 +45,9 @@ #include #include #include +#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 e4926bf..9e94a44 100644 --- a/gst-libs/gst/vulkan/vulkan_fwd.h +++ b/gst-libs/gst/vulkan/vulkan_fwd.h @@ -46,6 +46,18 @@ typedef struct _GstVulkanCommandPoolPrivate GstVulkanCommandPoolPrivate; typedef struct _GstVulkanCommandBuffer GstVulkanCommandBuffer; +typedef struct _GstVulkanDescriptorSet GstVulkanDescriptorSet; +typedef struct _GstVulkanDescriptorSetClass GstVulkanDescriptorSetClass; +typedef struct _GstVulkanDescriptorSetPrivate GstVulkanDescriptorSetPrivate; + +typedef struct _GstVulkanDescriptorPool GstVulkanDescriptorPool; +typedef struct _GstVulkanDescriptorPoolClass GstVulkanDescriptorPoolClass; +typedef struct _GstVulkanDescriptorPoolPrivate GstVulkanDescriptorPoolPrivate; + +typedef struct _GstVulkanDescriptorCache GstVulkanDescriptorCache; +typedef struct _GstVulkanDescriptorCacheClass GstVulkanDescriptorCacheClass; +typedef struct _GstVulkanDescriptorCachePrivate GstVulkanDescriptorCachePrivate; + typedef struct _GstVulkanDisplay GstVulkanDisplay; typedef struct _GstVulkanDisplayClass GstVulkanDisplayClass; typedef struct _GstVulkanDisplayPrivate GstVulkanDisplayPrivate; -- 2.7.4