From d8833d079833c62b4fd00325d0ba08ec0c8bc309 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Sat, 15 Feb 2025 12:02:27 -0500 Subject: [PATCH] Use Update After Bind Descriptors for Bind Groups With Binding Arrays (#6815) * Use Update After Bind Descriptors for Bind Groups With Binding Arrays Update After Bind x * Comments * Fix URL --- deno_webgpu/webidl.rs | 18 ++-- naga/src/valid/analyzer.rs | 7 +- naga/src/valid/mod.rs | 44 ++++----- tests/tests/binding_array/buffers.rs | 7 +- tests/tests/binding_array/storage_textures.rs | 4 +- wgpu-core/src/device/mod.rs | 9 +- wgpu-hal/src/dx12/adapter.rs | 2 +- wgpu-hal/src/metal/adapter.rs | 2 +- wgpu-hal/src/vulkan/adapter.rs | 92 +++++++++---------- wgpu-hal/src/vulkan/device.rs | 10 +- wgpu-types/src/features.rs | 36 ++++---- 11 files changed, 119 insertions(+), 112 deletions(-) diff --git a/deno_webgpu/webidl.rs b/deno_webgpu/webidl.rs index 98099b8a08..60ab54706c 100644 --- a/deno_webgpu/webidl.rs +++ b/deno_webgpu/webidl.rs @@ -391,8 +391,10 @@ pub enum GPUFeatureName { StorageResourceBindingArray, #[webidl(rename = "sampled-texture-and-storage-buffer-array-non-uniform-indexing")] SampledTextureAndStorageBufferArrayNonUniformIndexing, - #[webidl(rename = "uniform-buffer-and-storage-texture-array-non-uniform-indexing")] - UniformBufferAndStorageTextureArrayNonUniformIndexing, + #[webidl(rename = "storage-texture-array-non-uniform-indexing")] + StorageTextureArrayNonUniformIndexing, + #[webidl(rename = "uniform-buffer-binding-arrays")] + UniformBufferBindingArrays, #[webidl(rename = "partially-bound-binding-array")] PartiallyBoundBindingArray, #[webidl(rename = "multi-draw-indirect")] @@ -462,7 +464,8 @@ pub fn feature_names_to_features(names: Vec) -> wgpu_types::Feat GPUFeatureName::BufferBindingArray => Features::BUFFER_BINDING_ARRAY, GPUFeatureName::StorageResourceBindingArray => Features::STORAGE_RESOURCE_BINDING_ARRAY, GPUFeatureName::SampledTextureAndStorageBufferArrayNonUniformIndexing => Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, - GPUFeatureName::UniformBufferAndStorageTextureArrayNonUniformIndexing => Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + GPUFeatureName::StorageTextureArrayNonUniformIndexing => Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + GPUFeatureName::UniformBufferBindingArrays => Features::UNIFORM_BUFFER_BINDING_ARRAYS, GPUFeatureName::PartiallyBoundBindingArray => Features::PARTIALLY_BOUND_BINDING_ARRAY, GPUFeatureName::MultiDrawIndirect => Features::MULTI_DRAW_INDIRECT, GPUFeatureName::MultiDrawIndirectCount => Features::MULTI_DRAW_INDIRECT_COUNT, @@ -575,10 +578,11 @@ pub fn features_to_feature_names(features: wgpu_types::Features) -> HashSet { // these are nasty aliases, but these idents are too long and break rustfmt - let ub_st = super::Capabilities::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING; + let sto = super::Capabilities::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING; + let uni = super::Capabilities::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING; let st_sb = super::Capabilities::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING; let sampler = super::Capabilities::SAMPLER_NON_UNIFORM_INDEXING; @@ -542,7 +543,7 @@ impl FunctionInfo { needed_caps |= match *array_element_ty { // If we're an image, use the appropriate limit. crate::TypeInner::Image { class, .. } => match class { - crate::ImageClass::Storage { .. } => ub_st, + crate::ImageClass::Storage { .. } => sto, _ => st_sb, }, crate::TypeInner::Sampler { .. } => sampler, @@ -551,7 +552,7 @@ impl FunctionInfo { if let E::GlobalVariable(global_handle) = expression_arena[base] { let global = &resolve_context.global_vars[global_handle]; match global.space { - crate::AddressSpace::Uniform => ub_st, + crate::AddressSpace::Uniform => uni, crate::AddressSpace::Storage { .. } => st_sb, _ => unreachable!(), } diff --git a/naga/src/valid/mod.rs b/naga/src/valid/mod.rs index a6380cbe1e..8560404703 100644 --- a/naga/src/valid/mod.rs +++ b/naga/src/valid/mod.rs @@ -90,47 +90,49 @@ bitflags::bitflags! { const PRIMITIVE_INDEX = 1 << 2; /// Support for non-uniform indexing of sampled textures and storage buffer arrays. const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 1 << 3; - /// Support for non-uniform indexing of uniform buffers and storage texture arrays. - const UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 4; + /// Support for non-uniform indexing of storage texture arrays. + const STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 4; + /// Support for non-uniform indexing of uniform buffer arrays. + const UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 1 << 5; /// Support for non-uniform indexing of samplers. - const SAMPLER_NON_UNIFORM_INDEXING = 1 << 5; + const SAMPLER_NON_UNIFORM_INDEXING = 1 << 6; /// Support for [`BuiltIn::ClipDistance`]. /// /// [`BuiltIn::ClipDistance`]: crate::BuiltIn::ClipDistance - const CLIP_DISTANCE = 1 << 6; + const CLIP_DISTANCE = 1 << 7; /// Support for [`BuiltIn::CullDistance`]. /// /// [`BuiltIn::CullDistance`]: crate::BuiltIn::CullDistance - const CULL_DISTANCE = 1 << 7; + const CULL_DISTANCE = 1 << 8; /// Support for 16-bit normalized storage texture formats. - const STORAGE_TEXTURE_16BIT_NORM_FORMATS = 1 << 8; + const STORAGE_TEXTURE_16BIT_NORM_FORMATS = 1 << 9; /// Support for [`BuiltIn::ViewIndex`]. /// /// [`BuiltIn::ViewIndex`]: crate::BuiltIn::ViewIndex - const MULTIVIEW = 1 << 9; + const MULTIVIEW = 1 << 10; /// Support for `early_depth_test`. - const EARLY_DEPTH_TEST = 1 << 10; + const EARLY_DEPTH_TEST = 1 << 11; /// Support for [`BuiltIn::SampleIndex`] and [`Sampling::Sample`]. /// /// [`BuiltIn::SampleIndex`]: crate::BuiltIn::SampleIndex /// [`Sampling::Sample`]: crate::Sampling::Sample - const MULTISAMPLED_SHADING = 1 << 11; + const MULTISAMPLED_SHADING = 1 << 12; /// Support for ray queries and acceleration structures. - const RAY_QUERY = 1 << 12; + const RAY_QUERY = 1 << 13; /// Support for generating two sources for blending from fragment shaders. - const DUAL_SOURCE_BLENDING = 1 << 13; + const DUAL_SOURCE_BLENDING = 1 << 14; /// Support for arrayed cube textures. - const CUBE_ARRAY_TEXTURES = 1 << 14; + const CUBE_ARRAY_TEXTURES = 1 << 15; /// Support for 64-bit signed and unsigned integers. - const SHADER_INT64 = 1 << 15; + const SHADER_INT64 = 1 << 16; /// Support for subgroup operations. /// Implies support for subgroup operations in both fragment and compute stages, /// but not necessarily in the vertex stage, which requires [`Capabilities::SUBGROUP_VERTEX_STAGE`]. - const SUBGROUP = 1 << 16; + const SUBGROUP = 1 << 17; /// Support for subgroup barriers. - const SUBGROUP_BARRIER = 1 << 17; + const SUBGROUP_BARRIER = 1 << 18; /// Support for subgroup operations in the vertex stage. - const SUBGROUP_VERTEX_STAGE = 1 << 18; + const SUBGROUP_VERTEX_STAGE = 1 << 19; /// Support for [`AtomicFunction::Min`] and [`AtomicFunction::Max`] on /// 64-bit integers in the [`Storage`] address space, when the return /// value is not used. @@ -140,9 +142,9 @@ bitflags::bitflags! { /// [`AtomicFunction::Min`]: crate::AtomicFunction::Min /// [`AtomicFunction::Max`]: crate::AtomicFunction::Max /// [`Storage`]: crate::AddressSpace::Storage - const SHADER_INT64_ATOMIC_MIN_MAX = 1 << 19; + const SHADER_INT64_ATOMIC_MIN_MAX = 1 << 20; /// Support for all atomic operations on 64-bit integers. - const SHADER_INT64_ATOMIC_ALL_OPS = 1 << 20; + const SHADER_INT64_ATOMIC_ALL_OPS = 1 << 21; /// Support for [`AtomicFunction::Add`], [`AtomicFunction::Sub`], /// and [`AtomicFunction::Exchange { compare: None }`] on 32-bit floating-point numbers /// in the [`Storage`] address space. @@ -151,11 +153,11 @@ bitflags::bitflags! { /// [`AtomicFunction::Sub`]: crate::AtomicFunction::Sub /// [`AtomicFunction::Exchange { compare: None }`]: crate::AtomicFunction::Exchange /// [`Storage`]: crate::AddressSpace::Storage - const SHADER_FLOAT32_ATOMIC = 1 << 21; + const SHADER_FLOAT32_ATOMIC = 1 << 22; /// Support for atomic operations on images. - const TEXTURE_ATOMIC = 1 << 22; + const TEXTURE_ATOMIC = 1 << 23; /// Support for atomic operations on 64-bit images. - const TEXTURE_INT64_ATOMIC = 1 << 23; + const TEXTURE_INT64_ATOMIC = 1 << 24; } } diff --git a/tests/tests/binding_array/buffers.rs b/tests/tests/binding_array/buffers.rs index 9d5c26f894..ae6b0a6ea0 100644 --- a/tests/tests/binding_array/buffers.rs +++ b/tests/tests/binding_array/buffers.rs @@ -7,10 +7,7 @@ use wgpu_test::{gpu_test, FailureCase, GpuTestConfiguration, TestParameters, Tes static BINDING_ARRAY_UNIFORM_BUFFERS: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() - .features( - Features::BUFFER_BINDING_ARRAY - | Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, - ) + .features(Features::BUFFER_BINDING_ARRAY | Features::UNIFORM_BUFFER_BINDING_ARRAYS) .limits(Limits { max_uniform_buffers_per_shader_stage: 16, ..Limits::default() @@ -31,7 +28,7 @@ static PARTIAL_BINDING_ARRAY_UNIFORM_BUFFERS: GpuTestConfiguration = GpuTestConf .features( Features::BUFFER_BINDING_ARRAY | Features::PARTIALLY_BOUND_BINDING_ARRAY - | Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + | Features::UNIFORM_BUFFER_BINDING_ARRAYS, ) .limits(Limits { max_uniform_buffers_per_shader_stage: 32, diff --git a/tests/tests/binding_array/storage_textures.rs b/tests/tests/binding_array/storage_textures.rs index ed8e6b4edb..bee8db9b77 100644 --- a/tests/tests/binding_array/storage_textures.rs +++ b/tests/tests/binding_array/storage_textures.rs @@ -13,7 +13,7 @@ static BINDING_ARRAY_STORAGE_TEXTURES: GpuTestConfiguration = GpuTestConfigurati .features( Features::TEXTURE_BINDING_ARRAY | Features::STORAGE_RESOURCE_BINDING_ARRAY - | Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING | Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES, ) .limits(Limits { @@ -32,7 +32,7 @@ static PARTIAL_BINDING_ARRAY_STORAGE_TEXTURES: GpuTestConfiguration = GpuTestCon Features::TEXTURE_BINDING_ARRAY | Features::PARTIALLY_BOUND_BINDING_ARRAY | Features::STORAGE_RESOURCE_BINDING_ARRAY - | Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING | Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES, ) .limits(Limits { diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index e9600f72d6..bb2ffd6b03 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -392,9 +392,12 @@ pub fn create_validator( .contains(wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING), ); caps.set( - Caps::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, - features - .contains(wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING), + Caps::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + features.contains(wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING), + ); + caps.set( + Caps::UNIFORM_BUFFER_ARRAY_NON_UNIFORM_INDEXING, + features.contains(wgt::Features::UNIFORM_BUFFER_BINDING_ARRAYS), ); // TODO: This needs a proper wgpu feature caps.set( diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index edb03a3ffc..ea98cd142a 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -372,7 +372,7 @@ impl super::Adapter { features.set( wgt::Features::TEXTURE_BINDING_ARRAY | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY - | wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING | wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, shader_model >= naga::back::hlsl::ShaderModel::V5_1, ); diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index dae4cb3322..1031053fa9 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -925,7 +925,7 @@ impl super::PrivateCapabilities { features.set( F::TEXTURE_BINDING_ARRAY | F::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING - | F::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | F::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING | F::PARTIALLY_BOUND_BINDING_ARRAY, self.msl_version >= MTLLanguageVersion::V3_0 && self.supports_arrays_of_textures diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index 61020c2a34..339ff4954a 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -12,7 +12,8 @@ fn depth_stencil_required_flags() -> vk::FormatFeatureFlags { //TODO: const fn? fn indexing_features() -> wgt::Features { wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING - | wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | wgt::Features::UNIFORM_BUFFER_BINDING_ARRAYS | wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY } @@ -217,14 +218,12 @@ impl PhysicalDeviceFeatures { | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY | wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, ); - let needs_uniform_buffer_non_uniform = requested_features.contains( - wgt::Features::TEXTURE_BINDING_ARRAY - | wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, - ); + let needs_uniform_buffer_non_uniform = + requested_features.contains(wgt::Features::UNIFORM_BUFFER_BINDING_ARRAYS); let needs_storage_image_non_uniform = requested_features.contains( wgt::Features::TEXTURE_BINDING_ARRAY | wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY - | wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + | wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, ); let needs_partially_bound = requested_features.intersects(wgt::Features::PARTIALLY_BOUND_BINDING_ARRAY); @@ -498,7 +497,6 @@ impl PhysicalDeviceFeatures { phd: vk::PhysicalDevice, caps: &PhysicalDeviceProperties, ) -> (wgt::Features, wgt::DownlevelFlags) { - use crate::auxil::db; use wgt::{DownlevelFlags as Df, Features as F}; let mut features = F::empty() | F::SPIRV_SHADER_PASSTHROUGH @@ -583,31 +581,13 @@ impl PhysicalDeviceFeatures { F::VERTEX_WRITABLE_STORAGE, self.core.vertex_pipeline_stores_and_atomics != 0, ); - //if self.core.shader_image_gather_extended != 0 { - //if self.core.shader_storage_image_extended_formats != 0 { - features.set( - F::BUFFER_BINDING_ARRAY, - self.core.shader_uniform_buffer_array_dynamic_indexing != 0, - ); - features.set( - F::TEXTURE_BINDING_ARRAY, - self.core.shader_sampled_image_array_dynamic_indexing != 0, - ); - features.set(F::SHADER_PRIMITIVE_INDEX, self.core.geometry_shader != 0); - features.set( - F::STORAGE_RESOURCE_BINDING_ARRAY, - (features.contains(F::BUFFER_BINDING_ARRAY) - && self.core.shader_storage_buffer_array_dynamic_indexing != 0) - || (features.contains(F::TEXTURE_BINDING_ARRAY) - && self.core.shader_storage_image_array_dynamic_indexing != 0), - ); - //if self.core.shader_storage_image_array_dynamic_indexing != 0 { - //if self.core.shader_clip_distance != 0 { - //if self.core.shader_cull_distance != 0 { + features.set(F::SHADER_F64, self.core.shader_float64 != 0); features.set(F::SHADER_INT64, self.core.shader_int64 != 0); features.set(F::SHADER_I16, self.core.shader_int16 != 0); + features.set(F::SHADER_PRIMITIVE_INDEX, self.core.geometry_shader != 0); + if let Some(ref shader_atomic_int64) = self.shader_atomic_int64 { features.set( F::SHADER_INT64_ATOMIC_ALL_OPS | F::SHADER_INT64_ATOMIC_MIN_MAX, @@ -645,29 +625,38 @@ impl PhysicalDeviceFeatures { caps.supports_extension(ext::conservative_rasterization::NAME), ); - let intel_windows = caps.properties.vendor_id == db::intel::VENDOR && cfg!(windows); - if let Some(ref descriptor_indexing) = self.descriptor_indexing { - const STORAGE: F = F::STORAGE_RESOURCE_BINDING_ARRAY; - features.set( - F::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, - (features.contains(F::TEXTURE_BINDING_ARRAY) - && descriptor_indexing.shader_sampled_image_array_non_uniform_indexing != 0) - && (features.contains(F::BUFFER_BINDING_ARRAY | STORAGE) - && descriptor_indexing.shader_storage_buffer_array_non_uniform_indexing - != 0), - ); - features.set( - F::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, - (features.contains(F::BUFFER_BINDING_ARRAY) - && descriptor_indexing.shader_uniform_buffer_array_non_uniform_indexing != 0) - && (features.contains(F::TEXTURE_BINDING_ARRAY | STORAGE) - && descriptor_indexing.shader_storage_image_array_non_uniform_indexing - != 0), - ); - if descriptor_indexing.descriptor_binding_partially_bound != 0 && !intel_windows { - features |= F::PARTIALLY_BOUND_BINDING_ARRAY; - } + // We use update-after-bind descriptors for all bind groups containing binding arrays. + // + // In those bind groups, we allow all binding types except uniform buffers to be present. + // + // As we can only switch between update-after-bind and not on a per bind group basis, + // all supported binding types need to be able to be marked update after bind. + // + // As such, we enable all features as a whole, rather individually. + let supports_descriptor_indexing = + // Sampled Images + descriptor_indexing.shader_sampled_image_array_non_uniform_indexing != 0 + && descriptor_indexing.descriptor_binding_sampled_image_update_after_bind != 0 + // Storage Images + && descriptor_indexing.shader_storage_image_array_non_uniform_indexing != 0 + && descriptor_indexing.descriptor_binding_storage_image_update_after_bind != 0 + // Storage Buffers + && descriptor_indexing.shader_storage_buffer_array_non_uniform_indexing != 0 + && descriptor_indexing.descriptor_binding_storage_buffer_update_after_bind != 0; + + let descriptor_indexing_features = F::BUFFER_BINDING_ARRAY + | F::TEXTURE_BINDING_ARRAY + | F::STORAGE_RESOURCE_BINDING_ARRAY + | F::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING + | F::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING; + + features.set(descriptor_indexing_features, supports_descriptor_indexing); + + let supports_partially_bound = + descriptor_indexing.descriptor_binding_partially_bound != 0; + + features.set(F::PARTIALLY_BOUND_BINDING_ARRAY, supports_partially_bound); } features.set(F::DEPTH_CLIP_CONTROL, self.core.depth_clamp != 0); @@ -1835,7 +1824,8 @@ impl super::Adapter { if features.intersects( wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING - | wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING, + | wgt::Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING + | wgt::Features::UNIFORM_BUFFER_BINDING_ARRAYS, ) { capabilities.push(spv::Capability::ShaderNonUniform); } diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index 202edebcb5..31bcf020ee 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -1611,11 +1611,19 @@ impl crate::Device for super::Device { super::AccelerationStructure, >, ) -> Result { + let contains_binding_arrays = !desc.layout.binding_arrays.is_empty(); + + let desc_set_layout_flags = if contains_binding_arrays { + gpu_descriptor::DescriptorSetLayoutCreateFlags::UPDATE_AFTER_BIND + } else { + gpu_descriptor::DescriptorSetLayoutCreateFlags::empty() + }; + let mut vk_sets = unsafe { self.desc_allocator.lock().allocate( &*self.shared, &desc.layout.raw, - gpu_descriptor::DescriptorSetLayoutCreateFlags::empty(), + desc_set_layout_flags, &desc.layout.desc_count, 1, )? diff --git a/wgpu-types/src/features.rs b/wgpu-types/src/features.rs index 8585bc83aa..9724c6dd2a 100644 --- a/wgpu-types/src/features.rs +++ b/wgpu-types/src/features.rs @@ -756,31 +756,17 @@ bitflags_array! { /// /// This is a native only feature. const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 1 << 11; - /// Allows shaders to index uniform buffer and storage texture resource arrays with dynamically non-uniform values: + /// Allows shaders to index storage texture resource arrays with dynamically non-uniform values: /// /// ex. `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: - /// - /// ex. `layout(location = 0) nonuniformEXT flat in int vertex_data;` - /// - /// or as `nonuniformEXT` constructor: - /// - /// ex. `texture_array[nonuniformEXT(vertex_data)]` - /// - /// WGSL and HLSL do not need any extension. - /// /// Supported platforms: /// - DX12 /// - Metal (with MSL 2.0+ on macOS 10.13+) - /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderUniformBufferArrayNonUniformIndexing & shaderStorageTextureArrayNonUniformIndexing feature) + /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderStorageTextureArrayNonUniformIndexing feature) /// /// This is a native only feature. - const UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 12; + const STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 12; /// Allows the user to create bind groups containing arrays with less bindings than the BindGroupLayout. /// /// Supported platforms: @@ -1151,6 +1137,22 @@ bitflags_array! { /// This is a native only feature. const TEXTURE_INT64_ATOMIC = 1 << 45; + /// Allows uniform buffers to be bound as binding arrays. + /// + /// This allows: + /// - Shaders to contain `var buffer: binding_array;` + /// - The `count` field of `BindGroupLayoutEntry`s with `Uniform` buffers, to be set to `Some`. + /// + /// Supported platforms: + /// - None () + /// + /// Potential Platforms: + /// - DX12 + /// - Metal + /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s `shaderUniformBufferArrayNonUniformIndexing` feature) + /// + /// This is a native only feature. + const UNIFORM_BUFFER_BINDING_ARRAYS = 1 << 46; } /// Features that are not guaranteed to be supported.