vulkan/queue: be sure to take a lock around command submission

This ensures that only one thread is submitting commands at a time as
required by the Vulkan specification.
This commit is contained in:
Matthew Waters 2019-11-14 10:00:35 +11:00 committed by GStreamer Merge Bot
parent c89f21388d
commit 9f4b043161
7 changed files with 64 additions and 4 deletions

View file

@ -311,9 +311,11 @@ _image_to_raw_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
if (!fence) if (!fence)
goto error; goto error;
gst_vulkan_queue_submit_lock (raw->download->queue);
err = err =
vkQueueSubmit (raw->download->queue->queue, 1, &submit_info, vkQueueSubmit (raw->download->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence)); GST_VULKAN_FENCE_FENCE (fence));
gst_vulkan_queue_submit_unlock (raw->download->queue);
if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0) if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0)
goto error; goto error;

View file

@ -900,9 +900,11 @@ gst_vulkan_full_screen_render_submit (GstVulkanFullScreenRender * render,
gst_vulkan_fence_unref (render->last_fence); gst_vulkan_fence_unref (render->last_fence);
render->last_fence = gst_vulkan_fence_ref (fence); render->last_fence = gst_vulkan_fence_ref (fence);
gst_vulkan_queue_submit_lock (render->queue);
err = err =
vkQueueSubmit (render->queue->queue, 1, &submit_info, vkQueueSubmit (render->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence)); GST_VULKAN_FENCE_FENCE (fence));
gst_vulkan_queue_submit_unlock (render->queue);
if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0) if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0)
goto error; goto error;

View file

@ -987,9 +987,11 @@ _raw_to_image_perform (gpointer impl, GstBuffer * inbuf, GstBuffer ** outbuf)
if (!fence) if (!fence)
goto error; goto error;
gst_vulkan_queue_submit_lock (raw->upload->queue);
err = err =
vkQueueSubmit (raw->upload->queue->queue, 1, &submit_info, vkQueueSubmit (raw->upload->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence)); GST_VULKAN_FENCE_FENCE (fence));
gst_vulkan_queue_submit_unlock (raw->upload->queue);
if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0) if (gst_vulkan_error_to_g_error (err, &error, "vkQueueSubmit") < 0)
goto error; goto error;

View file

@ -49,21 +49,31 @@ _init_debug (void)
} }
} }
struct _GstVulkanQueuePrivate
{
GMutex submit_lock;
};
#define parent_class gst_vulkan_queue_parent_class #define parent_class gst_vulkan_queue_parent_class
G_DEFINE_TYPE_WITH_CODE (GstVulkanQueue, gst_vulkan_queue, GST_TYPE_OBJECT, G_DEFINE_TYPE_WITH_CODE (GstVulkanQueue, gst_vulkan_queue, GST_TYPE_OBJECT,
_init_debug ()); G_ADD_PRIVATE (GstVulkanQueue); _init_debug ());
#define GET_PRIV(queue) gst_vulkan_queue_get_instance_private (queue)
static void gst_vulkan_queue_dispose (GObject * object); static void gst_vulkan_queue_dispose (GObject * object);
static void static void
gst_vulkan_queue_init (GstVulkanQueue * device) gst_vulkan_queue_init (GstVulkanQueue * queue)
{ {
GstVulkanQueuePrivate *priv = GET_PRIV (queue);
g_mutex_init (&priv->submit_lock);
} }
static void static void
gst_vulkan_queue_class_init (GstVulkanQueueClass * device_class) gst_vulkan_queue_class_init (GstVulkanQueueClass * queue_class)
{ {
GObjectClass *gobject_class = (GObjectClass *) device_class; GObjectClass *gobject_class = (GObjectClass *) queue_class;
gobject_class->dispose = gst_vulkan_queue_dispose; gobject_class->dispose = gst_vulkan_queue_dispose;
} }
@ -72,11 +82,14 @@ static void
gst_vulkan_queue_dispose (GObject * object) gst_vulkan_queue_dispose (GObject * object)
{ {
GstVulkanQueue *queue = GST_VULKAN_QUEUE (object); GstVulkanQueue *queue = GST_VULKAN_QUEUE (object);
GstVulkanQueuePrivate *priv = GET_PRIV (queue);
if (queue->device) if (queue->device)
gst_object_unref (queue->device); gst_object_unref (queue->device);
queue->device = NULL; queue->device = NULL;
g_mutex_clear (&priv->submit_lock);
G_OBJECT_CLASS (parent_class)->dispose (object); G_OBJECT_CLASS (parent_class)->dispose (object);
} }
@ -291,3 +304,34 @@ gst_vulkan_queue_run_context_query (GstElement * element,
return FALSE; return FALSE;
} }
/**
* gst_vulkan_queue_submit_lock:
* @queue: a #GstVulkanQueue
*
* Locks the queue for command submission using `vkQueueSubmit()` to meet the
* Vulkan requirements for externally synchronised resources.
*/
void
gst_vulkan_queue_submit_lock (GstVulkanQueue * queue)
{
GstVulkanQueuePrivate *priv = GET_PRIV (queue);
g_mutex_lock (&priv->submit_lock);
}
/**
* gst_vulkan_queue_submit_unlock:
* @queue: a #GstVulkanQueue
*
* Unlocks the queue for command submission using `vkQueueSubmit()`.
*
* See gst_vulkan_queue_submit_lock() for details on when this call is needed.
*/
void
gst_vulkan_queue_submit_unlock (GstVulkanQueue * queue)
{
GstVulkanQueuePrivate *priv = GET_PRIV (queue);
g_mutex_unlock (&priv->submit_lock);
}

