diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index d8a65622..7e7b3ee5 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -1818,148 +1818,6 @@ static bool d3d12_command_list_update_current_framebuffer(struct d3d12_command_l return true; } -static VkPipeline d3d12_command_list_get_or_create_pipeline(struct d3d12_command_list *list, - struct d3d12_graphics_pipeline_state *state) -{ - struct VkVertexInputBindingDescription bindings[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; - const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; - struct VkPipelineVertexInputStateCreateInfo input_desc; - struct VkPipelineInputAssemblyStateCreateInfo ia_desc; - struct VkPipelineColorBlendStateCreateInfo blend_desc; - struct VkGraphicsPipelineCreateInfo pipeline_desc; - struct d3d12_device *device = list->device; - struct vkd3d_pipeline_key pipeline_key; - size_t binding_count = 0; - VkPipeline vk_pipeline; - unsigned int i; - uint32_t mask; - VkResult vr; - - static const struct VkPipelineViewportStateCreateInfo vp_desc = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .pNext = NULL, - .flags = 0, - .viewportCount = 1, - .pViewports = NULL, - .scissorCount = 1, - .pScissors = NULL, - }; - static const enum VkDynamicState dynamic_states[] = - { - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_BLEND_CONSTANTS, - VK_DYNAMIC_STATE_STENCIL_REFERENCE, - }; - static const struct VkPipelineDynamicStateCreateInfo dynamic_desc = - { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .pNext = NULL, - .flags = 0, - .dynamicStateCount = ARRAY_SIZE(dynamic_states), - .pDynamicStates = dynamic_states, - }; - - memset(&pipeline_key, 0, sizeof(pipeline_key)); - pipeline_key.state = state; - pipeline_key.topology = list->primitive_topology; - - for (i = 0, mask = 0; i < state->attribute_count; ++i) - { - struct VkVertexInputBindingDescription *b; - uint32_t binding; - - binding = state->attributes[i].binding; - if (mask & (1u << binding)) - continue; - - if (binding_count == ARRAY_SIZE(bindings)) - { - FIXME("Maximum binding count exceeded.\n"); - break; - } - - mask |= 1u << binding; - b = &bindings[binding_count]; - b->binding = binding; - b->stride = list->strides[binding]; - b->inputRate = state->input_rates[binding]; - - if (!b->stride) - FIXME("Invalid stride for input slot %u.\n", binding); - - pipeline_key.strides[binding_count] = list->strides[binding]; - - ++binding_count; - } - - if ((vk_pipeline = d3d12_device_find_cached_pipeline(device, &pipeline_key))) - return vk_pipeline; - - input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - input_desc.pNext = NULL; - input_desc.flags = 0; - input_desc.vertexBindingDescriptionCount = binding_count; - input_desc.pVertexBindingDescriptions = bindings; - input_desc.vertexAttributeDescriptionCount = state->attribute_count; - input_desc.pVertexAttributeDescriptions = state->attributes; - - ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - ia_desc.pNext = NULL; - ia_desc.flags = 0; - ia_desc.topology = list->primitive_topology; - ia_desc.primitiveRestartEnable = VK_FALSE; - - blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - blend_desc.pNext = NULL; - blend_desc.flags = 0; - blend_desc.logicOpEnable = VK_FALSE; - blend_desc.logicOp = VK_LOGIC_OP_COPY; - blend_desc.attachmentCount = state->attachment_count - state->rt_idx; - blend_desc.pAttachments = state->blend_attachments; - blend_desc.blendConstants[0] = D3D12_DEFAULT_BLEND_FACTOR_RED; - blend_desc.blendConstants[1] = D3D12_DEFAULT_BLEND_FACTOR_GREEN; - blend_desc.blendConstants[2] = D3D12_DEFAULT_BLEND_FACTOR_BLUE; - blend_desc.blendConstants[3] = D3D12_DEFAULT_BLEND_FACTOR_ALPHA; - - pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipeline_desc.pNext = NULL; - pipeline_desc.flags = 0; - pipeline_desc.stageCount = state->stage_count; - pipeline_desc.pStages = state->stages; - pipeline_desc.pVertexInputState = &input_desc; - pipeline_desc.pInputAssemblyState = &ia_desc; - pipeline_desc.pTessellationState = NULL; - pipeline_desc.pViewportState = &vp_desc; - pipeline_desc.pRasterizationState = &state->rs_desc; - pipeline_desc.pMultisampleState = &state->ms_desc; - pipeline_desc.pDepthStencilState = &state->ds_desc; - pipeline_desc.pColorBlendState = &blend_desc; - pipeline_desc.pDynamicState = &dynamic_desc; - pipeline_desc.layout = state->root_signature->vk_pipeline_layout; - pipeline_desc.renderPass = state->render_pass; - pipeline_desc.subpass = 0; - pipeline_desc.basePipelineHandle = VK_NULL_HANDLE; - pipeline_desc.basePipelineIndex = -1; - if ((vr = VK_CALL(vkCreateGraphicsPipelines(device->vk_device, device->vk_pipeline_cache, - 1, &pipeline_desc, NULL, &vk_pipeline))) < 0) - { - WARN("Failed to create Vulkan graphics pipeline, vr %d.\n", vr); - return VK_NULL_HANDLE; - } - - if (d3d12_device_put_pipeline_to_cache(device, &pipeline_key, vk_pipeline, &state->compiled_pipelines)) - return vk_pipeline; - - /* Other thread compiled the pipeline before us. */ - VK_CALL(vkDestroyPipeline(device->vk_device, vk_pipeline, NULL)); - vk_pipeline = d3d12_device_find_cached_pipeline(device, &pipeline_key); - if (!vk_pipeline) - ERR("Could not get the pipeline compiled by other thread from the cache.\n"); - return vk_pipeline; -} - static bool d3d12_command_list_update_current_pipeline(struct d3d12_command_list *list) { const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; @@ -1968,13 +1826,14 @@ static bool d3d12_command_list_update_current_pipeline(struct d3d12_command_list if (list->current_pipeline != VK_NULL_HANDLE) return true; - if (list->state->vk_bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS) + if (!d3d12_pipeline_state_is_graphics(list->state)) { - WARN("Pipeline state %p has bind point %#x.\n", list->state, list->state->vk_bind_point); + WARN("Pipeline state %p is not a graphics pipeline.\n", list->state); return false; } - if (!(vk_pipeline = d3d12_command_list_get_or_create_pipeline(list, &list->state->u.graphics))) + if (!(vk_pipeline = d3d12_pipeline_state_get_or_create_pipeline(list->state, + list->primitive_topology, list->strides))) return false; VK_CALL(vkCmdBindPipeline(list->vk_command_buffer, list->state->vk_bind_point, vk_pipeline)); diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index db761d88..7ee5f4dc 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1093,7 +1093,7 @@ static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_Release(ID3D12PipelineState const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; unsigned int i; - if (state->vk_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) + if (d3d12_pipeline_state_is_graphics(state)) { struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics; @@ -1105,7 +1105,7 @@ static ULONG STDMETHODCALLTYPE d3d12_pipeline_state_Release(ID3D12PipelineState d3d12_device_destroy_compiled_pipelines(device, &graphics->compiled_pipelines); } - else if (state->vk_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) + else if (d3d12_pipeline_state_is_compute(state)) { VK_CALL(vkDestroyPipeline(device->vk_device, state->u.compute.vk_pipeline, NULL)); } @@ -2234,3 +2234,147 @@ HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device, return S_OK; } + +VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state, + VkPrimitiveTopology topology, const uint32_t *strides) +{ + struct VkVertexInputBindingDescription bindings[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + const struct vkd3d_vk_device_procs *vk_procs = &state->device->vk_procs; + struct d3d12_graphics_pipeline_state *graphics = &state->u.graphics; + struct VkPipelineVertexInputStateCreateInfo input_desc; + struct VkPipelineInputAssemblyStateCreateInfo ia_desc; + struct VkPipelineColorBlendStateCreateInfo blend_desc; + struct VkGraphicsPipelineCreateInfo pipeline_desc; + struct d3d12_device *device = state->device; + struct vkd3d_pipeline_key pipeline_key; + size_t binding_count = 0; + VkPipeline vk_pipeline; + unsigned int i; + uint32_t mask; + VkResult vr; + + static const struct VkPipelineViewportStateCreateInfo vp_desc = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .viewportCount = 1, + .pViewports = NULL, + .scissorCount = 1, + .pScissors = NULL, + }; + static const enum VkDynamicState dynamic_states[] = + { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_BLEND_CONSTANTS, + VK_DYNAMIC_STATE_STENCIL_REFERENCE, + }; + static const struct VkPipelineDynamicStateCreateInfo dynamic_desc = + { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .dynamicStateCount = ARRAY_SIZE(dynamic_states), + .pDynamicStates = dynamic_states, + }; + + assert(d3d12_pipeline_state_is_graphics(state)); + + memset(&pipeline_key, 0, sizeof(pipeline_key)); + pipeline_key.topology = topology; + + for (i = 0, mask = 0; i < graphics->attribute_count; ++i) + { + struct VkVertexInputBindingDescription *b; + uint32_t binding; + + binding = graphics->attributes[i].binding; + if (mask & (1u << binding)) + continue; + + if (binding_count == ARRAY_SIZE(bindings)) + { + FIXME("Maximum binding count exceeded.\n"); + break; + } + + mask |= 1u << binding; + b = &bindings[binding_count]; + b->binding = binding; + b->stride = strides[binding]; + b->inputRate = graphics->input_rates[binding]; + + if (!b->stride) + FIXME("Invalid stride for input slot %u.\n", binding); + + pipeline_key.strides[binding_count] = strides[binding]; + + ++binding_count; + } + + if ((vk_pipeline = d3d12_device_find_cached_pipeline(device, &pipeline_key))) + return vk_pipeline; + + input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + input_desc.pNext = NULL; + input_desc.flags = 0; + input_desc.vertexBindingDescriptionCount = binding_count; + input_desc.pVertexBindingDescriptions = bindings; + input_desc.vertexAttributeDescriptionCount = graphics->attribute_count; + input_desc.pVertexAttributeDescriptions = graphics->attributes; + + ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_desc.pNext = NULL; + ia_desc.flags = 0; + ia_desc.topology = topology; + ia_desc.primitiveRestartEnable = VK_FALSE; + + blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_desc.pNext = NULL; + blend_desc.flags = 0; + blend_desc.logicOpEnable = VK_FALSE; + blend_desc.logicOp = VK_LOGIC_OP_COPY; + blend_desc.attachmentCount = graphics->attachment_count - graphics->rt_idx; + blend_desc.pAttachments = graphics->blend_attachments; + blend_desc.blendConstants[0] = D3D12_DEFAULT_BLEND_FACTOR_RED; + blend_desc.blendConstants[1] = D3D12_DEFAULT_BLEND_FACTOR_GREEN; + blend_desc.blendConstants[2] = D3D12_DEFAULT_BLEND_FACTOR_BLUE; + blend_desc.blendConstants[3] = D3D12_DEFAULT_BLEND_FACTOR_ALPHA; + + pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_desc.pNext = NULL; + pipeline_desc.flags = 0; + pipeline_desc.stageCount = graphics->stage_count; + pipeline_desc.pStages = graphics->stages; + pipeline_desc.pVertexInputState = &input_desc; + pipeline_desc.pInputAssemblyState = &ia_desc; + pipeline_desc.pTessellationState = NULL; + pipeline_desc.pViewportState = &vp_desc; + pipeline_desc.pRasterizationState = &graphics->rs_desc; + pipeline_desc.pMultisampleState = &graphics->ms_desc; + pipeline_desc.pDepthStencilState = &graphics->ds_desc; + pipeline_desc.pColorBlendState = &blend_desc; + pipeline_desc.pDynamicState = &dynamic_desc; + pipeline_desc.layout = graphics->root_signature->vk_pipeline_layout; + pipeline_desc.renderPass = graphics->render_pass; + pipeline_desc.subpass = 0; + pipeline_desc.basePipelineHandle = VK_NULL_HANDLE; + pipeline_desc.basePipelineIndex = -1; + if ((vr = VK_CALL(vkCreateGraphicsPipelines(device->vk_device, device->vk_pipeline_cache, + 1, &pipeline_desc, NULL, &vk_pipeline))) < 0) + { + WARN("Failed to create Vulkan graphics pipeline, vr %d.\n", vr); + return VK_NULL_HANDLE; + } + + if (d3d12_device_put_pipeline_to_cache(device, &pipeline_key, vk_pipeline, &graphics->compiled_pipelines)) + return vk_pipeline; + + /* Other thread compiled the pipeline before us. */ + VK_CALL(vkDestroyPipeline(device->vk_device, vk_pipeline, NULL)); + vk_pipeline = d3d12_device_find_cached_pipeline(device, &pipeline_key); + if (!vk_pipeline) + ERR("Could not get the pipeline compiled by other thread from the cache.\n"); + return vk_pipeline; +} diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index cb3d597a..99a59cb7 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -558,10 +558,17 @@ static inline bool d3d12_pipeline_state_is_compute(const struct d3d12_pipeline_s return state && state->vk_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE; } +static inline bool d3d12_pipeline_state_is_graphics(const struct d3d12_pipeline_state *state) +{ + return state && state->vk_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS; +} + HRESULT d3d12_pipeline_state_create_compute(struct d3d12_device *device, const D3D12_COMPUTE_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state) DECLSPEC_HIDDEN; HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc, struct d3d12_pipeline_state **state) DECLSPEC_HIDDEN; +VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state, + VkPrimitiveTopology topology, const uint32_t *strides) DECLSPEC_HIDDEN; bool d3d12_pipeline_state_is_render_pass_compatible(const struct d3d12_pipeline_state *state_a, const struct d3d12_pipeline_state *state_b) DECLSPEC_HIDDEN; struct d3d12_pipeline_state *unsafe_impl_from_ID3D12PipelineState(ID3D12PipelineState *iface) DECLSPEC_HIDDEN;