mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-20 06:08:14 +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,
|
||||
ID3D11RasterizerState ** rasterizer);
|
||||
|
||||
/* Used internally by gstd3d11utils.cpp */
|
||||
void gst_d3d11_device_mark_removed (GstD3D11Device * device, HRESULT reason);
|
||||
GST_D3D11_API
|
||||
void gst_d3d11_device_check_device_removed (GstD3D11Device * device);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -96,24 +96,31 @@ enum
|
|||
PROP_DESCRIPTION,
|
||||
PROP_CREATE_FLAGS,
|
||||
PROP_ADAPTER_LUID,
|
||||
PROP_DEVICE_REMOVED_REASON,
|
||||
};
|
||||
|
||||
static GParamSpec *pspec_removed_reason = nullptr;
|
||||
|
||||
#define DEFAULT_ADAPTER 0
|
||||
#define DEFAULT_CREATE_FLAGS 0
|
||||
|
||||
enum
|
||||
{
|
||||
/* signals */
|
||||
SIGNAL_DEVICE_REMOVED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint gst_d3d11_device_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
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 device_id = 0;
|
||||
guint vendor_id = 0;
|
||||
|
@ -123,6 +130,7 @@ struct _GstD3D11DevicePrivate
|
|||
gint64 adapter_luid = 0;
|
||||
|
||||
ID3D11Device *device = nullptr;
|
||||
ID3D11Device4 *device4 = nullptr;
|
||||
ID3D11Device5 *device5 = nullptr;
|
||||
ID3D11DeviceContext *device_context = nullptr;
|
||||
ID3D11DeviceContext4 *device_context4 = nullptr;
|
||||
|
@ -157,7 +165,11 @@ struct _GstD3D11DevicePrivate
|
|||
IDXGIInfoQueue *dxgi_info_queue = nullptr;
|
||||
#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* */
|
||||
|
||||
|
@ -430,18 +442,18 @@ gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
|
|||
G_MININT64, G_MAXINT64, 0, readable_flags));
|
||||
|
||||
/**
|
||||
* GstD3D11Device::device-removed:
|
||||
* @device: the #d3d11device
|
||||
* GstD3D11Device:device-removed-reason:
|
||||
*
|
||||
* Emitted when the D3D11Device gets suspended by the DirectX (error
|
||||
* DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DEVICE_RESET have been returned
|
||||
* after one of the DirectX operations).
|
||||
* Device removed reason HRESULT code
|
||||
*
|
||||
* Since: 1.26
|
||||
*/
|
||||
gst_d3d11_device_signals[SIGNAL_DEVICE_REMOVED] =
|
||||
g_signal_new ("device-removed", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
pspec_removed_reason =
|
||||
g_param_spec_int ("device-removed-reason", "Device Removed Reason",
|
||||
"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 ();
|
||||
}
|
||||
|
@ -700,6 +712,9 @@ gst_d3d11_device_get_property (GObject * object, guint prop_id,
|
|||
case PROP_ADAPTER_LUID:
|
||||
g_value_set_int64 (value, priv->adapter_luid);
|
||||
break;
|
||||
case PROP_DEVICE_REMOVED_REASON:
|
||||
g_value_set_int (value, priv->removed_reason);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -741,7 +756,14 @@ gst_d3d11_device_dispose (GObject * object)
|
|||
|
||||
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);
|
||||
|
||||
priv->ps_cache.clear ();
|
||||
priv->vs_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_msaa);
|
||||
GST_D3D11_CLEAR_COM (priv->device5);
|
||||
GST_D3D11_CLEAR_COM (priv->device4);
|
||||
GST_D3D11_CLEAR_COM (priv->device_context4);
|
||||
GST_D3D11_CLEAR_COM (priv->video_device);
|
||||
GST_D3D11_CLEAR_COM (priv->video_context);
|
||||
|
@ -977,12 +1000,47 @@ gst_d3d11_device_setup_debug_layer (GstD3D11Device * self)
|
|||
#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 *
|
||||
gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
|
||||
{
|
||||
ComPtr < IDXGIAdapter1 > adapter;
|
||||
ComPtr < IDXGIFactory1 > factory;
|
||||
ComPtr < ID3D11Device > device;
|
||||
ComPtr < ID3D11Device4 > device4;
|
||||
ComPtr < ID3D11Device5 > device5;
|
||||
ComPtr < ID3D11DeviceContext > device_context;
|
||||
ComPtr < ID3D11DeviceContext4 > device_context4;
|
||||
|
@ -1115,6 +1173,18 @@ gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
|
|||
|
||||
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);
|
||||
if (SUCCEEDED (hr))
|
||||
hr = device_context.As (&device_context4);
|
||||
|
@ -1430,18 +1500,6 @@ gst_d3d11_device_get_format (GstD3D11Device * device, GstVideoFormat format,
|
|||
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);
|
||||
|
||||
struct _GstD3D11FencePrivate
|
||||
|
|
|
@ -551,26 +551,6 @@ gst_d3d11_luid_to_int64 (const LUID * luid)
|
|||
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:
|
||||
* @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)
|
||||
{
|
||||
#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)) {
|
||||
gchar *error_text = NULL;
|
||||
|
||||
error_text = g_win32_error_message ((guint) hr);
|
||||
/* g_win32_error_message() doesn't cover all HERESULT return code,
|
||||
* 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,
|
||||
GST_STR_NULL (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
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return SUCCEEDED (hr);
|
||||
#endif
|
||||
if (SUCCEEDED (hr))
|
||||
return TRUE;
|
||||
|
||||
if (device)
|
||||
gst_d3d11_device_check_device_removed (device);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue