vkd3d: Introduce struct d3d12_pipeline_state_desc for graphics pipelines.

A generic container for both compute and graphics pipeline descriptions
to facilitate reading the description from a stream.
This commit is contained in:
Conor McCarthy 2023-11-14 12:49:17 +10:00 committed by Alexandre Julliard
parent 529c0f46b0
commit 39afbb8e32
Notes: Alexandre Julliard 2023-11-15 22:58:50 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/461
2 changed files with 105 additions and 50 deletions

View File

@ -1736,6 +1736,33 @@ void vkd3d_render_pass_cache_cleanup(struct vkd3d_render_pass_cache *cache,
cache->render_passes = NULL;
}
static void pipeline_state_desc_from_d3d12_graphics_desc(struct d3d12_pipeline_state_desc *desc,
const D3D12_GRAPHICS_PIPELINE_STATE_DESC *d3d12_desc)
{
memset(desc, 0, sizeof(*desc));
desc->root_signature = d3d12_desc->pRootSignature;
desc->vs = d3d12_desc->VS;
desc->ps = d3d12_desc->PS;
desc->ds = d3d12_desc->DS;
desc->hs = d3d12_desc->HS;
desc->gs = d3d12_desc->GS;
desc->stream_output = d3d12_desc->StreamOutput;
desc->blend_state = d3d12_desc->BlendState;
desc->sample_mask = d3d12_desc->SampleMask;
desc->rasterizer_state = d3d12_desc->RasterizerState;
memcpy(&desc->depth_stencil_state, &d3d12_desc->DepthStencilState, sizeof(d3d12_desc->DepthStencilState));
desc->input_layout = d3d12_desc->InputLayout;
desc->strip_cut_value = d3d12_desc->IBStripCutValue;
desc->primitive_topology_type = d3d12_desc->PrimitiveTopologyType;
desc->rtv_formats.NumRenderTargets = d3d12_desc->NumRenderTargets;
memcpy(desc->rtv_formats.RTFormats, d3d12_desc->RTVFormats, sizeof(desc->rtv_formats.RTFormats));
desc->dsv_format = d3d12_desc->DSVFormat;
desc->sample_desc = d3d12_desc->SampleDesc;
desc->node_mask = d3d12_desc->NodeMask;
desc->cached_pso = d3d12_desc->CachedPSO;
desc->flags = d3d12_desc->Flags;
}
struct vkd3d_pipeline_key
{
D3D12_PRIMITIVE_TOPOLOGY topology;
@ -2457,7 +2484,7 @@ static void vk_stencil_op_state_from_d3d12(struct VkStencilOpState *vk_desc,
}
static void ds_desc_from_d3d12(struct VkPipelineDepthStencilStateCreateInfo *vk_desc,
const D3D12_DEPTH_STENCIL_DESC *d3d12_desc)
const D3D12_DEPTH_STENCIL_DESC1 *d3d12_desc)
{
memset(vk_desc, 0, sizeof(*vk_desc));
vk_desc->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
@ -2738,12 +2765,12 @@ static VkLogicOp vk_logic_op_from_d3d12(D3D12_LOGIC_OP op)
}
static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *state,
struct d3d12_device *device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc)
struct d3d12_device *device, const struct d3d12_pipeline_state_desc *desc)
{
unsigned int ps_output_swizzle[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT];
struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics;
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
const D3D12_STREAM_OUTPUT_DESC *so_desc = &desc->StreamOutput;
const D3D12_STREAM_OUTPUT_DESC *so_desc = &desc->stream_output;
VkVertexInputBindingDivisorDescriptionEXT *binding_divisor;
const struct vkd3d_vulkan_info *vk_info = &device->vk_info;
uint32_t instance_divisors[D3D12_VS_INPUT_REGISTER_COUNT];
@ -2787,11 +2814,11 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
}
shader_stages[] =
{
{VK_SHADER_STAGE_VERTEX_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, VS)},
{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, HS)},
{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, DS)},
{VK_SHADER_STAGE_GEOMETRY_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, GS)},
{VK_SHADER_STAGE_FRAGMENT_BIT, offsetof(D3D12_GRAPHICS_PIPELINE_STATE_DESC, PS)},
{VK_SHADER_STAGE_VERTEX_BIT, offsetof(struct d3d12_pipeline_state_desc, vs)},
{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, offsetof(struct d3d12_pipeline_state_desc, hs)},
{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, offsetof(struct d3d12_pipeline_state_desc, ds)},
{VK_SHADER_STAGE_GEOMETRY_BIT, offsetof(struct d3d12_pipeline_state_desc, gs)},
{VK_SHADER_STAGE_FRAGMENT_BIT, offsetof(struct d3d12_pipeline_state_desc, ps)},
};
state->ID3D12PipelineState_iface.lpVtbl = &d3d12_pipeline_state_vtbl;
@ -2802,26 +2829,26 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
memset(&input_signature, 0, sizeof(input_signature));
for (i = desc->NumRenderTargets; i < ARRAY_SIZE(desc->RTVFormats); ++i)
for (i = desc->rtv_formats.NumRenderTargets; i < ARRAY_SIZE(desc->rtv_formats.RTFormats); ++i)
{
if (desc->RTVFormats[i] != DXGI_FORMAT_UNKNOWN)
if (desc->rtv_formats.RTFormats[i] != DXGI_FORMAT_UNKNOWN)
{
WARN("Format must be set to DXGI_FORMAT_UNKNOWN for inactive render targets.\n");
return E_INVALIDARG;
}
}
if (!(root_signature = unsafe_impl_from_ID3D12RootSignature(desc->pRootSignature)))
if (!(root_signature = unsafe_impl_from_ID3D12RootSignature(desc->root_signature)))
{
WARN("Root signature is NULL.\n");
return E_INVALIDARG;
}
sample_count = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
if (desc->SampleDesc.Count != 1 && desc->SampleDesc.Quality)
WARN("Ignoring sample quality %u.\n", desc->SampleDesc.Quality);
sample_count = vk_samples_from_dxgi_sample_desc(&desc->sample_desc);
if (desc->sample_desc.Count != 1 && desc->sample_desc.Quality)
WARN("Ignoring sample quality %u.\n", desc->sample_desc.Quality);
rt_count = desc->NumRenderTargets;
rt_count = desc->rtv_formats.NumRenderTargets;
if (rt_count > ARRAY_SIZE(graphics->blend_attachments))
{
FIXME("NumRenderTargets %zu > %zu, ignoring extra formats.\n",
@ -2829,40 +2856,40 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
rt_count = ARRAY_SIZE(graphics->blend_attachments);
}
graphics->om_logic_op_enable = desc->BlendState.RenderTarget[0].LogicOpEnable
graphics->om_logic_op_enable = desc->blend_state.RenderTarget[0].LogicOpEnable
&& device->feature_options.OutputMergerLogicOp;
graphics->om_logic_op = graphics->om_logic_op_enable
? vk_logic_op_from_d3d12(desc->BlendState.RenderTarget[0].LogicOp)
? vk_logic_op_from_d3d12(desc->blend_state.RenderTarget[0].LogicOp)
: VK_LOGIC_OP_COPY;
if (desc->BlendState.RenderTarget[0].LogicOpEnable && !graphics->om_logic_op_enable)
if (desc->blend_state.RenderTarget[0].LogicOpEnable && !graphics->om_logic_op_enable)
WARN("The device does not support output merger logic ops. Ignoring logic op %#x.\n",
desc->BlendState.RenderTarget[0].LogicOp);
desc->blend_state.RenderTarget[0].LogicOp);
graphics->null_attachment_mask = 0;
for (i = 0; i < rt_count; ++i)
{
const D3D12_RENDER_TARGET_BLEND_DESC *rt_desc;
if (desc->RTVFormats[i] == DXGI_FORMAT_UNKNOWN)
if (desc->rtv_formats.RTFormats[i] == DXGI_FORMAT_UNKNOWN)
{
graphics->null_attachment_mask |= 1u << i;
ps_output_swizzle[i] = VKD3D_SHADER_NO_SWIZZLE;
graphics->rtv_formats[i] = VK_FORMAT_UNDEFINED;
}
else if ((format = vkd3d_get_format(device, desc->RTVFormats[i], false)))
else if ((format = vkd3d_get_format(device, desc->rtv_formats.RTFormats[i], false)))
{
ps_output_swizzle[i] = vkd3d_get_rt_format_swizzle(format);
graphics->rtv_formats[i] = format->vk_format;
}
else
{
WARN("Invalid RTV format %#x.\n", desc->RTVFormats[i]);
WARN("Invalid RTV format %#x.\n", desc->rtv_formats.RTFormats[i]);
hr = E_INVALIDARG;
goto fail;
}
rt_desc = &desc->BlendState.RenderTarget[desc->BlendState.IndependentBlendEnable ? i : 0];
if (desc->BlendState.IndependentBlendEnable && rt_desc->LogicOpEnable)
rt_desc = &desc->blend_state.RenderTarget[desc->blend_state.IndependentBlendEnable ? i : 0];
if (desc->blend_state.IndependentBlendEnable && rt_desc->LogicOpEnable)
{
WARN("IndependentBlendEnable must be FALSE when logic operations are enabled.\n");
hr = E_INVALIDARG;
@ -2881,8 +2908,8 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->rtv_formats[i] = VK_FORMAT_UNDEFINED;
graphics->rt_count = rt_count;
ds_desc_from_d3d12(&graphics->ds_desc, &desc->DepthStencilState);
if (desc->DSVFormat == DXGI_FORMAT_UNKNOWN
ds_desc_from_d3d12(&graphics->ds_desc, &desc->depth_stencil_state);
if (desc->dsv_format == DXGI_FORMAT_UNKNOWN
&& graphics->ds_desc.depthTestEnable && !graphics->ds_desc.depthWriteEnable
&& graphics->ds_desc.depthCompareOp == VK_COMPARE_OP_ALWAYS && !graphics->ds_desc.stencilTestEnable)
{
@ -2893,13 +2920,13 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->dsv_format = VK_FORMAT_UNDEFINED;
if (graphics->ds_desc.depthTestEnable || graphics->ds_desc.stencilTestEnable)
{
if (desc->DSVFormat == DXGI_FORMAT_UNKNOWN)
if (desc->dsv_format == DXGI_FORMAT_UNKNOWN)
{
WARN("DSV format is DXGI_FORMAT_UNKNOWN.\n");
graphics->dsv_format = VK_FORMAT_UNDEFINED;
graphics->null_attachment_mask |= dsv_attachment_mask(graphics);
}
else if ((format = vkd3d_get_format(device, desc->DSVFormat, true)))
else if ((format = vkd3d_get_format(device, desc->dsv_format, true)))
{
if (!(format->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)))
FIXME("Format %#x is not depth/stencil format.\n", format->dxgi_format);
@ -2908,12 +2935,12 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
}
else
{
WARN("Invalid DSV format %#x.\n", desc->DSVFormat);
WARN("Invalid DSV format %#x.\n", desc->dsv_format);
hr = E_INVALIDARG;
goto fail;
}
if (!desc->PS.pShaderBytecode)
if (!desc->ps.pShaderBytecode)
{
if (FAILED(hr = create_shader_stage(device, &graphics->stages[graphics->stage_count],
VK_SHADER_STAGE_FRAGMENT_BIT, &default_ps, NULL)))
@ -2936,7 +2963,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
ps_target_info.extension_count = vk_info->shader_extension_count;
ps_target_info.parameters = ps_shader_parameters;
ps_target_info.parameter_count = ARRAY_SIZE(ps_shader_parameters);
ps_target_info.dual_source_blending = is_dual_source_blending(&desc->BlendState.RenderTarget[0]);
ps_target_info.dual_source_blending = is_dual_source_blending(&desc->blend_state.RenderTarget[0]);
ps_target_info.output_swizzles = ps_output_swizzle;
ps_target_info.output_swizzle_count = rt_count;
@ -2946,11 +2973,11 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
hr = E_INVALIDARG;
goto fail;
}
if (ps_target_info.dual_source_blending && desc->BlendState.IndependentBlendEnable)
if (ps_target_info.dual_source_blending && desc->blend_state.IndependentBlendEnable)
{
for (i = 1; i < ARRAY_SIZE(desc->BlendState.RenderTarget); ++i)
for (i = 1; i < ARRAY_SIZE(desc->blend_state.RenderTarget); ++i)
{
if (desc->BlendState.RenderTarget[i].BlendEnable)
if (desc->blend_state.RenderTarget[i].BlendEnable)
{
WARN("Blend enable cannot be set for render target %u when dual source blending is used.\n", i);
hr = E_INVALIDARG;
@ -2992,9 +3019,9 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
xfb_info.buffer_strides = so_desc->pBufferStrides;
xfb_info.buffer_stride_count = so_desc->NumStrides;
if (desc->GS.pShaderBytecode)
if (desc->gs.pShaderBytecode)
xfb_stage = VK_SHADER_STAGE_GEOMETRY_BIT;
else if (desc->DS.pShaderBytecode)
else if (desc->ds.pShaderBytecode)
xfb_stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
else
xfb_stage = VK_SHADER_STAGE_VERTEX_BIT;
@ -3046,7 +3073,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
if (desc->PrimitiveTopologyType != D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH)
if (desc->primitive_topology_type != D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH)
{
WARN("D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH must be used with tessellation shaders.\n");
hr = E_INVALIDARG;
@ -3088,7 +3115,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
++graphics->stage_count;
}
graphics->attribute_count = desc->InputLayout.NumElements;
graphics->attribute_count = desc->input_layout.NumElements;
if (graphics->attribute_count > ARRAY_SIZE(graphics->attributes))
{
FIXME("InputLayout.NumElements %zu > %zu, ignoring extra elements.\n",
@ -3104,13 +3131,13 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
goto fail;
}
if (FAILED(hr = compute_input_layout_offsets(device, &desc->InputLayout, aligned_offsets)))
if (FAILED(hr = compute_input_layout_offsets(device, &desc->input_layout, aligned_offsets)))
goto fail;
graphics->instance_divisor_count = 0;
for (i = 0, j = 0, mask = 0; i < graphics->attribute_count; ++i)
{
const D3D12_INPUT_ELEMENT_DESC *e = &desc->InputLayout.pInputElementDescs[i];
const D3D12_INPUT_ELEMENT_DESC *e = &desc->input_layout.pInputElementDescs[i];
const struct vkd3d_shader_signature_element *signature_element;
/* TODO: DXGI_FORMAT_UNKNOWN will succeed here, which may not match
@ -3194,30 +3221,30 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->attribute_count = j;
vkd3d_shader_free_shader_signature(&input_signature);
switch (desc->IBStripCutValue)
switch (desc->strip_cut_value)
{
case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED:
case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF:
case D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF:
graphics->index_buffer_strip_cut_value = desc->IBStripCutValue;
graphics->index_buffer_strip_cut_value = desc->strip_cut_value;
break;
default:
WARN("Invalid index buffer strip cut value %#x.\n", desc->IBStripCutValue);
WARN("Invalid index buffer strip cut value %#x.\n", desc->strip_cut_value);
hr = E_INVALIDARG;
goto fail;
}
is_dsv_format_unknown = graphics->null_attachment_mask & dsv_attachment_mask(graphics);
rs_desc_from_d3d12(&graphics->rs_desc, &desc->RasterizerState);
rs_desc_from_d3d12(&graphics->rs_desc, &desc->rasterizer_state);
have_attachment = graphics->rt_count || graphics->dsv_format || is_dsv_format_unknown;
if ((!have_attachment && !(desc->PS.pShaderBytecode && desc->PS.BytecodeLength))
if ((!have_attachment && !(desc->ps.pShaderBytecode && desc->ps.BytecodeLength))
|| (graphics->xfb_enabled && so_desc->RasterizedStream == D3D12_SO_NO_RASTERIZED_STREAM))
graphics->rs_desc.rasterizerDiscardEnable = VK_TRUE;
rs_stream_info_from_d3d12(&graphics->rs_stream_info, &graphics->rs_desc, so_desc, vk_info);
if (vk_info->EXT_depth_clip_enable)
rs_depth_clip_info_from_d3d12(&graphics->rs_depth_clip_info, &graphics->rs_desc, &desc->RasterizerState);
rs_depth_clip_info_from_d3d12(&graphics->rs_depth_clip_info, &graphics->rs_desc, &desc->rasterizer_state);
graphics->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
graphics->ms_desc.pNext = NULL;
@ -3226,14 +3253,14 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
graphics->ms_desc.sampleShadingEnable = VK_FALSE;
graphics->ms_desc.minSampleShading = 0.0f;
graphics->ms_desc.pSampleMask = NULL;
if (desc->SampleMask != ~0u)
if (desc->sample_mask != ~0u)
{
assert(DIV_ROUND_UP(sample_count, 32) <= ARRAY_SIZE(graphics->sample_mask));
graphics->sample_mask[0] = desc->SampleMask;
graphics->sample_mask[0] = desc->sample_mask;
graphics->sample_mask[1] = 0xffffffffu;
graphics->ms_desc.pSampleMask = graphics->sample_mask;
}
graphics->ms_desc.alphaToCoverageEnable = desc->BlendState.AlphaToCoverageEnable;
graphics->ms_desc.alphaToCoverageEnable = desc->blend_state.AlphaToCoverageEnable;
graphics->ms_desc.alphaToOneEnable = VK_FALSE;
/* We defer creating the render pass for pipelines with DSVFormat equal to
@ -3271,13 +3298,16 @@ fail:
HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device,
const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state)
{
struct d3d12_pipeline_state_desc pipeline_desc;
struct d3d12_pipeline_state *object;
HRESULT hr;
pipeline_state_desc_from_d3d12_graphics_desc(&pipeline_desc, desc);
if (!(object = vkd3d_malloc(sizeof(*object))))
return E_OUTOFMEMORY;
if (FAILED(hr = d3d12_pipeline_state_init_graphics(object, device, desc)))
if (FAILED(hr = d3d12_pipeline_state_init_graphics(object, device, &pipeline_desc)))
{
vkd3d_free(object);
return hr;

View File

@ -1317,6 +1317,31 @@ static inline bool d3d12_pipeline_state_has_unknown_dsv_format(struct d3d12_pipe
return false;
}
struct d3d12_pipeline_state_desc
{
ID3D12RootSignature *root_signature;
D3D12_SHADER_BYTECODE vs;
D3D12_SHADER_BYTECODE ps;
D3D12_SHADER_BYTECODE ds;
D3D12_SHADER_BYTECODE hs;
D3D12_SHADER_BYTECODE gs;
D3D12_SHADER_BYTECODE cs;
D3D12_STREAM_OUTPUT_DESC stream_output;
D3D12_BLEND_DESC blend_state;
unsigned int sample_mask;
D3D12_RASTERIZER_DESC rasterizer_state;
D3D12_DEPTH_STENCIL_DESC1 depth_stencil_state;
D3D12_INPUT_LAYOUT_DESC input_layout;
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE strip_cut_value;
D3D12_PRIMITIVE_TOPOLOGY_TYPE primitive_topology_type;
D3D12_RT_FORMAT_ARRAY rtv_formats;
DXGI_FORMAT dsv_format;
DXGI_SAMPLE_DESC sample_desc;
unsigned int node_mask;
D3D12_CACHED_PIPELINE_STATE cached_pso;
D3D12_PIPELINE_STATE_FLAGS flags;
};
HRESULT d3d12_pipeline_state_create_compute(struct d3d12_device *device,
const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state);
HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device,