From 2bbd4eff69593fd1064bf92ea36ec2c83486343b Mon Sep 17 00:00:00 2001 From: Rua Date: Thu, 28 Dec 2023 20:30:51 +0100 Subject: [PATCH] More robust extension and feature dependency checks (#2434) --- vulkano/autogen/extensions.rs | 44 ++++++++++++++ vulkano/src/device/mod.rs | 106 ++++++++++++++++++++++++++-------- 2 files changed, 125 insertions(+), 25 deletions(-) diff --git a/vulkano/autogen/extensions.rs b/vulkano/autogen/extensions.rs index 9bcd0716..9563fb23 100644 --- a/vulkano/autogen/extensions.rs +++ b/vulkano/autogen/extensions.rs @@ -179,6 +179,8 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { requires_all_of, .. }| { + let name_string = name.to_string(); + let requires_all_of_items = requires_all_of .iter() .filter( @@ -213,6 +215,14 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { let base_requirement_item = { let ident = format_ident!("{}", base_requirement); quote! { + assert!( + supported.#ident, + "The device extension `{}` is enabled, and it requires \ + the `{}` extension to be also enabled, but the device \ + does not support the required extension. \ + This is a bug in the Vulkan driver for this device.", + #name_string, #base_requirement, + ); self.#ident = true; } }; @@ -355,6 +365,8 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream { requires_all_of, .. }| { + let name_string = name.to_string(); + let requires_all_of_items = requires_all_of .iter() .filter( @@ -389,6 +401,14 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream { let base_requirement_item = { let ident = format_ident!("{}", base_requirement); quote! { + assert!( + supported.#ident, + "The instance extension `{}` is enabled, and it requires \ + the `{}` extension to be also enabled, but the device \ + does not support the required extension. \ + This is a bug in the Vulkan driver.", + #name_string, #base_requirement, + ); self.#ident = true; } }; @@ -471,6 +491,18 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } }); + let count_items = members.iter().map(|ExtensionsMember { name, .. }| { + quote! { + self.#name as u64 + } + }); + + let is_empty_items = members.iter().map(|ExtensionsMember { name, .. }| { + quote! { + self.#name + } + }); + let intersects_items = members.iter().map(|ExtensionsMember { name, .. }| { quote! { (self.#name && other.#name) @@ -565,6 +597,18 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } + /// Returns the number of members set in self. + #[inline] + pub const fn count(self) -> u64 { + #(#count_items)+* + } + + /// Returns whether no members are set in `self`. + #[inline] + pub const fn is_empty(self) -> bool { + !(#(#is_empty_items)||*) + } + /// Returns whether any members are set in both `self` and `other`. #[inline] pub const fn intersects(&self, other: &Self) -> bool { diff --git a/vulkano/src/device/mod.rs b/vulkano/src/device/mod.rs index f18d1f6b..715dc71c 100644 --- a/vulkano/src/device/mod.rs +++ b/vulkano/src/device/mod.rs @@ -230,47 +230,103 @@ impl Device { create_info.enabled_extensions.khr_portability_subset = true; } + macro_rules! enable_extension_required_features { + ( + $extension:ident, + $feature_to_enable:ident $(,)? + ) => { + if create_info.enabled_extensions.$extension { + assert!( + physical_device.supported_features().$feature_to_enable, + "The device extension `{}` is enabled, and it requires the `{}` feature \ + to be also enabled, but the device does not support the required feature. \ + This is a bug in the Vulkan driver for this device.", + stringify!($extension), + stringify!($feature_to_enable), + ); + create_info.enabled_features.$feature_to_enable = true; + } + }; + } + if physical_device.api_version() >= Version::V1_1 { // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-04476 - if create_info.enabled_extensions.khr_shader_draw_parameters { - create_info.enabled_features.shader_draw_parameters = true; - } + enable_extension_required_features!(khr_shader_draw_parameters, shader_draw_parameters); } if physical_device.api_version() >= Version::V1_2 { // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02831 - if create_info.enabled_extensions.khr_draw_indirect_count { - create_info.enabled_features.draw_indirect_count = true; - } + enable_extension_required_features!(khr_draw_indirect_count, draw_indirect_count); // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02832 - if create_info - .enabled_extensions - .khr_sampler_mirror_clamp_to_edge - { - create_info.enabled_features.sampler_mirror_clamp_to_edge = true; - } + enable_extension_required_features!( + khr_sampler_mirror_clamp_to_edge, + sampler_mirror_clamp_to_edge, + ); // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02833 - if create_info.enabled_extensions.ext_descriptor_indexing { - create_info.enabled_features.descriptor_indexing = true; - } + enable_extension_required_features!(ext_descriptor_indexing, descriptor_indexing); // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02834 - if create_info.enabled_extensions.ext_sampler_filter_minmax { - create_info.enabled_features.sampler_filter_minmax = true; - } + enable_extension_required_features!(ext_sampler_filter_minmax, sampler_filter_minmax); // VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-02835 - if create_info - .enabled_extensions - .ext_shader_viewport_index_layer - { - create_info.enabled_features.shader_output_viewport_index = true; - create_info.enabled_features.shader_output_layer = true; - } + enable_extension_required_features!( + ext_shader_viewport_index_layer, + shader_output_layer, + ); + enable_extension_required_features!( + ext_shader_viewport_index_layer, + shader_output_layer, + ); } + macro_rules! enable_feature_required_features { + ( + $feature:ident, + $feature_to_enable:ident $(,)? + ) => { + if create_info.enabled_features.$feature { + assert!( + physical_device.supported_features().$feature_to_enable, + "The device feature `{}` is enabled, and it requires the `{}` feature \ + to be also enabled, but the device does not support the required feature. \ + This is a bug in the Vulkan driver for this device.", + stringify!($feature), + stringify!($feature_to_enable), + ); + create_info.enabled_features.$feature_to_enable = true; + } + }; + } + + // VUID-VkPhysicalDeviceVariablePointersFeatures-variablePointers-01431 + enable_feature_required_features!(variable_pointers, variable_pointers_storage_buffer); + + // VUID-VkPhysicalDeviceMultiviewFeatures-multiviewGeometryShader-00580 + enable_feature_required_features!(multiview_geometry_shader, multiview); + + // VUID-VkPhysicalDeviceMultiviewFeatures-multiviewTessellationShader-00581 + enable_feature_required_features!(multiview_tessellation_shader, multiview); + + // VUID-VkPhysicalDeviceMeshShaderFeaturesEXT-multiviewMeshShader-07032 + enable_feature_required_features!(multiview_mesh_shader, multiview); + + // VUID-VkPhysicalDeviceMeshShaderFeaturesEXT-primitiveFragmentShadingRateMeshShader-07033 + enable_feature_required_features!( + primitive_fragment_shading_rate_mesh_shader, + primitive_fragment_shading_rate, + ); + + // VUID-VkPhysicalDeviceRayTracingPipelineFeaturesKHR-rayTracingPipelineShaderGroupHandleCaptureReplayMixed-03575 + enable_feature_required_features!( + ray_tracing_pipeline_shader_group_handle_capture_replay_mixed, + ray_tracing_pipeline_shader_group_handle_capture_replay, + ); + + // VUID-VkPhysicalDeviceRobustness2FeaturesEXT-robustBufferAccess2-04000 + enable_feature_required_features!(robust_buffer_access2, robust_buffer_access); + let &DeviceCreateInfo { ref queue_create_infos, ref enabled_extensions,