gstreamer/subprojects/gst-plugins-bad/tests/check/libs/d3d11device.cpp
Seungha Yang 5ac7a21ef0 d3d11: d3d11device: Add gst_d3d11_device_new_{for_adapter_luid,wrapped}
* gst_d3d11_device_new_for_adapter_luid()
  Used for creating D3D11 device for a DXGI adapter (i.e., GPU)
  corresponding to a LUID (Locally Unique Identifier).
  This method can be useful for interop with other APIs such as
  Direct3D12, MediaFoundation, CUDA, etc.
* gst_d3d11_device_new_wrapped()
  Allows creating a new GstD3D11Device object by using already
  configured ID3D11Device. This is conceptually equivalent to
  gst_gl_context_new_wrapped()

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1098>
2021-10-10 03:23:53 +09:00

209 lines
5.6 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 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);
out:
return s;
}
GST_CHECK_MAIN (d3d11device);