vkd3d: Make pipeline state responsible for creating Vulkan pipelines.

Signed-off-by: Józef Kucia <jkucia@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Józef Kucia 2018-10-24 13:16:28 +02:00 committed by Alexandre Julliard
parent fb7b1c9880
commit cfef906696
3 changed files with 157 additions and 147 deletions

View File

@ -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));

View File

@ -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;
}

View File

@ -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;