From 39afbb8e323030adbcc7287cc6ea67fe5f57ba48 Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Tue, 14 Nov 2023 12:49:17 +1000 Subject: [PATCH] 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. --- libs/vkd3d/state.c | 130 +++++++++++++++++++++++-------------- libs/vkd3d/vkd3d_private.h | 25 +++++++ 2 files changed, 105 insertions(+), 50 deletions(-) diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 2b83cfd8..9e3fac7e 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -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; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 148ee6c9..0a254aa7 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -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,