View file

@ -58,6 +58,11 @@ GST_VULKAN_API
GstVulkanCommandPool * gst_vulkan_queue_create_command_pool (GstVulkanQueue * queue, GstVulkanCommandPool * gst_vulkan_queue_create_command_pool (GstVulkanQueue * queue,
GError ** error); GError ** error);
GST_VULKAN_API
void gst_vulkan_queue_submit_lock (GstVulkanQueue * queue);
GST_VULKAN_API
void gst_vulkan_queue_submit_unlock (GstVulkanQueue * queue);
GST_VULKAN_API GST_VULKAN_API
void gst_context_set_vulkan_queue (GstContext * context, void gst_context_set_vulkan_queue (GstContext * context,
GstVulkanQueue * queue); GstVulkanQueue * queue);

View file

@ -1268,9 +1268,11 @@ reacquire:
if (!fence) if (!fence)
goto error; goto error;
gst_vulkan_queue_submit_lock (swapper->queue);
err = err =
vkQueueSubmit (swapper->queue->queue, 1, &submit_info, vkQueueSubmit (swapper->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence)); GST_VULKAN_FENCE_FENCE (fence));
gst_vulkan_queue_submit_unlock (swapper->queue);
if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0) if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0)
goto error; goto error;
@ -1325,9 +1327,11 @@ reacquire:
if (!fence) if (!fence)
goto error; goto error;
gst_vulkan_queue_submit_lock (swapper->queue);
err = err =
vkQueueSubmit (swapper->queue->queue, 1, &submit_info, vkQueueSubmit (swapper->queue->queue, 1, &submit_info,
GST_VULKAN_FENCE_FENCE (fence)); GST_VULKAN_FENCE_FENCE (fence));
gst_vulkan_queue_submit_unlock (swapper->queue);
if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0) if (gst_vulkan_error_to_g_error (err, error, "vkQueueSubmit") < 0)
goto error; goto error;

View file

@ -39,6 +39,7 @@ typedef struct _GstVulkanPhysicalDevicePrivate GstVulkanPhysicalDevicePrivate;
typedef struct _GstVulkanQueue GstVulkanQueue; typedef struct _GstVulkanQueue GstVulkanQueue;
typedef struct _GstVulkanQueueClass GstVulkanQueueClass; typedef struct _GstVulkanQueueClass GstVulkanQueueClass;
typedef struct _GstVulkanQueuePrivate GstVulkanQueuePrivate;
typedef struct _GstVulkanCommandPool GstVulkanCommandPool; typedef struct _GstVulkanCommandPool GstVulkanCommandPool;
typedef struct _GstVulkanCommandPoolClass GstVulkanCommandPoolClass; typedef struct _GstVulkanCommandPoolClass GstVulkanCommandPoolClass;