vkutils: add gst_vulkan_ensure_element_device

In order to keep the same device across
the elements in the pipeline, use either the device id
to create the device or get the device from the context
set by the peer elements.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7843>
This commit is contained in:
Stéphane Cerveau 2024-11-06 12:47:32 +01:00 committed by GStreamer Marge Bot
parent 9a771b6909
commit 0dd706a420
10 changed files with 113 additions and 87 deletions

View file

@ -7174,6 +7174,37 @@ retrieval is performed.</doc>
</parameter> </parameter>
</parameters> </parameters>
</function> </function>
<function name="vulkan_ensure_element_device" c:identifier="gst_vulkan_ensure_element_device" version="1.26">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkutils.c">Perform the steps necessary for retrieving a #GstVulkanDevice from
the surrounding elements or create a new device according to the device_id.
If the contents of @device_ptr is not %NULL, then no
#GstContext query is necessary and no #GstVulkanDevice
retrieval is performed.</doc>
<source-position filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkutils.h"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkutils.c">whether a #GstVulkanDevice exists in @device_ptr</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="element" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkutils.c">a #GstElement</doc>
<type name="Gst.Element" c:type="GstElement*"/>
</parameter>
<parameter name="instance" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkutils.c">the #GstVulkanInstance</doc>
<type name="VulkanInstance" c:type="GstVulkanInstance*"/>
</parameter>
<parameter name="device_ptr" direction="inout" caller-allocates="0" transfer-ownership="full" optional="1">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkutils.c">the resulting #GstVulkanDevice</doc>
<type name="VulkanDevice" c:type="GstVulkanDevice**"/>
</parameter>
<parameter name="device_id" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gst-plugins-bad/gst-libs/gst/vulkan/gstvkutils.c">The device number to use, 0 is default.</doc>
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="vulkan_error_quark" c:identifier="gst_vulkan_error_quark" moved-to="VulkanError.quark" version="1.18"> <function name="vulkan_error_quark" c:identifier="gst_vulkan_error_quark" moved-to="VulkanError.quark" version="1.18">
<return-value transfer-ownership="none"> <return-value transfer-ownership="none">
<type name="GLib.Quark" c:type="GQuark"/> <type name="GLib.Quark" c:type="GQuark"/>

View file

@ -569,21 +569,10 @@ gst_vulkan_download_change_state (GstElement * element,
("Failed to retrieve vulkan instance"), (NULL)); ("Failed to retrieve vulkan instance"), (NULL));
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (vk_download), if (!gst_vulkan_ensure_element_device (element, vk_download->instance,
&vk_download->device)) { &vk_download->device, 0)) {
GError *error = NULL;
GST_DEBUG_OBJECT (vk_download,
"No device retrieved from peer elements");
if (!(vk_download->device =
gst_vulkan_instance_create_device (vk_download->instance,
&error))) {
GST_ELEMENT_ERROR (vk_download, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"), ("%s",
error ? error->message : ""));
g_clear_error (&error);
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }
}
if (gst_vulkan_queue_run_context_query (GST_ELEMENT (vk_download), if (gst_vulkan_queue_run_context_query (GST_ELEMENT (vk_download),
&vk_download->queue)) { &vk_download->queue)) {

View file

@ -135,19 +135,10 @@ gst_vulkan_h264_decoder_open (GstVideoDecoder * decoder)
return FALSE; return FALSE;
} }
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (decoder), if (!gst_vulkan_ensure_element_device (GST_ELEMENT (decoder), self->instance,
&self->device)) { &self->device, 0)) {
GError *error = NULL;
GST_DEBUG_OBJECT (self, "No device retrieved from peer elements");
self->device = gst_vulkan_instance_create_device (self->instance, &error);
if (!self->device) {
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"),
("%s", error ? error->message : ""));
g_clear_error (&error);
return FALSE; return FALSE;
} }
}
if (!gst_vulkan_queue_run_context_query (GST_ELEMENT (self), if (!gst_vulkan_queue_run_context_query (GST_ELEMENT (self),
&self->graphic_queue)) { &self->graphic_queue)) {

View file

@ -193,19 +193,10 @@ gst_vulkan_h265_decoder_open (GstVideoDecoder * decoder)
return FALSE; return FALSE;
} }
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (decoder), if (!gst_vulkan_ensure_element_device (GST_ELEMENT (decoder), self->instance,
&self->device)) { &self->device, 0)) {
GError *error = NULL;
GST_DEBUG_OBJECT (self, "No device retrieved from peer elements");
self->device = gst_vulkan_instance_create_device (self->instance, &error);
if (!self->device) {
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"),
("%s", error ? error->message : ""));
g_clear_error (&error);
return FALSE; return FALSE;
} }
}
if (!gst_vulkan_queue_run_context_query (GST_ELEMENT (self), if (!gst_vulkan_queue_run_context_query (GST_ELEMENT (self),
&self->graphic_queue)) { &self->graphic_queue)) {

View file

@ -288,21 +288,10 @@ gst_vulkan_sink_change_state (GstElement * element, GstStateChange transition)
("Failed to retrieve vulkan instance/display"), (NULL)); ("Failed to retrieve vulkan instance/display"), (NULL));
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }
if (!gst_vulkan_ensure_element_device (element, vk_sink->instance,
if (!vk_sink->device) { &vk_sink->device, 0)) {
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (vk_sink),
&vk_sink->device)) {
if (!(vk_sink->device =
gst_vulkan_instance_create_device (vk_sink->instance,
&error))) {
GST_ELEMENT_ERROR (vk_sink, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"), ("%s",
error ? error->message : ""));
g_clear_error (&error);
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }
}
}
break; break;
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
/* FIXME: this probably doesn't need to be so early in the setup process */ /* FIXME: this probably doesn't need to be so early in the setup process */

