tests/d3d11: add concurrency test for gstd3d11device

We suspect that it's not thread safe to just create and
destroy the device from any thread, particularly because
of D3D11CreateDevice, that is not documented as thread-safe.
While D3D11CreateDevice is usually protected from outside
by the gst_d3d11_ensure_element_data, it still can cross
with the Release() method of another device.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6686>
This commit is contained in:
Alexander Slobodeniuk 2024-04-16 23:08:51 +02:00 committed by GStreamer Marge Bot
parent 13e17b9149
commit 8e0046a738
2 changed files with 57 additions and 1 deletions

View file

@ -186,6 +186,61 @@ check_d3d11_available (void)
return TRUE;
}
static gboolean stopping = FALSE;
static gpointer
test_device_new_concurrency_thread (gpointer)
{
GstVideoInfo in_info, out_info;
gst_video_info_set_format (&in_info, GST_VIDEO_FORMAT_I420, 320, 240);
gst_video_info_set_format (&out_info, GST_VIDEO_FORMAT_RGBx, 1920, 1080);
while (!g_atomic_int_get (&stopping)) {
GstD3D11Converter *converter;
GstD3D11Device *device = gst_d3d11_device_new (0, D3D11_CREATE_DEVICE_BGRA_SUPPORT);
gst_d3d11_device_lock (device);
converter = gst_d3d11_converter_new (device, &in_info, &out_info,
gst_structure_new ("converter-config",
GST_D3D11_CONVERTER_OPT_BACKEND, GST_TYPE_D3D11_CONVERTER_BACKEND,
GST_D3D11_CONVERTER_BACKEND_SHADER,
GST_D3D11_CONVERTER_OPT_GAMMA_MODE,
GST_TYPE_VIDEO_GAMMA_MODE, GST_VIDEO_GAMMA_MODE_NONE,
GST_D3D11_CONVERTER_OPT_PRIMARIES_MODE,
GST_TYPE_VIDEO_PRIMARIES_MODE, GST_VIDEO_PRIMARIES_MODE_NONE,
nullptr));
gst_d3d11_device_unlock (device);
g_usleep (g_random_int_range (10, 1000));
gst_d3d11_device_lock (device);
gst_object_unref (converter);
gst_d3d11_device_unlock (device);
gst_object_unref (device);
}
return NULL;
}
GST_START_TEST (test_device_new_concurrency)
{
#define NUM_THREADS 32
GThread *threads[NUM_THREADS];
for (int t = 0; t < NUM_THREADS; t++)
threads[t] = g_thread_new (NULL, test_device_new_concurrency_thread, NULL);
g_usleep (20 * G_TIME_SPAN_SECOND);
g_atomic_int_set (&stopping, TRUE);
for (int t = 0; t < NUM_THREADS; t++)
g_thread_join(threads[t]);
}
GST_END_TEST;
static Suite *
d3d11device_suite (void)
{
@ -200,6 +255,7 @@ d3d11device_suite (void)
tcase_add_test (tc_basic, test_device_new);
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);
out:
return s;

View file

@ -109,7 +109,7 @@ base_tests = [
[['libs/vkinstance.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
[['libs/vkimagebufferpool.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],
[['libs/vkvideodecode.c'], not gstvulkan_dep.found() or vulkan_conf.get('GST_VULKAN_HAVE_VIDEO_EXTENSIONS') != 1, [gstvulkan_dep]],
[['libs/d3d11device.cpp'], not gstd3d11_dep.found(), [gstd3d11_dep]],
[['libs/d3d11device.cpp'], not gstd3d11_dep.found(), [gstd3d11_dep, gstvideo_dep]],
[['libs/d3d11memory.c'], not gstd3d11_dep.found(), [gstd3d11_dep]],
[['libs/cudamemory.c'], not gstcuda_dep.found(), [gstcuda_dep, gstcuda_stub_dep]],
]