d3d11: Port to GstD3D11Fence

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2790>
This commit is contained in:
Seungha Yang 2022-07-23 00:41:49 +09:00 committed by GStreamer Marge Bot
parent ba259111d5
commit 6fff608f27
6 changed files with 76 additions and 88 deletions

View file

@ -58,6 +58,7 @@ struct _GstAmfEncoderPrivate
const wchar_t *codec_id; const wchar_t *codec_id;
GstD3D11Device *device; GstD3D11Device *device;
GstD3D11Fence *fence;
AMFContext *context; AMFContext *context;
AMFComponent *comp; AMFComponent *comp;
GstBufferPool *internal_pool; GstBufferPool *internal_pool;
@ -439,6 +440,7 @@ gst_amf_encoder_close (GstVideoEncoder * encoder)
priv->context = nullptr; priv->context = nullptr;
} }
gst_clear_d3d11_fence (&priv->fence);
gst_clear_object (&priv->device); gst_clear_object (&priv->device);
return TRUE; return TRUE;
@ -617,9 +619,6 @@ gst_amf_encoder_copy_d3d11 (GstAmfEncoder * self, GstBuffer * src_buffer,
GstFlowReturn ret; GstFlowReturn ret;
ComPtr < IDXGIResource > dxgi_resource; ComPtr < IDXGIResource > dxgi_resource;
ComPtr < ID3D11Texture2D > shared_texture; ComPtr < ID3D11Texture2D > shared_texture;
ComPtr < ID3D11Query > query;
D3D11_QUERY_DESC query_desc;
BOOL sync_done = FALSE;
HANDLE shared_handle; HANDLE shared_handle;
GstD3D11Device *device; GstD3D11Device *device;
HRESULT hr; 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); src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
if (shared) { if (shared) {
query_desc.Query = D3D11_QUERY_EVENT; if (priv->fence && priv->fence->device != device)
query_desc.MiscFlags = 0; gst_clear_d3d11_fence (&priv->fence);
hr = device_handle->CreateQuery (&query_desc, &query); if (!priv->fence)
if (!gst_d3d11_result (hr, device)) { priv->fence = gst_d3d11_device_create_fence (device);
GST_ERROR_OBJECT (self, "Couldn't Create event query, hr: 0x%x",
(guint) hr); if (!priv->fence) {
GST_ERROR_OBJECT (self, "Couldn't crete fence");
goto error; 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); 0, 0, 0, src_tex, subresource_idx, &src_box);
if (shared) { if (shared) {
device_context->End (query.Get ()); if (!gst_d3d11_fence_signal (priv->fence) ||
do { !gst_d3d11_fence_wait (priv->fence)) {
hr = device_context->GetData (query.Get (), &sync_done, sizeof (BOOL), 0); GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
} 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);
gst_d3d11_device_unlock (device); gst_d3d11_device_unlock (device);
gst_clear_d3d11_fence (&priv->fence);
goto error; goto error;
} }

View file

@ -231,6 +231,7 @@ class D3D11DesktopDupObject
public: public:
D3D11DesktopDupObject () D3D11DesktopDupObject ()
: device_(nullptr) : device_(nullptr)
, fence_(nullptr)
, metadata_buffer_(nullptr) , metadata_buffer_(nullptr)
, metadata_buffer_size_(0) , metadata_buffer_size_(0)
, vertex_buffer_(nullptr) , vertex_buffer_(nullptr)
@ -246,6 +247,7 @@ public:
if (vertex_buffer_) if (vertex_buffer_)
delete[] vertex_buffer_; delete[] vertex_buffer_;
gst_clear_d3d11_fence (&fence_);
gst_clear_object (&device_); gst_clear_object (&device_);
} }
@ -545,8 +547,8 @@ public:
{ {
ID3D11DeviceContext *context_handle = nullptr; ID3D11DeviceContext *context_handle = nullptr;
ComPtr <ID3D11Texture2D> tex; ComPtr <ID3D11Texture2D> tex;
ComPtr < ID3D11Query > query;
HRESULT hr; HRESULT hr;
gboolean is_shared = FALSE;
context_handle = gst_d3d11_device_get_device_context_handle (device); context_handle = gst_d3d11_device_get_device_context_handle (device);
@ -555,7 +557,6 @@ public:
} else { } else {
ID3D11Device *device_handle = nullptr; ID3D11Device *device_handle = nullptr;
ComPtr < IDXGIResource > dxgi_resource; ComPtr < IDXGIResource > dxgi_resource;
D3D11_QUERY_DESC query_desc;
HANDLE shared_handle; HANDLE shared_handle;
device_handle = gst_d3d11_device_get_device_handle (device); device_handle = gst_d3d11_device_get_device_handle (device);
@ -573,24 +574,24 @@ public:
if (!gst_d3d11_result (hr, device)) if (!gst_d3d11_result (hr, device))
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
query_desc.Query = D3D11_QUERY_EVENT; if (fence_ && fence_->device != device)
query_desc.MiscFlags = 0; gst_clear_d3d11_fence (&fence_);
hr = device_handle->CreateQuery (&query_desc, &query); if (!fence_)
if (!gst_d3d11_result (hr, device)) fence_ = gst_d3d11_device_create_fence (device);
if (!fence_)
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
is_shared = TRUE;
} }
context_handle->CopySubresourceRegion (texture, 0, 0, 0, 0, context_handle->CopySubresourceRegion (texture, 0, 0, 0, 0,
tex.Get(), 0, cropBox); tex.Get(), 0, cropBox);
if (query) { if (is_shared) {
BOOL sync_done = FALSE; if (!gst_d3d11_fence_signal (fence_) || !gst_d3d11_fence_wait (fence_))
return GST_FLOW_ERROR;
do {
hr = context_handle->GetData (query.Get (),
&sync_done, sizeof (BOOL), 0);
} while (!sync_done && (hr == S_OK || hr == S_FALSE));
} }
return GST_FLOW_OK; return GST_FLOW_OK;
@ -1471,6 +1472,7 @@ private:
PTR_INFO ptr_info_; PTR_INFO ptr_info_;
DXGI_OUTDUPL_DESC output_desc_; DXGI_OUTDUPL_DESC output_desc_;
GstD3D11Device * device_; GstD3D11Device * device_;
GstD3D11Fence * fence_;
ComPtr<ID3D11Texture2D> shared_texture_; ComPtr<ID3D11Texture2D> shared_texture_;
ComPtr<ID3D11RenderTargetView> rtv_; ComPtr<ID3D11RenderTargetView> rtv_;

