vkd3d: Disable primitive restart when using non-compatible topologies.

Primitive restart is only used for strip primitive types, and must be
ignored for lists. Use and require extended_dynamic_state2 for this
purpose.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2021-11-02 12:35:21 +01:00
parent cfeaa18b09
commit 6f43f450c8
6 changed files with 55 additions and 3 deletions

View File

@ -29,6 +29,7 @@ There are some hard requirements on drivers to be able to implement D3D12 in a r
- `VK_KHR_copy_commands2`
- `VK_KHR_dynamic_rendering`
- `VK_EXT_extended_dynamic_state`
- `VK_EXT_extended_dynamic_state2`
Some notable extensions that **should** be supported for optimal or correct behavior.
These extensions will likely become mandatory later.

View File

@ -5254,6 +5254,15 @@ static void d3d12_command_list_update_dynamic_state(struct d3d12_command_list *l
dyn_state->vk_primitive_topology));
}
if (dyn_state->dirty_flags & VKD3D_DYNAMIC_STATE_PRIMITIVE_RESTART)
{
/* The primitive restart dynamic state is only present if the PSO
* has a strip cut value, so we only need to check if the
* current primitive topology is a strip type. */
VK_CALL(vkCmdSetPrimitiveRestartEnableEXT(list->vk_command_buffer,
vk_primitive_topology_supports_restart(dyn_state->vk_primitive_topology)));
}
if (dyn_state->dirty_flags & VKD3D_DYNAMIC_STATE_VERTEX_BUFFER_STRIDE)
{
update_vbos = (dyn_state->dirty_vbos | dyn_state->dirty_vbo_strides) & list->state->graphics.vertex_buffer_mask;
@ -6796,7 +6805,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetPrimitiveTopology(d3d12_co
dyn_state->primitive_topology = topology;
dyn_state->vk_primitive_topology = vk_topology_from_d3d12_topology(topology);
d3d12_command_list_invalidate_current_pipeline(list, false);
dyn_state->dirty_flags |= VKD3D_DYNAMIC_STATE_TOPOLOGY;
dyn_state->dirty_flags |= VKD3D_DYNAMIC_STATE_TOPOLOGY | VKD3D_DYNAMIC_STATE_PRIMITIVE_RESTART;
}
static void STDMETHODCALLTYPE d3d12_command_list_RSSetViewports(d3d12_command_list_iface *iface,

View File

@ -102,6 +102,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
VK_EXTENSION(EXT_TRANSFORM_FEEDBACK, EXT_transform_feedback),
VK_EXTENSION(EXT_VERTEX_ATTRIBUTE_DIVISOR, EXT_vertex_attribute_divisor),
VK_EXTENSION(EXT_EXTENDED_DYNAMIC_STATE, EXT_extended_dynamic_state),
VK_EXTENSION(EXT_EXTENDED_DYNAMIC_STATE_2, EXT_extended_dynamic_state2),
VK_EXTENSION(EXT_EXTERNAL_MEMORY_HOST, EXT_external_memory_host),
VK_EXTENSION(EXT_4444_FORMATS, EXT_4444_formats),
VK_EXTENSION(EXT_SHADER_IMAGE_ATOMIC_INT64, EXT_shader_image_atomic_int64),
@ -1253,6 +1254,12 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i
vk_prepend_struct(&info->features2, &info->extended_dynamic_state_features);
}
if (vulkan_info->EXT_extended_dynamic_state2)
{
info->extended_dynamic_state2_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT;
vk_prepend_struct(&info->features2, &info->extended_dynamic_state2_features);
}
if (vulkan_info->EXT_external_memory_host)
{
info->external_memory_host_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
@ -1920,6 +1927,10 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
acceleration_structure = &physical_device_info->acceleration_structure_features;
acceleration_structure->accelerationStructureCaptureReplay = VK_FALSE;
/* Don't need or require these. */
physical_device_info->extended_dynamic_state2_features.extendedDynamicState2LogicOp = VK_FALSE;
physical_device_info->extended_dynamic_state2_features.extendedDynamicState2PatchControlPoints = VK_FALSE;
if (!physical_device_info->descriptor_indexing_properties.robustBufferAccessUpdateAfterBind)
{
/* Generally, we cannot enable robustness if this is not supported,
@ -1991,6 +2002,12 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
return E_INVALIDARG;
}
if (!physical_device_info->extended_dynamic_state2_features.extendedDynamicState2)
{
ERR("EXT_extended_dynamic_state2 is not supported by this implementation. This is required for correct operation.\n");
return E_INVALIDARG;
}
return S_OK;
}

View File

@ -2822,6 +2822,7 @@ static uint32_t d3d12_graphics_pipeline_state_init_dynamic_state(struct d3d12_pi
{ VKD3D_DYNAMIC_STATE_TOPOLOGY, VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT },
{ VKD3D_DYNAMIC_STATE_VERTEX_BUFFER_STRIDE, VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT },
{ VKD3D_DYNAMIC_STATE_FRAGMENT_SHADING_RATE, VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR },
{ VKD3D_DYNAMIC_STATE_PRIMITIVE_RESTART, VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT },
};
dynamic_state_flags = 0;
@ -2866,6 +2867,9 @@ static uint32_t d3d12_graphics_pipeline_state_init_dynamic_state(struct d3d12_pi
if (d3d12_device_supports_variable_shading_rate_tier_1(state->device) && graphics->rt_count)
dynamic_state_flags |= VKD3D_DYNAMIC_STATE_FRAGMENT_SHADING_RATE;
if (graphics->index_buffer_strip_cut_value)
dynamic_state_flags |= VKD3D_DYNAMIC_STATE_PRIMITIVE_RESTART;
/* Build dynamic state create info */
for (i = 0, count = 0; i < ARRAY_SIZE(dynamic_state_list); i++)
{
@ -4144,7 +4148,7 @@ VkPipeline d3d12_pipeline_state_get_or_create_pipeline(struct d3d12_pipeline_sta
/* Try to keep as much dynamic state as possible so we don't have to rebind state unnecessarily. */
if (graphics->primitive_topology_type != D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH &&
graphics->primitive_topology_type != D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED)
graphics->primitive_topology_type != D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED)
pipeline_key.dynamic_topology = true;
else
pipeline_key.topology = dyn_state->primitive_topology;

View File

@ -149,6 +149,7 @@ struct vkd3d_vulkan_info
bool EXT_transform_feedback;
bool EXT_vertex_attribute_divisor;
bool EXT_extended_dynamic_state;
bool EXT_extended_dynamic_state2;
bool EXT_external_memory_host;
bool EXT_4444_formats;
bool EXT_shader_image_atomic_int64;
@ -1416,7 +1417,7 @@ HRESULT vkd3d_create_descriptor_set_layout(struct d3d12_device *device,
VkDescriptorSetLayoutCreateFlags flags, unsigned int binding_count,
const VkDescriptorSetLayoutBinding *bindings, VkDescriptorSetLayout *set_layout);
#define VKD3D_MAX_DYNAMIC_STATE_COUNT (7)
#define VKD3D_MAX_DYNAMIC_STATE_COUNT (8)
enum vkd3d_dynamic_state_flag
{
@ -1429,6 +1430,7 @@ enum vkd3d_dynamic_state_flag
VKD3D_DYNAMIC_STATE_VERTEX_BUFFER = (1 << 6),
VKD3D_DYNAMIC_STATE_VERTEX_BUFFER_STRIDE = (1 << 7),
VKD3D_DYNAMIC_STATE_FRAGMENT_SHADING_RATE = (1 << 8),
VKD3D_DYNAMIC_STATE_PRIMITIVE_RESTART = (1 << 9),
};
struct vkd3d_shader_debug_ring_spec_constants
@ -1608,6 +1610,21 @@ HRESULT vkd3d_pipeline_state_desc_from_d3d12_compute_desc(struct d3d12_pipeline_
HRESULT vkd3d_pipeline_state_desc_from_d3d12_stream_desc(struct d3d12_pipeline_state_desc *desc,
const D3D12_PIPELINE_STATE_STREAM_DESC *d3d12_desc, VkPipelineBindPoint *vk_bind_point);
static inline bool vk_primitive_topology_supports_restart(VkPrimitiveTopology topology)
{
switch (topology)
{
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
return true;
default:
return false;
}
}
struct vkd3d_pipeline_key
{
D3D12_PRIMITIVE_TOPOLOGY topology;
@ -2958,6 +2975,7 @@ struct vkd3d_physical_device_info
VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR subgroup_extended_types_features;
VkPhysicalDeviceRobustness2FeaturesEXT robustness2_features;
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features;
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2_features;
VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE mutable_descriptor_features;
VkPhysicalDeviceRayTracingPipelineFeaturesKHR ray_tracing_pipeline_features;
VkPhysicalDeviceAccelerationStructureFeaturesKHR acceleration_structure_features;

View File

@ -245,6 +245,9 @@ VK_DEVICE_EXT_PFN(vkCmdSetPrimitiveTopologyEXT)
VK_DEVICE_EXT_PFN(vkCmdSetScissorWithCountEXT)
VK_DEVICE_EXT_PFN(vkCmdSetViewportWithCountEXT)
/* VK_EXT_extended_dynamic_state2 */
VK_DEVICE_EXT_PFN(vkCmdSetPrimitiveRestartEnableEXT)
/* VK_EXT_external_memory_host */
VK_DEVICE_EXT_PFN(vkGetMemoryHostPointerPropertiesEXT)