mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-20 14:18:34 +00:00
d3d11device: Add device-removed-reason property
In addition to device removed status monitoring in gst_d3d11_result() method, if ID3D11Device4 interface is available, an event handle will be used for device removed status update. And "device-removed" signal is removed since applications can monitor the device removed status via gobject notify Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6699>
This commit is contained in:
parent
b12b04eeef
commit
40f7d7f1f7
3 changed files with 104 additions and 76 deletions
|
@ -64,8 +64,8 @@ GST_D3D11_API
|
||||||
HRESULT gst_d3d11_device_get_rasterizer_msaa (GstD3D11Device * device,
|
HRESULT gst_d3d11_device_get_rasterizer_msaa (GstD3D11Device * device,
|
||||||
ID3D11RasterizerState ** rasterizer);
|
ID3D11RasterizerState ** rasterizer);
|
||||||
|
|
||||||
/* Used internally by gstd3d11utils.cpp */
|
GST_D3D11_API
|
||||||
void gst_d3d11_device_mark_removed (GstD3D11Device * device, HRESULT reason);
|
void gst_d3d11_device_check_device_removed (GstD3D11Device * device);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -96,24 +96,31 @@ enum
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
PROP_CREATE_FLAGS,
|
PROP_CREATE_FLAGS,
|
||||||
PROP_ADAPTER_LUID,
|
PROP_ADAPTER_LUID,
|
||||||
|
PROP_DEVICE_REMOVED_REASON,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GParamSpec *pspec_removed_reason = nullptr;
|
||||||
|
|
||||||
#define DEFAULT_ADAPTER 0
|
#define DEFAULT_ADAPTER 0
|
||||||
#define DEFAULT_CREATE_FLAGS 0
|
#define DEFAULT_CREATE_FLAGS 0
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* signals */
|
|
||||||
SIGNAL_DEVICE_REMOVED,
|
|
||||||
LAST_SIGNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
static guint gst_d3d11_device_signals[LAST_SIGNAL] = { 0, };
|
|
||||||
|
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
struct _GstD3D11DevicePrivate
|
struct _GstD3D11DevicePrivate
|
||||||
{
|
{
|
||||||
|
_GstD3D11DevicePrivate ()
|
||||||
|
{
|
||||||
|
device_removed_event =
|
||||||
|
CreateEventEx (nullptr, nullptr, 0, EVENT_ALL_ACCESS);
|
||||||
|
cancallable =
|
||||||
|
CreateEventEx (nullptr, nullptr, 0, EVENT_ALL_ACCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
~_GstD3D11DevicePrivate ()
|
||||||
|
{
|
||||||
|
CloseHandle (device_removed_event);
|
||||||
|
CloseHandle (cancallable);
|
||||||
|
}
|
||||||
|
|
||||||
guint adapter = 0;
|
guint adapter = 0;
|
||||||
guint device_id = 0;
|
guint device_id = 0;
|
||||||
guint vendor_id = 0;
|
guint vendor_id = 0;
|
||||||
|
@ -123,6 +130,7 @@ struct _GstD3D11DevicePrivate
|
||||||
gint64 adapter_luid = 0;
|
gint64 adapter_luid = 0;
|
||||||
|
|
||||||
ID3D11Device *device = nullptr;
|
ID3D11Device *device = nullptr;
|
||||||
|
ID3D11Device4 *device4 = nullptr;
|
||||||
ID3D11Device5 *device5 = nullptr;
|
ID3D11Device5 *device5 = nullptr;
|
||||||
ID3D11DeviceContext *device_context = nullptr;
|
ID3D11DeviceContext *device_context = nullptr;
|
||||||
ID3D11DeviceContext4 *device_context4 = nullptr;
|
ID3D11DeviceContext4 *device_context4 = nullptr;
|
||||||
|
@ -157,7 +165,11 @@ struct _GstD3D11DevicePrivate
|
||||||
IDXGIInfoQueue *dxgi_info_queue = nullptr;
|
IDXGIInfoQueue *dxgi_info_queue = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gboolean device_removed = FALSE;
|
DWORD device_removed_cookie = 0;
|
||||||
|
GThread *device_removed_monitor_thread = nullptr;
|
||||||
|
HANDLE device_removed_event;
|
||||||
|
HANDLE cancallable;
|
||||||
|
std::atomic<HRESULT> removed_reason = { S_OK };
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
@ -430,18 +442,18 @@ gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
|
||||||
G_MININT64, G_MAXINT64, 0, readable_flags));
|
G_MININT64, G_MAXINT64, 0, readable_flags));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstD3D11Device::device-removed:
|
* GstD3D11Device:device-removed-reason:
|
||||||
* @device: the #d3d11device
|
|
||||||
*
|
*
|
||||||
* Emitted when the D3D11Device gets suspended by the DirectX (error
|
* Device removed reason HRESULT code
|
||||||
* DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET have been returned
|
|
||||||
* after one of the DirectX operations).
|
|
||||||
*
|
*
|
||||||
* Since: 1.26
|
* Since: 1.26
|
||||||
*/
|
*/
|
||||||
gst_d3d11_device_signals[SIGNAL_DEVICE_REMOVED] =
|
pspec_removed_reason =
|
||||||
g_signal_new ("device-removed", G_TYPE_FROM_CLASS (klass),
|
g_param_spec_int ("device-removed-reason", "Device Removed Reason",
|
||||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
|
"HRESULT code returned from ID3D11Device::GetDeviceRemovedReason",
|
||||||
|
G_MININT32, G_MAXINT32, 0, readable_flags);
|
||||||
|
g_object_class_install_property (gobject_class, PROP_DEVICE_REMOVED_REASON,
|
||||||
|
pspec_removed_reason);
|
||||||
|
|
||||||
gst_d3d11_memory_init_once ();
|
gst_d3d11_memory_init_once ();
|
||||||
}
|
}
|
||||||
|
@ -700,6 +712,9 @@ gst_d3d11_device_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_ADAPTER_LUID:
|
case PROP_ADAPTER_LUID:
|
||||||
g_value_set_int64 (value, priv->adapter_luid);
|
g_value_set_int64 (value, priv->adapter_luid);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DEVICE_REMOVED_REASON:
|
||||||
|
g_value_set_int (value, priv->removed_reason);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -741,7 +756,14 @@ gst_d3d11_device_dispose (GObject * object)
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "dispose");
|
GST_LOG_OBJECT (self, "dispose");
|
||||||
|
|
||||||
|
if (priv->device4 && priv->device_removed_monitor_thread) {
|
||||||
|
priv->device4->UnregisterDeviceRemoved (priv->device_removed_cookie);
|
||||||
|
SetEvent (priv->cancallable);
|
||||||
|
g_clear_pointer (&priv->device_removed_monitor_thread, g_thread_join);
|
||||||
|
}
|
||||||
|
|
||||||
AcquireSRWLockExclusive (&_device_creation_rwlock);
|
AcquireSRWLockExclusive (&_device_creation_rwlock);
|
||||||
|
|
||||||
priv->ps_cache.clear ();
|
priv->ps_cache.clear ();
|
||||||
priv->vs_cache.clear ();
|
priv->vs_cache.clear ();
|
||||||
priv->sampler_cache.clear ();
|
priv->sampler_cache.clear ();
|
||||||
|
@ -749,6 +771,7 @@ gst_d3d11_device_dispose (GObject * object)
|
||||||
GST_D3D11_CLEAR_COM (priv->rs);
|
GST_D3D11_CLEAR_COM (priv->rs);
|
||||||
GST_D3D11_CLEAR_COM (priv->rs_msaa);
|
GST_D3D11_CLEAR_COM (priv->rs_msaa);
|
||||||
GST_D3D11_CLEAR_COM (priv->device5);
|
GST_D3D11_CLEAR_COM (priv->device5);
|
||||||
|
GST_D3D11_CLEAR_COM (priv->device4);
|
||||||
GST_D3D11_CLEAR_COM (priv->device_context4);
|
GST_D3D11_CLEAR_COM (priv->device_context4);
|
||||||
GST_D3D11_CLEAR_COM (priv->video_device);
|
GST_D3D11_CLEAR_COM (priv->video_device);
|
||||||
GST_D3D11_CLEAR_COM (priv->video_context);
|
GST_D3D11_CLEAR_COM (priv->video_context);
|
||||||
|
@ -977,12 +1000,47 @@ gst_d3d11_device_setup_debug_layer (GstD3D11Device * self)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_d3d11_device_check_device_removed (GstD3D11Device * self)
|
||||||
|
{
|
||||||
|
auto priv = self->priv;
|
||||||
|
auto removed_reason = priv->device->GetDeviceRemovedReason ();
|
||||||
|
|
||||||
|
if (removed_reason == S_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
HRESULT expected = S_OK;
|
||||||
|
if (std::atomic_compare_exchange_strong (&priv->removed_reason,
|
||||||
|
&expected, removed_reason)) {
|
||||||
|
auto error_text = g_win32_error_message ((guint) priv->removed_reason);
|
||||||
|
GST_ERROR_OBJECT (self, "DeviceRemovedReason: 0x%x, %s",
|
||||||
|
(guint) priv->removed_reason, GST_STR_NULL (error_text));
|
||||||
|
g_free (error_text);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), pspec_removed_reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
gst_d3d11_device_removed_monitor_thread (GstD3D11Device * self)
|
||||||
|
{
|
||||||
|
auto priv = self->priv;
|
||||||
|
HANDLE waitables[] = { priv->device_removed_event, priv->cancallable };
|
||||||
|
|
||||||
|
auto ret = WaitForMultipleObjects (2, waitables, FALSE, INFINITE);
|
||||||
|
if (ret == WAIT_OBJECT_0)
|
||||||
|
gst_d3d11_device_check_device_removed (self);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static GstD3D11Device *
|
static GstD3D11Device *
|
||||||
gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
|
gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
|
||||||
{
|
{
|
||||||
ComPtr < IDXGIAdapter1 > adapter;
|
ComPtr < IDXGIAdapter1 > adapter;
|
||||||
ComPtr < IDXGIFactory1 > factory;
|
ComPtr < IDXGIFactory1 > factory;
|
||||||
ComPtr < ID3D11Device > device;
|
ComPtr < ID3D11Device > device;
|
||||||
|
ComPtr < ID3D11Device4 > device4;
|
||||||
ComPtr < ID3D11Device5 > device5;
|
ComPtr < ID3D11Device5 > device5;
|
||||||
ComPtr < ID3D11DeviceContext > device_context;
|
ComPtr < ID3D11DeviceContext > device_context;
|
||||||
ComPtr < ID3D11DeviceContext4 > device_context4;
|
ComPtr < ID3D11DeviceContext4 > device_context4;
|
||||||
|
@ -1115,6 +1173,18 @@ gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
|
||||||
|
|
||||||
priv = self->priv;
|
priv = self->priv;
|
||||||
|
|
||||||
|
hr = device.As (&device4);
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
hr = device4->RegisterDeviceRemovedEvent (priv->device_removed_event,
|
||||||
|
&priv->device_removed_cookie);
|
||||||
|
if (SUCCEEDED (hr)) {
|
||||||
|
priv->device4 = device4.Detach ();
|
||||||
|
priv->device_removed_monitor_thread =
|
||||||
|
g_thread_new ("d3d11-removed-monitor",
|
||||||
|
(GThreadFunc) gst_d3d11_device_removed_monitor_thread, self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hr = device.As (&device5);
|
hr = device.As (&device5);
|
||||||
if (SUCCEEDED (hr))
|
if (SUCCEEDED (hr))
|
||||||
hr = device_context.As (&device_context4);
|
hr = device_context.As (&device_context4);
|
||||||
|
@ -1430,18 +1500,6 @@ gst_d3d11_device_get_format (GstD3D11Device * device, GstVideoFormat format,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
gst_d3d11_device_mark_removed (GstD3D11Device * device, HRESULT reason)
|
|
||||||
{
|
|
||||||
g_return_if_fail (GST_IS_D3D11_DEVICE (device));
|
|
||||||
|
|
||||||
if (!device->priv->device_removed) {
|
|
||||||
g_signal_emit (device, gst_d3d11_device_signals[SIGNAL_DEVICE_REMOVED], 0,
|
|
||||||
reason);
|
|
||||||
device->priv->device_removed = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEFINE_MINI_OBJECT_TYPE (GstD3D11Fence, gst_d3d11_fence);
|
GST_DEFINE_MINI_OBJECT_TYPE (GstD3D11Fence, gst_d3d11_fence);
|
||||||
|
|
||||||
struct _GstD3D11FencePrivate
|
struct _GstD3D11FencePrivate
|
||||||
|
|
|
@ -551,26 +551,6 @@ gst_d3d11_luid_to_int64 (const LUID * luid)
|
||||||
return val.QuadPart;
|
return val.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
|
||||||
static void
|
|
||||||
gst_d3d11_log_gpu_remove_reason (HRESULT hr, GstD3D11Device * device,
|
|
||||||
GstDebugCategory * cat, const gchar * file, const gchar * function,
|
|
||||||
gint line)
|
|
||||||
{
|
|
||||||
gchar *error_text = g_win32_error_message ((guint) hr);
|
|
||||||
|
|
||||||
gst_debug_log (cat, GST_LEVEL_ERROR, file, function, line,
|
|
||||||
NULL, "DeviceRemovedReason: 0x%x, %s", (guint) hr,
|
|
||||||
GST_STR_NULL (error_text));
|
|
||||||
if (hr != DXGI_ERROR_DEVICE_REMOVED)
|
|
||||||
g_critical ("D3D11Device have been removed. Reason (0x%x): %s",
|
|
||||||
(guint) hr, GST_STR_NULL (error_text));
|
|
||||||
g_free (error_text);
|
|
||||||
|
|
||||||
gst_d3d11_device_log_live_objects (device, file, function, line);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _gst_d3d11_result:
|
* _gst_d3d11_result:
|
||||||
* @result: HRESULT D3D11 API return code
|
* @result: HRESULT D3D11 API return code
|
||||||
|
@ -591,11 +571,14 @@ _gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
|
||||||
const gchar * file, const gchar * function, gint line)
|
const gchar * file, const gchar * function, gint line)
|
||||||
{
|
{
|
||||||
#ifndef GST_DISABLE_GST_DEBUG
|
#ifndef GST_DISABLE_GST_DEBUG
|
||||||
gboolean ret = TRUE;
|
#if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
|
||||||
|
if (device) {
|
||||||
|
gst_d3d11_device_d3d11_debug (device, file, function, line);
|
||||||
|
gst_d3d11_device_dxgi_debug (device, file, function, line);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (FAILED (hr)) {
|
if (FAILED (hr)) {
|
||||||
gchar *error_text = NULL;
|
gchar *error_text = NULL;
|
||||||
|
|
||||||
error_text = g_win32_error_message ((guint) hr);
|
error_text = g_win32_error_message ((guint) hr);
|
||||||
/* g_win32_error_message() doesn't cover all HERESULT return code,
|
/* g_win32_error_message() doesn't cover all HERESULT return code,
|
||||||
* so it could be empty string, or null if there was an error
|
* so it could be empty string, or null if there was an error
|
||||||
|
@ -604,29 +587,16 @@ _gst_d3d11_result (HRESULT hr, GstD3D11Device * device, GstDebugCategory * cat,
|
||||||
NULL, "D3D11 call failed: 0x%x, %s", (guint) hr,
|
NULL, "D3D11 call failed: 0x%x, %s", (guint) hr,
|
||||||
GST_STR_NULL (error_text));
|
GST_STR_NULL (error_text));
|
||||||
g_free (error_text);
|
g_free (error_text);
|
||||||
|
|
||||||
if (device) {
|
|
||||||
ID3D11Device *device_handle = gst_d3d11_device_get_device_handle (device);
|
|
||||||
hr = device_handle->GetDeviceRemovedReason ();
|
|
||||||
if (hr != S_OK) {
|
|
||||||
gst_d3d11_log_gpu_remove_reason (hr, device, cat, file, function, line);
|
|
||||||
gst_d3d11_device_mark_removed (device, hr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = FALSE;
|
|
||||||
}
|
|
||||||
#if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
|
|
||||||
if (device) {
|
|
||||||
gst_d3d11_device_d3d11_debug (device, file, function, line);
|
|
||||||
gst_d3d11_device_dxgi_debug (device, file, function, line);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
if (SUCCEEDED (hr))
|
||||||
#else
|
return TRUE;
|
||||||
return SUCCEEDED (hr);
|
|
||||||
#endif
|
if (device)
|
||||||
|
gst_d3d11_device_check_device_removed (device);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue