d3d12converter: Add support for blending

Create new PSO if blend state update is required

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5875>
This commit is contained in:
Seungha Yang 2023-12-30 23:40:39 +09:00 committed by GStreamer Marge Bot
parent 7c701058ed
commit f4fe17d8d2
5 changed files with 116 additions and 7 deletions

View file

@ -1833,7 +1833,7 @@ gst_d3d12_convert_set_info (GstD3D12BaseFilter * filter,
auto ctx = std::make_unique < ConvertContext > (filter->device);
ctx->conv = gst_d3d12_converter_new (filter->device, in_info,
out_info, config);
out_info, nullptr, nullptr, config);
if (!ctx->conv) {
GST_ERROR_OBJECT (self, "Couldn't create converter");
return FALSE;

View file

@ -203,6 +203,7 @@ enum
/* *INDENT-OFF* */
struct QuadData
{
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc;
ComPtr<ID3D12PipelineState> pso;
guint num_rtv;
};
@ -231,6 +232,9 @@ struct _GstD3D12ConverterPrivate
{
transform = g_matrix_identity;
custom_transform = g_matrix_identity;
blend_desc = CD3DX12_BLEND_DESC (D3D12_DEFAULT);
for (guint i = 0; i < 4; i++)
blend_factor[i] = 1.0f;
}
~_GstD3D12ConverterPrivate ()
@ -251,6 +255,8 @@ struct _GstD3D12ConverterPrivate
D3D12_RECT scissor_rect[GST_VIDEO_MAX_PLANES];
D3D12_BLEND_DESC blend_desc;
FLOAT blend_factor[4];
gboolean update_pso = FALSE;
ConverterRootSignaturePtr crs;
ComPtr<ID3D12RootSignature> rs;
@ -663,7 +669,7 @@ gst_d3d12_converter_setup_resource (GstD3D12Converter * self,
pso_desc.pRootSignature = priv->rs.Get ();
pso_desc.VS = vs_blob;
pso_desc.PS = psblob_list[i].bytecode;
pso_desc.BlendState = CD3DX12_BLEND_DESC (D3D12_DEFAULT);
pso_desc.BlendState = priv->blend_desc;
pso_desc.SampleMask = UINT_MAX;
pso_desc.RasterizerState = CD3DX12_RASTERIZER_DESC (D3D12_DEFAULT);
pso_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
@ -686,6 +692,7 @@ 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;
}
@ -1532,7 +1539,8 @@ gst_d3d12_converter_calculate_border_color (GstD3D12Converter * self)
GstD3D12Converter *
gst_d3d12_converter_new (GstD3D12Device * device, const GstVideoInfo * in_info,
const GstVideoInfo * out_info, GstStructure * config)
const GstVideoInfo * out_info, const D3D12_BLEND_DESC * blend_desc,
const gfloat blend_factor[4], GstStructure * config)
{
GstD3D12Converter *self;
GstD3D12Format in_d3d12_format;
@ -1551,6 +1559,14 @@ gst_d3d12_converter_new (GstD3D12Device * device, const GstVideoInfo * in_info,
gst_object_ref_sink (self);
auto priv = self->priv;
if (blend_desc)
priv->blend_desc = *blend_desc;
if (blend_factor) {
for (guint i = 0; i < 4; i++)
priv->blend_factor[i] = blend_factor[i];
}
if (config) {
gint value;
if (gst_structure_get_enum (config, GST_D3D12_CONVERTER_OPT_GAMMA_MODE,
@ -1706,6 +1722,48 @@ gst_d3d12_converter_new (GstD3D12Device * device, const GstVideoInfo * in_info,
return self;
}
static gboolean
gst_d3d12_converter_update_pso (GstD3D12Converter * self)
{
auto priv = self->priv;
if (!priv->update_pso)
return TRUE;
std::vector < QuadData > quad_data;
quad_data.resize (priv->quad_data.size ());
auto device = gst_d3d12_device_get_device_handle (self->device);
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;
ComPtr < ID3D12PipelineState > pso;
auto hr =
device->CreateGraphicsPipelineState (&pso_desc, IID_PPV_ARGS (&pso));
if (!gst_d3d12_result (hr, self->device)) {
GST_ERROR_OBJECT (self, "Couldn't create pso");
return FALSE;
}
quad_data[i].desc = pso_desc;
quad_data[i].pso = pso;
quad_data[i].num_rtv = priv->quad_data[i].num_rtv;
}
priv->update_pso = FALSE;
priv->quad_data = quad_data;
return TRUE;
}
static void
pso_free_func (ID3D12PipelineState * pso)
{
if (pso)
pso->Release ();
}
static gboolean
gst_d3d12_converter_execute (GstD3D12Converter * self,
GstBuffer * in_buf, GstBuffer * out_buf, GstD3D12FenceData * fence_data,
@ -1764,6 +1822,11 @@ gst_d3d12_converter_execute (GstD3D12Converter * self,
return FALSE;
}
if (!gst_d3d12_converter_update_pso (self)) {
GST_ERROR_OBJECT (self, "Failed to update pso");
return FALSE;
}
auto & barriers = priv->barriers;
auto & rtv_handles = priv->rtv_handles;
@ -1913,8 +1976,10 @@ gst_d3d12_converter_execute (GstD3D12Converter * self,
}
}
auto pso = priv->quad_data[0].pso.Get ();
cl->SetGraphicsRootSignature (priv->rs.Get ());
cl->SetPipelineState (priv->quad_data[0].pso.Get ());
cl->SetPipelineState (pso);
ID3D12DescriptorHeap *heaps[] = { srv_heap.Get () };
cl->SetDescriptorHeaps (1, heaps);
@ -1934,17 +1999,28 @@ gst_d3d12_converter_execute (GstD3D12Converter * self,
cl->RSSetScissorRects (priv->quad_data[0].num_rtv, priv->scissor_rect);
cl->OMSetRenderTargets (priv->quad_data[0].num_rtv,
rtv_handles.data (), FALSE, nullptr);
cl->OMSetBlendFactor (priv->blend_factor);
cl->DrawIndexedInstanced (6, 1, 0, 0, 0);
pso->AddRef ();
gst_d3d12_fence_data_add_notify (fence_data, pso,
(GDestroyNotify) pso_free_func);
auto offset = priv->quad_data[0].num_rtv;
if (priv->quad_data.size () == 2) {
cl->SetPipelineState (priv->quad_data[1].pso.Get ());
pso = priv->quad_data[1].pso.Get ();
cl->SetPipelineState (pso);
cl->RSSetViewports (priv->quad_data[1].num_rtv, &priv->viewport[offset]);
cl->RSSetScissorRects (priv->quad_data[1].num_rtv,
&priv->scissor_rect[offset]);
cl->OMSetRenderTargets (priv->quad_data[1].num_rtv,
rtv_handles.data () + offset, FALSE, nullptr);
cl->DrawIndexedInstanced (6, 1, 0, 0, 0);
pso->AddRef ();
gst_d3d12_fence_data_add_notify (fence_data, pso,
(GDestroyNotify) pso_free_func);
}
gst_d3d12_fence_data_add_notify (fence_data,
@ -2028,3 +2104,30 @@ gst_d3d12_converter_convert_buffer (GstD3D12Converter * converter,
return ret;
}
gboolean
gst_d3d12_converter_update_blend_state (GstD3D12Converter * converter,
const D3D12_BLEND_DESC * blend_desc, const gfloat blend_factor[4])
{
g_return_val_if_fail (GST_IS_D3D12_CONVERTER (converter), FALSE);
auto priv = converter->priv;
std::lock_guard < std::mutex > lk (priv->prop_lock);
D3D12_BLEND_DESC new_blend = CD3DX12_BLEND_DESC (D3D12_DEFAULT);
if (blend_desc)
new_blend = *blend_desc;
if (memcmp (&priv->blend_desc, &new_blend, sizeof (D3D12_BLEND_DESC)) != 0)
priv->update_pso = TRUE;
if (blend_factor) {
for (guint i = 0; i < 4; i++)
priv->blend_factor[i] = blend_factor[i];
} else {
for (guint i = 0; i < 4; i++)
priv->blend_factor[i] = 1.0f;
}
return TRUE;
}

View file

@ -136,6 +136,8 @@ GType gst_d3d12_converter_get_type (void);
GstD3D12Converter * gst_d3d12_converter_new (GstD3D12Device * device,
const GstVideoInfo * in_info,
const GstVideoInfo * out_info,
const D3D12_BLEND_DESC * blend_desc,
const gfloat blend_factor[4],
GstStructure * config);
gboolean gst_d3d12_converter_convert_buffer (GstD3D12Converter * converter,
@ -144,4 +146,8 @@ gboolean gst_d3d12_converter_convert_buffer (GstD3D12Converter * conv
GstD3D12FenceData * fence_data,
ID3D12GraphicsCommandList * command_list);
gboolean gst_d3d12_converter_update_blend_state (GstD3D12Converter * converter,
const D3D12_BLEND_DESC * blend_desc,
const gfloat blend_factor[4]);
G_END_DECLS

View file

@ -1523,7 +1523,7 @@ gst_d3d12_test_src_setup_context (GstD3D12TestSrc * self, GstCaps * caps)
gst_video_info_set_format (&draw_info, GST_VIDEO_FORMAT_BGRA,
priv->info.width, priv->info.height);
ctx->conv = gst_d3d12_converter_new (self->device,
&draw_info, &priv->info, config);
&draw_info, &priv->info, nullptr, nullptr, config);
if (!ctx->conv) {
GST_ERROR_OBJECT (self, "Failed to create converter");

View file

@ -1074,7 +1074,7 @@ gst_d3d12_window_prepare (GstD3D12Window * window, GstD3D12Device * device,
}
priv->ctx->conv = gst_d3d12_converter_new (window->device,
&priv->input_info, &priv->display_info, config);
&priv->input_info, &priv->display_info, nullptr, nullptr, config);
if (!priv->ctx->conv) {
GST_ERROR_OBJECT (window, "Couldn't create converter");
priv->ctx = nullptr;