From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- libs/vkd3d/device.c | 1 + libs/vkd3d/state.c | 45 +++++++++++++++++++++++++++++++++----- libs/vkd3d/vkd3d_private.h | 4 +++- 3 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index abb991942199..7a7f7f36d187 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -905,6 +905,7 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
vulkan_info->device_limits = device_properties2.properties.limits; vulkan_info->sparse_properties = device_properties2.properties.sparseProperties; + vulkan_info->max_vertex_attrib_divisor = max(vertex_divisor_properties.maxVertexAttribDivisor, 1);
device->feature_options.DoublePrecisionFloatShaderOps = features->shaderFloat64; device->feature_options.OutputMergerLogicOp = features->logicOp; diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 0deea28edb6b..7e0b1eeea553 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1866,7 +1866,10 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s 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; + VkVertexInputBindingDivisorDescriptionEXT *binding_divisor; + const struct vkd3d_vulkan_info *vk_info = &device->vk_info; const struct vkd3d_shader_compile_arguments *compile_args; + uint32_t instance_divisors[D3D12_VS_INPUT_REGISTER_COUNT]; uint32_t aligned_offsets[D3D12_VS_INPUT_REGISTER_COUNT]; struct vkd3d_shader_compile_arguments ps_compile_args; const struct d3d12_root_signature *root_signature; @@ -1877,6 +1880,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s VkSampleCountFlagBits sample_count; const struct vkd3d_format *format; enum VkVertexInputRate input_rate; + unsigned int instance_divisor; unsigned int i, j; size_t rt_count; uint32_t mask; @@ -2106,6 +2110,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s if (FAILED(hr = compute_input_layout_offsets(&desc->InputLayout, 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]; @@ -2118,7 +2123,8 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s goto fail; }
- if (e->InputSlot >= ARRAY_SIZE(graphics->input_rates)) + if (e->InputSlot >= ARRAY_SIZE(graphics->input_rates) + || e->InputSlot >= ARRAY_SIZE(instance_divisors)) { WARN("Invalid input slot %#x.\n", e->InputSlot); hr = E_INVALIDARG; @@ -2145,12 +2151,18 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s { case D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA: input_rate = VK_VERTEX_INPUT_RATE_VERTEX; + instance_divisor = 1; break;
case D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA: - if (e->InstanceDataStepRate != 1) - FIXME("Ignoring step rate %#x on input element %u.\n", e->InstanceDataStepRate, i); input_rate = VK_VERTEX_INPUT_RATE_INSTANCE; + instance_divisor = e->InstanceDataStepRate; + if (instance_divisor > vk_info->max_vertex_attrib_divisor + || (!instance_divisor && !vk_info->vertex_attrib_zero_divisor)) + { + FIXME("Instance divisor %u not supported by Vulkan implementation.\n", instance_divisor); + instance_divisor = 1; + } break;
default: @@ -2159,14 +2171,25 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s goto fail; }
- if (mask & (1u << e->InputSlot) && graphics->input_rates[e->InputSlot] != input_rate) + if (mask & (1u << e->InputSlot) && (graphics->input_rates[e->InputSlot] != input_rate + || instance_divisors[e->InputSlot] != instance_divisor)) { - FIXME("Input slot class %#x on input element %u conflicts with earlier input slot class %#x.\n", - e->InputSlotClass, e->InputSlot, graphics->input_rates[e->InputSlot]); + FIXME("Input slot rate %#x, instance divisor %u on input element %u conflicts " + "with earlier input slot rate %#x, instance divisor %u.\n", + input_rate, instance_divisor, e->InputSlot, + graphics->input_rates[e->InputSlot], instance_divisors[e->InputSlot]); hr = E_INVALIDARG; goto fail; } + graphics->input_rates[e->InputSlot] = input_rate; + instance_divisors[e->InputSlot] = instance_divisor; + if (instance_divisor != 1 && !(mask & (1u << e->InputSlot))) + { + binding_divisor = &graphics->instance_divisors[graphics->instance_divisor_count++]; + binding_divisor->binding = e->InputSlot; + binding_divisor->divisor = instance_divisor; + } mask |= 1u << e->InputSlot; } graphics->attribute_count = j; @@ -2331,6 +2354,7 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta 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; + VkPipelineVertexInputDivisorStateCreateInfoEXT input_divisor_info; struct VkPipelineVertexInputStateCreateInfo input_desc; struct VkPipelineInputAssemblyStateCreateInfo ia_desc; struct VkPipelineColorBlendStateCreateInfo blend_desc; @@ -2414,6 +2438,15 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta 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 = NULL; ia_desc.flags = 0; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 3f539805785e..a2bf4048aebb 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -86,6 +86,7 @@ struct vkd3d_vulkan_info bool EXT_vertex_attribute_divisor;
bool vertex_attrib_zero_divisor; + unsigned int max_vertex_attrib_divisor;
VkPhysicalDeviceLimits device_limits; VkPhysicalDeviceSparseProperties sparse_properties; @@ -513,6 +514,8 @@ struct d3d12_graphics_pipeline_state
struct VkVertexInputAttributeDescription attributes[D3D12_VS_INPUT_REGISTER_COUNT]; enum VkVertexInputRate input_rates[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + VkVertexInputBindingDivisorDescriptionEXT instance_divisors[D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; + size_t instance_divisor_count; size_t attribute_count;
struct VkAttachmentDescription attachments[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT + 1]; @@ -767,7 +770,6 @@ struct d3d12_device struct vkd3d_fence_worker fence_worker;
pthread_mutex_t pipeline_cache_mutex; - struct rb_tree pipeline_cache; VkPipelineCache vk_pipeline_cache;
/* A sampler used for SpvOpImageFetch. */