From b5c8889d4f8a64b1cd22786b4228304c9c0f93d4 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Fri, 12 Jun 2020 20:11:29 +0900 Subject: [PATCH] d3d11videosink: Use GPU memory copy if possible Even if fallback buffer is required (e.g., shader resource view is unavailable), use direct GPU memory copy if possible. It must be much faster than system memory copy approach. Part-of: --- sys/d3d11/gstd3d11videosink.c | 53 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/sys/d3d11/gstd3d11videosink.c b/sys/d3d11/gstd3d11videosink.c index 3ada96fe96..abee04211e 100644 --- a/sys/d3d11/gstd3d11videosink.c +++ b/sys/d3d11/gstd3d11videosink.c @@ -784,6 +784,45 @@ invalid_buffer: } } +static gboolean +gst_d3d11_video_sink_copy_d3d11_to_d3d11 (GstD3D11VideoSink * self, + GstBuffer * inbuf, GstBuffer * outbuf) +{ + gint i; + ID3D11DeviceContext *context_handle = + gst_d3d11_device_get_device_context_handle (self->device); + + g_return_val_if_fail (gst_buffer_n_memory (inbuf) == + gst_buffer_n_memory (outbuf), FALSE); + + GST_LOG_OBJECT (self, "Copy to fallback buffer using device memory copy"); + + gst_d3d11_device_lock (self->device); + for (i = 0; i < gst_buffer_n_memory (inbuf); i++) { + GstD3D11Memory *in_mem = + (GstD3D11Memory *) gst_buffer_peek_memory (inbuf, i); + GstD3D11Memory *out_mem = + (GstD3D11Memory *) gst_buffer_peek_memory (outbuf, i); + D3D11_BOX src_box; + + /* input buffer might be larger than render size */ + src_box.left = 0; + src_box.top = 0; + src_box.front = 0; + src_box.back = 1; + src_box.right = out_mem->desc.Width; + src_box.bottom = out_mem->desc.Height; + + ID3D11DeviceContext_CopySubresourceRegion (context_handle, + (ID3D11Resource *) out_mem->texture, 0, 0, 0, 0, + (ID3D11Resource *) in_mem->texture, in_mem->subresource_index, + &src_box); + } + gst_d3d11_device_unlock (self->device); + + return TRUE; +} + static GstFlowReturn gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) { @@ -793,6 +832,7 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) GstVideoRectangle rect = { 0, }; GstBuffer *render_buf; gboolean need_unref = FALSE; + gboolean do_device_copy = TRUE; gint i; render_buf = buf; @@ -805,6 +845,7 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) if (!gst_is_d3d11_memory (mem)) { GST_LOG_OBJECT (sink, "not a d3d11 memory, need fallback"); render_buf = NULL; + do_device_copy = FALSE; break; } @@ -812,6 +853,7 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) if (dmem->device != self->device) { GST_LOG_OBJECT (sink, "different d3d11 device, need fallback"); render_buf = NULL; + do_device_copy = FALSE; break; } @@ -834,7 +876,7 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) GST_LOG_OBJECT (sink, "shader resource view is unavailable, need fallback"); render_buf = NULL; - break; + /* keep run loop in order to upload staging memory to device memory */ } } @@ -860,7 +902,14 @@ gst_d3d11_video_sink_show_frame (GstVideoSink * sink, GstBuffer * buf) } } - if (!gst_d3d11_video_sink_upload_frame (self, buf, render_buf)) { + if (do_device_copy) { + if (!gst_d3d11_video_sink_copy_d3d11_to_d3d11 (self, buf, render_buf)) { + GST_ERROR_OBJECT (self, "cannot copy frame"); + gst_buffer_unref (render_buf); + + return GST_FLOW_ERROR; + } + } else if (!gst_d3d11_video_sink_upload_frame (self, buf, render_buf)) { GST_ERROR_OBJECT (self, "cannot upload frame"); gst_buffer_unref (render_buf);