diff --git a/subprojects/gst-plugins-bad/sys/amfcodec/gstamfencoder.cpp b/subprojects/gst-plugins-bad/sys/amfcodec/gstamfencoder.cpp index 0fdd78c9bc..a14cb92d5d 100644 --- a/subprojects/gst-plugins-bad/sys/amfcodec/gstamfencoder.cpp +++ b/subprojects/gst-plugins-bad/sys/amfcodec/gstamfencoder.cpp @@ -58,6 +58,7 @@ struct _GstAmfEncoderPrivate const wchar_t *codec_id; GstD3D11Device *device; + GstD3D11Fence *fence; AMFContext *context; AMFComponent *comp; GstBufferPool *internal_pool; @@ -439,6 +440,7 @@ gst_amf_encoder_close (GstVideoEncoder * encoder) priv->context = nullptr; } + gst_clear_d3d11_fence (&priv->fence); gst_clear_object (&priv->device); return TRUE; @@ -617,9 +619,6 @@ gst_amf_encoder_copy_d3d11 (GstAmfEncoder * self, GstBuffer * src_buffer, GstFlowReturn ret; ComPtr < IDXGIResource > dxgi_resource; ComPtr < ID3D11Texture2D > shared_texture; - ComPtr < ID3D11Query > query; - D3D11_QUERY_DESC query_desc; - BOOL sync_done = FALSE; HANDLE shared_handle; GstD3D11Device *device; HRESULT hr; @@ -699,13 +698,14 @@ gst_amf_encoder_copy_d3d11 (GstAmfEncoder * self, GstBuffer * src_buffer, src_box.bottom = MIN (src_desc.Height, dst_desc.Height); if (shared) { - query_desc.Query = D3D11_QUERY_EVENT; - query_desc.MiscFlags = 0; + if (priv->fence && priv->fence->device != device) + gst_clear_d3d11_fence (&priv->fence); - hr = device_handle->CreateQuery (&query_desc, &query); - if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (self, "Couldn't Create event query, hr: 0x%x", - (guint) hr); + if (!priv->fence) + priv->fence = gst_d3d11_device_create_fence (device); + + if (!priv->fence) { + GST_ERROR_OBJECT (self, "Couldn't crete fence"); goto error; } @@ -716,15 +716,11 @@ gst_amf_encoder_copy_d3d11 (GstAmfEncoder * self, GstBuffer * src_buffer, 0, 0, 0, src_tex, subresource_idx, &src_box); if (shared) { - device_context->End (query.Get ()); - do { - hr = device_context->GetData (query.Get (), &sync_done, sizeof (BOOL), 0); - } while (!sync_done && (hr == S_OK || hr == S_FALSE)); - - if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (self, "Couldn't sync GPU operation, hr: 0x%x", - (guint) hr); + if (!gst_d3d11_fence_signal (priv->fence) || + !gst_d3d11_fence_wait (priv->fence)) { + GST_ERROR_OBJECT (self, "Couldn't sync GPU operation"); gst_d3d11_device_unlock (device); + gst_clear_d3d11_fence (&priv->fence); goto error; } diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp index 3bbfd18ed0..14b7c06793 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11screencapture.cpp @@ -231,6 +231,7 @@ class D3D11DesktopDupObject public: D3D11DesktopDupObject () : device_(nullptr) + , fence_(nullptr) , metadata_buffer_(nullptr) , metadata_buffer_size_(0) , vertex_buffer_(nullptr) @@ -246,6 +247,7 @@ public: if (vertex_buffer_) delete[] vertex_buffer_; + gst_clear_d3d11_fence (&fence_); gst_clear_object (&device_); } @@ -545,8 +547,8 @@ public: { ID3D11DeviceContext *context_handle = nullptr; ComPtr tex; - ComPtr < ID3D11Query > query; HRESULT hr; + gboolean is_shared = FALSE; context_handle = gst_d3d11_device_get_device_context_handle (device); @@ -555,7 +557,6 @@ public: } else { ID3D11Device *device_handle = nullptr; ComPtr < IDXGIResource > dxgi_resource; - D3D11_QUERY_DESC query_desc; HANDLE shared_handle; device_handle = gst_d3d11_device_get_device_handle (device); @@ -573,24 +574,24 @@ public: if (!gst_d3d11_result (hr, device)) return GST_FLOW_ERROR; - query_desc.Query = D3D11_QUERY_EVENT; - query_desc.MiscFlags = 0; + if (fence_ && fence_->device != device) + gst_clear_d3d11_fence (&fence_); - hr = device_handle->CreateQuery (&query_desc, &query); - if (!gst_d3d11_result (hr, device)) + if (!fence_) + fence_ = gst_d3d11_device_create_fence (device); + + if (!fence_) return GST_FLOW_ERROR; + + is_shared = TRUE; } context_handle->CopySubresourceRegion (texture, 0, 0, 0, 0, - tex.Get(), 0, cropBox); + tex.Get(), 0, cropBox); - if (query) { - BOOL sync_done = FALSE; - - do { - hr = context_handle->GetData (query.Get (), - &sync_done, sizeof (BOOL), 0); - } while (!sync_done && (hr == S_OK || hr == S_FALSE)); + if (is_shared) { + if (!gst_d3d11_fence_signal (fence_) || !gst_d3d11_fence_wait (fence_)) + return GST_FLOW_ERROR; } return GST_FLOW_OK; @@ -1471,6 +1472,7 @@ private: PTR_INFO ptr_info_; DXGI_OUTDUPL_DESC output_desc_; GstD3D11Device * device_; + GstD3D11Fence * fence_; ComPtr shared_texture_; ComPtr rtv_; diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp index d8028f5b4f..c92ccd042b 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11window_dummy.cpp @@ -40,6 +40,8 @@ struct _GstD3D11WindowDummy ID3D11Texture2D *fallback_texture; ID3D11VideoProcessorOutputView *fallback_pov; ID3D11RenderTargetView *fallback_rtv; + + GstD3D11Fence *fence; }; #define gst_d3d11_window_dummy_parent_class parent_class @@ -50,6 +52,7 @@ static void gst_d3d11_window_dummy_on_resize (GstD3D11Window * window, guint width, guint height); static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window, guint display_width, guint display_height, GstCaps * caps, GError ** error); +static void gst_d3d11_window_dummy_unprepare (GstD3D11Window * window); static gboolean gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window, GstD3D11WindowSharedHandleData * data); @@ -65,6 +68,8 @@ gst_d3d11_window_dummy_class_init (GstD3D11WindowDummyClass * klass) window_class->on_resize = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_on_resize); window_class->prepare = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_prepare); + window_class->unprepare = + GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_unprepare); window_class->open_shared_handle = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_open_shared_handle); window_class->release_shared_handle = @@ -144,6 +149,14 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window, return TRUE; } +static void +gst_d3d11_window_dummy_unprepare (GstD3D11Window * window) +{ + GstD3D11WindowDummy *self = GST_D3D11_WINDOW_DUMMY (window); + + gst_clear_d3d11_fence (&self->fence); +} + static void gst_d3d11_window_dummy_on_resize (GstD3D11Window * window, guint width, guint height) @@ -286,34 +299,19 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window, GST_D3D11_CLEAR_COM (data->keyed_mutex); } else { - /* *INDENT-OFF* */ - ComPtr query; - /* *INDENT-ON* */ - D3D11_QUERY_DESC query_desc; - ID3D11Device *device_handle = gst_d3d11_device_get_device_handle (device); - ID3D11DeviceContext *context_handle = - gst_d3d11_device_get_device_context_handle (device); - BOOL sync_done = FALSE; - /* If keyed mutex is not used, let's handle sync manually by using - * ID3D11Query. Issued GPU commands might not be finished yet */ - query_desc.Query = D3D11_QUERY_EVENT; - query_desc.MiscFlags = 0; + * fence. Issued GPU commands might not be finished yet */ - hr = device_handle->CreateQuery (&query_desc, &query); - if (!gst_d3d11_result (hr, device)) { + if (!self->fence) + self->fence = gst_d3d11_device_create_fence (device); + + if (!self->fence) { GST_ERROR_OBJECT (self, "Couldn't Create event query"); return FALSE; } - context_handle->End (query.Get ()); - - /* Wait until all issued GPU commands are finished */ - do { - hr = context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0); - } while (!sync_done && (hr == S_OK || hr == S_FALSE)); - - if (!gst_d3d11_result (hr, device)) { + if (!gst_d3d11_fence_signal (self->fence) || + !gst_d3d11_fence_wait (self->fence)) { GST_ERROR_OBJECT (self, "Couldn't sync GPU operation"); return FALSE; } diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.cpp b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.cpp index 01f657c0d3..11566f1940 100644 --- a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.cpp +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.cpp @@ -264,6 +264,7 @@ gst_mf_video_encoder_close (GstVideoEncoder * enc) gst_clear_object (&self->other_d3d11_device); gst_clear_object (&self->d3d11_device); + gst_clear_d3d11_fence (&self->fence); #endif return TRUE; @@ -1064,9 +1065,6 @@ gst_mf_video_encoder_create_input_sample_d3d11 (GstMFVideoEncoder * self, ComPtr < ID3D11Texture2D > mf_texture; ComPtr < IDXGIResource > dxgi_resource; ComPtr < ID3D11Texture2D > shared_texture; - ComPtr < ID3D11Query > query; - D3D11_QUERY_DESC query_desc; - BOOL sync_done = FALSE; HANDLE shared_handle; GstMemory *mem; GstD3D11Memory *dmem; @@ -1171,30 +1169,27 @@ gst_mf_video_encoder_create_input_sample_d3d11 (GstMFVideoEncoder * self, src_box.right = MIN (src_desc.Width, dst_desc.Width); src_box.bottom = MIN (src_desc.Height, dst_desc.Height); - /* CopySubresourceRegion() might not be able to guarantee - * copying. To ensure it, we will make use of d3d11 query */ - query_desc.Query = D3D11_QUERY_EVENT; - query_desc.MiscFlags = 0; + gst_d3d11_device_lock (dmem->device); + if (self->fence && self->fence->device != dmem->device) + gst_clear_d3d11_fence (&self->fence); - hr = device_handle->CreateQuery (&query_desc, &query); - if (!gst_d3d11_result (hr, dmem->device)) { - GST_ERROR_OBJECT (self, "Couldn't Create event query"); + if (!self->fence) + self->fence = gst_d3d11_device_create_fence (dmem->device); + + if (!self->fence) { + GST_ERROR_OBJECT (self, "Couldn't create fence object"); + gst_d3d11_device_unlock (dmem->device); gst_memory_unmap (mem, &info); return FALSE; } - gst_d3d11_device_lock (dmem->device); context_handle->CopySubresourceRegion (shared_texture.Get (), 0, 0, 0, 0, texture, subidx, &src_box); - context_handle->End (query.Get ()); - /* Wait until all issued GPU commands are finished */ - do { - hr = context_handle->GetData (query.Get (), &sync_done, sizeof (BOOL), 0); - } while (!sync_done && (hr == S_OK || hr == S_FALSE)); - - if (!gst_d3d11_result (hr, dmem->device)) { + if (!gst_d3d11_fence_signal (self->fence) || + !gst_d3d11_fence_wait (self->fence)) { GST_ERROR_OBJECT (self, "Couldn't sync GPU operation"); + gst_clear_d3d11_fence (&self->fence); gst_d3d11_device_unlock (dmem->device); gst_memory_unmap (mem, &info); diff --git a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.h b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.h index 69892bd22e..dc4b11c26d 100644 --- a/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.h +++ b/subprojects/gst-plugins-bad/sys/mediafoundation/gstmfvideoencoder.h @@ -116,6 +116,7 @@ struct _GstMFVideoEncoder IMFDXGIDeviceManager *device_manager; UINT reset_token; IMFVideoSampleAllocatorEx *mf_allocator; + GstD3D11Fence *fence; #endif }; diff --git a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp index 3ea8203267..7c843788f5 100644 --- a/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp +++ b/subprojects/gst-plugins-bad/sys/nvcodec/gstnvencoder.cpp @@ -60,6 +60,7 @@ struct _GstNvEncoderPrivate GstCudaContext *context; #ifdef GST_CUDA_HAS_D3D GstD3D11Device *device; + GstD3D11Fence *fence; #endif GstNvEncoderDeviceMode subclass_device_mode; @@ -439,6 +440,7 @@ gst_nv_encoder_close (GstVideoEncoder * encoder) gst_clear_object (&priv->context); #ifdef GST_CUDA_HAS_D3D + gst_clear_d3d11_fence (&priv->fence); gst_clear_object (&priv->device); #endif @@ -1558,9 +1560,6 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self, GstFlowReturn ret; ComPtr < IDXGIResource > dxgi_resource; ComPtr < ID3D11Texture2D > shared_texture; - ComPtr < ID3D11Query > query; - D3D11_QUERY_DESC query_desc; - BOOL sync_done = FALSE; HANDLE shared_handle; GstD3D11Device *device; HRESULT hr; @@ -1639,13 +1638,14 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self, src_box.bottom = MIN (src_desc.Height, dst_desc.Height); if (shared) { - query_desc.Query = D3D11_QUERY_EVENT; - query_desc.MiscFlags = 0; + if (priv->fence && priv->fence->device != device) + gst_clear_d3d11_fence (&priv->fence); - hr = device_handle->CreateQuery (&query_desc, &query); - if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (self, "Couldn't Create event query, hr: 0x%x", - (guint) hr); + if (!priv->fence) + priv->fence = gst_d3d11_device_create_fence (device); + + if (!priv->fence) { + GST_ERROR_OBJECT (self, "Couldn't crete fence"); goto error; } @@ -1656,15 +1656,11 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self, 0, 0, 0, src_tex, subresource_idx, &src_box); if (shared) { - device_context->End (query.Get ()); - do { - hr = device_context->GetData (query.Get (), &sync_done, sizeof (BOOL), 0); - } while (!sync_done && (hr == S_OK || hr == S_FALSE)); - - if (!gst_d3d11_result (hr, device)) { - GST_ERROR_OBJECT (self, "Couldn't sync GPU operation, hr: 0x%x", - (guint) hr); + if (!gst_d3d11_fence_signal (priv->fence) || + !gst_d3d11_fence_wait (priv->fence)) { + GST_ERROR_OBJECT (self, "Couldn't sync GPU operation"); gst_d3d11_device_unlock (device); + gst_clear_d3d11_fence (&priv->fence); goto error; }