d3d12videosink: Add support for MSAA

Adding "msaa" property to support MSAA rendering

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5891>
This commit is contained in:
Seungha Yang 2024-01-05 20:40:33 +09:00 committed by GStreamer Marge Bot
parent de331217aa
commit 72237d2563
8 changed files with 286 additions and 43 deletions

View file

@ -203,7 +203,8 @@ enum
/* *INDENT-OFF* */
struct QuadData
{
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc;
D3D12_INPUT_ELEMENT_DESC input_desc[2];
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { };
ComPtr<ID3D12PipelineState> pso;
guint num_rtv;
};
@ -235,6 +236,9 @@ struct _GstD3D12ConverterPrivate
blend_desc = CD3DX12_BLEND_DESC (D3D12_DEFAULT);
for (guint i = 0; i < 4; i++)
blend_factor[i] = 1.0f;
sample_desc.Count = 1;
sample_desc.Quality = 0;
}
~_GstD3D12ConverterPrivate ()
@ -260,6 +264,7 @@ struct _GstD3D12ConverterPrivate
D3D12_BLEND_DESC blend_desc;
FLOAT blend_factor[4];
DXGI_SAMPLE_DESC sample_desc;
gboolean update_pso = FALSE;
GstVideoInfo fallback_pool_info;
@ -673,7 +678,10 @@ gst_d3d12_converter_setup_resource (GstD3D12Converter * self,
priv->quad_data.resize (psblob_list.size ());
for (size_t i = 0; i < psblob_list.size (); i++) {
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = { };
priv->quad_data[i].input_desc[0] = input_desc[0];
priv->quad_data[i].input_desc[1] = input_desc[1];
auto & pso_desc = priv->quad_data[i].desc;
pso_desc.pRootSignature = priv->rs.Get ();
pso_desc.VS = vs_blob;
pso_desc.PS = psblob_list[i].bytecode;
@ -683,8 +691,8 @@ gst_d3d12_converter_setup_resource (GstD3D12Converter * self,
pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
pso_desc.DepthStencilState.DepthEnable = FALSE;
pso_desc.DepthStencilState.StencilEnable = FALSE;
pso_desc.InputLayout.pInputElementDescs = input_desc;
pso_desc.InputLayout.NumElements = G_N_ELEMENTS (input_desc);
pso_desc.InputLayout.pInputElementDescs = priv->quad_data[i].input_desc;
pso_desc.InputLayout.NumElements = 2;
pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
pso_desc.NumRenderTargets = psblob_list[i].num_rtv;
for (UINT j = 0; j < pso_desc.NumRenderTargets; j++) {
@ -700,7 +708,6 @@ gst_d3d12_converter_setup_resource (GstD3D12Converter * self,
return FALSE;
}
priv->quad_data[i].desc = pso_desc;
priv->quad_data[i].pso = pso;
priv->quad_data[i].num_rtv = psblob_list[i].num_rtv;
}
@ -1781,6 +1788,7 @@ gst_d3d12_converter_update_pso (GstD3D12Converter * self)
for (size_t i = 0; i < quad_data.size (); i++) {
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = priv->quad_data[i].desc;
pso_desc.BlendState = priv->blend_desc;
pso_desc.SampleDesc = priv->sample_desc;
ComPtr < ID3D12PipelineState > pso;
auto hr =
@ -1829,6 +1837,16 @@ gst_d3d12_converter_execute (GstD3D12Converter * self,
priv->update_src_rect = TRUE;
}
mem = (GstD3D12Memory *) gst_buffer_peek_memory (out_buf, 0);
resource = gst_d3d12_memory_get_resource_handle (mem);
desc = resource->GetDesc ();
if (desc.SampleDesc.Count != priv->sample_desc.Count ||
desc.SampleDesc.Quality != priv->sample_desc.Quality) {
GST_DEBUG_OBJECT (self, "Sample desc updated");
priv->sample_desc = desc.SampleDesc;
priv->update_pso = TRUE;
}
if (!gst_d3d12_converter_update_dest_rect (self)) {
GST_ERROR_OBJECT (self, "Failed to update dest rect");
return FALSE;

View file

@ -561,6 +561,8 @@ gst_d3d12_memory_get_render_target_view_heap (GstD3D12Memory * mem,
D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = { };
rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
if (priv->desc.SampleDesc.Count > 1)
rtv_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
auto cpu_handle =
CD3DX12_CPU_DESCRIPTOR_HANDLE
@ -568,6 +570,7 @@ gst_d3d12_memory_get_render_target_view_heap (GstD3D12Memory * mem,
for (guint i = 0; i < priv->num_subresources; i++) {
rtv_desc.Format = priv->resource_formats[i];
if (priv->desc.SampleDesc.Count == 1)
rtv_desc.Texture2D.PlaneSlice = i;
device->CreateRenderTargetView (priv->resource.Get (), &rtv_desc,
cpu_handle);

View file

@ -75,6 +75,12 @@ GST_DEFINE_MINI_OBJECT_TYPE (GstD3D12OverlayRect, gst_d3d12_overlay_rect);
struct GstD3D12OverlayCompositorPrivate
{
GstD3D12OverlayCompositorPrivate ()
{
sample_desc.Count = 1;
sample_desc.Quality = 0;
}
~GstD3D12OverlayCompositorPrivate ()
{
if (overlays)
@ -89,6 +95,11 @@ struct GstD3D12OverlayCompositorPrivate
D3D12_VIEWPORT viewport;
D3D12_RECT scissor_rect;
D3D12_INPUT_ELEMENT_DESC input_desc[2];
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = { };
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_premul_desc = { };
DXGI_SAMPLE_DESC sample_desc;
ComPtr<ID3D12RootSignature> rs;
ComPtr<ID3D12PipelineState> pso;
ComPtr<ID3D12PipelineState> pso_premul;
@ -424,24 +435,25 @@ gst_d3d12_overlay_compositor_setup_shader (GstD3D12OverlayCompositor * self)
device->CreateRootSignature (0, rs_blob->GetBufferPointer (),
rs_blob->GetBufferSize (), IID_PPV_ARGS (&rs));
D3D12_INPUT_ELEMENT_DESC input_desc[2];
input_desc[0].SemanticName = "POSITION";
input_desc[0].SemanticIndex = 0;
input_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
input_desc[0].InputSlot = 0;
input_desc[0].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT;
input_desc[0].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
input_desc[0].InstanceDataStepRate = 0;
priv->input_desc[0].SemanticName = "POSITION";
priv->input_desc[0].SemanticIndex = 0;
priv->input_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
priv->input_desc[0].InputSlot = 0;
priv->input_desc[0].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT;
priv->input_desc[0].InputSlotClass =
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
priv->input_desc[0].InstanceDataStepRate = 0;
input_desc[1].SemanticName = "TEXCOORD";
input_desc[1].SemanticIndex = 0;
input_desc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
input_desc[1].InputSlot = 0;
input_desc[1].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT;
input_desc[1].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
input_desc[1].InstanceDataStepRate = 0;
priv->input_desc[1].SemanticName = "TEXCOORD";
priv->input_desc[1].SemanticIndex = 0;
priv->input_desc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
priv->input_desc[1].InputSlot = 0;
priv->input_desc[1].AlignedByteOffset = D3D12_APPEND_ALIGNED_ELEMENT;
priv->input_desc[1].InputSlotClass =
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
priv->input_desc[1].InstanceDataStepRate = 0;
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = { };
auto & pso_desc = priv->pso_desc;
pso_desc.pRootSignature = rs.Get ();
pso_desc.VS.BytecodeLength = sizeof (g_VSMain_coord);
pso_desc.VS.pShaderBytecode = g_VSMain_coord;
@ -465,8 +477,8 @@ gst_d3d12_overlay_compositor_setup_shader (GstD3D12OverlayCompositor * self)
pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
pso_desc.DepthStencilState.DepthEnable = FALSE;
pso_desc.DepthStencilState.StencilEnable = FALSE;
pso_desc.InputLayout.pInputElementDescs = input_desc;
pso_desc.InputLayout.NumElements = G_N_ELEMENTS (input_desc);
pso_desc.InputLayout.pInputElementDescs = priv->input_desc;
pso_desc.InputLayout.NumElements = 2;
pso_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
pso_desc.NumRenderTargets = 1;
pso_desc.RTVFormats[0] = device_format.resource_format[0];
@ -480,9 +492,11 @@ gst_d3d12_overlay_compositor_setup_shader (GstD3D12OverlayCompositor * self)
}
ComPtr < ID3D12PipelineState > pso_premul;
pso_desc.PS.BytecodeLength = sizeof (g_PSMain_sample_premul);
pso_desc.PS.pShaderBytecode = g_PSMain_sample_premul;
hr = device->CreateGraphicsPipelineState (&pso_desc,
auto & pso_premul_desc = priv->pso_premul_desc;
pso_premul_desc = priv->pso_desc;
pso_premul_desc.PS.BytecodeLength = sizeof (g_PSMain_sample_premul);
pso_premul_desc.PS.pShaderBytecode = g_PSMain_sample_premul;
hr = device->CreateGraphicsPipelineState (&pso_premul_desc,
IID_PPV_ARGS (&pso_premul));
if (!gst_d3d12_result (hr, self->device)) {
GST_ERROR_OBJECT (self, "Couldn't create pso");
@ -678,6 +692,13 @@ gst_d3d12_overlay_compositor_update_viewport (GstD3D12OverlayCompositor *
return TRUE;
}
static void
pso_free_func (ID3D12PipelineState * pso)
{
if (pso)
pso->Release ();
}
static gboolean
gst_d3d12_overlay_compositor_execute (GstD3D12OverlayCompositor * self,
GstBuffer * buf, GstD3D12FenceData * fence_data,
@ -750,6 +771,14 @@ gst_d3d12_overlay_compositor_execute (GstD3D12OverlayCompositor * self,
prev_pso = pso;
}
priv->pso->AddRef ();
gst_d3d12_fence_data_add_notify (fence_data, priv->pso.Get (),
(GDestroyNotify) pso_free_func);
priv->pso_premul->AddRef ();
gst_d3d12_fence_data_add_notify (fence_data, priv->pso_premul.Get (),
(GDestroyNotify) pso_free_func);
return TRUE;
}
@ -768,6 +797,41 @@ gst_d3d12_overlay_compositor_draw (GstD3D12OverlayCompositor * compositor,
if (!priv->overlays)
return TRUE;
auto mem = (GstD3D12Memory *) gst_buffer_peek_memory (buf, 0);
auto resource = gst_d3d12_memory_get_resource_handle (mem);
auto desc = resource->GetDesc ();
if (desc.SampleDesc.Count != priv->sample_desc.Count ||
desc.SampleDesc.Quality != priv->sample_desc.Quality) {
auto device = gst_d3d12_device_get_device_handle (compositor->device);
auto pso_desc = priv->pso_desc;
pso_desc.SampleDesc = desc.SampleDesc;
ComPtr < ID3D12PipelineState > pso;
auto hr = device->CreateGraphicsPipelineState (&pso_desc,
IID_PPV_ARGS (&pso));
if (!gst_d3d12_result (hr, compositor->device)) {
GST_ERROR_OBJECT (compositor, "Couldn't create pso");
return FALSE;
}
ComPtr < ID3D12PipelineState > pso_premul;
auto pso_premul_desc = priv->pso_premul_desc;
pso_premul_desc.SampleDesc = desc.SampleDesc;
hr = device->CreateGraphicsPipelineState (&pso_premul_desc,
IID_PPV_ARGS (&pso_premul));
if (!gst_d3d12_result (hr, compositor->device)) {
GST_ERROR_OBJECT (compositor, "Couldn't create pso");
return FALSE;
}
priv->pso = nullptr;
priv->pso_premul = nullptr;
priv->pso = pso;
priv->pso_premul = pso_premul;
priv->sample_desc = desc.SampleDesc;
}
return gst_d3d12_overlay_compositor_execute (compositor,
buf, fence_data, command_list);
}

View file

@ -70,6 +70,25 @@ gst_d3d12_sampling_method_to_native (GstD3D12SamplingMethod method)
return D3D12_FILTER_MIN_MAG_MIP_POINT;
}
GType
gst_d3d12_msaa_mode_get_type (void)
{
static GType type = 0;
static const GEnumValue msaa_mode[] = {
{GST_D3D12_MSAA_DISABLED, "Disabled", "disabled"},
{GST_D3D12_MSAA_2X, "2x MSAA", "2x"},
{GST_D3D12_MSAA_4X, "4x MSAA", "4x"},
{GST_D3D12_MSAA_8X, "8x MSAA", "8x"},
{0, nullptr, nullptr},
};
GST_D3D12_CALL_ONCE_BEGIN {
type = g_enum_register_static ("GstD3D12MSAAMode", msaa_mode);
} GST_D3D12_CALL_ONCE_END;
return type;
}
void
gst_d3d12_buffer_after_write (GstBuffer * buffer, guint64 fence_value)
{

View file

@ -25,19 +25,30 @@
G_BEGIN_DECLS
typedef enum
enum GstD3D12SamplingMethod
{
GST_D3D12_SAMPLING_METHOD_NEAREST,
GST_D3D12_SAMPLING_METHOD_BILINEAR,
GST_D3D12_SAMPLING_METHOD_LINEAR_MINIFICATION,
GST_D3D12_SAMPLING_METHOD_ANISOTROPIC,
} GstD3D12SamplingMethod;
};
#define GST_TYPE_D3D12_SAMPLING_METHOD (gst_d3d12_sampling_method_get_type())
GType gst_d3d12_sampling_method_get_type (void);
D3D12_FILTER gst_d3d12_sampling_method_to_native (GstD3D12SamplingMethod method);
enum GstD3D12MSAAMode
{
GST_D3D12_MSAA_DISABLED,
GST_D3D12_MSAA_2X,
GST_D3D12_MSAA_4X,
GST_D3D12_MSAA_8X,
};
#define GST_TYPE_D3D12_MSAA_MODE (gst_d3d12_msaa_mode_get_type())
GType gst_d3d12_msaa_mode_get_type (void);
void gst_d3d12_buffer_after_write (GstBuffer * buffer,
guint64 fence_value);

View file

@ -37,6 +37,7 @@ enum
PROP_ROTATE_METHOD,
PROP_FULLSCREEN_ON_ALT_ENTER,
PROP_FULLSCREEN,
PROP_MSAA,
};
#define DEFAULT_ADAPTER -1
@ -45,6 +46,7 @@ enum
#define DEFAULT_ROTATE_METHOD GST_VIDEO_ORIENTATION_IDENTITY
#define DEFAULT_FULLSCREEN_ON_ALT_ENTER FALSE
#define DEFAULT_FULLSCREEN FALSE
#define DEFAULT_MSAA GST_D3D12_MSAA_DISABLED
static GstStaticPadTemplate sink_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
@ -102,6 +104,7 @@ struct GstD3D12VideoSinkPrivate
GstVideoOrientationMethod orientation_selected = DEFAULT_ROTATE_METHOD;
gboolean fullscreen_on_alt_enter = DEFAULT_FULLSCREEN_ON_ALT_ENTER;
gboolean fullscreen = DEFAULT_FULLSCREEN;
GstD3D12MSAAMode msaa = DEFAULT_MSAA;
};
/* *INDENT-ON* */
@ -214,6 +217,12 @@ gst_d3d12_video_sink_class_init (GstD3D12VideoSinkClass * klass)
"Fullscreen mode", DEFAULT_FULLSCREEN,
(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)));
element_class->set_context =
GST_DEBUG_FUNCPTR (gst_d3d12_video_sink_set_context);
@ -237,6 +246,8 @@ gst_d3d12_video_sink_class_init (GstD3D12VideoSinkClass * klass)
videosink_class->set_info = GST_DEBUG_FUNCPTR (gst_d3d12_video_sink_set_info);
videosink_class->show_frame =
GST_DEBUG_FUNCPTR (gst_d3d12_video_sink_show_frame);
gst_type_mark_as_plugin_api (GST_TYPE_D3D12_MSAA_MODE, (GstPluginAPIFlags) 0);
}
static void
@ -299,6 +310,10 @@ gst_d3d12_videosink_set_property (GObject * object, guint prop_id,
priv->fullscreen = g_value_get_boolean (value);
gst_d3d12_window_set_fullscreen (priv->window, priv->fullscreen);
break;
case PROP_MSAA:
priv->msaa = (GstD3D12MSAAMode) g_value_get_enum (value);
gst_d3d12_window_set_msaa (priv->window, priv->msaa);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -332,6 +347,9 @@ gst_d3d12_videosink_get_property (GObject * object, guint prop_id,
case PROP_FULLSCREEN:
g_value_set_boolean (value, priv->fullscreen);
break;
case PROP_MSAA:
g_value_set_enum (value, priv->msaa);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View file

@ -23,7 +23,6 @@
#include "gstd3d12window.h"
#include "gstd3d12overlaycompositor.h"
#include "gstd3d12pluginutils.h"
#include <directx/d3dx12.h>
#include <mutex>
#include <condition_variable>
@ -118,6 +117,7 @@ struct DeviceContext
gst_clear_buffer (&cached_buf);
gst_clear_object (&conv);
gst_clear_object (&comp);
gst_clear_buffer (&msaa_buf);
gst_clear_object (&device);
}
@ -131,6 +131,7 @@ struct DeviceContext
ComPtr<ID3D12GraphicsCommandList> cl;
ComPtr<IDXGISwapChain4> swapchain;
GstBuffer *msaa_buf = nullptr;
std::vector<std::shared_ptr<SwapBuffer>> swap_buffers;
D3D12_RESOURCE_DESC buffer_desc;
GstD3D12Converter *conv = nullptr;
@ -202,6 +203,8 @@ struct GstD3D12WindowPrivate
std::wstring title;
gboolean update_title = FALSE;
GstD3D12MSAAMode msaa = GST_D3D12_MSAA_DISABLED;
/* Win32 window handles */
std::mutex hwnd_lock;
std::condition_variable hwnd_cond;
@ -693,7 +696,7 @@ gst_d3d12_window_create_hwnd (GstD3D12Window * self)
int h = 0;
DWORD style = WS_GST_D3D12;
std::wstring title = L"Direct3D12 renderer";
std::wstring title = L"Direct3D12 Renderer";
if (!priv->title.empty ())
title = priv->title;
@ -1072,6 +1075,7 @@ gst_d3d12_window_on_resize (GstD3D12Window * self)
if (priv->ctx->fence_val != 0)
priv->ctx->WaitGpu ();
priv->ctx->swap_buffers.clear ();
gst_clear_buffer (&priv->ctx->msaa_buf);
DXGI_SWAP_CHAIN_DESC desc = { };
priv->ctx->swapchain->GetDesc (&desc);
@ -1100,6 +1104,67 @@ gst_d3d12_window_on_resize (GstD3D12Window * self)
priv->ctx->swap_buffers.push_back (std::make_shared < SwapBuffer > (buf));
}
guint sample_count = 1;
switch (priv->msaa) {
case GST_D3D12_MSAA_2X:
sample_count = 2;
break;
case GST_D3D12_MSAA_4X:
sample_count = 4;
break;
case GST_D3D12_MSAA_8X:
sample_count = 8;
break;
default:
break;
}
auto device = gst_d3d12_device_get_device_handle (self->device);
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS feature_data = { };
feature_data.Format = priv->ctx->buffer_desc.Format;
feature_data.SampleCount = sample_count;
while (feature_data.SampleCount > 1) {
hr = device->CheckFeatureSupport (D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&feature_data, sizeof (feature_data));
if (SUCCEEDED (hr) && feature_data.NumQualityLevels > 0)
break;
feature_data.SampleCount /= 2;
}
if (feature_data.SampleCount > 1 && feature_data.NumQualityLevels > 0) {
GST_DEBUG_OBJECT (self, "Enable MSAA x%d with quality level %d",
feature_data.SampleCount, feature_data.NumQualityLevels - 1);
D3D12_HEAP_PROPERTIES heap_prop =
CD3DX12_HEAP_PROPERTIES (D3D12_HEAP_TYPE_DEFAULT);
D3D12_RESOURCE_DESC resource_desc =
CD3DX12_RESOURCE_DESC::Tex2D (priv->ctx->buffer_desc.Format,
priv->ctx->buffer_desc.Width, priv->ctx->buffer_desc.Height,
1, 1, feature_data.SampleCount, feature_data.NumQualityLevels - 1,
D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
D3D12_CLEAR_VALUE clear_value = { };
clear_value.Format = priv->ctx->buffer_desc.Format;
clear_value.Color[0] = 0.0f;
clear_value.Color[1] = 0.0f;
clear_value.Color[2] = 0.0f;
clear_value.Color[3] = 1.0f;
ComPtr < ID3D12Resource > msaa_texture;
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)) {
GST_ERROR_OBJECT (self, "Couldn't create MSAA texture");
return GST_FLOW_ERROR;
}
auto mem = gst_d3d12_allocator_alloc_wrapped (nullptr, self->device,
msaa_texture.Get (), 0);
priv->ctx->msaa_buf = gst_buffer_new ();
gst_buffer_append_memory (priv->ctx->msaa_buf, mem);
}
priv->first_present = TRUE;
priv->backbuf_rendered = FALSE;
@ -1396,32 +1461,62 @@ gst_d3d12_window_set_buffer (GstD3D12Window * window, GstBuffer * buffer)
(GDestroyNotify) gst_d3d12_command_allocator_unref);
auto mem = (GstD3D12Memory *) gst_buffer_peek_memory (swapbuf->backbuf, 0);
auto resource = gst_d3d12_memory_get_resource_handle (mem);
auto backbuf_texture = gst_d3d12_memory_get_resource_handle (mem);
ID3D12Resource *msaa_resource = nullptr;
GstBuffer *conv_outbuf = swapbuf->backbuf;
if (priv->ctx->msaa_buf) {
conv_outbuf = priv->ctx->msaa_buf;
mem = (GstD3D12Memory *) gst_buffer_peek_memory (priv->ctx->msaa_buf, 0);
msaa_resource = gst_d3d12_memory_get_resource_handle (mem);
/* MSAA resource must be render target state here already */
} else {
D3D12_RESOURCE_BARRIER barrier =
CD3DX12_RESOURCE_BARRIER::Transition (resource,
CD3DX12_RESOURCE_BARRIER::Transition (backbuf_texture,
D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_RENDER_TARGET);
cl->ResourceBarrier (1, &barrier);
}
if (!gst_d3d12_converter_convert_buffer (priv->ctx->conv,
priv->ctx->cached_buf, swapbuf->backbuf, fence_data, cl.Get ())) {
priv->ctx->cached_buf, conv_outbuf, fence_data, cl.Get ())) {
GST_ERROR_OBJECT (window, "Couldn't build convert command");
gst_d3d12_fence_data_unref (fence_data);
return GST_FLOW_ERROR;
}
if (!gst_d3d12_overlay_compositor_draw (priv->ctx->comp,
swapbuf->backbuf, fence_data, cl.Get ())) {
conv_outbuf, fence_data, cl.Get ())) {
GST_ERROR_OBJECT (window, "Couldn't build overlay command");
gst_d3d12_fence_data_unref (fence_data);
return GST_FLOW_ERROR;
}
barrier = CD3DX12_RESOURCE_BARRIER::Transition (resource,
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,
priv->display_format);
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 {
D3D12_RESOURCE_BARRIER 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, priv->ctx->device)) {
@ -1619,3 +1714,14 @@ gst_d3d12_window_set_fullscreen (GstD3D12Window * window, gboolean enable)
if (priv->hwnd && priv->applied_fullscreen != priv->requested_fullscreen)
PostMessageW (priv->hwnd, WM_GST_D3D12_FULLSCREEN, 0, 0);
}
void
gst_d3d12_window_set_msaa (GstD3D12Window * window, GstD3D12MSAAMode msaa)
{
auto priv = window->priv;
std::lock_guard < std::recursive_mutex > lk (priv->lock);
if (priv->msaa != msaa) {
priv->msaa = msaa;
gst_d3d12_window_on_resize (window);
}
}

View file

@ -22,6 +22,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include "gstd3d12.h"
#include "gstd3d12pluginutils.h"
G_BEGIN_DECLS
@ -83,5 +84,8 @@ void gst_d3d12_window_enable_fullscreen_on_alt_enter (GstD3D12Window
void gst_d3d12_window_set_fullscreen (GstD3D12Window * window,
gboolean enable);
void gst_d3d12_window_set_msaa (GstD3D12Window * window,
GstD3D12MSAAMode msaa);
G_END_DECLS