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;
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;
}

View file

@ -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 <ID3D11Texture2D> 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);
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<ID3D11Texture2D> shared_texture_;
ComPtr<ID3D11RenderTargetView> rtv_;

View file

@ -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<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
* 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;
}

View file

@ -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);

View file

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

View file

@ -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;
}