2 * Copyright (C) 2019 Seungha Yang <seungha.yang@navercorp.com>
3 * Copyright (C) 2020 Seungha Yang <seungha@centricular.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include "gstd3d11device.h"
26 #include "gstd3d11utils.h"
27 #include "gstd3d11format.h"
28 #include "gstd3d11-private.h"
29 #include "gstd3d11memory.h"
34 #include <versionhelpers.h>
37 * SECTION:gstd3d11device
38 * @title: GstD3D11Device
39 * @short_description: Direct3D11 device abstraction
41 * #GstD3D11Device wraps ID3D11Device and ID3D11DeviceContext for GPU resources
42 * to be able to be shared among various elements. Caller can get native
43 * Direct3D11 handles via getter method.
44 * Basically Direct3D11 API doesn't require dedicated thread like that of
45 * OpenGL context, and ID3D11Device APIs are supposed to be thread-safe.
46 * But concurrent call for ID3D11DeviceContext and DXGI API are not allowed.
47 * To protect such object, callers need to make use of gst_d3d11_device_lock()
48 * and gst_d3d11_device_unlock()
52 using namespace Microsoft::WRL;
55 #if HAVE_D3D11SDKLAYERS_H
56 #include <d3d11sdklayers.h>
58 /* mingw header does not define D3D11_RLDO_IGNORE_INTERNAL
59 * D3D11_RLDO_SUMMARY = 0x1,
60 D3D11_RLDO_DETAIL = 0x2,
61 * D3D11_RLDO_IGNORE_INTERNAL = 0x4
63 #define GST_D3D11_RLDO_FLAGS (0x2 | 0x4)
67 #include <dxgidebug.h>
68 typedef HRESULT (WINAPI * DXGIGetDebugInterface_t) (REFIID riid,
70 static DXGIGetDebugInterface_t GstDXGIGetDebugInterface = nullptr;
74 #if (HAVE_D3D11SDKLAYERS_H || HAVE_DXGIDEBUG_H)
75 GST_DEBUG_CATEGORY_STATIC (gst_d3d11_debug_layer_debug);
77 GST_DEBUG_CATEGORY_STATIC (gst_d3d11_device_debug);
78 #define GST_CAT_DEFAULT gst_d3d11_device_debug
92 #define DEFAULT_ADAPTER 0
93 #define DEFAULT_CREATE_FLAGS 0
95 struct _GstD3D11DevicePrivate
105 ID3D11Device *device;
106 ID3D11Device5 *device5;
107 ID3D11DeviceContext *device_context;
108 ID3D11DeviceContext4 *device_context4;
110 ID3D11VideoDevice *video_device;
111 ID3D11VideoContext *video_context;
113 IDXGIFactory1 *factory;
114 GArray *format_table;
116 CRITICAL_SECTION extern_lock;
117 SRWLOCK resource_lock;
119 LARGE_INTEGER frequency;
121 #if HAVE_D3D11SDKLAYERS_H
122 ID3D11Debug *d3d11_debug;
123 ID3D11InfoQueue *d3d11_info_queue;
127 IDXGIDebug *dxgi_debug;
128 IDXGIInfoQueue *dxgi_info_queue;
133 debug_init_once (void)
135 GST_D3D11_CALL_ONCE_BEGIN {
136 GST_DEBUG_CATEGORY_INIT (gst_d3d11_device_debug,
137 "d3d11device", 0, "d3d11 device object");
138 #if defined(HAVE_D3D11SDKLAYERS_H) || defined(HAVE_DXGIDEBUG_H)
139 GST_DEBUG_CATEGORY_INIT (gst_d3d11_debug_layer_debug,
140 "d3d11debuglayer", 0, "native d3d11 and dxgi debug");
142 } GST_D3D11_CALL_ONCE_END;
145 #define gst_d3d11_device_parent_class parent_class
146 G_DEFINE_TYPE_WITH_CODE (GstD3D11Device, gst_d3d11_device, GST_TYPE_OBJECT,
147 G_ADD_PRIVATE (GstD3D11Device); debug_init_once ());
149 static void gst_d3d11_device_get_property (GObject * object, guint prop_id,
150 GValue * value, GParamSpec * pspec);
151 static void gst_d3d11_device_dispose (GObject * object);
152 static void gst_d3d11_device_finalize (GObject * object);
154 #if HAVE_D3D11SDKLAYERS_H
156 gst_d3d11_device_enable_d3d11_debug (void)
158 static GModule *d3d11_debug_module = nullptr;
159 /* If all below libraries are unavailable, d3d11 device would fail with
160 * D3D11_CREATE_DEVICE_DEBUG flag */
161 static const gchar *sdk_dll_names[] = {
162 "d3d11sdklayers.dll",
163 "d3d11_1sdklayers.dll",
164 "d3d11_2sdklayers.dll",
165 "d3d11_3sdklayers.dll",
168 GST_D3D11_CALL_ONCE_BEGIN {
169 for (guint i = 0; i < G_N_ELEMENTS (sdk_dll_names); i++) {
170 d3d11_debug_module = g_module_open (sdk_dll_names[i], G_MODULE_BIND_LAZY);
171 if (d3d11_debug_module)
175 GST_D3D11_CALL_ONCE_END;
177 if (d3d11_debug_module)
183 static inline GstDebugLevel
184 d3d11_message_severity_to_gst (D3D11_MESSAGE_SEVERITY level)
187 case D3D11_MESSAGE_SEVERITY_CORRUPTION:
188 case D3D11_MESSAGE_SEVERITY_ERROR:
189 return GST_LEVEL_ERROR;
190 case D3D11_MESSAGE_SEVERITY_WARNING:
191 return GST_LEVEL_WARNING;
192 case D3D11_MESSAGE_SEVERITY_INFO:
193 return GST_LEVEL_INFO;
194 case D3D11_MESSAGE_SEVERITY_MESSAGE:
195 return GST_LEVEL_DEBUG;
200 return GST_LEVEL_LOG;
204 gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
205 const gchar * file, const gchar * function, gint line)
207 GstD3D11DevicePrivate *priv = device->priv;
212 ID3D11InfoQueue *info_queue = priv->d3d11_info_queue;
217 num_msg = info_queue->GetNumStoredMessages ();
219 for (i = 0; i < num_msg; i++) {
222 hr = info_queue->GetMessage (i, NULL, &msg_len);
224 if (FAILED (hr) || msg_len == 0) {
228 msg = (D3D11_MESSAGE *) g_alloca (msg_len);
229 hr = info_queue->GetMessage (i, msg, &msg_len);
231 level = d3d11_message_severity_to_gst (msg->Severity);
232 if (msg->Category == D3D11_MESSAGE_CATEGORY_STATE_CREATION &&
233 level > GST_LEVEL_ERROR) {
234 /* Do not warn for live object, since there would be live object
235 * when ReportLiveDeviceObjects was called */
236 level = GST_LEVEL_INFO;
239 gst_debug_log (gst_d3d11_debug_layer_debug, level, file, function, line,
240 G_OBJECT (device), "D3D11InfoQueue: %s", msg->pDescription);
243 info_queue->ClearStoredMessages ();
249 gst_d3d11_device_d3d11_debug (GstD3D11Device * device,
250 const gchar * file, const gchar * function, gint line)
259 gst_d3d11_device_enable_dxgi_debug (void)
261 static GModule *dxgi_debug_module = nullptr;
263 GST_D3D11_CALL_ONCE_BEGIN {
264 #if (!GST_D3D11_WINAPI_ONLY_APP)
265 dxgi_debug_module = g_module_open ("dxgidebug.dll", G_MODULE_BIND_LAZY);
267 if (dxgi_debug_module)
268 g_module_symbol (dxgi_debug_module,
269 "DXGIGetDebugInterface", (gpointer *) & GstDXGIGetDebugInterface);
271 GstDXGIGetDebugInterface = DXGIGetDebugInterface1;
273 } GST_D3D11_CALL_ONCE_END;
275 if (!GstDXGIGetDebugInterface)
282 gst_d3d11_device_dxgi_get_device_interface (REFIID riid, void **debug)
284 #if (!GST_D3D11_WINAPI_ONLY_APP)
285 if (GstDXGIGetDebugInterface) {
286 return GstDXGIGetDebugInterface (riid, debug);
288 return E_NOINTERFACE;
291 return DXGIGetDebugInterface1 (0, riid, debug);
295 static inline GstDebugLevel
296 dxgi_info_queue_message_severity_to_gst (DXGI_INFO_QUEUE_MESSAGE_SEVERITY level)
299 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION:
300 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR:
301 return GST_LEVEL_ERROR;
302 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING:
303 return GST_LEVEL_WARNING;
304 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO:
305 return GST_LEVEL_INFO;
306 case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE:
307 return GST_LEVEL_DEBUG;
312 return GST_LEVEL_LOG;
316 gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
317 const gchar * file, const gchar * function, gint line)
319 GstD3D11DevicePrivate *priv = device->priv;
320 DXGI_INFO_QUEUE_MESSAGE *msg;
324 IDXGIInfoQueue *info_queue = priv->dxgi_info_queue;
329 num_msg = info_queue->GetNumStoredMessages (DXGI_DEBUG_ALL);
331 for (i = 0; i < num_msg; i++) {
334 hr = info_queue->GetMessage (DXGI_DEBUG_ALL, i, NULL, &msg_len);
336 if (FAILED (hr) || msg_len == 0) {
340 msg = (DXGI_INFO_QUEUE_MESSAGE *) g_alloca (msg_len);
341 hr = info_queue->GetMessage (DXGI_DEBUG_ALL, i, msg, &msg_len);
343 level = dxgi_info_queue_message_severity_to_gst (msg->Severity);
344 gst_debug_log (gst_d3d11_debug_layer_debug, level, file, function, line,
345 G_OBJECT (device), "DXGIInfoQueue: %s", msg->pDescription);
348 info_queue->ClearStoredMessages (DXGI_DEBUG_ALL);
354 gst_d3d11_device_dxgi_debug (GstD3D11Device * device,
355 const gchar * file, const gchar * function, gint line)
363 gst_d3d11_device_class_init (GstD3D11DeviceClass * klass)
365 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
366 GParamFlags readable_flags =
367 (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
369 gobject_class->get_property = gst_d3d11_device_get_property;
370 gobject_class->dispose = gst_d3d11_device_dispose;
371 gobject_class->finalize = gst_d3d11_device_finalize;
373 g_object_class_install_property (gobject_class, PROP_ADAPTER,
374 g_param_spec_uint ("adapter", "Adapter",
375 "DXGI Adapter index for creating device",
376 0, G_MAXUINT32, DEFAULT_ADAPTER, readable_flags));
378 g_object_class_install_property (gobject_class, PROP_DEVICE_ID,
379 g_param_spec_uint ("device-id", "Device Id",
380 "DXGI Device ID", 0, G_MAXUINT32, 0, readable_flags));
382 g_object_class_install_property (gobject_class, PROP_VENDOR_ID,
383 g_param_spec_uint ("vendor-id", "Vendor Id",
384 "DXGI Vendor ID", 0, G_MAXUINT32, 0, readable_flags));
386 g_object_class_install_property (gobject_class, PROP_HARDWARE,
387 g_param_spec_boolean ("hardware", "Hardware",
388 "Whether hardware device or not", TRUE, readable_flags));
390 g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
391 g_param_spec_string ("description", "Description",
392 "Human readable device description", NULL, readable_flags));
394 g_object_class_install_property (gobject_class, PROP_ADAPTER_LUID,
395 g_param_spec_int64 ("adapter-luid", "Adapter LUID",
396 "DXGI Adapter LUID (Locally Unique Identifier) of created device",
397 G_MININT64, G_MAXINT64, 0, readable_flags));
399 gst_d3d11_memory_init_once ();
403 gst_d3d11_device_init (GstD3D11Device * self)
405 GstD3D11DevicePrivate *priv;
407 priv = (GstD3D11DevicePrivate *)
408 gst_d3d11_device_get_instance_private (self);
409 priv->adapter = DEFAULT_ADAPTER;
410 priv->format_table = g_array_sized_new (FALSE, FALSE,
411 sizeof (GstD3D11Format), GST_D3D11_N_FORMATS);
413 InitializeCriticalSection (&priv->extern_lock);
419 is_windows_8_or_greater (void)
421 static gboolean ret = FALSE;
423 GST_D3D11_CALL_ONCE_BEGIN {
424 #if (!GST_D3D11_WINAPI_ONLY_APP)
425 if (IsWindows8OrGreater ())
430 } GST_D3D11_CALL_ONCE_END;
436 check_format_support (GstD3D11Device * self, DXGI_FORMAT format)
438 GstD3D11DevicePrivate *priv = self->priv;
439 ID3D11Device *handle = priv->device;
443 hr = handle->CheckFormatSupport (format, &format_support);
444 if (FAILED (hr) || format_support == 0)
447 return format_support;
451 dump_format (GstD3D11Device * self, GstD3D11Format * format)
453 gchar *format_support_str = g_flags_to_string (GST_TYPE_D3D11_FORMAT_SUPPORT,
454 format->format_support[0]);
456 GST_LOG_OBJECT (self, "%s -> %s (%d), "
457 "resource format: %s (%d), %s (%d), %s (%d), %s (%d), flags (0x%x) %s",
458 gst_video_format_to_string (format->format),
459 gst_d3d11_dxgi_format_to_string (format->dxgi_format),
461 gst_d3d11_dxgi_format_to_string (format->resource_format[0]),
462 format->resource_format[0],
463 gst_d3d11_dxgi_format_to_string (format->resource_format[1]),
464 format->resource_format[1],
465 gst_d3d11_dxgi_format_to_string (format->resource_format[2]),
466 format->resource_format[2],
467 gst_d3d11_dxgi_format_to_string (format->resource_format[3]),
468 format->resource_format[3], format->format_support[0],
471 g_free (format_support_str);
475 gst_d3d11_device_setup_format_table (GstD3D11Device * self)
477 GstD3D11DevicePrivate *priv = self->priv;
479 for (guint i = 0; i < G_N_ELEMENTS (_gst_d3d11_default_format_map); i++) {
480 const GstD3D11Format *iter = &_gst_d3d11_default_format_map[i];
481 GstD3D11Format format;
482 guint support[GST_VIDEO_MAX_PLANES] = { 0, };
483 gboolean native = TRUE;
485 switch (iter->format) {
487 case GST_VIDEO_FORMAT_BGRA:
488 case GST_VIDEO_FORMAT_BGRx:
489 case GST_VIDEO_FORMAT_RGBA:
490 case GST_VIDEO_FORMAT_RGBx:
491 case GST_VIDEO_FORMAT_RGB10A2_LE:
492 case GST_VIDEO_FORMAT_RGBA64_LE:
493 case GST_VIDEO_FORMAT_GRAY8:
494 case GST_VIDEO_FORMAT_GRAY16_LE:
495 support[0] = check_format_support (self, iter->dxgi_format);
497 const gchar *format_name =
498 gst_d3d11_dxgi_format_to_string (iter->dxgi_format);
499 GST_INFO_OBJECT (self, "DXGI_FORMAT_%s (%d) for %s is not supported",
500 format_name, (guint) iter->dxgi_format,
501 gst_video_format_to_string (iter->format));
505 /* YUV DXGI native formats */
506 case GST_VIDEO_FORMAT_VUYA:
507 case GST_VIDEO_FORMAT_Y410:
508 case GST_VIDEO_FORMAT_NV12:
509 case GST_VIDEO_FORMAT_P010_10LE:
510 case GST_VIDEO_FORMAT_P012_LE:
511 case GST_VIDEO_FORMAT_P016_LE:{
512 gboolean supported = TRUE;
514 if (is_windows_8_or_greater ())
515 support[0] = check_format_support (self, iter->dxgi_format);
518 GST_DEBUG_OBJECT (self,
519 "DXGI_FORMAT_%s (%d) for %s is not supported, "
520 "checking resource format",
521 gst_d3d11_dxgi_format_to_string (iter->dxgi_format),
522 (guint) iter->dxgi_format,
523 gst_video_format_to_string (iter->format));
526 for (guint j = 0; j < GST_VIDEO_MAX_PLANES; j++) {
527 if (iter->resource_format[j] == DXGI_FORMAT_UNKNOWN)
530 support[j] = check_format_support (self, iter->resource_format[j]);
531 if (support[j] == 0) {
538 GST_INFO_OBJECT (self, "%s is not supported",
539 gst_video_format_to_string (iter->format));
545 /* YUV non-DXGI native formats */
546 case GST_VIDEO_FORMAT_NV21:
547 case GST_VIDEO_FORMAT_I420:
548 case GST_VIDEO_FORMAT_YV12:
549 case GST_VIDEO_FORMAT_I420_10LE:
550 case GST_VIDEO_FORMAT_I420_12LE:
551 case GST_VIDEO_FORMAT_Y42B:
552 case GST_VIDEO_FORMAT_I422_10LE:
553 case GST_VIDEO_FORMAT_I422_12LE:
554 case GST_VIDEO_FORMAT_Y444:
555 case GST_VIDEO_FORMAT_Y444_10LE:
556 case GST_VIDEO_FORMAT_Y444_12LE:
557 case GST_VIDEO_FORMAT_Y444_16LE:
558 case GST_VIDEO_FORMAT_AYUV:
559 case GST_VIDEO_FORMAT_AYUV64:{
560 gboolean supported = TRUE;
563 for (guint j = 0; j < GST_VIDEO_MAX_PLANES; j++) {
564 if (iter->resource_format[j] == DXGI_FORMAT_UNKNOWN)
567 support[j] = check_format_support (self, iter->resource_format[j]);
568 if (support[j] == 0) {
575 GST_INFO_OBJECT (self, "%s is not supported",
576 gst_video_format_to_string (iter->format));
582 g_assert_not_reached ();
589 format.dxgi_format = DXGI_FORMAT_UNKNOWN;
591 for (guint j = 0; j < GST_VIDEO_MAX_PLANES; j++)
592 format.format_support[j] = support[j];
594 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_LOG)
595 dump_format (self, &format);
597 g_array_append_val (priv->format_table, format);
600 /* FIXME: d3d11 sampler doesn't support packed-and-subsampled formats
601 * very well (and it's really poorly documented).
602 * As per observation, d3d11 samplers seems to be dropping the second
603 * Y componet from "Y0-U0-Y1-V0" pair which results in bad visual quality
604 * than 4:2:0 subsampled formats. We should revisit this later */
606 /* TODO: The best would be using d3d11 compute shader to handle this kinds of
607 * samples but comute shader is not implemented yet by us.
609 * Another simple approach is using d3d11 video processor,
610 * but capability will be very device dependent because it depends on
611 * GPU vendor's driver implementation, moreover, software fallback does
612 * not support d3d11 video processor. So it's not reliable in this case */
614 /* NOTE: packted yuv 4:2:2 YUY2, UYVY, and VYUY formats are not natively
615 * supported render target view formats
616 * (i.e., cannot be output format of shader pipeline) */
617 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_YUY2;
618 if (can_support_format (self, DXGI_FORMAT_YUY2,
619 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) {
620 priv->format_table[n_formats].resource_format[0] =
621 DXGI_FORMAT_R8G8B8A8_UNORM;
622 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_YUY2;
624 /* If DXGI_FORMAT_YUY2 format is not supported, use this format,
625 * it's analogous to YUY2 */
626 priv->format_table[n_formats].resource_format[0] =
627 DXGI_FORMAT_G8R8_G8B8_UNORM;
631 /* No native DXGI format available for UYVY */
632 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_UYVY;
633 priv->format_table[n_formats].resource_format[0] =
634 DXGI_FORMAT_R8G8_B8G8_UNORM;
637 /* No native DXGI format available for VYUY */
638 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_VYUY;
639 priv->format_table[n_formats].resource_format[0] =
640 DXGI_FORMAT_R8G8_B8G8_UNORM;
643 /* Y210 and Y410 formats cannot support rtv */
644 priv->format_table[n_formats].format = GST_VIDEO_FORMAT_Y210;
645 priv->format_table[n_formats].resource_format[0] =
646 DXGI_FORMAT_R16G16B16A16_UNORM;
647 if (can_support_format (self, DXGI_FORMAT_Y210,
648 D3D11_FORMAT_SUPPORT_SHADER_SAMPLE))
649 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_Y210;
651 priv->format_table[n_formats].dxgi_format = DXGI_FORMAT_UNKNOWN;
657 gst_d3d11_device_get_property (GObject * object, guint prop_id,
658 GValue * value, GParamSpec * pspec)
660 GstD3D11Device *self = GST_D3D11_DEVICE (object);
661 GstD3D11DevicePrivate *priv = self->priv;
665 g_value_set_uint (value, priv->adapter);
668 g_value_set_uint (value, priv->device_id);
671 g_value_set_uint (value, priv->vendor_id);
674 g_value_set_boolean (value, priv->hardware);
676 case PROP_DESCRIPTION:
677 g_value_set_string (value, priv->description);
679 case PROP_ADAPTER_LUID:
680 g_value_set_int64 (value, priv->adapter_luid);
683 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
689 gst_d3d11_device_dispose (GObject * object)
691 GstD3D11Device *self = GST_D3D11_DEVICE (object);
692 GstD3D11DevicePrivate *priv = self->priv;
694 GST_LOG_OBJECT (self, "dispose");
696 GST_D3D11_CLEAR_COM (priv->device5);
697 GST_D3D11_CLEAR_COM (priv->device_context4);
698 GST_D3D11_CLEAR_COM (priv->video_device);
699 GST_D3D11_CLEAR_COM (priv->video_context);
700 GST_D3D11_CLEAR_COM (priv->device);
701 GST_D3D11_CLEAR_COM (priv->device_context);
702 GST_D3D11_CLEAR_COM (priv->factory);
703 #if HAVE_D3D11SDKLAYERS_H
704 if (priv->d3d11_debug) {
705 priv->d3d11_debug->ReportLiveDeviceObjects ((D3D11_RLDO_FLAGS)
706 GST_D3D11_RLDO_FLAGS);
708 GST_D3D11_CLEAR_COM (priv->d3d11_debug);
710 if (priv->d3d11_info_queue)
711 gst_d3d11_device_d3d11_debug (self, __FILE__, GST_FUNCTION, __LINE__);
713 GST_D3D11_CLEAR_COM (priv->d3d11_info_queue);
717 if (priv->dxgi_debug) {
718 priv->dxgi_debug->ReportLiveObjects (DXGI_DEBUG_ALL,
719 (DXGI_DEBUG_RLO_FLAGS) GST_D3D11_RLDO_FLAGS);
721 GST_D3D11_CLEAR_COM (priv->dxgi_debug);
723 if (priv->dxgi_info_queue)
724 gst_d3d11_device_dxgi_debug (self, __FILE__, GST_FUNCTION, __LINE__);
726 GST_D3D11_CLEAR_COM (priv->dxgi_info_queue);
729 G_OBJECT_CLASS (parent_class)->dispose (object);
733 gst_d3d11_device_finalize (GObject * object)
735 GstD3D11Device *self = GST_D3D11_DEVICE (object);
736 GstD3D11DevicePrivate *priv = self->priv;
738 GST_LOG_OBJECT (self, "finalize");
740 g_array_unref (priv->format_table);
741 DeleteCriticalSection (&priv->extern_lock);
742 g_free (priv->description);
744 G_OBJECT_CLASS (parent_class)->finalize (object);
749 DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX,
750 DEVICE_CONSTRUCT_FOR_ADAPTER_LUID,
751 DEVICE_CONSTRUCT_WRAPPED,
752 } GstD3D11DeviceConstructType;
754 typedef struct _GstD3D11DeviceConstructData
760 ID3D11Device *device;
762 GstD3D11DeviceConstructType type;
764 } GstD3D11DeviceConstructData;
767 _gst_d3d11_device_get_adapter (const GstD3D11DeviceConstructData * data,
768 IDXGIFactory1 * factory, guint * index, DXGI_ADAPTER_DESC * adapter_desc,
769 IDXGIAdapter1 ** dxgi_adapter)
772 ComPtr < IDXGIAdapter1 > adapter1;
773 DXGI_ADAPTER_DESC desc;
775 switch (data->type) {
776 case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
778 hr = factory->EnumAdapters1 (data->data.adapter_index, &adapter1);
782 hr = adapter1->GetDesc (&desc);
786 *index = data->data.adapter_index;
787 *adapter_desc = desc;
788 *dxgi_adapter = adapter1.Detach ();
792 case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
794 for (guint i = 0;; i++) {
799 hr = factory->EnumAdapters1 (i, &adapter1);
803 hr = adapter1->GetDesc (&desc);
807 luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
808 if (luid != data->data.adapter_luid)
812 *adapter_desc = desc;
813 *dxgi_adapter = adapter1.Detach ();
820 case DEVICE_CONSTRUCT_WRAPPED:
822 ComPtr < IDXGIDevice > dxgi_device;
823 ComPtr < IDXGIAdapter > adapter;
824 ID3D11Device *device = data->data.device;
827 hr = device->QueryInterface (IID_PPV_ARGS (&dxgi_device));
831 hr = dxgi_device->GetAdapter (&adapter);
835 hr = adapter.As (&adapter1);
839 hr = adapter1->GetDesc (&desc);
843 luid = gst_d3d11_luid_to_int64 (&desc.AdapterLuid);
845 for (guint i = 0;; i++) {
846 DXGI_ADAPTER_DESC tmp_desc;
847 ComPtr < IDXGIAdapter1 > tmp;
849 hr = factory->EnumAdapters1 (i, &tmp);
853 hr = tmp->GetDesc (&tmp_desc);
857 if (luid != gst_d3d11_luid_to_int64 (&tmp_desc.AdapterLuid))
861 *adapter_desc = desc;
862 *dxgi_adapter = adapter1.Detach ();
870 g_assert_not_reached ();
878 gst_d3d11_device_setup_debug_layer (GstD3D11Device * self)
881 if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
883 GstD3D11DevicePrivate *priv = self->priv;
885 if (gst_d3d11_device_enable_dxgi_debug ()) {
886 IDXGIDebug *debug = nullptr;
887 IDXGIInfoQueue *info_queue = nullptr;
890 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
891 "dxgi debug library was loaded");
892 hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS (&debug));
894 if (SUCCEEDED (hr)) {
895 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
896 "IDXGIDebug interface available");
897 priv->dxgi_debug = debug;
899 hr = gst_d3d11_device_dxgi_get_device_interface (IID_PPV_ARGS
901 if (SUCCEEDED (hr)) {
902 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
903 "IDXGIInfoQueue interface available");
904 priv->dxgi_info_queue = info_queue;
908 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
909 "couldn't load dxgi debug library");
914 #if HAVE_D3D11SDKLAYERS_H
915 if ((self->priv->create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
916 GstD3D11DevicePrivate *priv = self->priv;
918 ID3D11InfoQueue *info_queue;
921 hr = priv->device->QueryInterface (IID_PPV_ARGS (&debug));
923 if (SUCCEEDED (hr)) {
924 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
925 "D3D11Debug interface available");
926 priv->d3d11_debug = debug;
928 hr = priv->device->QueryInterface (IID_PPV_ARGS (&info_queue));
929 if (SUCCEEDED (hr)) {
930 GST_CAT_INFO_OBJECT (gst_d3d11_debug_layer_debug, self,
931 "ID3D11InfoQueue interface available");
932 priv->d3d11_info_queue = info_queue;
939 static GstD3D11Device *
940 gst_d3d11_device_new_internal (const GstD3D11DeviceConstructData * data)
942 ComPtr < IDXGIAdapter1 > adapter;
943 ComPtr < IDXGIFactory1 > factory;
944 ComPtr < ID3D11Device > device;
945 ComPtr < ID3D11Device5 > device5;
946 ComPtr < ID3D11DeviceContext > device_context;
947 ComPtr < ID3D11DeviceContext4 > device_context4;
950 guint adapter_index = 0;
951 DXGI_ADAPTER_DESC adapter_desc;
952 static const D3D_FEATURE_LEVEL feature_levels[] = {
953 D3D_FEATURE_LEVEL_11_1,
954 D3D_FEATURE_LEVEL_11_0,
955 D3D_FEATURE_LEVEL_10_1,
956 D3D_FEATURE_LEVEL_10_0,
957 D3D_FEATURE_LEVEL_9_3,
958 D3D_FEATURE_LEVEL_9_2,
959 D3D_FEATURE_LEVEL_9_1
961 D3D_FEATURE_LEVEL selected_level;
965 hr = CreateDXGIFactory1 (IID_PPV_ARGS (&factory));
966 if (!gst_d3d11_result (hr, NULL)) {
967 GST_WARNING ("cannot create dxgi factory, hr: 0x%x", (guint) hr);
972 if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
973 create_flags = data->create_flags;
974 #if HAVE_D3D11SDKLAYERS_H
975 if (gst_debug_category_get_threshold (gst_d3d11_debug_layer_debug) >
977 /* DirectX SDK should be installed on system for this */
978 if (gst_d3d11_device_enable_d3d11_debug ()) {
979 GST_CAT_INFO (gst_d3d11_debug_layer_debug,
980 "d3d11 debug library was loaded");
981 create_flags |= D3D11_CREATE_DEVICE_DEBUG;
983 GST_CAT_INFO (gst_d3d11_debug_layer_debug,
984 "couldn't load d3d11 debug library");
990 /* Ensure valid device handle */
991 if (data->type == DEVICE_CONSTRUCT_WRAPPED) {
992 ID3D11Device *external_device = data->data.device;
994 hr = external_device->QueryInterface (IID_PPV_ARGS (&device));
996 GST_WARNING ("Not a valid external ID3D11Device handle");
1000 device->GetImmediateContext (&device_context);
1003 hr = _gst_d3d11_device_get_adapter (data, factory.Get (), &adapter_index,
1004 &adapter_desc, &adapter);
1006 GST_INFO ("Failed to get DXGI adapter");
1010 if (data->type != DEVICE_CONSTRUCT_WRAPPED) {
1011 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1012 NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
1013 D3D11_SDK_VERSION, &device, &selected_level, &device_context);
1016 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
1017 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1018 NULL, create_flags, &feature_levels[1],
1019 G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
1020 &selected_level, &device_context);
1023 /* if D3D11_CREATE_DEVICE_DEBUG was enabled but couldn't create device,
1024 * try it without the flag again */
1025 if (FAILED (hr) && (create_flags & D3D11_CREATE_DEVICE_DEBUG) != 0) {
1026 create_flags &= ~D3D11_CREATE_DEVICE_DEBUG;
1028 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1029 NULL, create_flags, feature_levels, G_N_ELEMENTS (feature_levels),
1030 D3D11_SDK_VERSION, &device, &selected_level, &device_context);
1033 /* Retry if the system could not recognize D3D_FEATURE_LEVEL_11_1 */
1034 hr = D3D11CreateDevice (adapter.Get (), D3D_DRIVER_TYPE_UNKNOWN,
1035 NULL, create_flags, &feature_levels[1],
1036 G_N_ELEMENTS (feature_levels) - 1, D3D11_SDK_VERSION, &device,
1037 &selected_level, &device_context);
1043 switch (data->type) {
1044 case DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX:
1046 GST_INFO ("Failed to create d3d11 device for adapter index %d"
1047 " with flags 0x%x, hr: 0x%x", data->data.adapter_index,
1048 create_flags, (guint) hr);
1051 case DEVICE_CONSTRUCT_FOR_ADAPTER_LUID:
1053 GST_WARNING ("Failed to create d3d11 device for adapter luid %"
1054 G_GINT64_FORMAT " with flags 0x%x, hr: 0x%x",
1055 data->data.adapter_luid, create_flags, (guint) hr);
1065 GstD3D11Device *self = nullptr;
1066 GstD3D11DevicePrivate *priv;
1068 self = (GstD3D11Device *) g_object_new (GST_TYPE_D3D11_DEVICE, nullptr);
1069 gst_object_ref_sink (self);
1073 hr = device.As (&device5);
1075 hr = device_context.As (&device_context4);
1076 if (SUCCEEDED (hr)) {
1077 priv->device5 = device5.Detach ();
1078 priv->device_context4 = device_context4.Detach ();
1081 priv->adapter = adapter_index;
1082 priv->device = device.Detach ();
1083 priv->device_context = device_context.Detach ();
1084 priv->factory = factory.Detach ();
1086 priv->vendor_id = adapter_desc.VendorId;
1087 priv->device_id = adapter_desc.DeviceId;
1088 priv->description = g_utf16_to_utf8 ((gunichar2 *) adapter_desc.Description,
1089 -1, nullptr, nullptr, nullptr);
1090 priv->adapter_luid = gst_d3d11_luid_to_int64 (&adapter_desc.AdapterLuid);
1092 DXGI_ADAPTER_DESC1 desc1;
1093 hr = adapter->GetDesc1 (&desc1);
1095 /* DXGI_ADAPTER_FLAG_SOFTWARE is missing in dxgi.h of mingw */
1096 if (SUCCEEDED (hr) && (desc1.Flags & 0x2) != 0x2)
1097 priv->hardware = TRUE;
1099 priv->create_flags = create_flags;
1100 gst_d3d11_device_setup_format_table (self);
1101 gst_d3d11_device_setup_debug_layer (self);
1103 BOOL ret = QueryPerformanceFrequency (&priv->frequency);
1110 * gst_d3d11_device_new:
1111 * @adapter_index: the index of adapter for creating d3d11 device
1112 * @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
1114 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_index
1115 * or %NULL when failed to create D3D11 device with given adapter index.
1120 gst_d3d11_device_new (guint adapter_index, guint flags)
1122 GstD3D11DeviceConstructData data;
1124 data.data.adapter_index = adapter_index;
1125 data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_INDEX;
1126 data.create_flags = flags;
1128 return gst_d3d11_device_new_internal (&data);
1132 * gst_d3d11_device_new_for_adapter_luid:
1133 * @adapter_luid: an int64 representation of the DXGI adapter LUID
1134 * @flags: a D3D11_CREATE_DEVICE_FLAG value used for creating d3d11 device
1136 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @adapter_luid
1137 * or %NULL when failed to create D3D11 device with given adapter luid.
1142 gst_d3d11_device_new_for_adapter_luid (gint64 adapter_luid, guint flags)
1144 GstD3D11DeviceConstructData data;
1146 data.data.adapter_luid = adapter_luid;
1147 data.type = DEVICE_CONSTRUCT_FOR_ADAPTER_LUID;
1148 data.create_flags = flags;
1150 return gst_d3d11_device_new_internal (&data);
1154 * gst_d3d11_device_new_wrapped:
1155 * @device: (transfer none): an existing ID3D11Device handle
1157 * Returns: (transfer full) (nullable): a new #GstD3D11Device for @device
1158 * or %NULL if an error occurred
1163 gst_d3d11_device_new_wrapped (ID3D11Device * device)
1165 GstD3D11DeviceConstructData data;
1167 g_return_val_if_fail (device != nullptr, nullptr);
1169 data.data.device = device;
1170 data.type = DEVICE_CONSTRUCT_WRAPPED;
1171 data.create_flags = 0;
1173 return gst_d3d11_device_new_internal (&data);
1177 * gst_d3d11_device_get_device_handle:
1178 * @device: a #GstD3D11Device
1180 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1183 * Returns: (transfer none): the ID3D11Device handle
1188 gst_d3d11_device_get_device_handle (GstD3D11Device * device)
1190 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1192 return device->priv->device;
1196 * gst_d3d11_device_get_device_context_handle:
1197 * @device: a #GstD3D11Device
1199 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1200 * object. Any ID3D11DeviceContext call needs to be protected by
1201 * gst_d3d11_device_lock() and gst_d3d11_device_unlock() method.
1203 * Returns: (transfer none): the immeidate ID3D11DeviceContext handle
1207 ID3D11DeviceContext *
1208 gst_d3d11_device_get_device_context_handle (GstD3D11Device * device)
1210 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1212 return device->priv->device_context;
1216 * gst_d3d11_device_get_dxgi_factory_handle:
1217 * @device: a #GstD3D11Device
1219 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1222 * Returns: (transfer none): the IDXGIFactory1 handle
1227 gst_d3d11_device_get_dxgi_factory_handle (GstD3D11Device * device)
1229 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1231 return device->priv->factory;
1235 * gst_d3d11_device_get_video_device_handle:
1236 * @device: a #GstD3D11Device
1238 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1241 * Returns: (nullable) (transfer none) : the ID3D11VideoDevice handle or %NULL
1242 * if ID3D11VideoDevice is unavailable.
1247 gst_d3d11_device_get_video_device_handle (GstD3D11Device * device)
1249 GstD3D11DevicePrivate *priv;
1251 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1253 priv = device->priv;
1254 GstD3D11SRWLockGuard lk (&priv->resource_lock);
1255 if (!priv->video_device) {
1257 ID3D11VideoDevice *video_device = NULL;
1259 hr = priv->device->QueryInterface (IID_PPV_ARGS (&video_device));
1260 if (gst_d3d11_result (hr, device))
1261 priv->video_device = video_device;
1264 return priv->video_device;
1268 * gst_d3d11_device_get_video_context_handle:
1269 * @device: a #GstD3D11Device
1271 * Used for various D3D11 APIs directly. Caller must not destroy returned device
1274 * Returns: (nullable) (transfer none): the ID3D11VideoContext handle or %NULL
1275 * if ID3D11VideoContext is unavailable.
1279 ID3D11VideoContext *
1280 gst_d3d11_device_get_video_context_handle (GstD3D11Device * device)
1282 GstD3D11DevicePrivate *priv;
1284 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), NULL);
1286 priv = device->priv;
1287 GstD3D11SRWLockGuard lk (&priv->resource_lock);
1288 if (!priv->video_context) {
1290 ID3D11VideoContext *video_context = NULL;
1292 hr = priv->device_context->QueryInterface (IID_PPV_ARGS (&video_context));
1293 if (gst_d3d11_result (hr, device))
1294 priv->video_context = video_context;
1297 return priv->video_context;
1301 * gst_d3d11_device_lock:
1302 * @device: a #GstD3D11Device
1304 * Take lock for @device. Any thread-unsafe API call needs to be
1305 * protected by this method. This call must be paired with
1306 * gst_d3d11_device_unlock()
1311 gst_d3d11_device_lock (GstD3D11Device * device)
1313 GstD3D11DevicePrivate *priv;
1315 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
1317 priv = device->priv;
1319 GST_TRACE_OBJECT (device, "device locking");
1320 EnterCriticalSection (&priv->extern_lock);
1321 GST_TRACE_OBJECT (device, "device locked");
1325 * gst_d3d11_device_unlock:
1326 * @device: a #GstD3D11Device
1328 * Release lock for @device. This call must be paired with
1329 * gst_d3d11_device_lock()
1334 gst_d3d11_device_unlock (GstD3D11Device * device)
1336 GstD3D11DevicePrivate *priv;
1338 g_return_if_fail (GST_IS_D3D11_DEVICE (device));
1340 priv = device->priv;
1342 LeaveCriticalSection (&priv->extern_lock);
1343 GST_TRACE_OBJECT (device, "device unlocked");
1347 * gst_d3d11_device_get_format:
1348 * @device: a #GstD3D11Device
1349 * @format: a #GstVideoFormat
1350 * @device_format: (out caller-allocates) (nullable): a #GstD3D11Format
1352 * Converts @format to #GstD3D11Format if the @format is supported
1355 * Returns: %TRUE if @format is supported by @device
1360 gst_d3d11_device_get_format (GstD3D11Device * device, GstVideoFormat format,
1361 GstD3D11Format * device_format)
1363 GstD3D11DevicePrivate *priv;
1365 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), FALSE);
1367 priv = device->priv;
1369 for (guint i = 0; i < priv->format_table->len; i++) {
1370 const GstD3D11Format *d3d11_fmt =
1371 &g_array_index (priv->format_table, GstD3D11Format, i);
1373 if (d3d11_fmt->format != format)
1377 *device_format = *d3d11_fmt;
1383 gst_d3d11_format_init (device_format);
1388 GST_DEFINE_MINI_OBJECT_TYPE (GstD3D11Fence, gst_d3d11_fence);
1390 struct _GstD3D11FencePrivate
1395 HANDLE event_handle;
1401 _gst_d3d11_fence_free (GstD3D11Fence * fence)
1403 GstD3D11FencePrivate *priv = fence->priv;
1405 GST_D3D11_CLEAR_COM (priv->fence);
1406 GST_D3D11_CLEAR_COM (priv->query);
1407 if (priv->event_handle)
1408 CloseHandle (priv->event_handle);
1410 gst_clear_object (&fence->device);
1417 * gst_d3d11_device_create_fence:
1418 * @device: a #GstD3D11Device
1420 * Creates fence object (i.e., ID3D11Fence) if available, otherwise
1421 * ID3D11Query with D3D11_QUERY_EVENT is created.
1423 * Returns: a #GstD3D11Fence object
1428 gst_d3d11_device_create_fence (GstD3D11Device * device)
1430 GstD3D11DevicePrivate *priv;
1431 ID3D11Fence *fence = nullptr;
1433 GstD3D11Fence *self;
1435 g_return_val_if_fail (GST_IS_D3D11_DEVICE (device), nullptr);
1437 priv = device->priv;
1439 if (priv->device5 && priv->device_context4) {
1440 hr = priv->device5->CreateFence (0, D3D11_FENCE_FLAG_NONE,
1441 IID_PPV_ARGS (&fence));
1443 if (!gst_d3d11_result (hr, device))
1444 GST_WARNING_OBJECT (device, "Failed to create fence object");
1447 self = g_new0 (GstD3D11Fence, 1);
1448 self->device = (GstD3D11Device *) gst_object_ref (device);
1449 self->priv = g_new0 (GstD3D11FencePrivate, 1);
1450 self->priv->fence = fence;
1452 self->priv->event_handle = CreateEventEx (nullptr, nullptr,
1453 0, EVENT_ALL_ACCESS);
1456 gst_mini_object_init (GST_MINI_OBJECT_CAST (self), 0,
1457 GST_TYPE_D3D11_FENCE, nullptr, nullptr,
1458 (GstMiniObjectFreeFunction) _gst_d3d11_fence_free);
1464 * gst_d3d11_fence_signal:
1465 * @fence: a #GstD3D11Fence
1467 * Sets sync point to fence for waiting.
1468 * Must be called with gst_d3d11_device_lock() held
1470 * Returns: %TRUE if successful
1475 gst_d3d11_fence_signal (GstD3D11Fence * fence)
1478 GstD3D11Device *device;
1479 GstD3D11DevicePrivate *device_priv;
1480 GstD3D11FencePrivate *priv;
1482 g_return_val_if_fail (GST_IS_D3D11_FENCE (fence), FALSE);
1484 device = fence->device;
1485 device_priv = device->priv;
1488 priv->signalled = FALSE;
1489 priv->synced = FALSE;
1492 priv->fence_value++;
1494 GST_LOG_OBJECT (device, "Signals with fence value %" G_GUINT64_FORMAT,
1497 hr = device_priv->device_context4->Signal (priv->fence, priv->fence_value);
1498 if (!gst_d3d11_result (hr, device)) {
1499 GST_ERROR_OBJECT (device, "Failed to signal fence value %"
1500 G_GUINT64_FORMAT, fence->priv->fence_value);
1504 D3D11_QUERY_DESC desc;
1506 GST_D3D11_CLEAR_COM (priv->query);
1508 desc.Query = D3D11_QUERY_EVENT;
1511 GST_LOG_OBJECT (device, "Creating query object");
1513 hr = device_priv->device->CreateQuery (&desc, &priv->query);
1514 if (!gst_d3d11_result (hr, device)) {
1515 GST_ERROR_OBJECT (device, "Failed to create query object");
1519 device_priv->device_context->End (priv->query);
1522 priv->signalled = TRUE;
1528 * gst_d3d11_fence_wait:
1529 * @fence: a #GstD3D11Fence
1531 * Waits until previously issued GPU commands have been completed
1532 * Must be called with gst_d3d11_device_lock() held
1534 * Returns: %TRUE if successful
1539 gst_d3d11_fence_wait (GstD3D11Fence * fence)
1542 GstD3D11Device *device;
1543 GstD3D11DevicePrivate *device_priv;
1544 GstD3D11FencePrivate *priv;
1546 LARGE_INTEGER current_time, now;
1548 g_return_val_if_fail (GST_IS_D3D11_FENCE (fence), FALSE);
1550 device = fence->device;
1551 device_priv = device->priv;
1554 if (!priv->signalled) {
1555 GST_DEBUG_OBJECT (device, "Fence is not signalled, nothing to wait");
1560 GST_DEBUG_OBJECT (device, "Already synced");
1564 timer_ret = QueryPerformanceCounter (¤t_time);
1565 g_assert (timer_ret);
1570 GST_LOG_OBJECT (device, "Waiting fence value %" G_GUINT64_FORMAT,
1573 if (fence->priv->fence->GetCompletedValue () < fence->priv->fence_value) {
1574 hr = fence->priv->fence->SetEventOnCompletion (fence->priv->fence_value,
1575 fence->priv->event_handle);
1576 if (!gst_d3d11_result (hr, device)) {
1577 GST_WARNING_OBJECT (device, "Failed set event handle");
1581 /* 20 seconds should be sufficient time */
1582 DWORD ret = WaitForSingleObject (priv->event_handle, 20000);
1583 if (ret != WAIT_OBJECT_0) {
1584 GST_WARNING_OBJECT (device,
1585 "Failed to wait object, ret 0x%x", (guint) ret);
1591 BOOL sync_done = FALSE;
1593 g_assert (priv->query != nullptr);
1595 /* 20 sec timeout */
1596 timeout = now.QuadPart + 20 * device_priv->frequency.QuadPart;
1598 GST_LOG_OBJECT (device, "Waiting event");
1600 while (now.QuadPart < timeout && !sync_done) {
1601 hr = device_priv->device_context->GetData (priv->query,
1602 &sync_done, sizeof (BOOL), 0);
1604 GST_WARNING_OBJECT (device, "Failed to get event data");
1612 timer_ret = QueryPerformanceCounter (&now);
1613 g_assert (timer_ret);
1617 GST_WARNING_OBJECT (device, "Timeout");
1621 GST_D3D11_CLEAR_COM (priv->query);
1624 #ifndef GST_DISABLE_GST_DEBUG
1625 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_LOG) {
1626 GstClockTime elapsed;
1628 QueryPerformanceCounter (&now);
1629 elapsed = gst_util_uint64_scale (now.QuadPart - current_time.QuadPart,
1630 GST_SECOND, device_priv->frequency.QuadPart);
1632 GST_LOG_OBJECT (device, "Wait done, elapsed %" GST_TIME_FORMAT,
1633 GST_TIME_ARGS (elapsed));
1637 priv->signalled = FALSE;
1638 priv->synced = TRUE;