From 28281001439c2f6bf0b35788373616db96fb87b2 Mon Sep 17 00:00:00 2001 From: Alex S Date: Sat, 19 Jun 2021 18:33:57 +0300 Subject: [PATCH 1/2] Reduce feature flag surface for descriptor arrays. DYNAMIC_INDEXING is checked by default, since WGPU doesn't allow for any kind of specialization constants and constant indexing is nigh useless. STORAGE_RESOURCE_BINDING_ARRAY is enabled iff the device supports: - both or neither of uniform and buffer arrays with dynamic indexing; - both or neither of sampled and storage images with dynamic indexing. NONUNIFORM_INDEXING is enabled iff for ALL types of descriptor arrays *that are supported for dynamic indexing*, nonuniform indexing is also allowed. These flags have a limitation in that some platforms (eg. https://vulkan.gpuinfo.org/displayreport.php?id=11692#features_core_12) may support a strange subset of those features (example device supporting non-uniform indexing for textures and storage buffers, but NOT for storage textures or uniform buffers). In that case feature will be reported as missing, even though it is partially present. In the author's opinion, this flag set is convenient for the users to query; however, due to aforementioned limitations, it would be desirable to obtain statistics about "edge-case" platforms and what percentage of reports they comprise. --- wgpu-core/src/device/mod.rs | 15 ++- wgpu-hal/src/metal/adapter.rs | 18 ++- wgpu-hal/src/vulkan/adapter.rs | 165 +++++++++++++++++++-------- wgpu-types/src/lib.rs | 165 ++++----------------------- wgpu/examples/texture-arrays/main.rs | 22 ++-- wgpu/src/backend/direct.rs | 5 +- 6 files changed, 164 insertions(+), 226 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index a1a861bbfc..50d5ae839f 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -988,11 +988,20 @@ impl Device { Bt::Buffer { ty: wgt::BufferBindingType::Storage { read_only }, .. - } => (Some(wgt::Features::BUFFER_BINDING_ARRAY), !read_only), + } => ( + Some( + wgt::Features::BUFFER_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY, + ), + !read_only, + ), Bt::Sampler { .. } => (None, false), - Bt::Texture { .. } => (Some(wgt::Features::SAMPLED_TEXTURE_BINDING_ARRAY), false), + Bt::Texture { .. } => (Some(wgt::Features::TEXTURE_BINDING_ARRAY), false), Bt::StorageTexture { access, .. } => ( - Some(wgt::Features::STORAGE_TEXTURE_BINDING_ARRAY), + Some( + wgt::Features::TEXTURE_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY, + ), match access { wgt::StorageTextureAccess::ReadOnly => false, wgt::StorageTextureAccess::WriteOnly => true, diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index b9d55e3a22..936a8423ed 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -848,22 +848,18 @@ impl super::PrivateCapabilities { | F::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES; features.set( - F::SAMPLED_TEXTURE_BINDING_ARRAY - | F::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING - | F::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + F::TEXTURE_BINDING_ARRAY | F::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, self.msl_version >= MTLLanguageVersion::V2_0 && self.supports_arrays_of_textures, ); //// XXX: this is technically not true, as read-only storage images can be used in arrays //// on precisely the same conditions that sampled textures can. But texel fetch from a //// sampled texture is a thing; should we bother introducing another feature flag? - features.set( - F::STORAGE_TEXTURE_BINDING_ARRAY - | F::STORAGE_TEXTURE_ARRAY_DYNAMIC_INDEXING - | F::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, - self.msl_version >= MTLLanguageVersion::V2_2 - && self.supports_arrays_of_textures - && self.supports_arrays_of_textures_write, - ); + if self.msl_version >= MTLLanguageVersion::V2_2 + && self.supports_arrays_of_textures + && self.supports_arrays_of_textures_write + { + features.insert(F::STORAGE_RESOURCE_BINDING_ARRAY); + } features.set( F::ADDRESS_MODE_CLAMP_TO_BORDER, self.sampler_clamp_to_border, diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index a886925f5a..dbf0df96e7 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -11,9 +11,7 @@ use std::{ffi::CStr, mem, ptr, sync::Arc}; //TODO: const fn? fn indexing_features() -> wgt::Features { - wgt::Features::UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING - | wgt::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING - | wgt::Features::STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING + wgt::Features::BUFFER_BINDING_ARRAY | wgt::Features::TEXTURE_BINDING_ARRAY } /// Aggregate of the `vk::PhysicalDevice*Features` structs used by `gfx`. @@ -106,17 +104,19 @@ impl PhysicalDeviceFeatures { //.shader_image_gather_extended( //.shader_storage_image_extended_formats( .shader_uniform_buffer_array_dynamic_indexing( - requested_features - .contains(wgt::Features::UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING), + requested_features.contains(wgt::Features::BUFFER_BINDING_ARRAY), ) + .shader_storage_buffer_array_dynamic_indexing(requested_features.contains( + wgt::Features::BUFFER_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY, + )) .shader_sampled_image_array_dynamic_indexing( - requested_features - .contains(wgt::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING), - ) - .shader_storage_buffer_array_dynamic_indexing( - requested_features - .contains(wgt::Features::STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING), + requested_features.contains(wgt::Features::TEXTURE_BINDING_ARRAY), ) + .shader_storage_buffer_array_dynamic_indexing(requested_features.contains( + wgt::Features::TEXTURE_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY, + )) //.shader_storage_image_array_dynamic_indexing( //.shader_clip_distance(requested_features.contains(wgt::Features::SHADER_CLIP_DISTANCE)) //.shader_cull_distance(requested_features.contains(wgt::Features::SHADER_CULL_DISTANCE)) @@ -135,18 +135,30 @@ impl PhysicalDeviceFeatures { .descriptor_indexing(requested_features.intersects(indexing_features())) .shader_sampled_image_array_non_uniform_indexing( requested_features.contains( - wgt::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + wgt::Features::TEXTURE_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, ), ) .shader_storage_image_array_non_uniform_indexing( requested_features.contains( - wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + wgt::Features::TEXTURE_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, ), ) //.shader_storage_buffer_array_non_uniform_indexing( .shader_uniform_buffer_array_non_uniform_indexing( - requested_features - .contains(wgt::Features::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING), + requested_features.contains( + wgt::Features::BUFFER_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, + ), + ) + .shader_storage_buffer_array_non_uniform_indexing( + requested_features.contains( + wgt::Features::BUFFER_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, + ), ) .runtime_descriptor_array( requested_features.contains(wgt::Features::UNSIZED_BINDING_ARRAY), @@ -165,18 +177,30 @@ impl PhysicalDeviceFeatures { vk::PhysicalDeviceDescriptorIndexingFeaturesEXT::builder() .shader_sampled_image_array_non_uniform_indexing( requested_features.contains( - wgt::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + wgt::Features::TEXTURE_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, ), ) .shader_storage_image_array_non_uniform_indexing( requested_features.contains( - wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + wgt::Features::TEXTURE_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, ), ) //.shader_storage_buffer_array_non_uniform_indexing( .shader_uniform_buffer_array_non_uniform_indexing( - requested_features - .contains(wgt::Features::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING), + requested_features.contains( + wgt::Features::BUFFER_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, + ), + ) + .shader_storage_buffer_array_non_uniform_indexing( + requested_features.contains( + wgt::Features::BUFFER_BINDING_ARRAY + | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY + | wgt::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING, + ), ) .runtime_descriptor_array( requested_features.contains(wgt::Features::UNSIZED_BINDING_ARRAY), @@ -207,9 +231,6 @@ impl PhysicalDeviceFeatures { | F::MAPPABLE_PRIMARY_BUFFERS | F::PUSH_CONSTANTS | F::ADDRESS_MODE_CLAMP_TO_BORDER - | F::SAMPLED_TEXTURE_BINDING_ARRAY - | F::STORAGE_TEXTURE_BINDING_ARRAY - | F::BUFFER_BINDING_ARRAY | F::TIMESTAMP_QUERY | F::PIPELINE_STATISTICS_QUERY | F::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES; @@ -250,21 +271,28 @@ impl PhysicalDeviceFeatures { //if self.core.shader_image_gather_extended != 0 { //if self.core.shader_storage_image_extended_formats != 0 { features.set( - F::UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING, + F::BUFFER_BINDING_ARRAY, self.core.shader_uniform_buffer_array_dynamic_indexing != 0, ); features.set( - F::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING, + F::TEXTURE_BINDING_ARRAY, self.core.shader_sampled_image_array_dynamic_indexing != 0, ); - features.set( - F::STORAGE_TEXTURE_ARRAY_DYNAMIC_INDEXING, - self.core.shader_storage_image_array_dynamic_indexing != 0, - ); - features.set( - F::STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING, - self.core.shader_storage_buffer_array_dynamic_indexing != 0, - ); + if Self::all_features_supported( + &features, + &[ + ( + F::BUFFER_BINDING_ARRAY, + self.core.shader_storage_buffer_array_dynamic_indexing, + ), + ( + F::TEXTURE_BINDING_ARRAY, + self.core.shader_storage_image_array_dynamic_indexing, + ), + ], + ) { + features.insert(F::STORAGE_RESOURCE_BINDING_ARRAY); + } //if self.core.shader_storage_image_array_dynamic_indexing != 0 { //if self.core.shader_clip_distance != 0 { //if self.core.shader_cull_distance != 0 { @@ -284,15 +312,29 @@ impl PhysicalDeviceFeatures { ); if let Some(ref vulkan_1_2) = self.vulkan_1_2 { - if vulkan_1_2.shader_sampled_image_array_non_uniform_indexing != 0 { - features |= F::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING; - } - if vulkan_1_2.shader_storage_image_array_non_uniform_indexing != 0 { - features |= F::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING; - } - //if vulkan_1_2.shader_storage_buffer_array_non_uniform_indexing != 0 { - if vulkan_1_2.shader_uniform_buffer_array_non_uniform_indexing != 0 { - features |= F::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING; + const STORAGE: F = F::STORAGE_RESOURCE_BINDING_ARRAY; + if Self::all_features_supported( + &features, + &[ + ( + F::BUFFER_BINDING_ARRAY, + vulkan_1_2.shader_uniform_buffer_array_non_uniform_indexing, + ), + ( + F::TEXTURE_BINDING_ARRAY, + vulkan_1_2.shader_sampled_image_array_non_uniform_indexing, + ), + ( + F::BUFFER_BINDING_ARRAY | STORAGE, + vulkan_1_2.shader_storage_buffer_array_non_uniform_indexing, + ), + ( + F::TEXTURE_BINDING_ARRAY | STORAGE, + vulkan_1_2.shader_storage_image_array_non_uniform_indexing, + ), + ], + ) { + features.insert(F::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING); } if vulkan_1_2.runtime_descriptor_array != 0 { features |= F::UNSIZED_BINDING_ARRAY; @@ -305,15 +347,29 @@ impl PhysicalDeviceFeatures { } if let Some(ref descriptor_indexing) = self.descriptor_indexing { - if descriptor_indexing.shader_sampled_image_array_non_uniform_indexing != 0 { - features |= F::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING; - } - if descriptor_indexing.shader_storage_image_array_non_uniform_indexing != 0 { - features |= F::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING; - } - //if descriptor_indexing.shader_storage_buffer_array_non_uniform_indexing != 0 { - if descriptor_indexing.shader_uniform_buffer_array_non_uniform_indexing != 0 { - features |= F::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING; + const STORAGE: F = F::STORAGE_RESOURCE_BINDING_ARRAY; + if Self::all_features_supported( + &features, + &[ + ( + F::BUFFER_BINDING_ARRAY, + descriptor_indexing.shader_uniform_buffer_array_non_uniform_indexing, + ), + ( + F::TEXTURE_BINDING_ARRAY, + descriptor_indexing.shader_sampled_image_array_non_uniform_indexing, + ), + ( + F::BUFFER_BINDING_ARRAY | STORAGE, + descriptor_indexing.shader_storage_buffer_array_non_uniform_indexing, + ), + ( + F::TEXTURE_BINDING_ARRAY | STORAGE, + descriptor_indexing.shader_storage_image_array_non_uniform_indexing, + ), + ], + ) { + features.insert(F::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING); } if descriptor_indexing.runtime_descriptor_array != 0 { features |= F::UNSIZED_BINDING_ARRAY; @@ -322,6 +378,15 @@ impl PhysicalDeviceFeatures { (features, dl_flags) } + + fn all_features_supported( + features: &wgt::Features, + implications: &[(wgt::Features, vk::Bool32)], + ) -> bool { + implications + .iter() + .all(|&(flag, support)| !features.contains(flag) || support != 0) + } } /// Information gathered about a physical device capabilities. diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 8455888181..af865e3def 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -235,11 +235,16 @@ bitflags::bitflags! { /// /// This is a native only feature. const MAPPABLE_PRIMARY_BUFFERS = 0x0000_0000_0001_0000; - /// Allows the user to create uniform arrays of sampled textures in shaders: + /// Allows the user to create uniform arrays of textures in shaders: /// /// eg. `uniform texture2D textures[10]`. /// - /// This capability allows them to exist and to be indexed by compile time constant + /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user + /// may also create uniform arrays of storage textures. + /// + /// eg. `uniform image2D textures[10]`. + /// + /// This capability allows them to exist and to be indexed by dynamically uniform /// values. /// /// Supported platforms: @@ -248,21 +253,8 @@ bitflags::bitflags! { /// - Vulkan /// /// This is a native only feature. - const SAMPLED_TEXTURE_BINDING_ARRAY = 0x0000_0000_0002_0000; - /// Allows shaders to index sampled texture arrays with dynamically uniform values: - /// - /// eg. `texture_array[uniform_value]` - /// - /// This capability means the hardware will also support SAMPLED_TEXTURE_BINDING_ARRAY. - /// - /// Supported platforms: - /// - DX12 - /// - Metal (with MSL 2.0+ on macOS 10.13+) - /// - Vulkan's shaderSampledImageArrayDynamicIndexing feature - /// - /// This is a native only feature. - const SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING = 0x0000_0000_0004_0000; - /// Allows shaders to index sampled texture arrays with dynamically non-uniform values: + const TEXTURE_BINDING_ARRAY = 0x0000_0000_0002_0000; + /// Allows shaders to index resource arrays with dynamically non-uniform values: /// /// eg. `texture_array[vertex_data]` /// @@ -280,21 +272,18 @@ bitflags::bitflags! { /// /// HLSL does not need any extension. /// - /// This capability means the hardware will also support SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING - /// and SAMPLED_TEXTURE_BINDING_ARRAY. - /// /// Supported platforms: /// - DX12 /// - Metal (with MSL 2.0+ on macOS 10.13+) /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderSampledImageArrayNonUniformIndexing feature) /// /// This is a native only feature. - const SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 0x0000_0000_0008_0000; + const RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING = 0x0000_0000_0008_0000; /// Allows the user to create unsized uniform arrays of bindings: /// /// eg. `uniform texture2D textures[]`. /// - /// If this capability is supported, SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING is very likely + /// If this capability is supported, [`Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING`] is very likely /// to also be supported /// /// Supported platforms: @@ -437,93 +426,20 @@ bitflags::bitflags! { /// /// eg. `uniform myBuffer { .... } buffer_array[10]`. /// - /// This capability allows them to exist and to be indexed by compile time constant + /// This capability allows them to exist and to be indexed by dynamically uniform /// values. /// + /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user + /// may also create arrays of storage buffers. + /// + /// eg. `buffer myBuffer { ... } buffer_array[10]` + /// /// Supported platforms: /// - DX12 /// - Vulkan /// /// This is a native only feature. const BUFFER_BINDING_ARRAY = 0x0000_0001_0000_0000; - /// Allows shaders to index uniform buffer arrays with dynamically uniform values: - /// - /// eg. `buffer_array[uniform_value]` - /// - /// This capability means the hardware will also support BUFFER_BINDING_ARRAY. - /// - /// Supported platforms: - /// - DX12 - /// - Vulkan's shaderUniformBufferArrayDynamicIndexing feature - /// - /// This is a native only feature. - const UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING = 0x0000_0002_0000_0000; - /// Allows shaders to index uniform buffer arrays with dynamically non-uniform values: - /// - /// eg. `buffer_array[vertex_data]` - /// - /// In order to use this capability, the corresponding GLSL extension must be enabled like so: - /// - /// `#extension GL_EXT_nonuniform_qualifier : require` - /// - /// and then used either as `nonuniformEXT` qualifier in variable declaration: - /// - /// eg. `layout(location = 0) nonuniformEXT flat in int vertex_data;` - /// - /// or as `nonuniformEXT` constructor: - /// - /// eg. `buffer_array[nonuniformEXT(vertex_data)]` - /// - /// HLSL does not need any extension. - /// - /// This capability means the hardware will also support UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING - /// and BUFFER_BINDING_ARRAY. - /// - /// Supported platforms: - /// - DX12 - /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderUniformBufferArrayNonUniformIndexing feature) - /// - /// This is a native only feature. - const UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 0x0000_0004_0000_0000; - /// Allows shaders to index storage buffer arrays with dynamically uniform values: - /// - /// eg. `buffer_array[uniform_value]` - /// - /// This capability means the hardware will also support BUFFER_BINDING_ARRAY. - /// - /// Supported platforms: - /// - DX12 - /// - Vulkan's shaderStorageBufferArrayDynamicIndexing feature - /// - /// This is a native only feature. - const STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING = 0x0000_0008_0000_0000; - /// Allows shaders to index storage buffer arrays with dynamically non-uniform values: - /// - /// eg. `buffer_array[vertex_data]` - /// - /// In order to use this capability, the corresponding GLSL extension must be enabled like so: - /// - /// `#extension GL_EXT_nonuniform_qualifier : require` - /// - /// and then used either as `nonuniformEXT` qualifier in variable declaration: - /// - /// eg. `layout(location = 0) nonuniformEXT flat in int vertex_data;` - /// - /// or as `nonuniformEXT` constructor: - /// - /// eg. `buffer_array[nonuniformEXT(vertex_data)]` - /// - /// HLSL does not need any extension. - /// - /// This capability means the hardware will also support STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING - /// and BUFFER_BINDING_ARRAY. - /// - /// Supported platforms: - /// - DX12 - /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderStorageBufferArrayNonUniformIndexing feature) - /// - /// This is a native only feature. - const STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 0x0000_0010_0000_0000; /// Enables bindings of writable storage buffers and textures visible to vertex shaders. /// /// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects. @@ -533,11 +449,11 @@ bitflags::bitflags! { /// /// This is a native-only feature. const VERTEX_WRITABLE_STORAGE = 0x0000_0020_0000_0000; - /// Allows the user to create uniform arrays of storage textures in shaders: + /// Allows the user to create uniform arrays of storage buffers or textures in shaders, + /// if resp. [`Features::BUFFER_BINDING_ARRAY`] or [`Features::TEXTURE_BINDING_ARRAY`] + /// is supported. /// - /// eg. `uniform image2D textures[10]`. - /// - /// This capability allows them to exist and to be indexed by compile time constant + /// This capability allows them to exist and to be indexed by dynamically uniform /// values. /// /// Supported platforms: @@ -545,44 +461,7 @@ bitflags::bitflags! { /// - Vulkan /// /// This is a native only feature. - const STORAGE_TEXTURE_BINDING_ARRAY = 0x0000_0040_0000_0000; - /// Allows shaders to index storage texture arrays with dynamically uniform values: - /// - /// eg. `texture_array[uniform_value]` - /// - /// This capability means the hardware will also support STORAGE_TEXTURE_BINDING_ARRAY. - /// - /// Supported platforms: - /// - Metal (with MSL 2.2+ on macOS 10.13+) - /// - Vulkan's shaderSampledImageArrayDynamicIndexing feature - /// - /// This is a native only feature. - const STORAGE_TEXTURE_ARRAY_DYNAMIC_INDEXING = 0x0000_0080_0000_0000; - /// Allows shaders to index storage texture arrays with dynamically non-uniform values: - /// - /// eg. `texture_array[vertex_data]` - /// - /// In order to use this capability, the corresponding GLSL extension must be enabled like so: - /// - /// `#extension GL_EXT_nonuniform_qualifier : require` - /// - /// and then used either as `nonuniformEXT` qualifier in variable declaration: - /// - /// eg. `layout(location = 0) nonuniformEXT flat in int vertex_data;` - /// - /// or as `nonuniformEXT` constructor: - /// - /// eg. `texture_array[nonuniformEXT(vertex_data)]` - /// - /// This capability means the hardware will also support STORAGE_TEXTURE_ARRAY_DYNAMIC_INDEXING - /// and STORAGE_TEXTURE_BINDING_ARRAY. - /// - /// Supported platforms: - /// - Metal (with MSL 2.2+ on macOS 10.13+) - /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderSampledImageArrayNonUniformIndexing feature) - /// - /// This is a native only feature. - const STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 0x0000_0100_0000_0000; + const STORAGE_RESOURCE_BINDING_ARRAY = 0x0000_0040_0000_0000; /// Enables clear to zero for buffers & images. /// /// Supported platforms: diff --git a/wgpu/examples/texture-arrays/main.rs b/wgpu/examples/texture-arrays/main.rs index 8dbbac9870..41cbaf7fec 100644 --- a/wgpu/examples/texture-arrays/main.rs +++ b/wgpu/examples/texture-arrays/main.rs @@ -72,12 +72,11 @@ struct Example { impl framework::Example for Example { fn optional_features() -> wgpu::Features { wgpu::Features::UNSIZED_BINDING_ARRAY - | wgpu::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING - | wgpu::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING + | wgpu::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING | wgpu::Features::PUSH_CONSTANTS } fn required_features() -> wgpu::Features { - wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY | wgpu::Features::SPIRV_SHADER_PASSTHROUGH + wgpu::Features::TEXTURE_BINDING_ARRAY | wgpu::Features::SPIRV_SHADER_PASSTHROUGH } fn required_limits() -> wgpu::Limits { wgpu::Limits { @@ -94,23 +93,16 @@ impl framework::Example for Example { let mut uniform_workaround = false; let vs_module = device.create_shader_module(&wgpu::include_spirv!("shader.vert.spv")); let fs_source = match device.features() { - //f if f.contains(wgpu::Features::UNSIZED_BINDING_ARRAY) => { - // wgpu::include_spirv_raw!("unsized-non-uniform.frag.spv") - //} - f if f.contains(wgpu::Features::SAMPLED_TEXTURE_ARRAY_NON_UNIFORM_INDEXING) => { + f if f.contains(wgpu::Features::UNSIZED_BINDING_ARRAY) => { + wgpu::include_spirv_raw!("unsized-non-uniform.frag.spv") + } + f if f.contains(wgpu::Features::RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING) => { wgpu::include_spirv_raw!("non-uniform.frag.spv") } - f if f.contains( - wgpu::Features::SAMPLED_TEXTURE_ARRAY_DYNAMIC_INDEXING - | wgpu::Features::PUSH_CONSTANTS, - ) => - { + f if f.contains(wgpu::Features::TEXTURE_BINDING_ARRAY) => { uniform_workaround = true; wgpu::include_spirv_raw!("uniform.frag.spv") } - f if f.contains(wgpu::Features::SAMPLED_TEXTURE_BINDING_ARRAY) => { - wgpu::include_spirv_raw!("constant.frag.spv") - } _ => unreachable!(), }; let fs_module = unsafe { device.create_shader_module_spirv(&fs_source) }; diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 27c2bc2a7c..c5fc381593 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -896,10 +896,7 @@ impl crate::Context for Context { use wgc::binding_model as bm; let mut arrayed_texture_views = Vec::new(); - if device - .features - .contains(Features::SAMPLED_TEXTURE_BINDING_ARRAY) - { + if device.features.contains(Features::TEXTURE_BINDING_ARRAY) { // gather all the array view IDs first for entry in desc.entries.iter() { if let BindingResource::TextureViewArray(array) = entry.resource { From b4b3dd720c483701139ca7fc99158fb0e51e11ba Mon Sep 17 00:00:00 2001 From: Alex S Date: Mon, 28 Jun 2021 14:12:12 +0300 Subject: [PATCH 2/2] Reorder & reassign flags to group up the binding flags together. --- player/tests/data/buffer-clear.ron | 2 +- player/tests/data/clear-buffer-image.ron | 4 +- wgpu-types/src/lib.rs | 99 +++++++++++++----------- 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/player/tests/data/buffer-clear.ron b/player/tests/data/buffer-clear.ron index c11b15800b..a6a29f1af9 100644 --- a/player/tests/data/buffer-clear.ron +++ b/player/tests/data/buffer-clear.ron @@ -1,5 +1,5 @@ ( - features: (bits: 0x0000_0001_0000_0000), + features: (bits: 0x0000_0004_0000_0000), expectations: [ ( name: "basic", diff --git a/player/tests/data/clear-buffer-image.ron b/player/tests/data/clear-buffer-image.ron index 42fff3a0b1..9cd31b8372 100644 --- a/player/tests/data/clear-buffer-image.ron +++ b/player/tests/data/clear-buffer-image.ron @@ -1,5 +1,5 @@ ( - features: (bits: 0x0000_0200_0000_0000), + features: (bits: 0x0000_0004_0000_0000), expectations: [ ( name: "Quad", @@ -95,4 +95,4 @@ ) ]), ], -) \ No newline at end of file +) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index af865e3def..c05f8c2a67 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -254,6 +254,37 @@ bitflags::bitflags! { /// /// This is a native only feature. const TEXTURE_BINDING_ARRAY = 0x0000_0000_0002_0000; + /// Allows the user to create arrays of buffers in shaders: + /// + /// eg. `uniform myBuffer { .... } buffer_array[10]`. + /// + /// This capability allows them to exist and to be indexed by dynamically uniform + /// values. + /// + /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user + /// may also create arrays of storage buffers. + /// + /// eg. `buffer myBuffer { ... } buffer_array[10]` + /// + /// Supported platforms: + /// - DX12 + /// - Vulkan + /// + /// This is a native only feature. + const BUFFER_BINDING_ARRAY = 0x0000_0000_0004_0000; + /// Allows the user to create uniform arrays of storage buffers or textures in shaders, + /// if resp. [`Features::BUFFER_BINDING_ARRAY`] or [`Features::TEXTURE_BINDING_ARRAY`] + /// is supported. + /// + /// This capability allows them to exist and to be indexed by dynamically uniform + /// values. + /// + /// Supported platforms: + /// - Metal (with MSL 2.2+ on macOS 10.13+) + /// - Vulkan + /// + /// This is a native only feature. + const STORAGE_RESOURCE_BINDING_ARRAY = 0x0000_0000_0008_0000; /// Allows shaders to index resource arrays with dynamically non-uniform values: /// /// eg. `texture_array[vertex_data]` @@ -278,7 +309,7 @@ bitflags::bitflags! { /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderSampledImageArrayNonUniformIndexing feature) /// /// This is a native only feature. - const RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING = 0x0000_0000_0008_0000; + const RESOURCE_BINDING_ARRAY_NON_UNIFORM_INDEXING = 0x0000_0000_0010_0000; /// Allows the user to create unsized uniform arrays of bindings: /// /// eg. `uniform texture2D textures[]`. @@ -291,7 +322,7 @@ bitflags::bitflags! { /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s runtimeDescriptorArray feature /// /// This is a native only feature. - const UNSIZED_BINDING_ARRAY = 0x0000_0000_0010_0000; + const UNSIZED_BINDING_ARRAY = 0x0000_0000_0020_0000; /// Allows the user to call [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`]. /// /// Allows multiple indirect calls to be dispatched from a single buffer. @@ -302,7 +333,7 @@ bitflags::bitflags! { /// - Vulkan /// /// This is a native only feature. - const MULTI_DRAW_INDIRECT = 0x0000_0000_0020_0000; + const MULTI_DRAW_INDIRECT = 0x0000_0000_0040_0000; /// Allows the user to call [`RenderPass::multi_draw_indirect_count`] and [`RenderPass::multi_draw_indexed_indirect_count`]. /// /// This allows the use of a buffer containing the actual number of draw calls. @@ -312,7 +343,7 @@ bitflags::bitflags! { /// - Vulkan 1.2+ (or VK_KHR_draw_indirect_count) /// /// This is a native only feature. - const MULTI_DRAW_INDIRECT_COUNT = 0x0000_0000_0040_0000; + const MULTI_DRAW_INDIRECT_COUNT = 0x0000_0000_0080_0000; /// Allows the use of push constants: small, fast bits of memory that can be updated /// inside a [`RenderPass`]. /// @@ -329,7 +360,7 @@ bitflags::bitflags! { /// - OpenGL (emulated with uniforms) /// /// This is a native only feature. - const PUSH_CONSTANTS = 0x0000_0000_0080_0000; + const PUSH_CONSTANTS = 0x0000_0000_0100_0000; /// Allows the use of [`AddressMode::ClampToBorder`]. /// /// Supported platforms: @@ -340,7 +371,7 @@ bitflags::bitflags! { /// - OpenGL /// /// This is a web and native feature. - const ADDRESS_MODE_CLAMP_TO_BORDER = 0x0000_0000_0100_0000; + const ADDRESS_MODE_CLAMP_TO_BORDER = 0x0000_0000_0200_0000; /// Allows the user to set a non-fill polygon mode in [`PrimitiveState::polygon_mode`] /// /// This allows drawing polygons/triangles as lines (wireframe) or points instead of filled @@ -350,7 +381,7 @@ bitflags::bitflags! { /// - Vulkan /// /// This is a native only feature. - const NON_FILL_POLYGON_MODE = 0x0000_0000_0200_0000; + const NON_FILL_POLYGON_MODE = 0x0000_0000_0400_0000; /// Enables ETC family of compressed textures. All ETC textures use 4x4 pixel blocks. /// ETC2 RGB and RGBA1 are 8 bytes per block. RTC2 RGBA8 and EAC are 16 bytes per block. /// @@ -365,7 +396,7 @@ bitflags::bitflags! { /// - Mobile (some) /// /// This is a native-only feature. - const TEXTURE_COMPRESSION_ETC2 = 0x0000_0000_0400_0000; + const TEXTURE_COMPRESSION_ETC2 = 0x0000_0000_0800_0000; /// Enables ASTC family of compressed textures. ASTC textures use pixel blocks varying from 4x4 to 12x12. /// Blocks are always 16 bytes. /// @@ -380,7 +411,7 @@ bitflags::bitflags! { /// - Mobile (some) /// /// This is a native-only feature. - const TEXTURE_COMPRESSION_ASTC_LDR = 0x0000_0000_0800_0000; + const TEXTURE_COMPRESSION_ASTC_LDR = 0x0000_0000_1000_0000; /// Enables device specific texture format features. /// /// See `TextureFormatFeatures` for a listing of the features in question. @@ -392,7 +423,7 @@ bitflags::bitflags! { /// This extension does not enable additional formats. /// /// This is a native-only feature. - const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 0x0000_0000_1000_0000; + const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 0x0000_0000_2000_0000; /// Enables 64-bit floating point types in SPIR-V shaders. /// /// Note: even when supported by GPU hardware, 64-bit floating point operations are @@ -402,7 +433,7 @@ bitflags::bitflags! { /// - Vulkan /// /// This is a native-only feature. - const SHADER_FLOAT64 = 0x0000_0000_2000_0000; + const SHADER_FLOAT64 = 0x0000_0000_4000_0000; /// Enables using 64-bit types for vertex attributes. /// /// Requires SHADER_FLOAT64. @@ -410,7 +441,7 @@ bitflags::bitflags! { /// Supported Platforms: N/A /// /// This is a native-only feature. - const VERTEX_ATTRIBUTE_64BIT = 0x0000_0000_4000_0000; + const VERTEX_ATTRIBUTE_64BIT = 0x0000_0000_8000_0000; /// Allows the user to set a overestimation-conservative-rasterization in [`PrimitiveState::conservative`] /// /// Processing of degenerate triangles/lines is hardware specific. @@ -421,25 +452,7 @@ bitflags::bitflags! { /// - Vulkan /// /// This is a native only feature. - const CONSERVATIVE_RASTERIZATION = 0x0000_0000_8000_0000; - /// Allows the user to create arrays of buffers in shaders: - /// - /// eg. `uniform myBuffer { .... } buffer_array[10]`. - /// - /// This capability allows them to exist and to be indexed by dynamically uniform - /// values. - /// - /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user - /// may also create arrays of storage buffers. - /// - /// eg. `buffer myBuffer { ... } buffer_array[10]` - /// - /// Supported platforms: - /// - DX12 - /// - Vulkan - /// - /// This is a native only feature. - const BUFFER_BINDING_ARRAY = 0x0000_0001_0000_0000; + const CONSERVATIVE_RASTERIZATION = 0x0000_0001_0000_0000; /// Enables bindings of writable storage buffers and textures visible to vertex shaders. /// /// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects. @@ -448,27 +461,14 @@ bitflags::bitflags! { /// - All /// /// This is a native-only feature. - const VERTEX_WRITABLE_STORAGE = 0x0000_0020_0000_0000; - /// Allows the user to create uniform arrays of storage buffers or textures in shaders, - /// if resp. [`Features::BUFFER_BINDING_ARRAY`] or [`Features::TEXTURE_BINDING_ARRAY`] - /// is supported. - /// - /// This capability allows them to exist and to be indexed by dynamically uniform - /// values. - /// - /// Supported platforms: - /// - Metal (with MSL 2.2+ on macOS 10.13+) - /// - Vulkan - /// - /// This is a native only feature. - const STORAGE_RESOURCE_BINDING_ARRAY = 0x0000_0040_0000_0000; + const VERTEX_WRITABLE_STORAGE = 0x0000_0002_0000_0000; /// Enables clear to zero for buffers & images. /// /// Supported platforms: /// - All /// /// This is a native only feature. - const CLEAR_COMMANDS = 0x0000_0200_0000_0000; + const CLEAR_COMMANDS = 0x0000_0400_0000_0000; /// Enables creating shader modules from SPIR-V binary data (unsafe). /// /// SPIR-V data is not parsed or interpreted in any way; you can use @@ -480,7 +480,12 @@ bitflags::bitflags! { /// Vulkan implementation. /// /// This is a native only feature. - const SPIRV_SHADER_PASSTHROUGH = 0x0000_0400_0000_0000; + const SPIRV_SHADER_PASSTHROUGH = 0x0000_0800_0000_0000; + + /// Features which are part of the upstream WebGPU standard. + const ALL_WEBGPU = 0x0000_0000_0000_FFFF; + /// Features that are only available when targeting native (not web). + const ALL_NATIVE = 0xFFFF_FFFF_FFFF_0000; } }