HACK: Hook up VK_HACK_d3d12_dynamic_state.

This commit is contained in:
Hans-Kristian Arntzen 2019-10-03 13:10:24 +02:00
parent a019a21f70
commit 048d5376a0
4 changed files with 192 additions and 1 deletions

View File

@ -136,6 +136,10 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
VK_EXTENSION(EXT_TEXEL_BUFFER_ALIGNMENT, EXT_texel_buffer_alignment),
VK_EXTENSION(EXT_TRANSFORM_FEEDBACK, EXT_transform_feedback),
VK_EXTENSION(EXT_VERTEX_ATTRIBUTE_DIVISOR, EXT_vertex_attribute_divisor),
/* HACKs */
#ifdef VK_HACK_d3d12_dynamic_state
VK_EXTENSION(HACK_D3D12_DYNAMIC_STATE, HACK_d3d12_dynamic_state),
#endif
};
static unsigned int get_spec_version(const VkExtensionProperties *extensions,

View File

@ -1200,6 +1200,9 @@ static void d3d12_pipeline_state_destroy_graphics(struct d3d12_pipeline_state *s
struct vkd3d_compiled_pipeline *current, *e;
unsigned int i;
if (graphics->static_pipeline)
VK_CALL(vkDestroyPipeline(device->vk_device, graphics->static_pipeline, NULL));
for (i = 0; i < graphics->stage_count; ++i)
{
VK_CALL(vkDestroyShaderModule(device->vk_device, graphics->stages[i].module, NULL));
@ -1978,6 +1981,8 @@ static HRESULT d3d12_graphics_pipeline_state_create_render_pass(
return vkd3d_render_pass_cache_find(&device->render_pass_cache, device, &key, vk_render_pass);
}
static VkPipeline d3d12_pipeline_state_create_static_pipeline(struct d3d12_pipeline_state *state);
static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *state,
struct d3d12_device *device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC *desc)
{
@ -2039,6 +2044,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
state->vk_pipeline_layout = VK_NULL_HANDLE;
state->vk_set_layout = VK_NULL_HANDLE;
state->uav_counters = NULL;
graphics->static_pipeline = VK_NULL_HANDLE;
state->uav_counter_mask = 0;
graphics->stage_count = 0;
@ -2460,6 +2466,10 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
goto fail;
state->vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
graphics->topology_type = desc->PrimitiveTopologyType;
graphics->static_pipeline = d3d12_pipeline_state_create_static_pipeline(state);
d3d12_device_add_ref(state->device = device);
return S_OK;
@ -2496,6 +2506,25 @@ HRESULT d3d12_pipeline_state_create_graphics(struct d3d12_device *device,
return S_OK;
}
static enum VkPrimitiveTopologyTypeHACK vk_topology_type_from_d3d12_topology_type(
D3D12_PRIMITIVE_TOPOLOGY_TYPE topology_type)
{
switch (topology_type)
{
case D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE:
return VK_PRIMITIVE_TOPOLOGY_TYPE_LINE_HACK;
case D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT:
return VK_PRIMITIVE_TOPOLOGY_TYPE_POINT_HACK;
case D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE:
return VK_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE_HACK;
case D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH:
return VK_PRIMITIVE_TOPOLOGY_TYPE_PATCH_HACK;
default:
FIXME("Unhandled primitive topology type %#x.\n", topology_type);
assert(0);
}
}
static enum VkPrimitiveTopology vk_topology_from_d3d12_topology(D3D12_PRIMITIVE_TOPOLOGY topology)
{
switch (topology)
@ -2620,6 +2649,148 @@ static bool d3d12_pipeline_state_put_pipeline_to_cache(struct d3d12_pipeline_sta
return compiled_pipeline;
}
static VkPipeline d3d12_pipeline_state_create_static_pipeline(struct d3d12_pipeline_state *state)
{
#ifdef VK_HACK_d3d12_dynamic_state
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;
VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_info;
VkPipelineTessellationStateCreateInfo tessellation_info;
VkPipelineVertexInputStateCreateInfo input_desc;
VkPipelineInputAssemblyStateCreateInfo ia_desc;
VkPipelinePrimitiveTopologyTypeCreateInfoHACK ia_type_desc;
VkPipelineColorBlendStateCreateInfo blend_desc;
struct d3d12_device *device = state->device;
VkGraphicsPipelineCreateInfo pipeline_desc;
size_t binding_count = 0;
VkPipeline vk_pipeline;
unsigned int i;
VkResult vr;
static const VkDynamicState dynamic_states[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_BLEND_CONSTANTS,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
VK_DYNAMIC_STATE_VIEWPORT_COUNT_HACK,
VK_DYNAMIC_STATE_SCISSOR_COUNT_HACK,
VK_DYNAMIC_STATE_VERTEX_BUFFER_STRIDE_HACK,
VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_HACK,
};
static const VkPipelineDynamicStateCreateInfo dynamic_desc = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.dynamicStateCount = ARRAY_SIZE(dynamic_states),
.pDynamicStates = dynamic_states,
};
/* Need to fall back to late creation. */
if (!state->device->vk_info.HACK_d3d12_dynamic_state)
return VK_NULL_HANDLE;
assert(d3d12_pipeline_state_is_graphics(state));
for (i = 0; i < graphics->attribute_count; ++i)
{
struct VkVertexInputBindingDescription *b;
uint32_t binding;
binding = graphics->attributes[i].binding;
if (binding_count == ARRAY_SIZE(bindings))
{
FIXME("Maximum binding count exceeded.\n");
break;
}
b = &bindings[binding_count];
b->binding = binding;
b->stride = 0; /* Dynamic, just set to 0. */
b->inputRate = graphics->input_rates[binding];
++binding_count;
}
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;
if (graphics->instance_divisor_count)
{
input_desc.pNext = &input_divisor_info;
input_divisor_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
input_divisor_info.pNext = NULL;
input_divisor_info.vertexBindingDivisorCount = graphics->instance_divisor_count;
input_divisor_info.pVertexBindingDivisors = graphics->instance_divisors;
}
ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
ia_desc.pNext = &ia_type_desc;
ia_desc.flags = 0;
ia_desc.primitiveRestartEnable = !!graphics->index_buffer_strip_cut_value;
ia_type_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_PRIMITIVE_TOPOLOGY_TYPE_CREATE_INFO_HACK;
ia_type_desc.pNext = NULL;
ia_type_desc.topologyType = vk_topology_type_from_d3d12_topology_type(graphics->topology_type);
tessellation_info.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tessellation_info.pNext = NULL;
tessellation_info.flags = 0;
tessellation_info.patchControlPoints = 1; /* FIXME: Deduce from shader? */
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->rt_count;
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 = &tessellation_info;
pipeline_desc.pViewportState = NULL; /* Dynamic. */
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.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;
}
return vk_pipeline;
#else
(void)state;
return VK_NULL_HANDLE;
#endif
}
VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_state *state,
D3D12_PRIMITIVE_TOPOLOGY topology, const uint32_t *strides, VkFormat dsv_format,
VkRenderPass *vk_render_pass)

View File

@ -109,6 +109,9 @@ struct vkd3d_vulkan_info
bool EXT_texel_buffer_alignment;
bool EXT_transform_feedback;
bool EXT_vertex_attribute_divisor;
#ifdef VK_HACK_d3d12_dynamic_state
bool HACK_d3d12_dynamic_state;
#endif
bool rasterization_stream;
bool transform_feedback_queries;
@ -712,7 +715,9 @@ int vkd3d_parse_root_signature_v_1_0(const struct vkd3d_shader_code *dxbc,
struct d3d12_graphics_pipeline_state
{
VkPipelineShaderStageCreateInfo stages[VKD3D_MAX_SHADER_STAGES];
VkPipeline static_pipeline;
VkPipelineShaderStageCreateInfo stages[VKD3D_MAX_SHADER_STAGES];
size_t stage_count;
VkVertexInputAttributeDescription attributes[D3D12_VS_INPUT_REGISTER_COUNT];
@ -733,6 +738,8 @@ struct d3d12_graphics_pipeline_state
VkPipelineMultisampleStateCreateInfo ms_desc;
VkPipelineDepthStencilStateCreateInfo ds_desc;
D3D12_PRIMITIVE_TOPOLOGY_TYPE topology_type;
VkSampleMask sample_mask[2];
VkPipelineRasterizationDepthClipStateCreateInfoEXT rs_depth_clip_info;
VkPipelineRasterizationStateStreamCreateInfoEXT rs_stream_info;

View File

@ -206,6 +206,15 @@ VK_DEVICE_EXT_PFN(vkCmdBindTransformFeedbackBuffersEXT)
VK_DEVICE_EXT_PFN(vkCmdEndQueryIndexedEXT)
VK_DEVICE_EXT_PFN(vkCmdEndTransformFeedbackEXT)
#ifdef VK_HACK_d3d12_dynamic_state
VK_DEVICE_EXT_PFN(vkCmdSetViewportCountHACK)
VK_DEVICE_EXT_PFN(vkCmdSetScissorCountHACK)
VK_DEVICE_EXT_PFN(vkCmdBindVertexBuffersWithStrideHACK)
VK_DEVICE_EXT_PFN(vkCmdSetPrimitiveTopologyHACK)
#else
#warning "Header does not have VK_HACK_d3d12_dynamic_state entrypoints."
#endif
#undef VK_INSTANCE_PFN
#undef VK_INSTANCE_EXT_PFN
#undef VK_DEVICE_PFN