View file

@ -1151,20 +1151,10 @@ gst_vulkan_upload_change_state (GstElement * element, GstStateChange transition)
("Failed to retrieve vulkan instance"), (NULL)); ("Failed to retrieve vulkan instance"), (NULL));
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (vk_upload), if (!gst_vulkan_ensure_element_device (element, vk_upload->instance,
&vk_upload->device)) { &vk_upload->device, 0)) {
GError *error = NULL;
GST_DEBUG_OBJECT (vk_upload, "No device retrieved from peer elements");
if (!(vk_upload->device =
gst_vulkan_instance_create_device (vk_upload->instance,
&error))) {
GST_ELEMENT_ERROR (vk_upload, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"), ("%s",
error ? error->message : ""));
g_clear_error (&error);
return GST_STATE_CHANGE_FAILURE; return GST_STATE_CHANGE_FAILURE;
} }
}
// Issue with NVIDIA driver where the output gets artifacts if I select another // Issue with NVIDIA driver where the output gets artifacts if I select another
// queue seen the codec one does not support VK_QUEUE_GRAPHICS_BIT but VK_QUEUE_TRANSFER_BIT. // queue seen the codec one does not support VK_QUEUE_GRAPHICS_BIT but VK_QUEUE_TRANSFER_BIT.
if (gst_vulkan_queue_run_context_query (GST_ELEMENT (vk_upload), if (gst_vulkan_queue_run_context_query (GST_ELEMENT (vk_upload),

View file

@ -309,6 +309,61 @@ gst_vulkan_ensure_element_data (GstElement * element,
return *display_ptr != NULL && *instance_ptr != NULL; return *display_ptr != NULL && *instance_ptr != NULL;
} }
/**
* gst_vulkan_ensure_element_device:
* @element: a #GstElement
* @instance: the #GstVulkanInstance
* @device_ptr: (inout) (optional): the resulting #GstVulkanDevice
* @device_id: The device number to use, 0 is default.
*
* Perform the steps necessary for retrieving a #GstVulkanDevice from
* the surrounding elements or create a new device according to the device_id.
*
* If the contents of @device_ptr is not %NULL, then no
* #GstContext query is necessary and no #GstVulkanDevice
* retrieval is performed.
*
* Returns: whether a #GstVulkanDevice exists in @device_ptr
*
* Since: 1.26
*/
gboolean
gst_vulkan_ensure_element_device (GstElement * element,
GstVulkanInstance * instance, GstVulkanDevice ** device_ptr,
guint device_id)
{
g_return_val_if_fail (instance != NULL, FALSE);
if (!gst_vulkan_device_run_context_query (element, device_ptr)) {
GError *error = NULL;
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"No device retrieved from peer elements");
/* If no neighboor, or application not interested, use system default by device id */
*device_ptr =
gst_vulkan_instance_create_device_with_index (instance, device_id,
&error);
if (!*device_ptr) {
GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"),
("%s", error ? error->message : ""));
g_clear_error (&error);
return FALSE;
}
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"Created a new device from %s",
(*device_ptr)->physical_device->properties.deviceName);
} else {
if ((*device_ptr)->physical_device->device_index != device_id) {
GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
"A device with a different id has been selected from a peer element");
}
}
return *device_ptr != NULL;
}
/** /**
* gst_vulkan_handle_set_context: * gst_vulkan_handle_set_context:
* @element: a #GstElement * @element: a #GstElement

View file

@ -30,6 +30,11 @@ gboolean gst_vulkan_ensure_element_data (GstElement * el
GstVulkanDisplay ** display_ptr, GstVulkanDisplay ** display_ptr,
GstVulkanInstance ** instance_ptr); GstVulkanInstance ** instance_ptr);
GST_VULKAN_API GST_VULKAN_API
gboolean gst_vulkan_ensure_element_device (GstElement * element,
GstVulkanInstance * instance,
GstVulkanDevice ** device_ptr,
guint device_id);
GST_VULKAN_API
gboolean gst_vulkan_handle_set_context (GstElement * element, gboolean gst_vulkan_handle_set_context (GstElement * element,
GstContext * context, GstContext * context,
GstVulkanDisplay ** display, GstVulkanDisplay ** display,

View file

@ -274,18 +274,11 @@ gst_vulkan_video_filter_start (GstBaseTransform * bt)
("Failed to retrieve vulkan instance"), (NULL)); ("Failed to retrieve vulkan instance"), (NULL));
return FALSE; return FALSE;
} }
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (render),
&render->device)) { if (!gst_vulkan_ensure_element_device (GST_ELEMENT (bt), render->instance,
GError *error = NULL; &render->device, 0)) {
GST_DEBUG_OBJECT (render, "No device retrieved from peer elements");
if (!(render->device =
gst_vulkan_instance_create_device (render->instance, &error))) {
GST_ELEMENT_ERROR (render, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"), ("%s", error->message));
g_clear_error (&error);
return FALSE; return FALSE;
} }
}
if (!gst_vulkan_queue_run_context_query (GST_ELEMENT (render), if (!gst_vulkan_queue_run_context_query (GST_ELEMENT (render),
&render->queue)) { &render->queue)) {

View file

@ -643,18 +643,10 @@ gst_vtdec_negotiate (GstVideoDecoder * decoder)
gst_vulkan_ensure_element_data (GST_ELEMENT (vtdec), NULL, gst_vulkan_ensure_element_data (GST_ELEMENT (vtdec), NULL,
&vtdec->instance); &vtdec->instance);
if (!gst_vulkan_device_run_context_query (GST_ELEMENT (vtdec), if (!gst_vulkan_ensure_element_device (GST_ELEMENT (vtdec),
&vtdec->device)) { vtdec->instance, &vtdec->device, 0)) {
GError *error = NULL;
GST_DEBUG_OBJECT (vtdec, "No device retrieved from peer elements");
if (!(vtdec->device =
gst_vulkan_instance_create_device (vtdec->instance, &error))) {
GST_ELEMENT_ERROR (vtdec, RESOURCE, NOT_FOUND,
("Failed to create vulkan device"), ("%s", error->message));
g_clear_error (&error);
return FALSE; return FALSE;
} }
}
GST_INFO_OBJECT (vtdec, "pushing vulkan images, device %" GST_PTR_FORMAT GST_INFO_OBJECT (vtdec, "pushing vulkan images, device %" GST_PTR_FORMAT
" old device %" GST_PTR_FORMAT, vtdec->device, " old device %" GST_PTR_FORMAT, vtdec->device,