View file

@ -40,6 +40,8 @@ struct _GstD3D11WindowDummy
ID3D11Texture2D *fallback_texture; ID3D11Texture2D *fallback_texture;
ID3D11VideoProcessorOutputView *fallback_pov; ID3D11VideoProcessorOutputView *fallback_pov;
ID3D11RenderTargetView *fallback_rtv; ID3D11RenderTargetView *fallback_rtv;
GstD3D11Fence *fence;
}; };
#define gst_d3d11_window_dummy_parent_class parent_class #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); guint width, guint height);
static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window, static gboolean gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
guint display_width, guint display_height, GstCaps * caps, GError ** error); guint display_width, guint display_height, GstCaps * caps, GError ** error);
static void gst_d3d11_window_dummy_unprepare (GstD3D11Window * window);
static gboolean static gboolean
gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window, gst_d3d11_window_dummy_open_shared_handle (GstD3D11Window * window,
GstD3D11WindowSharedHandleData * data); GstD3D11WindowSharedHandleData * data);
@ -65,6 +68,8 @@ gst_d3d11_window_dummy_class_init (GstD3D11WindowDummyClass * klass)
window_class->on_resize = window_class->on_resize =
GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_on_resize); GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_on_resize);
window_class->prepare = GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_prepare); 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 = window_class->open_shared_handle =
GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_open_shared_handle); GST_DEBUG_FUNCPTR (gst_d3d11_window_dummy_open_shared_handle);
window_class->release_shared_handle = window_class->release_shared_handle =
@ -144,6 +149,14 @@ gst_d3d11_window_dummy_prepare (GstD3D11Window * window,
return TRUE; 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 static void
gst_d3d11_window_dummy_on_resize (GstD3D11Window * window, gst_d3d11_window_dummy_on_resize (GstD3D11Window * window,
guint width, guint height) guint width, guint height)
@ -286,34 +299,19 @@ gst_d3d11_window_dummy_release_shared_handle (GstD3D11Window * window,
GST_D3D11_CLEAR_COM (data->keyed_mutex); GST_D3D11_CLEAR_COM (data->keyed_mutex);
} else { } else {
/* *INDENT-OFF* */
ComPtr<ID3D11Query> 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 /* If keyed mutex is not used, let's handle sync manually by using
* ID3D11Query. Issued GPU commands might not be finished yet */ * fence. Issued GPU commands might not be finished yet */
query_desc.Query = D3D11_QUERY_EVENT;
query_desc.MiscFlags = 0;
hr = device_handle->CreateQuery (&query_desc, &query); if (!self->fence)
if (!gst_d3d11_result (hr, device)) { self->fence = gst_d3d11_device_create_fence (device);
if (!self->fence) {
GST_ERROR_OBJECT (self, "Couldn't Create event query"); GST_ERROR_OBJECT (self, "Couldn't Create event query");
return FALSE; return FALSE;
} }
context_handle->End (query.Get ()); if (!gst_d3d11_fence_signal (self->fence) ||
!gst_d3d11_fence_wait (self->fence)) {
/* 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)) {
GST_ERROR_OBJECT (self, "Couldn't sync GPU operation"); GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
return FALSE; return FALSE;
} }

View file

@ -264,6 +264,7 @@ gst_mf_video_encoder_close (GstVideoEncoder * enc)
gst_clear_object (&self->other_d3d11_device); gst_clear_object (&self->other_d3d11_device);
gst_clear_object (&self->d3d11_device); gst_clear_object (&self->d3d11_device);
gst_clear_d3d11_fence (&self->fence);
#endif #endif
return TRUE; return TRUE;
@ -1064,9 +1065,6 @@ gst_mf_video_encoder_create_input_sample_d3d11 (GstMFVideoEncoder * self,
ComPtr < ID3D11Texture2D > mf_texture; ComPtr < ID3D11Texture2D > mf_texture;
ComPtr < IDXGIResource > dxgi_resource; ComPtr < IDXGIResource > dxgi_resource;
ComPtr < ID3D11Texture2D > shared_texture; ComPtr < ID3D11Texture2D > shared_texture;
ComPtr < ID3D11Query > query;
D3D11_QUERY_DESC query_desc;
BOOL sync_done = FALSE;
HANDLE shared_handle; HANDLE shared_handle;
GstMemory *mem; GstMemory *mem;
GstD3D11Memory *dmem; 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.right = MIN (src_desc.Width, dst_desc.Width);
src_box.bottom = MIN (src_desc.Height, dst_desc.Height); src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
/* CopySubresourceRegion() might not be able to guarantee gst_d3d11_device_lock (dmem->device);
* copying. To ensure it, we will make use of d3d11 query */ if (self->fence && self->fence->device != dmem->device)
query_desc.Query = D3D11_QUERY_EVENT; gst_clear_d3d11_fence (&self->fence);
query_desc.MiscFlags = 0;
hr = device_handle->CreateQuery (&query_desc, &query); if (!self->fence)
if (!gst_d3d11_result (hr, dmem->device)) { self->fence = gst_d3d11_device_create_fence (dmem->device);
GST_ERROR_OBJECT (self, "Couldn't Create event query");
if (!self->fence) {
GST_ERROR_OBJECT (self, "Couldn't create fence object");
gst_d3d11_device_unlock (dmem->device);
gst_memory_unmap (mem, &info); gst_memory_unmap (mem, &info);
return FALSE; return FALSE;
} }
gst_d3d11_device_lock (dmem->device);
context_handle->CopySubresourceRegion (shared_texture.Get (), 0, 0, 0, 0, context_handle->CopySubresourceRegion (shared_texture.Get (), 0, 0, 0, 0,
texture, subidx, &src_box); texture, subidx, &src_box);
context_handle->End (query.Get ());
/* Wait until all issued GPU commands are finished */ if (!gst_d3d11_fence_signal (self->fence) ||
do { !gst_d3d11_fence_wait (self->fence)) {
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)) {
GST_ERROR_OBJECT (self, "Couldn't sync GPU operation"); GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
gst_clear_d3d11_fence (&self->fence);
gst_d3d11_device_unlock (dmem->device); gst_d3d11_device_unlock (dmem->device);
gst_memory_unmap (mem, &info); gst_memory_unmap (mem, &info);

View file

@ -116,6 +116,7 @@ struct _GstMFVideoEncoder
IMFDXGIDeviceManager *device_manager; IMFDXGIDeviceManager *device_manager;
UINT reset_token; UINT reset_token;
IMFVideoSampleAllocatorEx *mf_allocator; IMFVideoSampleAllocatorEx *mf_allocator;
GstD3D11Fence *fence;
#endif #endif
}; };

View file

@ -60,6 +60,7 @@ struct _GstNvEncoderPrivate
GstCudaContext *context; GstCudaContext *context;
#ifdef GST_CUDA_HAS_D3D #ifdef GST_CUDA_HAS_D3D
GstD3D11Device *device; GstD3D11Device *device;
GstD3D11Fence *fence;
#endif #endif
GstNvEncoderDeviceMode subclass_device_mode; GstNvEncoderDeviceMode subclass_device_mode;
@ -439,6 +440,7 @@ gst_nv_encoder_close (GstVideoEncoder * encoder)
gst_clear_object (&priv->context); gst_clear_object (&priv->context);
#ifdef GST_CUDA_HAS_D3D #ifdef GST_CUDA_HAS_D3D
gst_clear_d3d11_fence (&priv->fence);
gst_clear_object (&priv->device); gst_clear_object (&priv->device);
#endif #endif
@ -1558,9 +1560,6 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self,
GstFlowReturn ret; GstFlowReturn ret;
ComPtr < IDXGIResource > dxgi_resource; ComPtr < IDXGIResource > dxgi_resource;
ComPtr < ID3D11Texture2D > shared_texture; ComPtr < ID3D11Texture2D > shared_texture;
ComPtr < ID3D11Query > query;
D3D11_QUERY_DESC query_desc;
BOOL sync_done = FALSE;
HANDLE shared_handle; HANDLE shared_handle;
GstD3D11Device *device; GstD3D11Device *device;
HRESULT hr; HRESULT hr;
@ -1639,13 +1638,14 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self,
src_box.bottom = MIN (src_desc.Height, dst_desc.Height); src_box.bottom = MIN (src_desc.Height, dst_desc.Height);
if (shared) { if (shared) {
query_desc.Query = D3D11_QUERY_EVENT; if (priv->fence && priv->fence->device != device)
query_desc.MiscFlags = 0; gst_clear_d3d11_fence (&priv->fence);
hr = device_handle->CreateQuery (&query_desc, &query); if (!priv->fence)
if (!gst_d3d11_result (hr, device)) { priv->fence = gst_d3d11_device_create_fence (device);
GST_ERROR_OBJECT (self, "Couldn't Create event query, hr: 0x%x",
(guint) hr); if (!priv->fence) {
GST_ERROR_OBJECT (self, "Couldn't crete fence");
goto error; goto error;
} }
@ -1656,15 +1656,11 @@ gst_nv_encoder_copy_d3d11 (GstNvEncoder * self,
0, 0, 0, src_tex, subresource_idx, &src_box); 0, 0, 0, src_tex, subresource_idx, &src_box);
if (shared) { if (shared) {
device_context->End (query.Get ()); if (!gst_d3d11_fence_signal (priv->fence) ||
do { !gst_d3d11_fence_wait (priv->fence)) {
hr = device_context->GetData (query.Get (), &sync_done, sizeof (BOOL), 0); GST_ERROR_OBJECT (self, "Couldn't sync GPU operation");
} 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);
gst_d3d11_device_unlock (device); gst_d3d11_device_unlock (device);
gst_clear_d3d11_fence (&priv->fence);
goto error; goto error;
} }