mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
d3d12swapchainsink: Add support for MSAA
Adding "msaa" property and enable MSAA if supported by device Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7550>
This commit is contained in:
parent
ce5321be68
commit
9dee102867
1 changed files with 114 additions and 15 deletions
|
@ -45,6 +45,7 @@ enum
|
||||||
PROP_BORDER_COLOR,
|
PROP_BORDER_COLOR,
|
||||||
PROP_SWAPCHAIN,
|
PROP_SWAPCHAIN,
|
||||||
PROP_SAMPLING_METHOD,
|
PROP_SAMPLING_METHOD,
|
||||||
|
PROP_MSAA,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_ADAPTER -1
|
#define DEFAULT_ADAPTER -1
|
||||||
|
@ -53,6 +54,7 @@ enum
|
||||||
#define DEFAULT_HEIGHT 720
|
#define DEFAULT_HEIGHT 720
|
||||||
#define DEFAULT_BORDER_COLOR (G_GUINT64_CONSTANT(0xffff000000000000))
|
#define DEFAULT_BORDER_COLOR (G_GUINT64_CONSTANT(0xffff000000000000))
|
||||||
#define DEFAULT_SAMPLING_METHOD GST_D3D12_SAMPLING_METHOD_BILINEAR
|
#define DEFAULT_SAMPLING_METHOD GST_D3D12_SAMPLING_METHOD_BILINEAR
|
||||||
|
#define DEFAULT_MSAA GST_D3D12_MSAA_DISABLED
|
||||||
|
|
||||||
#define BACK_BUFFER_COUNT 2
|
#define BACK_BUFFER_COUNT 2
|
||||||
|
|
||||||
|
@ -131,6 +133,7 @@ struct GstD3D12SwapChainSinkPrivate
|
||||||
}
|
}
|
||||||
gst_clear_caps (&caps);
|
gst_clear_caps (&caps);
|
||||||
gst_clear_buffer (&cached_buf);
|
gst_clear_buffer (&cached_buf);
|
||||||
|
gst_clear_buffer (&msaa_buf);
|
||||||
gst_clear_object (&conv);
|
gst_clear_object (&conv);
|
||||||
backbuf.clear ();
|
backbuf.clear ();
|
||||||
convert_format = GST_VIDEO_FORMAT_UNKNOWN;
|
convert_format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||||
|
@ -165,6 +168,7 @@ struct GstD3D12SwapChainSinkPrivate
|
||||||
GstD3D12CommandQueue *cq = nullptr;
|
GstD3D12CommandQueue *cq = nullptr;
|
||||||
GstD3D12CommandAllocatorPool *ca_pool = nullptr;
|
GstD3D12CommandAllocatorPool *ca_pool = nullptr;
|
||||||
GstBuffer *cached_buf = nullptr;
|
GstBuffer *cached_buf = nullptr;
|
||||||
|
GstBuffer *msaa_buf = nullptr;
|
||||||
GstCaps *caps = nullptr;
|
GstCaps *caps = nullptr;
|
||||||
GstD3D12Converter *conv = nullptr;
|
GstD3D12Converter *conv = nullptr;
|
||||||
GstD3D12OverlayCompositor *comp = nullptr;
|
GstD3D12OverlayCompositor *comp = nullptr;
|
||||||
|
@ -182,6 +186,7 @@ struct GstD3D12SwapChainSinkPrivate
|
||||||
guint height = DEFAULT_HEIGHT;
|
guint height = DEFAULT_HEIGHT;
|
||||||
guint64 border_color = DEFAULT_BORDER_COLOR;
|
guint64 border_color = DEFAULT_BORDER_COLOR;
|
||||||
GstD3D12SamplingMethod sampling_method = DEFAULT_SAMPLING_METHOD;
|
GstD3D12SamplingMethod sampling_method = DEFAULT_SAMPLING_METHOD;
|
||||||
|
GstD3D12MSAAMode msaa_mode = DEFAULT_MSAA;
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
@ -276,6 +281,12 @@ gst_d3d12_swapchain_sink_class_init (GstD3D12SwapChainSinkClass * klass)
|
||||||
DEFAULT_SAMPLING_METHOD,
|
DEFAULT_SAMPLING_METHOD,
|
||||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class, PROP_MSAA,
|
||||||
|
g_param_spec_enum ("msaa", "MSAA",
|
||||||
|
"MSAA (Multi-Sampling Anti-Aliasing) level",
|
||||||
|
GST_TYPE_D3D12_MSAA_MODE, DEFAULT_MSAA,
|
||||||
|
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
d3d12_swapchain_sink_signals[SIGNAL_RESIZE] =
|
d3d12_swapchain_sink_signals[SIGNAL_RESIZE] =
|
||||||
g_signal_new_class_handler ("resize", G_TYPE_FROM_CLASS (klass),
|
g_signal_new_class_handler ("resize", G_TYPE_FROM_CLASS (klass),
|
||||||
(GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
(GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
@ -310,6 +321,7 @@ gst_d3d12_swapchain_sink_class_init (GstD3D12SwapChainSinkClass * klass)
|
||||||
|
|
||||||
gst_type_mark_as_plugin_api (GST_TYPE_D3D12_SAMPLING_METHOD,
|
gst_type_mark_as_plugin_api (GST_TYPE_D3D12_SAMPLING_METHOD,
|
||||||
(GstPluginAPIFlags) 0);
|
(GstPluginAPIFlags) 0);
|
||||||
|
gst_type_mark_as_plugin_api (GST_TYPE_D3D12_MSAA_MODE, (GstPluginAPIFlags) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -368,6 +380,15 @@ gst_d3d12_swapchain_sink_set_property (GObject * object, guint prop_id,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PROP_MSAA:
|
||||||
|
{
|
||||||
|
auto msaa = (GstD3D12MSAAMode) g_value_get_enum (value);
|
||||||
|
if (priv->msaa_mode != msaa) {
|
||||||
|
priv->msaa_mode = msaa;
|
||||||
|
gst_d3d12_swapchain_sink_resize (self, priv->width, priv->height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -420,6 +441,43 @@ gst_d3d12_swapchain_sink_resize_unlocked (GstD3D12SwapChainSink * self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_clear_buffer (&priv->msaa_buf);
|
||||||
|
if (priv->swapchain) {
|
||||||
|
DXGI_SAMPLE_DESC sample_desc = { };
|
||||||
|
gst_d3d12_calculate_sample_desc_for_msaa (self->device,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM, priv->msaa_mode, &sample_desc);
|
||||||
|
|
||||||
|
if (sample_desc.Count > 1) {
|
||||||
|
auto device = gst_d3d12_device_get_device_handle (self->device);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (self, "Enable MSAA x%d with quality level %d",
|
||||||
|
sample_desc.Count, sample_desc.Quality);
|
||||||
|
D3D12_HEAP_PROPERTIES heap_prop =
|
||||||
|
CD3DX12_HEAP_PROPERTIES (D3D12_HEAP_TYPE_DEFAULT);
|
||||||
|
D3D12_RESOURCE_DESC resource_desc =
|
||||||
|
CD3DX12_RESOURCE_DESC::Tex2D (DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
priv->width, priv->height,
|
||||||
|
1, 1, sample_desc.Count, sample_desc.Quality,
|
||||||
|
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
|
||||||
|
D3D12_CLEAR_VALUE clear_value = { };
|
||||||
|
clear_value.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
for (guint i = 0; i < 4; i++)
|
||||||
|
clear_value.Color[i] = priv->border_color_val[i];
|
||||||
|
|
||||||
|
ComPtr < ID3D12Resource > msaa_texture;
|
||||||
|
auto hr = device->CreateCommittedResource (&heap_prop,
|
||||||
|
D3D12_HEAP_FLAG_NONE,
|
||||||
|
&resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clear_value,
|
||||||
|
IID_PPV_ARGS (&msaa_texture));
|
||||||
|
if (gst_d3d12_result (hr, self->device)) {
|
||||||
|
auto mem = gst_d3d12_allocator_alloc_wrapped (nullptr, self->device,
|
||||||
|
msaa_texture.Get (), 0, nullptr, nullptr);
|
||||||
|
priv->msaa_buf = gst_buffer_new ();
|
||||||
|
gst_buffer_append_memory (priv->msaa_buf, mem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,6 +569,9 @@ gst_d3d12_swapchain_sink_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_SAMPLING_METHOD:
|
case PROP_SAMPLING_METHOD:
|
||||||
g_value_set_enum (value, priv->sampling_method);
|
g_value_set_enum (value, priv->sampling_method);
|
||||||
break;
|
break;
|
||||||
|
case PROP_MSAA:
|
||||||
|
g_value_set_enum (value, priv->msaa_mode);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -730,11 +791,22 @@ gst_d3d12_swapchain_sink_render (GstD3D12SwapChainSink * self)
|
||||||
|
|
||||||
auto mem = (GstD3D12Memory *) gst_buffer_peek_memory (backbuf, 0);
|
auto mem = (GstD3D12Memory *) gst_buffer_peek_memory (backbuf, 0);
|
||||||
auto backbuf_texture = gst_d3d12_memory_get_resource_handle (mem);
|
auto backbuf_texture = gst_d3d12_memory_get_resource_handle (mem);
|
||||||
D3D12_RESOURCE_BARRIER barrier =
|
GstBuffer *conv_outbuf = backbuf;
|
||||||
CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
ID3D12Resource *msaa_resource = nullptr;
|
||||||
D3D12_RESOURCE_STATE_COMMON,
|
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
if (priv->msaa_buf) {
|
||||||
cl->ResourceBarrier (1, &barrier);
|
conv_outbuf = priv->msaa_buf;
|
||||||
|
mem = (GstD3D12Memory *) gst_buffer_peek_memory (conv_outbuf, 0);
|
||||||
|
msaa_resource = gst_d3d12_memory_get_resource_handle (mem);
|
||||||
|
auto msaa_buf = gst_buffer_ref (priv->msaa_buf);
|
||||||
|
gst_d3d12_fence_data_push (fence_data, FENCE_NOTIFY_MINI_OBJECT (msaa_buf));
|
||||||
|
} else {
|
||||||
|
D3D12_RESOURCE_BARRIER barrier =
|
||||||
|
CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
||||||
|
D3D12_RESOURCE_STATE_COMMON,
|
||||||
|
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||||
|
cl->ResourceBarrier (1, &barrier);
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->viewport.x != 0 || priv->viewport.y != 0 ||
|
if (priv->viewport.x != 0 || priv->viewport.y != 0 ||
|
||||||
(guint) priv->viewport.w != priv->width ||
|
(guint) priv->viewport.w != priv->width ||
|
||||||
|
@ -745,25 +817,45 @@ gst_d3d12_swapchain_sink_render (GstD3D12SwapChainSink * self)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_d3d12_converter_convert_buffer (priv->conv,
|
if (!gst_d3d12_converter_convert_buffer (priv->conv,
|
||||||
priv->cached_buf, backbuf, fence_data, cl.Get (), TRUE)) {
|
priv->cached_buf, conv_outbuf, fence_data, cl.Get (), TRUE)) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't build convert command");
|
GST_ERROR_OBJECT (self, "Couldn't build convert command");
|
||||||
gst_d3d12_fence_data_unref (fence_data);
|
gst_d3d12_fence_data_unref (fence_data);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_d3d12_overlay_compositor_draw (priv->comp,
|
if (!gst_d3d12_overlay_compositor_draw (priv->comp,
|
||||||
backbuf, fence_data, cl.Get ())) {
|
conv_outbuf, fence_data, cl.Get ())) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't build overlay command");
|
GST_ERROR_OBJECT (self, "Couldn't build overlay command");
|
||||||
gst_d3d12_fence_data_unref (fence_data);
|
gst_d3d12_fence_data_unref (fence_data);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
barrier =
|
if (msaa_resource) {
|
||||||
CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
std::vector < D3D12_RESOURCE_BARRIER > barriers;
|
||||||
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COMMON);
|
barriers.push_back (CD3DX12_RESOURCE_BARRIER::Transition (msaa_resource,
|
||||||
cl->ResourceBarrier (1, &barrier);
|
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||||
hr = cl->Close ();
|
D3D12_RESOURCE_STATE_RESOLVE_SOURCE));
|
||||||
|
barriers.push_back (CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
||||||
|
D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_RESOLVE_DEST));
|
||||||
|
cl->ResourceBarrier (barriers.size (), barriers.data ());
|
||||||
|
|
||||||
|
cl->ResolveSubresource (backbuf_texture, 0, msaa_resource, 0,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||||
|
|
||||||
|
barriers.clear ();
|
||||||
|
barriers.push_back (CD3DX12_RESOURCE_BARRIER::Transition (msaa_resource,
|
||||||
|
D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
|
||||||
|
D3D12_RESOURCE_STATE_RENDER_TARGET));
|
||||||
|
barriers.push_back (CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
||||||
|
D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_COMMON));
|
||||||
|
cl->ResourceBarrier (barriers.size (), barriers.data ());
|
||||||
|
} else {
|
||||||
|
auto barrier = CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
||||||
|
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COMMON);
|
||||||
|
cl->ResourceBarrier (1, &barrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = cl->Close ();
|
||||||
if (!gst_d3d12_result (hr, self->device)) {
|
if (!gst_d3d12_result (hr, self->device)) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't close command list");
|
GST_ERROR_OBJECT (self, "Couldn't close command list");
|
||||||
gst_d3d12_fence_data_unref (fence_data);
|
gst_d3d12_fence_data_unref (fence_data);
|
||||||
|
@ -825,7 +917,6 @@ gst_d3d12_swapchain_sink_set_buffer (GstD3D12SwapChainSink * self,
|
||||||
if (priv->convert_format != format)
|
if (priv->convert_format != format)
|
||||||
gst_clear_object (&priv->conv);
|
gst_clear_object (&priv->conv);
|
||||||
|
|
||||||
|
|
||||||
priv->display_width = GST_VIDEO_SINK_WIDTH (self);
|
priv->display_width = GST_VIDEO_SINK_WIDTH (self);
|
||||||
priv->display_height = GST_VIDEO_SINK_HEIGHT (self);
|
priv->display_height = GST_VIDEO_SINK_HEIGHT (self);
|
||||||
priv->convert_format = format;
|
priv->convert_format = format;
|
||||||
|
@ -835,6 +926,10 @@ gst_d3d12_swapchain_sink_set_buffer (GstD3D12SwapChainSink * self,
|
||||||
gst_clear_buffer (&priv->cached_buf);
|
gst_clear_buffer (&priv->cached_buf);
|
||||||
|
|
||||||
if (!priv->conv) {
|
if (!priv->conv) {
|
||||||
|
DXGI_SAMPLE_DESC sample_desc = { };
|
||||||
|
gst_d3d12_calculate_sample_desc_for_msaa (self->device,
|
||||||
|
DXGI_FORMAT_R8G8B8A8_UNORM, priv->msaa_mode, &sample_desc);
|
||||||
|
|
||||||
gst_structure_set (priv->convert_config,
|
gst_structure_set (priv->convert_config,
|
||||||
GST_D3D12_CONVERTER_OPT_DEST_ALPHA_MODE,
|
GST_D3D12_CONVERTER_OPT_DEST_ALPHA_MODE,
|
||||||
GST_TYPE_D3D12_CONVERTER_ALPHA_MODE,
|
GST_TYPE_D3D12_CONVERTER_ALPHA_MODE,
|
||||||
|
@ -843,7 +938,11 @@ gst_d3d12_swapchain_sink_set_buffer (GstD3D12SwapChainSink * self,
|
||||||
GST_D3D12_CONVERTER_ALPHA_MODE_UNSPECIFIED,
|
GST_D3D12_CONVERTER_ALPHA_MODE_UNSPECIFIED,
|
||||||
GST_D3D12_CONVERTER_OPT_SAMPLER_FILTER,
|
GST_D3D12_CONVERTER_OPT_SAMPLER_FILTER,
|
||||||
GST_TYPE_D3D12_CONVERTER_SAMPLER_FILTER,
|
GST_TYPE_D3D12_CONVERTER_SAMPLER_FILTER,
|
||||||
gst_d3d12_sampling_method_to_native (priv->sampling_method), nullptr);
|
gst_d3d12_sampling_method_to_native (priv->sampling_method),
|
||||||
|
GST_D3D12_CONVERTER_OPT_PSO_SAMPLE_DESC_COUNT, G_TYPE_UINT,
|
||||||
|
sample_desc.Count,
|
||||||
|
GST_D3D12_CONVERTER_OPT_PSO_SAMPLE_DESC_QUALITY, G_TYPE_UINT,
|
||||||
|
sample_desc.Quality, nullptr);
|
||||||
|
|
||||||
priv->conv = gst_d3d12_converter_new (self->device, nullptr, &priv->info,
|
priv->conv = gst_d3d12_converter_new (self->device, nullptr, &priv->info,
|
||||||
&priv->display_info, nullptr, nullptr,
|
&priv->display_info, nullptr, nullptr,
|
||||||
|
@ -931,7 +1030,7 @@ gst_d3d12_swapchain_sink_resize (GstD3D12SwapChainSink * self, guint width,
|
||||||
|
|
||||||
if (priv->swapchain && priv->cached_buf &&
|
if (priv->swapchain && priv->cached_buf &&
|
||||||
gst_d3d12_swapchain_sink_render (self)) {
|
gst_d3d12_swapchain_sink_render (self)) {
|
||||||
GST_ERROR_OBJECT (self, "resize %ux%u", width, height);
|
GST_DEBUG_OBJECT (self, "resize %ux%u", width, height);
|
||||||
auto hr = priv->swapchain->Present (0, 0);
|
auto hr = priv->swapchain->Present (0, 0);
|
||||||
if (!gst_d3d12_result (hr, self->device))
|
if (!gst_d3d12_result (hr, self->device))
|
||||||
GST_ERROR_OBJECT (self, "Present failed");
|
GST_ERROR_OBJECT (self, "Present failed");
|
||||||
|
|
Loading…
Reference in a new issue