d3d11device: protect device_lock vs device_new

It seems that when D3D11CreateDevice collides in time
with other D3D11 calls, in particular the proccess of
creating a shader, it can corrupt the memory in the driver.
D3D11 spec doesn't seem to require any thread safety from
D3D11CreateDevice. Following MSDN, it is supposed to be called
in the beginning of the proccess, while GStreamer calls it with each
new pipeline.
Such crashes in the driver were frequently reproducing on the
Intel UHD 630 machine.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6686>
This commit is contained in:
Alexander Slobodeniuk 2024-04-18 10:18:05 +02:00 committed by GStreamer Marge Bot
parent 8e0046a738
commit 926d5366b9
2 changed files with 24 additions and 0 deletions

View file

@ -731,6 +731,8 @@ gst_d3d11_device_log_live_objects (GstD3D11Device * device,
#endif
}
static SRWLOCK _device_creation_rwlock = SRWLOCK_INIT;
static void
gst_d3d11_device_dispose (GObject * object)
{
@ -739,6 +741,7 @@ gst_d3d11_device_dispose (GObject * object)
GST_LOG_OBJECT (self, "dispose");
AcquireSRWLockExclusive (&_device_creation_rwlock);
priv->ps_cache.clear ();
priv->vs_cache.clear ();
priv->sampler_cache.clear ();
@ -764,6 +767,7 @@ gst_d3d11_device_dispose (GObject * object)
GST_D3D11_CLEAR_COM (priv->dxgi_info_queue);
#endif
ReleaseSRWLockExclusive (&_device_creation_rwlock);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@ -996,6 +1000,7 @@ gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
debug_init_once ();
GstD3D11SRWLockGuard lk (&_device_creation_rwlock);
hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
if (!gst_d3d11_result (hr, NULL)) {
GST_WARNING ("cannot create dxgi factory, hr: 0x%x", (guint) hr);
@ -1357,6 +1362,8 @@ gst_d3d11_device_lock (GstD3D11Device * device)
priv = device->priv;
AcquireSRWLockShared (&_device_creation_rwlock);
GST_TRACE_OBJECT (device, "device locking");
priv->extern_lock.lock ();
GST_TRACE_OBJECT (device, "device locked");
@ -1382,6 +1389,8 @@ gst_d3d11_device_unlock (GstD3D11Device * device)
priv->extern_lock.unlock ();
GST_TRACE_OBJECT (device, "device unlocked");
ReleaseSRWLockShared (&_device_creation_rwlock);
}
/**

View file

@ -241,6 +241,20 @@ GST_START_TEST (test_device_new_concurrency)
GST_END_TEST;
GST_START_TEST (test_device_lock_recursiveness)
{
GstD3D11Device *device = gst_d3d11_device_new (0, 0);
gst_d3d11_device_lock (device);
gst_d3d11_device_lock (device);
gst_d3d11_device_unlock (device);
gst_d3d11_device_unlock (device);
gst_object_unref (device);
}
GST_END_TEST;
static Suite *
d3d11device_suite (void)
{
@ -256,6 +270,7 @@ d3d11device_suite (void)
tcase_add_test (tc_basic, test_device_for_adapter_luid);
tcase_add_test (tc_basic, test_device_new_wrapped);
tcase_add_test (tc_basic, test_device_new_concurrency);
tcase_add_test (tc_basic, test_device_lock_recursiveness);
out:
return s;