diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12-private.h b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12-private.h index 496b322501..bd86fa2f51 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12-private.h +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12-private.h @@ -191,7 +191,3 @@ static const GstD3D12Format g_gst_d3d12_default_format_map[] = { void gst_d3d12_device_clear_yuv_texture (GstD3D12Device * device, GstMemory * mem); - -void gst_d3d12_init_background_thread (void); - -void gst_d3d12_sync_background_thread (void); diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12commandqueue.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12commandqueue.cpp index c603d42779..c3a4e381fc 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12commandqueue.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12commandqueue.cpp @@ -396,7 +396,6 @@ gst_d3d12_command_queue_set_notify (GstD3D12CommandQueue * queue, std::lock_guard < std::mutex > elk (priv->execute_lock); auto gc_data = std::make_shared < GCData > (fence_data, notify, fence_value); if (!priv->gc_thread) { - gst_d3d12_init_background_thread (); priv->gc_thread = g_thread_new ("GstD3D12Gc", (GThreadFunc) gst_d3d12_command_queue_gc_thread, queue); } diff --git a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.cpp b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.cpp index 85c8c7d16e..1a820ffecb 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/gstd3d12device.cpp @@ -40,9 +40,21 @@ #include #include -GST_DEBUG_CATEGORY_STATIC (gst_d3d12_device_debug); GST_DEBUG_CATEGORY_STATIC (gst_d3d12_sdk_debug); -#define GST_CAT_DEFAULT gst_d3d12_device_debug + +#ifndef GST_DISABLE_GST_DEBUG +#define GST_CAT_DEFAULT ensure_debug_category() +static GstDebugCategory * +ensure_debug_category (void) +{ + static GstDebugCategory *cat = nullptr; + GST_D3D12_CALL_ONCE_BEGIN { + cat = _gst_debug_category_new ("d3d12device", 0, "d3d12device"); + } GST_D3D12_CALL_ONCE_END; + + return cat; +} +#endif /* GST_DISABLE_GST_DEBUG */ enum { @@ -58,19 +70,11 @@ enum /* *INDENT-OFF* */ using namespace Microsoft::WRL; -struct _GstD3D12DevicePrivate +struct DeviceInner { - ~_GstD3D12DevicePrivate () + ~DeviceInner () { - auto hr = device->GetDeviceRemovedReason (); - /* If device were not removed, make sure no pending command in queue */ - if (hr == S_OK) { - if (direct_queue) - gst_d3d12_command_queue_fence_wait (direct_queue, G_MAXUINT64, nullptr); - - if (copy_queue) - gst_d3d12_command_queue_fence_wait (copy_queue, G_MAXUINT64, nullptr); - } + Drain (); gst_clear_object (&direct_queue); gst_clear_object (©_queue); @@ -85,39 +89,59 @@ struct _GstD3D12DevicePrivate adapter = nullptr; d3d11on12 = nullptr; - if (info_queue && device) { - ComPtr debug_dev; - device.As (&debug_dev); - if (debug_dev) { - debug_dev->ReportLiveDeviceObjects (D3D12_RLDO_DETAIL | - D3D12_RLDO_IGNORE_INTERNAL); + ReportLiveObjects (); + } - UINT64 num_msg = info_queue->GetNumStoredMessages (); - for (UINT64 i = 0; i < num_msg; i++) { - HRESULT hr; - SIZE_T msg_len; - D3D12_MESSAGE *msg; + void Drain () + { + if (direct_queue) + gst_d3d12_command_queue_drain (direct_queue); - hr = info_queue->GetMessage (i, nullptr, &msg_len); - if (FAILED (hr) || msg_len == 0) - continue; + if (copy_queue) + gst_d3d12_command_queue_drain (copy_queue); + } - msg = (D3D12_MESSAGE *) g_malloc0 (msg_len); - hr = info_queue->GetMessage (i, msg, &msg_len); - if (FAILED (hr) || msg_len == 0) { - g_free (msg); - continue; - } + void ReportLiveObjects () + { + if (!info_queue || !device) + return; - gst_debug_log (gst_d3d12_sdk_debug, GST_LEVEL_INFO, - __FILE__, GST_FUNCTION, __LINE__, nullptr, - "D3D12InfoQueue: %s", msg->pDescription); - g_free (msg); - } + ComPtr debug_dev; + device.As (&debug_dev); + if (!debug_dev) + return; - info_queue->ClearStoredMessages (); + debug_dev->ReportLiveDeviceObjects (D3D12_RLDO_DETAIL | + D3D12_RLDO_IGNORE_INTERNAL); + + GST_DEBUG ("Begin live object report %s", description.c_str ()); + + UINT64 num_msg = info_queue->GetNumStoredMessages (); + for (UINT64 i = 0; i < num_msg; i++) { + HRESULT hr; + SIZE_T msg_len; + D3D12_MESSAGE *msg; + + hr = info_queue->GetMessage (i, nullptr, &msg_len); + if (FAILED (hr) || msg_len == 0) + continue; + + msg = (D3D12_MESSAGE *) g_malloc0 (msg_len); + hr = info_queue->GetMessage (i, msg, &msg_len); + if (FAILED (hr) || msg_len == 0) { + g_free (msg); + continue; } + + gst_debug_log (gst_d3d12_sdk_debug, GST_LEVEL_INFO, + __FILE__, GST_FUNCTION, __LINE__, nullptr, + "D3D12InfoQueue: %s", msg->pDescription); + g_free (msg); } + + GST_DEBUG ("End live object report %s", description.c_str ()); + + info_queue->ClearStoredMessages (); } ComPtr device; @@ -149,6 +173,13 @@ struct _GstD3D12DevicePrivate gint64 adapter_luid = 0; }; +typedef std::shared_ptr DeviceInnerPtr; + +struct _GstD3D12DevicePrivate +{ + DeviceInnerPtr inner; +}; + enum GstD3D12DeviceConstructType { GST_D3D12_DEVICE_CONSTRUCT_FOR_INDEX, @@ -168,30 +199,6 @@ struct GstD3D12DeviceConstructData static GstD3D12Device * gst_d3d12_device_new_internal (const GstD3D12DeviceConstructData * data); -struct DeviceCache -{ - ~DeviceCache() - { - if (priv) - delete priv; - } - - GstD3D12Device *device = nullptr; - GstD3D12DevicePrivate *priv = nullptr; - guint64 token = 0; -}; - -/* Because ID3D12Device instance is a singleton per adapter, - * this DeviceCacheManager object will cache GstD3D12Device object and - * will return the same GstD3D12Device object for create request - * if instanted object exists already. - * - * Another role of this object dtor thread management. - * GstD3D12CommandQueue object held by GstD3D12Device will run background - * garbage collection thread and releasing garbage collection data - * could result in releasing GstD3D12Device object, which can cause self-thread - * joining. This manager will run one background thread to avoid it - */ class DeviceCacheManager { public: @@ -207,155 +214,61 @@ public: return inst; } - void InitThread () - { - std::lock_guard lk (lock_); - if (!thread_) - thread_ = new std::thread (&DeviceCacheManager::threadFunc, this); - } - - void Sync () - { - guint64 to_wait = 0; - - { - std::lock_guard lk (lock_); - if (!thread_) - return; - - token_++; - to_wait = token_; - - auto empty_item = std::make_shared (); - empty_item->token = to_wait; - - std::lock_guard olk (thread_lock_); - to_remove_.push (std::move (empty_item)); - thread_cond_.notify_one (); - } - - std::unique_lock olk (token_lock_); - while (token_synced_ < to_wait) - token_cond_.wait (olk); - } - - GstD3D12Device * Create (const GstD3D12DeviceConstructData * data) + GstD3D12Device * GetDevice (const GstD3D12DeviceConstructData * data) { std::lock_guard lk (lock_); auto it = std::find_if (list_.begin (), list_.end (), - [&] (const auto & cache) { - const auto priv = cache->priv; + [&] (const auto & device) { if (data->type == GST_D3D12_DEVICE_CONSTRUCT_FOR_INDEX) - return priv->adapter_index == data->data.index; + return device->adapter_index == data->data.index; - return priv->adapter_luid == data->data.luid; + return device->adapter_luid == data->data.luid; }); - if (it != list_.end ()) - return (GstD3D12Device *) gst_object_ref ((*it)->device); + if (it != list_.end ()) { + GST_DEBUG ("Reusing created device"); + auto device = (GstD3D12Device *) + g_object_new (GST_TYPE_D3D12_DEVICE, nullptr); + gst_object_ref_sink (device); + device->priv->inner = *it; + return device; + } auto device = gst_d3d12_device_new_internal (data); if (!device) return nullptr; - gst_object_ref_sink (device); + GST_DEBUG ("Created new device"); - auto item = std::make_shared (); - item->device = device; - item->priv = device->priv; - - g_object_weak_ref (G_OBJECT (device), DeviceCacheManager::NotifyCb, this); - list_.push_back (item); + list_.push_back (device->priv->inner); return device; } - static void NotifyCb (gpointer data, GObject * device) + void ReleaseDevice (guint64 luid) { - auto self = (DeviceCacheManager *) data; - self->remove ((GstD3D12Device *) device); + std::lock_guard lk (lock_); + for (const auto & it : list_) { + if (it->adapter_luid == luid) { + if (it.use_count () == 1) { + it->Drain (); + it->ReportLiveObjects (); + } + return; + } + } } private: DeviceCacheManager () {} ~DeviceCacheManager () {} - void threadFunc () - { - while (true) { - std::unique_lock lk (thread_lock_); - while (to_remove_.empty ()) - thread_cond_.wait (lk); - - while (!to_remove_.empty ()) { - guint64 token; - - { - auto item = to_remove_.front (); - to_remove_.pop (); - token = item->token; - } - - std::lock_guard olk (token_lock_); - token_synced_ = token; - token_cond_.notify_all (); - } - } - } - - void remove (GstD3D12Device * device) - { - std::lock_guard lk (lock_); - auto it = std::find_if (list_.begin (), list_.end (), - [&] (const auto & cache) { - return cache->device == device; - }); - - std::shared_ptr cached; - if (it != list_.end ()) { - cached = *it; - list_.erase (it); - } else { - GST_WARNING ("Couldn't find device from cache"); - } - - if (cached && thread_) { - std::lock_guard tlk (thread_lock_); - token_++; - cached->token = token_; - to_remove_.push (std::move (cached)); - thread_cond_.notify_one (); - } - } - private: std::mutex lock_; - std::vector> list_; - std::mutex thread_lock_; - std::condition_variable thread_cond_; - std::thread *thread_ = nullptr; - std::queue> to_remove_; - std::mutex token_lock_; - std::condition_variable token_cond_; - guint64 token_ = 0; - guint64 token_synced_ = 0; + std::vector list_; }; /* *INDENT-ON* */ -void -gst_d3d12_init_background_thread (void) -{ - auto manager = DeviceCacheManager::GetInstance (); - manager->InitThread (); -} - -void -gst_d3d12_sync_background_thread (void) -{ - auto manager = DeviceCacheManager::GetInstance (); - manager->Sync (); -} - static gboolean gst_d3d12_device_enable_debug (void) { @@ -462,7 +375,14 @@ gst_d3d12_device_finalize (GObject * object) GST_DEBUG_OBJECT (self, "Finalize"); - /* Don't delete private struct. DeviceCacheManager will destroy it */ + guint64 luid = 0; + if (self->priv->inner) + luid = self->priv->inner->adapter_luid; + + delete self->priv; + + auto manager = DeviceCacheManager::GetInstance (); + manager->ReleaseDevice (luid); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -471,8 +391,8 @@ static void gst_d3d12_device_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstD3D12Device *self = GST_D3D12_DEVICE (object); - GstD3D12DevicePrivate *priv = self->priv; + auto self = GST_D3D12_DEVICE (object); + auto priv = self->priv->inner; switch (prop_id) { case PROP_ADAPTER_INDEX: @@ -500,7 +420,7 @@ static gboolean check_format_support (GstD3D12Device * self, DXGI_FORMAT format, guint flags, D3D12_FEATURE_DATA_FORMAT_SUPPORT * support) { - ID3D12Device *device = self->priv->device.Get (); + auto device = self->priv->inner->device; HRESULT hr; support->Format = format; @@ -526,7 +446,7 @@ check_format_support (GstD3D12Device * self, DXGI_FORMAT format, static void gst_d3d12_device_setup_format_table (GstD3D12Device * self) { - auto priv = self->priv; + auto priv = self->priv->inner; for (guint i = 0; i < GST_D3D12_N_FORMATS; i++) { const auto iter = &g_gst_d3d12_default_format_map[i]; @@ -722,9 +642,6 @@ gst_d3d12_device_new_internal (const GstD3D12DeviceConstructData * data) UINT factory_flags = 0; guint index = 0; - GST_DEBUG_CATEGORY_INIT (gst_d3d12_device_debug, - "d3d12device", 0, "d3d12 device object"); - gst_d3d12_device_enable_debug (); hr = CreateDXGIFactory2 (factory_flags, IID_PPV_ARGS (&factory)); @@ -753,9 +670,10 @@ gst_d3d12_device_new_internal (const GstD3D12DeviceConstructData * data) return nullptr; } - GstD3D12Device *self = (GstD3D12Device *) - g_object_new (GST_TYPE_D3D12_DEVICE, nullptr); - GstD3D12DevicePrivate *priv = self->priv; + auto self = (GstD3D12Device *) g_object_new (GST_TYPE_D3D12_DEVICE, nullptr); + gst_object_ref_sink (self); + self->priv->inner = std::make_shared < DeviceInner > (); + auto priv = self->priv->inner; priv->factory = factory; priv->adapter = adapter; @@ -835,7 +753,7 @@ gst_d3d12_device_new (guint adapter_index) data.data.index = adapter_index; data.type = GST_D3D12_DEVICE_CONSTRUCT_FOR_INDEX; - return manager->Create (&data); + return manager->GetDevice (&data); } GstD3D12Device * @@ -846,7 +764,7 @@ gst_d3d12_device_new_for_adapter_luid (gint64 adapter_luid) data.data.luid = adapter_luid; data.type = GST_D3D12_DEVICE_CONSTRUCT_FOR_LUID; - return manager->Create (&data); + return manager->GetDevice (&data); } ID3D12Device * @@ -854,7 +772,7 @@ gst_d3d12_device_get_device_handle (GstD3D12Device * device) { g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr); - return device->priv->device.Get (); + return device->priv->inner->device.Get (); } IDXGIAdapter1 * @@ -862,7 +780,7 @@ gst_d3d12_device_get_adapter_handle (GstD3D12Device * device) { g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr); - return device->priv->adapter.Get (); + return device->priv->inner->adapter.Get (); } IDXGIFactory2 * @@ -870,7 +788,7 @@ gst_d3d12_device_get_factory_handle (GstD3D12Device * device) { g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr); - return device->priv->factory.Get (); + return device->priv->inner->factory.Get (); } gboolean @@ -880,7 +798,7 @@ gst_d3d12_device_get_d3d11on12_device (GstD3D12Device * device, g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), FALSE); g_return_val_if_fail (d3d11on12, FALSE); - auto priv = device->priv; + auto priv = device->priv->inner; std::lock_guard < std::mutex > lk (priv->lock); if (!priv->d3d11on12) { @@ -905,7 +823,7 @@ gst_d3d12_device_lock (GstD3D12Device * device) { g_return_if_fail (GST_IS_D3D12_DEVICE (device)); - auto priv = device->priv; + auto priv = device->priv->inner; priv->extern_lock.lock (); } @@ -914,7 +832,7 @@ gst_d3d12_device_unlock (GstD3D12Device * device) { g_return_if_fail (GST_IS_D3D12_DEVICE (device)); - auto priv = device->priv; + auto priv = device->priv->inner; priv->extern_lock.unlock (); } @@ -925,7 +843,7 @@ gst_d3d12_device_get_format (GstD3D12Device * device, g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), FALSE); g_return_val_if_fail (device_format != nullptr, FALSE); - auto priv = device->priv; + auto priv = device->priv->inner; const auto & target = priv->format_table.find (format); if (target == priv->format_table.end ()) return FALSE; @@ -942,7 +860,7 @@ gst_d3d12_device_get_command_queue (GstD3D12Device * device, { g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), nullptr); - auto priv = device->priv; + auto priv = device->priv->inner; switch (queue_type) { case D3D12_COMMAND_LIST_TYPE_DIRECT: @@ -965,7 +883,7 @@ gst_d3d12_device_execute_command_lists (GstD3D12Device * device, { g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), FALSE); - auto priv = device->priv; + auto priv = device->priv->inner; GstD3D12CommandQueue *queue; switch (queue_type) { @@ -992,7 +910,7 @@ gst_d3d12_device_get_completed_value (GstD3D12Device * device, { g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), G_MAXUINT64); - auto priv = device->priv; + auto priv = device->priv->inner; GstD3D12CommandQueue *queue; switch (queue_type) { @@ -1018,7 +936,7 @@ gst_d3d12_device_set_fence_notify (GstD3D12Device * device, g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), FALSE); g_return_val_if_fail (fence_data, FALSE); - auto priv = device->priv; + auto priv = device->priv->inner; GstD3D12CommandQueue *queue; switch (queue_type) { @@ -1046,7 +964,7 @@ gst_d3d12_device_fence_wait (GstD3D12Device * device, { g_return_val_if_fail (GST_IS_D3D12_DEVICE (device), FALSE); - auto priv = device->priv; + auto priv = device->priv->inner; GstD3D12CommandQueue *queue; switch (queue_type) { @@ -1077,7 +995,7 @@ gst_d3d12_device_copy_texture_region (GstD3D12Device * device, g_return_val_if_fail (args, FALSE); HRESULT hr; - auto priv = device->priv; + auto priv = device->priv->inner; GstD3D12CommandAllocatorPool *ca_pool; GstD3D12CommandAllocator *gst_ca = nullptr; GstD3D12CommandListPool *cl_pool; @@ -1186,11 +1104,10 @@ gst_d3d12_device_d3d12_debug (GstD3D12Device * device, const gchar * file, { g_return_if_fail (GST_IS_D3D12_DEVICE (device)); - if (!device->priv->info_queue) + auto priv = device->priv->inner; + if (!priv->info_queue) return; - GstD3D12DevicePrivate *priv = device->priv; - std::lock_guard < std::recursive_mutex > lk (priv->extern_lock); ID3D12InfoQueue *info_queue = priv->info_queue.Get (); UINT64 num_msg = info_queue->GetNumStoredMessages (); @@ -1233,7 +1150,7 @@ gst_d3d12_device_d3d12_debug (GstD3D12Device * device, const gchar * file, void gst_d3d12_device_clear_yuv_texture (GstD3D12Device * device, GstMemory * mem) { - auto priv = device->priv; + auto priv = device->priv->inner; auto dmem = GST_D3D12_MEMORY_CAST (mem); ComPtr < ID3D12DescriptorHeap > heap; diff --git a/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp b/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp index ef42cdb8b7..488635adfb 100644 --- a/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d12/plugin.cpp @@ -64,7 +64,6 @@ GST_DEBUG_CATEGORY (gst_d3d12_utils_debug); static void plugin_deinit (gpointer data) { - gst_d3d12_sync_background_thread (); } static gboolean