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.
This commit is contained in:
Matthew Waters 2019-11-06 22:19:42 +11:00 committed by GStreamer Merge Bot
parent 1c89096b4f
commit 32b3387ae6
18 changed files with 1024 additions and 192 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;
}
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 (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;
}
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);
if (vk_identity->descriptor_pool)
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;
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_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
(render->last_fence), vk_identity->sampler));
(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;
@ -676,6 +654,9 @@ gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
if (gst_vulkan_error_to_g_error (err, &error, "vkEndCommandBuffer") < 0)
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));

View file

@ -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;

View file

@ -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;
}
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);
static VkDescriptorSet
_create_descriptor_set (GstVulkanViewConvert * 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
@ -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)) {

View file

@ -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;

View file

@ -0,0 +1,33 @@
/*
* 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__ */

View file

@ -0,0 +1,193 @@
/*
* 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.
*/
#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);
}

View file

@ -0,0 +1,56 @@
/*
* 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_H__
#define __GST_VULKAN_DESCRIPTOR_CACHE_H__
#include <gst/vulkan/gstvkqueue.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))
#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__ */

View file

@ -0,0 +1,231 @@
/*
* 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.
*/
#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;
}

View file

@ -0,0 +1,65 @@
/*
* 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_POOL_H__
#define __GST_VULKAN_DESCRIPTOR_POOL_H__
#include <gst/vulkan/gstvkqueue.h>
#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__ */

View file

@ -0,0 +1,136 @@
/*
* 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: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);

View file

@ -0,0 +1,113 @@
/*
* 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_SET_H__
#define __GST_VULKAN_DESCRIPTOR_SET_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_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;
/* <protected> */
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_ */

View file

@ -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',

View file

@ -45,6 +45,9 @@
#include <gst/vulkan/gstvkutils.h>
#include <gst/vulkan/gstvkcommandbuffer.h>
#include <gst/vulkan/gstvkcommandpool.h>
#include <gst/vulkan/gstvkdescriptorcache.h>
#include <gst/vulkan/gstvkdescriptorset.h>
#include <gst/vulkan/gstvkdescriptorpool.h>
#include <gst/vulkan/gstvkhandle.h>
#include <gst/vulkan/gstvktrash.h>
#include <gst/vulkan/gstvkswapper.h>

View file

@ -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;