From f4b5abf0c8aef7834e065b05404adbdcc33357c9 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Sat, 30 Mar 2024 16:52:31 -0700 Subject: [PATCH] [hal/vulkan] Don't advertise features without prerequisites present. Don't advertise features like `STORAGE_RESOURCE_BINDING_ARRAY` unless at least one of the features it extends, like `BUFFER_BINDING_ARRAY` or `TEXTURE_BINDING_ARRAY`, is actually present. See the comments on `PhysicalDevicefeatures::prequisites_satisfied` for more details. --- wgpu-hal/src/vulkan/adapter.rs | 40 ++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 4a2c328fe..27da88eeb 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -510,7 +510,7 @@ impl PhysicalDeviceFeatures { self.core.shader_sampled_image_array_dynamic_indexing != 0, ); features.set(F::SHADER_PRIMITIVE_INDEX, self.core.geometry_shader != 0); - if Self::all_features_supported( + if Self::prerequisites_satisfied( &features, &[ ( @@ -547,7 +547,7 @@ impl PhysicalDeviceFeatures { if let Some(ref descriptor_indexing) = self.descriptor_indexing { const STORAGE: F = F::STORAGE_RESOURCE_BINDING_ARRAY; - if Self::all_features_supported( + if Self::prerequisites_satisfied( &features, &[ ( @@ -562,7 +562,7 @@ impl PhysicalDeviceFeatures { ) { features.insert(F::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING); } - if Self::all_features_supported( + if Self::prerequisites_satisfied( &features, &[ ( @@ -689,13 +689,39 @@ impl PhysicalDeviceFeatures { (features, dl_flags) } - fn all_features_supported( + /// Check whether the Vulkan features needed for a wgpu [`Features`] flag are present. + /// + /// Some wgpu `Features` flags describe an extension to multiple other + /// flags. For example, [`STORAGE_RESOURCE_BINDING_ARRAY`] says that if + /// [`BUFFER_BINDING_ARRAY`] or [`TEXTURE_BINDING_ARRAY`] is present, then + /// those arrays can, furthermore, be dynamically indexed. For each of the + /// basic `Features` flags, a specific set of Vulkan features must be + /// available for the extending flag to be available. + /// + /// Given `features`, the set of [`Features`] already discovered, check if: + /// - some `Features` set in `implications` is present, and + /// - for any set that is present, the corresponding Vulkan features + /// (evaluated by the caller and passed as a bool) are available. + /// + /// [`Features`]: wgt::Features + /// [`STORAGE_RESOURCE_BINDING_ARRAY`]: wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY + /// [`BUFFER_BINDING_ARRAY`]: wgt::Features::BUFFER_BINDING_ARRAY + /// [`TEXTURE_BINDING_ARRAY`]: wgt::Features::TEXTURE_BINDING_ARRAY + fn prerequisites_satisfied( features: &wgt::Features, implications: &[(wgt::Features, vk::Bool32)], ) -> bool { - implications - .iter() - .all(|&(flag, support)| !features.contains(flag) || support != 0) + // This is both a conjunction (all the implications must be true) and a + // disjunction (at least one of them must have its antecedent + // satisfied), so the `Iterator` adapters don't clarify very much. + let mut any = false; + for &(wgpu_base_feature, vulkan_support) in implications.iter() { + if features.contains(wgpu_base_feature) && vulkan_support == 0 { + return false; + } + any = true; + } + any } }