gstreamer/subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp
Seungha Yang f47a198977 Revert "d3d11device: protect device_lock vs device_new"
This reverts commit 926d5366b9.

AcquireSRWLockExclusive seems to be acquiring lock in exclusive mode
when the same lock is combined with write lock access.
Reverting the commit because of this is unexpected behavior
and unavoidable OS bug.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6904>
2024-05-23 15:16:02 +00:00

264 lines
7.2 KiB
C++

/* GStreamer
* Copyright (C) 2021 Seungha Yang <seungha@centricular.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <gst/check/gstcheck.h>
#include <gst/d3d11/gstd3d11.h>
#include <wrl.h>
/* *INDENT-OFF* */
using namespace Microsoft::WRL;
/* *INDENT-ON* */
static gboolean have_multiple_adapters = FALSE;
GST_START_TEST (test_device_new)
{
GstD3D11Device *device = nullptr;
guint adapter_index = G_MAXINT;
device = gst_d3d11_device_new (0, 0);
fail_unless (GST_IS_D3D11_DEVICE (device));
g_object_get (device, "adapter", &adapter_index, nullptr);
fail_unless_equals_int (adapter_index, 0);
gst_clear_object (&device);
if (have_multiple_adapters) {
device = gst_d3d11_device_new (1, 0);
fail_unless (GST_IS_D3D11_DEVICE (device));
g_object_get (device, "adapter", &adapter_index, nullptr);
fail_unless_equals_int (adapter_index, 1);
}
gst_clear_object (&device);
}
GST_END_TEST;
GST_START_TEST (test_device_for_adapter_luid)
{
GstD3D11Device *device = nullptr;
HRESULT hr;
ComPtr < IDXGIAdapter1 > adapter;
ComPtr < IDXGIFactory1 > factory;
DXGI_ADAPTER_DESC desc;
guint adapter_index = G_MAXINT;
gint64 adapter_luid = 0;
gint64 luid;
hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
if (SUCCEEDED (hr))
hr = factory->EnumAdapters1 (0, &adapter);
if (SUCCEEDED (hr))
hr = adapter->GetDesc (&desc);
if (SUCCEEDED (hr)) {
luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
device = gst_d3d11_device_new_for_adapter_luid (luid, 0);
fail_unless (GST_IS_D3D11_DEVICE (device));
g_object_get (device, "adapter", &adapter_index, "adapter-luid",
&adapter_luid, nullptr);
/* adapter_luid is corresponding to the first enumerated adapter,
* so adapter index should be zero here */
fail_unless_equals_int (adapter_index, 0);
fail_unless_equals_int64 (adapter_luid, luid);
}
gst_clear_object (&device);
adapter = nullptr;
if (have_multiple_adapters) {
if (SUCCEEDED (hr))
hr = factory->EnumAdapters1 (1, &adapter);
if (SUCCEEDED (hr))
hr = adapter->GetDesc (&desc);
if (SUCCEEDED (hr)) {
luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
device = gst_d3d11_device_new_for_adapter_luid (luid, 0);
fail_unless (GST_IS_D3D11_DEVICE (device));
g_object_get (device, "adapter", &adapter_index, "adapter-luid",
&adapter_luid, nullptr);
fail_unless_equals_int (adapter_index, 1);
fail_unless_equals_int64 (adapter_luid, luid);
}
}
gst_clear_object (&device);
}
GST_END_TEST;
GST_START_TEST (test_device_new_wrapped)
{
GstD3D11Device *device = nullptr;
GstD3D11Device *device_clone = nullptr;
ID3D11Device *device_handle, *device_handle_clone;
ID3D11DeviceContext *context_handle, *context_handle_clone;
guint adapter_index = 0;
guint index;
gint64 luid, luid_clone;
if (have_multiple_adapters)
adapter_index = 1;
device = gst_d3d11_device_new (adapter_index, 0);
fail_unless (GST_IS_D3D11_DEVICE (device));
device_handle = gst_d3d11_device_get_device_handle (device);
fail_unless (device_handle != nullptr);
context_handle = gst_d3d11_device_get_device_context_handle (device);
fail_unless (context_handle != nullptr);
g_object_get (device, "adapter", &index, "adapter-luid", &luid, nullptr);
fail_unless_equals_int (index, adapter_index);
device_clone = gst_d3d11_device_new_wrapped (device_handle);
fail_unless (GST_IS_D3D11_DEVICE (device_clone));
device_handle_clone = gst_d3d11_device_get_device_handle (device_clone);
fail_unless_equals_pointer (device_handle, device_handle_clone);
context_handle_clone =
gst_d3d11_device_get_device_context_handle (device_clone);
fail_unless_equals_pointer (context_handle, context_handle_clone);
g_object_get (device_clone,
"adapter", &index, "adapter-luid", &luid_clone, nullptr);
fail_unless_equals_int (index, adapter_index);
fail_unless_equals_int64 (luid, luid_clone);
gst_clear_object (&device);
gst_clear_object (&device_clone);
}
GST_END_TEST;
static gboolean
check_d3d11_available (void)
{
HRESULT hr;
ComPtr < IDXGIAdapter1 > adapter;
ComPtr < IDXGIFactory1 > factory;
hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
if (FAILED (hr))
return FALSE;
hr = factory->EnumAdapters1 (0, &adapter);
if (FAILED (hr))
return FALSE;
adapter = nullptr;
hr = factory->EnumAdapters1 (1, &adapter);
if (SUCCEEDED (hr))
have_multiple_adapters = TRUE;
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)
{
Suite *s = suite_create ("d3d11device");
TCase *tc_basic = tcase_create ("general");
suite_add_tcase (s, tc_basic);
if (!check_d3d11_available ())
goto out;
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;
}
GST_CHECK_MAIN (d3d11device);