From 184522d253aa16a7d04e471f780e0f7e63b4d1f9 Mon Sep 17 00:00:00 2001 From: Jacob Hughes Date: Tue, 24 Oct 2023 11:19:51 -0700 Subject: [PATCH] Separate subgroup feature into one flag per shader stage --- CHANGELOG.md | 2 +- tests/tests/subgroup_operations/mod.rs | 2 +- wgpu-core/src/device/resource.rs | 29 ++++++++++++- wgpu-hal/src/dx12/adapter.rs | 4 +- wgpu-hal/src/metal/adapter.rs | 2 +- wgpu-hal/src/vulkan/adapter.rs | 58 ++++++++++++++++---------- wgpu-types/src/lib.rs | 42 +++++++++++++------ 7 files changed, 101 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e63c27d2fb..fb00aa2c297 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -200,7 +200,7 @@ By @teoxoy in [#4185](https://github.com/gfx-rs/wgpu/pull/4185) - Re-export Naga. By @exrook in [#4172](https://github.com/gfx-rs/wgpu/pull/4172) - Add WinUI 3 SwapChainPanel support. By @ddrboxman in [#4191](https://github.com/gfx-rs/wgpu/pull/4191) -- Add `SUBGROUP_OPERATIONS` feature. By @exrook and @lichtso in [#4240](https://github.com/gfx-rs/wgpu/pull/4240) +- Add `SUBGROUP_COMPUTE, SUBGROUP_FRAGMENT, SUBGROUP_VERTEX` features. By @exrook and @lichtso in [#4240](https://github.com/gfx-rs/wgpu/pull/4240) ### Changes diff --git a/tests/tests/subgroup_operations/mod.rs b/tests/tests/subgroup_operations/mod.rs index 6e2ee72304c..91e883fd8dc 100644 --- a/tests/tests/subgroup_operations/mod.rs +++ b/tests/tests/subgroup_operations/mod.rs @@ -8,7 +8,7 @@ const THREAD_COUNT: u64 = 128; static SUBGROUP_OPERATIONS: GpuTestConfiguration = GpuTestConfiguration::new() .parameters( TestParameters::default() - .features(wgpu::Features::SUBGROUP_OPERATIONS) + .features(wgpu::Features::SUBGROUP_COMPUTE) .limits(wgpu::Limits::downlevel_defaults()), ) .run_sync(|ctx| { diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index a521f3d030b..76aca5fe9f8 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -1318,7 +1318,11 @@ impl Device { ); caps.set( Caps::SUBGROUP, - self.features.contains(wgt::Features::SUBGROUP_OPERATIONS), + self.features.intersects( + wgt::Features::SUBGROUP_COMPUTE + | wgt::Features::SUBGROUP_FRAGMENT + | wgt::Features::SUBGROUP_VERTEX, + ), ); let debug_source = if self.instance_flags.contains(wgt::InstanceFlags::DEBUG) { @@ -1334,7 +1338,30 @@ impl Device { None }; + let mut subgroup_stages = naga::valid::ShaderStages::empty(); + subgroup_stages.set( + naga::valid::ShaderStages::COMPUTE, + self.features.contains(wgt::Features::SUBGROUP_COMPUTE), + ); + subgroup_stages.set( + naga::valid::ShaderStages::FRAGMENT, + self.features.contains(wgt::Features::SUBGROUP_FRAGMENT), + ); + subgroup_stages.set( + naga::valid::ShaderStages::VERTEX, + self.features.contains(wgt::Features::SUBGROUP_VERTEX), + ); + + let subgroup_operations = if caps.contains(Caps::SUBGROUP) { + use naga::valid::SubgroupOperationSet as S; + S::BASIC | S::VOTE | S::ARITHMETIC | S::BALLOT | S::SHUFFLE | S::SHUFFLE_RELATIVE + } else { + naga::valid::SubgroupOperationSet::empty() + }; + let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps) + .subgroup_stages(subgroup_stages) + .subgroup_operations(subgroup_operations) .validate(&module) .map_err(|inner| { pipeline::CreateShaderModuleError::Validation(pipeline::ShaderError { diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 76e48e76543..24db1fb7195 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -293,7 +293,9 @@ impl super::Adapter { ); features.set( - wgt::Features::SUBGROUP_OPERATIONS, + wgt::Features::SUBGROUP_COMPUTE + | wgt::Features::SUBGROUP_FRAGMENT + | wgt::Features::SUBGROUP_VERTEX, shader_model_support.HighestShaderModel >= d3d12_ty::D3D_SHADER_MODEL_6_0 && matches!(dx12_shader_compiler, &wgt::Dx12Compiler::Dxc { .. }), ); diff --git a/wgpu-hal/src/metal/adapter.rs b/wgpu-hal/src/metal/adapter.rs index 028d0baef7d..e56e6e29374 100644 --- a/wgpu-hal/src/metal/adapter.rs +++ b/wgpu-hal/src/metal/adapter.rs @@ -885,7 +885,7 @@ impl super::PrivateCapabilities { features.set(F::SHADER_UNUSED_VERTEX_OUTPUT, true); if self.supports_simd_scoped_operations { - features.insert(F::SUBGROUP_OPERATIONS); + features.insert(F::SUBGROUP_COMPUTE | F::SUBGROUP_FRAGMENT | F::SUBGROUP_VERTEX); } features diff --git a/wgpu-hal/src/vulkan/adapter.rs b/wgpu-hal/src/vulkan/adapter.rs index e0a210a787e..1cc2ead6ee5 100644 --- a/wgpu-hal/src/vulkan/adapter.rs +++ b/wgpu-hal/src/vulkan/adapter.rs @@ -490,21 +490,33 @@ impl PhysicalDeviceFeatures { } if let Some(ref subgroup) = caps.subgroup { - features.set( - F::SUBGROUP_OPERATIONS, - subgroup.supported_operations.contains( - vk::SubgroupFeatureFlags::BASIC - | vk::SubgroupFeatureFlags::VOTE - | vk::SubgroupFeatureFlags::ARITHMETIC - | vk::SubgroupFeatureFlags::BALLOT - | vk::SubgroupFeatureFlags::SHUFFLE - | vk::SubgroupFeatureFlags::SHUFFLE_RELATIVE - | vk::SubgroupFeatureFlags::CLUSTERED - | vk::SubgroupFeatureFlags::QUAD, - ) && subgroup - .supported_stages - .contains(vk::ShaderStageFlags::COMPUTE | vk::ShaderStageFlags::FRAGMENT), - ); + if subgroup.supported_operations.contains( + vk::SubgroupFeatureFlags::BASIC + | vk::SubgroupFeatureFlags::VOTE + | vk::SubgroupFeatureFlags::ARITHMETIC + | vk::SubgroupFeatureFlags::BALLOT + | vk::SubgroupFeatureFlags::SHUFFLE + | vk::SubgroupFeatureFlags::SHUFFLE_RELATIVE, + ) { + features.set( + F::SUBGROUP_COMPUTE, + subgroup + .supported_stages + .contains(vk::ShaderStageFlags::COMPUTE), + ); + features.set( + F::SUBGROUP_FRAGMENT, + subgroup + .supported_stages + .contains(vk::ShaderStageFlags::FRAGMENT), + ); + features.set( + F::SUBGROUP_VERTEX, + subgroup + .supported_stages + .contains(vk::ShaderStageFlags::VERTEX), + ); + } } let supports_depth_format = |format| { @@ -1279,17 +1291,17 @@ impl super::Adapter { capabilities.push(spv::Capability::Geometry); } - if features.contains(wgt::Features::SUBGROUP_OPERATIONS) { + if features.intersects( + wgt::Features::SUBGROUP_COMPUTE + | wgt::Features::SUBGROUP_FRAGMENT + | wgt::Features::SUBGROUP_VERTEX, + ) { capabilities.push(spv::Capability::GroupNonUniform); capabilities.push(spv::Capability::GroupNonUniformVote); capabilities.push(spv::Capability::GroupNonUniformArithmetic); capabilities.push(spv::Capability::GroupNonUniformBallot); capabilities.push(spv::Capability::GroupNonUniformShuffle); capabilities.push(spv::Capability::GroupNonUniformShuffleRelative); - capabilities.push(spv::Capability::GroupNonUniformClustered); - capabilities.push(spv::Capability::GroupNonUniformQuad); - capabilities.push(spv::Capability::SubgroupBallotKHR); - capabilities.push(spv::Capability::SubgroupVoteKHR); } if features.intersects( @@ -1319,7 +1331,11 @@ impl super::Adapter { true, // could check `super::Workarounds::SEPARATE_ENTRY_POINTS` ); spv::Options { - lang_version: if features.contains(wgt::Features::SUBGROUP_OPERATIONS) { + lang_version: if features.intersects( + wgt::Features::SUBGROUP_COMPUTE + | wgt::Features::SUBGROUP_FRAGMENT + | wgt::Features::SUBGROUP_VERTEX, + ) { (1, 3) } else { (1, 0) diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 4095d24e7ac..c9a9567e35b 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -299,17 +299,7 @@ bitflags::bitflags! { /// This is a web and native feature. const SHADER_F16 = 1 << 8; - /// Allows shaders to use the subgroup operation built-ins - /// - /// Supported Platforms: - /// - Vulkan - /// - DX12 - /// - Metal - /// - /// This is a web and native feature. - const SUBGROUP_OPERATIONS = 1 << 9; - - // 10..14 available + // 9..14 available // Texture Formats: @@ -766,10 +756,38 @@ bitflags::bitflags! { /// - OpenGL const SHADER_UNUSED_VERTEX_OUTPUT = 1 << 54; - // 54..59 available + // 55 available // Shader: + /// Allows compute shaders to use the subgroup operation built-ins + /// + /// Supported Platforms: + /// - Vulkan + /// - DX12 + /// - Metal + /// + /// This is a native only feature. + const SUBGROUP_COMPUTE = 1 << 56; + /// Allows fragment shaders to use the subgroup operation built-ins + /// + /// Supported Platforms: + /// - Vulkan + /// - DX12 + /// - Metal + /// + /// This is a native only feature. + const SUBGROUP_FRAGMENT = 1 << 57; + /// Allows vertx shaders to use the subgroup operation built-ins + /// + /// Supported Platforms: + /// - Vulkan + /// - DX12 + /// - Metal + /// + /// This is a native only feature. + const SUBGROUP_VERTEX = 1 << 58; + /// Enables 64-bit floating point types in SPIR-V shaders. /// /// Note: even when supported by GPU hardware, 64-bit floating point operations are