vkimagebufferpool: refactor common code

Both gst_vulkan_image_buffer_pool_set_config() and
gst_vulkan_image_buffer_pool_alloc() functions share the same code to create
Vulkan images for different purposes.

This patch refactor them in a new helper function that creates the images and
stores them in a buffer if it's passed as output parameters, such as the
offsets.

This patch also adds specifics guards for Vulkan's symbols for better grained
API usage, but also for prepare_buffer() the guard is set where the symbol is
used.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9492>
This commit is contained in:
Víctor Manuel Jáquez Leal 2025-07-31 17:56:17 +02:00 committed by GStreamer Marge Bot
parent f3f319a630
commit 1a7f0f1627

View File

@ -58,8 +58,8 @@ struct _GstVulkanImageBufferPoolPrivate
VkFormat vk_fmts[GST_VIDEO_MAX_PLANES];
int n_imgs;
guint32 n_layers;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
guint32 n_profiles;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
GstVulkanVideoProfile profiles[2];
#endif
GstVulkanOperation *exec;
@ -207,6 +207,93 @@ internal_config_get_allocation_params (GstStructure * config,
gst_structure_get (config, "encode-caps", GST_TYPE_CAPS, encode_caps, NULL);
}
static gboolean
gst_vulkan_image_buffer_pool_fill_buffer (GstVulkanImageBufferPool * vk_pool,
VkImageTiling tiling, gsize offset[GST_VIDEO_MAX_PLANES],
GstBuffer * buffer)
{
GstVulkanImageBufferPoolPrivate *priv = GET_PRIV (vk_pool);
int i;
VkImageCreateInfo image_info;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
VkVideoProfileInfoKHR profiles[2];
VkVideoProfileListInfoKHR profile_list = {
.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR,
.pProfiles = profiles,
};
#endif
/* *INDENT-OFF* */
image_info = (VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = NULL,
.flags = priv->img_flags,
.imageType = VK_IMAGE_TYPE_2D,
/* .format = fill per image, */
/* .extent = fill per plane, */
.mipLevels = 1,
.arrayLayers = priv->n_layers,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = tiling,
.usage = priv->usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = NULL,
.initialLayout = priv->initial_layout == VK_IMAGE_LAYOUT_PREINITIALIZED
? VK_IMAGE_LAYOUT_PREINITIALIZED
: VK_IMAGE_LAYOUT_UNDEFINED,
};
/* *INDENT-ON* */
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
if (priv->n_profiles > 0) {
for (i = 0; i < priv->n_profiles; i++)
profiles[i] = priv->profiles[i].profile;
image_info.pNext = &profile_list;
}
#endif
priv->v_info.size = 0;
for (i = 0; i < priv->n_imgs; i++) {
GstMemory *mem;
guint width, height;
if (GST_VIDEO_INFO_N_PLANES (&priv->v_info) != priv->n_imgs) {
width = GST_VIDEO_INFO_WIDTH (&priv->v_info);
height = GST_VIDEO_INFO_HEIGHT (&priv->v_info);
} else {
width = GST_VIDEO_INFO_COMP_WIDTH (&priv->v_info, i);
height = GST_VIDEO_INFO_COMP_HEIGHT (&priv->v_info, i);
}
image_info.format = priv->vk_fmts[i];
/* *INDENT-OFF* */
image_info.extent = (VkExtent3D) { width, height, 1 };
/* *INDENT-ON* */
mem = gst_vulkan_image_memory_alloc_with_image_info (vk_pool->device,
&image_info, priv->mem_props);
if (!mem)
return FALSE;
if (buffer) {
if (i < GST_VIDEO_MAX_PLANES - 1)
offset[i + 1] = mem->size;
gst_buffer_append_memory (buffer, mem);
} else {
GstVulkanImageMemory *img_mem = (GstVulkanImageMemory *) mem;
priv->v_info.offset[i] = priv->v_info.size;
priv->v_info.size += img_mem->requirements.size;
gst_memory_unref (mem);
}
}
return TRUE;
}
static gboolean
gst_vulkan_image_buffer_pool_set_config (GstBufferPool * pool,
GstStructure * config)
@ -215,12 +302,10 @@ gst_vulkan_image_buffer_pool_set_config (GstBufferPool * pool,
GstVulkanImageBufferPoolPrivate *priv = GET_PRIV (vk_pool);
VkImageTiling tiling;
VkImageUsageFlags requested_usage;
VkImageCreateInfo image_info;
guint min_buffers, max_buffers;
GstCaps *caps = NULL, *decode_caps = NULL, *encode_caps = NULL;
GstCapsFeatures *features;
gboolean found, no_multiplane;
guint i;
if (!gst_buffer_pool_config_get_params (config, &caps, NULL, &min_buffers,
&max_buffers))
@ -246,11 +331,13 @@ gst_vulkan_image_buffer_pool_set_config (GstBufferPool * pool,
&priv->mem_props, &priv->initial_layout, &priv->initial_access,
&priv->n_layers, &decode_caps, &encode_caps);
priv->n_profiles = 0;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
{
guint n = 0;
priv->n_profiles = 0;
#if defined(VK_KHR_video_decode_queue)
if (decode_caps && ((requested_usage
& (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR
| VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR)) != 0)) {
@ -259,7 +346,8 @@ gst_vulkan_image_buffer_pool_set_config (GstBufferPool * pool,
decode_caps, GST_VULKAN_VIDEO_OPERATION_DECODE))
priv->n_profiles++;
}
gst_clear_caps (&decode_caps);
#endif
#if defined(VK_KHR_video_encode_queue)
if (encode_caps && ((requested_usage
& (VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR
| VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)) != 0)) {
@ -268,18 +356,17 @@ gst_vulkan_image_buffer_pool_set_config (GstBufferPool * pool,
encode_caps, GST_VULKAN_VIDEO_OPERATION_ENCODE))
priv->n_profiles++;
}
gst_clear_caps (&encode_caps);
#endif
if (priv->n_profiles != n)
goto missing_profile;
}
if (priv->n_profiles > 0) {
no_multiplane = FALSE;
} else
#endif
{
no_multiplane = TRUE;
}
#endif /* GST_VULKAN_HAVE_VIDEO_EXTENSIONS */
gst_clear_caps (&decode_caps);
gst_clear_caps (&encode_caps);
no_multiplane = (priv->n_profiles == 0);
tiling = priv->raw_caps ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
found = gst_vulkan_format_from_video_info_2 (vk_pool->device,
@ -291,15 +378,21 @@ gst_vulkan_image_buffer_pool_set_config (GstBufferPool * pool,
{
gboolean video = FALSE, sampleable;
const GstVulkanFormatMap *vkmap;
VkImageUsageFlags video_usage = 0;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
video = (requested_usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR
| VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR
| VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR
| VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR));
#if defined(VK_KHR_video_decode_queue)
video_usage |= (VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR
| VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR);
#endif
sampleable = requested_usage &
(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
#if defined(VK_KHR_video_encode_queue)
video_usage |= (VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR
| VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR);
#endif
video = ((requested_usage & video_usage) != 0);
sampleable = ((requested_usage &
(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)) != 0);
if (sampleable && !video) {
vkmap = gst_vulkan_format_get_map (GST_VIDEO_INFO_FORMAT (&priv->v_info));
@ -312,79 +405,15 @@ gst_vulkan_image_buffer_pool_set_config (GstBufferPool * pool,
}
}
priv->usage = requested_usage;
/* get the size of the buffer to allocate */
/* *INDENT-OFF* */
image_info = (VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = NULL,
.flags = priv->img_flags,
.imageType = VK_IMAGE_TYPE_2D,
/* .format = fill per image, */
/* .extent = fill per plane, */
.mipLevels = 1,
.arrayLayers = priv->n_layers,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = tiling,
.usage = requested_usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = NULL,
.initialLayout = priv->initial_layout == VK_IMAGE_LAYOUT_PREINITIALIZED
? VK_IMAGE_LAYOUT_PREINITIALIZED
: VK_IMAGE_LAYOUT_UNDEFINED,
};
/* *INDENT-ON* */
priv->v_info.size = 0;
for (i = 0; i < priv->n_imgs; i++) {
GstVulkanImageMemory *img_mem;
guint width, height;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
VkVideoProfileInfoKHR profiles[] =
{ priv->profiles[0].profile, priv->profiles[1].profile };
VkVideoProfileListInfoKHR profile_list = {
.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR,
.profileCount = priv->n_profiles,
.pProfiles = profiles,
};
#endif
if (GST_VIDEO_INFO_N_PLANES (&priv->v_info) != priv->n_imgs) {
width = GST_VIDEO_INFO_WIDTH (&priv->v_info);
height = GST_VIDEO_INFO_HEIGHT (&priv->v_info);
} else {
width = GST_VIDEO_INFO_COMP_WIDTH (&priv->v_info, i);
height = GST_VIDEO_INFO_COMP_HEIGHT (&priv->v_info, i);
}
image_info.format = priv->vk_fmts[i];
/* *INDENT-OFF* */
image_info.extent = (VkExtent3D) { width, height, 1 };
/* *INDENT-ON* */
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
if (priv->n_profiles > 0)
image_info.pNext = &profile_list;
#endif
img_mem = (GstVulkanImageMemory *)
gst_vulkan_image_memory_alloc_with_image_info (vk_pool->device,
&image_info, priv->mem_props);
if (!img_mem)
goto mem_create_failed;
if (!img_mem)
goto image_failed;
priv->v_info.offset[i] = priv->v_info.size;
priv->v_info.size += img_mem->requirements.size;
gst_memory_unref (GST_MEMORY_CAST (img_mem));
}
if (!gst_vulkan_image_buffer_pool_fill_buffer (vk_pool, tiling, NULL, NULL))
goto image_failed;
gst_buffer_pool_config_set_params (config, caps,
priv->v_info.size, min_buffers, max_buffers);
priv->usage = requested_usage;
/* enable metadata based on config of the pool */
priv->add_videometa = gst_buffer_pool_config_has_option (config,
GST_BUFFER_POOL_OPTION_VIDEO_META);
@ -414,14 +443,12 @@ no_vk_format:
gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&priv->v_info)));
return FALSE;
}
mem_create_failed:
{
GST_WARNING_OBJECT (pool, "Could not create Vulkan Memory");
return FALSE;
}
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
missing_profile:
{
gst_clear_caps (&decode_caps);
gst_clear_caps (&encode_caps);
GST_WARNING_OBJECT (pool, "missing or invalid decode-caps");
return FALSE;
}
@ -436,7 +463,6 @@ image_failed:
static gboolean
prepare_buffer (GstVulkanImageBufferPool * vk_pool, GstBuffer * buffer)
{
#if defined(VK_KHR_synchronization2)
GstVulkanImageBufferPoolPrivate *priv = GET_PRIV (vk_pool);
GArray *barriers = NULL;
GError *error = NULL;
@ -477,6 +503,7 @@ prepare_buffer (GstVulkanImageBufferPool * vk_pool, GstBuffer * buffer)
barriers = gst_vulkan_operation_retrieve_image_barriers (priv->exec);
if (barriers->len > 0) {
if (gst_vulkan_operation_use_sync2 (priv->exec)) {
#if defined(VK_KHR_synchronization2)
VkDependencyInfoKHR dependency_info = {
.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,
.pImageMemoryBarriers = (gpointer) barriers->data,
@ -484,6 +511,7 @@ prepare_buffer (GstVulkanImageBufferPool * vk_pool, GstBuffer * buffer)
};
gst_vulkan_operation_pipeline_barrier2 (priv->exec, &dependency_info);
#endif
} else {
gst_vulkan_command_buffer_lock (priv->exec->cmd_buf);
vkCmdPipelineBarrier (priv->exec->cmd_buf->cmd,
@ -507,8 +535,6 @@ error:
}
return FALSE;
}
#endif
return TRUE;
}
/* This function handles GstBuffer creation */
@ -520,79 +546,15 @@ gst_vulkan_image_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
GstVulkanImageBufferPoolPrivate *priv = GET_PRIV (vk_pool);
VkImageTiling tiling =
priv->raw_caps ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
VkImageCreateInfo image_info;
GstBuffer *buf;
guint i;
gsize offset[GST_VIDEO_MAX_PLANES] = { 0, };
/* *INDENT-OFF* */
image_info = (VkImageCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = NULL,
.flags = priv->img_flags,
.imageType = VK_IMAGE_TYPE_2D,
/* .format = fill per image, */
/* .extent = fill per plane, */
.mipLevels = 1,
.arrayLayers = priv->n_layers,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = tiling,
.usage = priv->usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = NULL,
.initialLayout = priv->initial_layout == VK_IMAGE_LAYOUT_PREINITIALIZED
? VK_IMAGE_LAYOUT_PREINITIALIZED
: VK_IMAGE_LAYOUT_UNDEFINED,
};
/* *INDENT-ON* */
if (!(buf = gst_buffer_new ())) {
goto no_buffer;
}
for (i = 0; i < priv->n_imgs; i++) {
GstMemory *mem;
guint width, height;
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
VkVideoProfileInfoKHR profiles[] =
{ priv->profiles[0].profile, priv->profiles[1].profile };
VkVideoProfileListInfoKHR profile_list = {
.sType = VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR,
.profileCount = priv->n_profiles,
.pProfiles = profiles,
};
#endif
if (GST_VIDEO_INFO_N_PLANES (&priv->v_info) != priv->n_imgs) {
width = GST_VIDEO_INFO_WIDTH (&priv->v_info);
height = GST_VIDEO_INFO_HEIGHT (&priv->v_info);
} else {
width = GST_VIDEO_INFO_COMP_WIDTH (&priv->v_info, i);
height = GST_VIDEO_INFO_COMP_HEIGHT (&priv->v_info, i);
}
image_info.format = priv->vk_fmts[i];
/* *INDENT-OFF* */
image_info.extent = (VkExtent3D) { width, height, 1 };
/* *INDENT-ON* */
#if GST_VULKAN_HAVE_VIDEO_EXTENSIONS
if (priv->n_profiles > 0)
image_info.pNext = &profile_list;
#endif
mem = gst_vulkan_image_memory_alloc_with_image_info (vk_pool->device,
&image_info, priv->mem_props);
if (!mem) {
gst_buffer_unref (buf);
goto mem_create_failed;
}
if (i < GST_VIDEO_MAX_PLANES - 1)
offset[i + 1] = mem->size;
gst_buffer_append_memory (buf, mem);
}
if (!gst_vulkan_image_buffer_pool_fill_buffer (vk_pool, tiling, offset, buf))
goto mem_create_failed;
prepare_buffer (vk_pool, buf);
@ -618,6 +580,8 @@ no_buffer:
}
mem_create_failed:
{
gst_buffer_unref (buf);
GST_WARNING_OBJECT (pool, "Could not create Vulkan Memory");
return GST_FLOW_ERROR;
}