mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +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_SWAPCHAIN,
|
||||
PROP_SAMPLING_METHOD,
|
||||
PROP_MSAA,
|
||||
};
|
||||
|
||||
#define DEFAULT_ADAPTER -1
|
||||
|
@ -53,6 +54,7 @@ enum
|
|||
#define DEFAULT_HEIGHT 720
|
||||
#define DEFAULT_BORDER_COLOR (G_GUINT64_CONSTANT(0xffff000000000000))
|
||||
#define DEFAULT_SAMPLING_METHOD GST_D3D12_SAMPLING_METHOD_BILINEAR
|
||||
#define DEFAULT_MSAA GST_D3D12_MSAA_DISABLED
|
||||
|
||||
#define BACK_BUFFER_COUNT 2
|
||||
|
||||
|
@ -131,6 +133,7 @@ struct GstD3D12SwapChainSinkPrivate
|
|||
}
|
||||
gst_clear_caps (&caps);
|
||||
gst_clear_buffer (&cached_buf);
|
||||
gst_clear_buffer (&msaa_buf);
|
||||
gst_clear_object (&conv);
|
||||
backbuf.clear ();
|
||||
convert_format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
|
@ -165,6 +168,7 @@ struct GstD3D12SwapChainSinkPrivate
|
|||
GstD3D12CommandQueue *cq = nullptr;
|
||||
GstD3D12CommandAllocatorPool *ca_pool = nullptr;
|
||||
GstBuffer *cached_buf = nullptr;
|
||||
GstBuffer *msaa_buf = nullptr;
|
||||
GstCaps *caps = nullptr;
|
||||
GstD3D12Converter *conv = nullptr;
|
||||
GstD3D12OverlayCompositor *comp = nullptr;
|
||||
|
@ -182,6 +186,7 @@ struct GstD3D12SwapChainSinkPrivate
|
|||
guint height = DEFAULT_HEIGHT;
|
||||
guint64 border_color = DEFAULT_BORDER_COLOR;
|
||||
GstD3D12SamplingMethod sampling_method = DEFAULT_SAMPLING_METHOD;
|
||||
GstD3D12MSAAMode msaa_mode = DEFAULT_MSAA;
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
@ -276,6 +281,12 @@ gst_d3d12_swapchain_sink_class_init (GstD3D12SwapChainSinkClass * klass)
|
|||
DEFAULT_SAMPLING_METHOD,
|
||||
(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] =
|
||||
g_signal_new_class_handler ("resize", G_TYPE_FROM_CLASS (klass),
|
||||
(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,
|
||||
(GstPluginAPIFlags) 0);
|
||||
gst_type_mark_as_plugin_api (GST_TYPE_D3D12_MSAA_MODE, (GstPluginAPIFlags) 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -368,6 +380,15 @@ gst_d3d12_swapchain_sink_set_property (GObject * object, guint prop_id,
|
|||
}
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -511,6 +569,9 @@ gst_d3d12_swapchain_sink_get_property (GObject * object, guint prop_id,
|
|||
case PROP_SAMPLING_METHOD:
|
||||
g_value_set_enum (value, priv->sampling_method);
|
||||
break;
|
||||
case PROP_MSAA:
|
||||
g_value_set_enum (value, priv->msaa_mode);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -730,11 +791,22 @@ gst_d3d12_swapchain_sink_render (GstD3D12SwapChainSink * self)
|
|||
|
||||
auto mem = (GstD3D12Memory *) gst_buffer_peek_memory (backbuf, 0);
|
||||
auto backbuf_texture = gst_d3d12_memory_get_resource_handle (mem);
|
||||
D3D12_RESOURCE_BARRIER barrier =
|
||||
CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
cl->ResourceBarrier (1, &barrier);
|
||||
GstBuffer *conv_outbuf = backbuf;
|
||||
ID3D12Resource *msaa_resource = nullptr;
|
||||
|
||||
if (priv->msaa_buf) {
|
||||
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 ||
|
||||
(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,
|
||||
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_d3d12_fence_data_unref (fence_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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_d3d12_fence_data_unref (fence_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
barrier =
|
||||
CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COMMON);
|
||||
cl->ResourceBarrier (1, &barrier);
|
||||
hr = cl->Close ();
|
||||
if (msaa_resource) {
|
||||
std::vector < D3D12_RESOURCE_BARRIER > barriers;
|
||||
barriers.push_back (CD3DX12_RESOURCE_BARRIER::Transition (msaa_resource,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET,
|
||||
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)) {
|
||||
GST_ERROR_OBJECT (self, "Couldn't close command list");
|
||||
gst_d3d12_fence_data_unref (fence_data);
|
||||
|
@ -825,7 +917,6 @@ gst_d3d12_swapchain_sink_set_buffer (GstD3D12SwapChainSink * self,
|
|||
if (priv->convert_format != format)
|
||||
gst_clear_object (&priv->conv);
|
||||
|
||||
|
||||
priv->display_width = GST_VIDEO_SINK_WIDTH (self);
|
||||
priv->display_height = GST_VIDEO_SINK_HEIGHT (self);
|
||||
priv->convert_format = format;
|
||||
|
@ -835,6 +926,10 @@ gst_d3d12_swapchain_sink_set_buffer (GstD3D12SwapChainSink * self,
|
|||
gst_clear_buffer (&priv->cached_buf);
|
||||
|
||||
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_D3D12_CONVERTER_OPT_DEST_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_OPT_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->display_info, nullptr, nullptr,
|
||||
|
@ -931,7 +1030,7 @@ gst_d3d12_swapchain_sink_resize (GstD3D12SwapChainSink * self, guint width,
|
|||
|
||||
if (priv->swapchain && priv->cached_buf &&
|
||||
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);
|
||||
if (!gst_d3d12_result (hr, self->device))
|
||||
GST_ERROR_OBJECT (self, "Present failed");
|
||||
|
|
Loading…
Reference in a new issue