mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-22 07:08:23 +00:00
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:
parent
de331217aa
commit
72237d2563
8 changed files with 286 additions and 43 deletions
|
@ -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;
|
||||
|
|
|
@ -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,7 +570,8 @@ 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];
|
||||
rtv_desc.Texture2D.PlaneSlice = i;
|
||||
if (priv->desc.SampleDesc.Count == 1)
|
||||
rtv_desc.Texture2D.PlaneSlice = i;
|
||||
device->CreateRenderTargetView (priv->resource.Get (), &rtv_desc,
|
||||
cpu_handle);
|
||||
cpu_handle.Offset (priv->rtv_inc_size);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 (backbuf_texture,
|
||||
D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||
cl->ResourceBarrier (1, &barrier);
|
||||
}
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier =
|
||||
CD3DX12_RESOURCE_BARRIER::Transition (resource,
|
||||
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,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COMMON);
|
||||
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->ResourceBarrier (1, &barrier);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue