@@ -1166,6 +1166,16 @@ fn validation_error(
1166
1166
. map_err ( |e| e. into_inner ( ) ) // TODO(https://github.com/gfx-rs/wgpu/issues/8153): Add tests for spans
1167
1167
}
1168
1168
1169
+ /// Check that a shader validates successfully.
1170
+ ///
1171
+ /// In a few tests it is useful to check conditions where a validation error
1172
+ /// should be absent alongside conditions where it should be present. This
1173
+ /// wrapper is less confusing than `validation_error().unwrap()`.
1174
+ #[ track_caller]
1175
+ fn no_validation_error ( source : & str , caps : naga:: valid:: Capabilities ) {
1176
+ validation_error ( source, caps) . unwrap ( ) ;
1177
+ }
1178
+
1169
1179
#[ test]
1170
1180
fn int64_capability ( ) {
1171
1181
check_validation ! {
@@ -3585,6 +3595,7 @@ fn issue7165() {
3585
3595
fn invalid_return_type(a: Struct) -> i32 { return a; }
3586
3596
" ;
3587
3597
3598
+ // We need the span for the error, so have to invoke manually.
3588
3599
let module = naga:: front:: wgsl:: parse_str ( shader) . unwrap ( ) ;
3589
3600
let err = naga:: valid:: Validator :: new (
3590
3601
naga:: valid:: ValidationFlags :: all ( ) ,
@@ -3834,6 +3845,171 @@ fn const_eval_value_errors() {
3834
3845
assert ! ( variant( "f32(abs(-9223372036854775807 - 1))" ) . is_ok( ) ) ;
3835
3846
}
3836
3847
3848
+ #[ test]
3849
+ fn subgroup_capability ( ) {
3850
+ // Some of these tests should be `check_extension_validation` tests that
3851
+ // also check handling of the enable directive, but that handling is not
3852
+ // currently correct. https://github.com/gfx-rs/wgpu/issues/8202
3853
+
3854
+ // Non-barrier subgroup operations...
3855
+
3856
+ // ...in fragment and compute shaders require [`Capabilities::SUBGROUP`]`.
3857
+ for stage in [ naga:: ShaderStage :: Fragment , naga:: ShaderStage :: Compute ] {
3858
+ let stage_attr = match stage {
3859
+ naga:: ShaderStage :: Fragment => "@fragment" ,
3860
+ naga:: ShaderStage :: Compute => "@compute @workgroup_size(1)" ,
3861
+ _ => unreachable ! ( ) ,
3862
+ } ;
3863
+ check_one_validation ! {
3864
+ & format!( "
3865
+ {stage_attr}
3866
+ fn main() {{
3867
+ subgroupBallot();
3868
+ }}
3869
+ " ) ,
3870
+ Err ( naga:: valid:: ValidationError :: EntryPoint {
3871
+ stage: err_stage,
3872
+ source: naga:: valid:: EntryPointError :: Function (
3873
+ naga:: valid:: FunctionError :: MissingCapability ( Capabilities :: SUBGROUP )
3874
+ ) ,
3875
+ ..
3876
+ } ) if * err_stage == stage
3877
+ }
3878
+ }
3879
+
3880
+ // ...in fragment and compute shaders require *only* [`Capabilities::SUBGROUP`]`.
3881
+ for stage in [ naga:: ShaderStage :: Fragment , naga:: ShaderStage :: Compute ] {
3882
+ let stage_attr = match stage {
3883
+ naga:: ShaderStage :: Fragment => "@fragment" ,
3884
+ naga:: ShaderStage :: Compute => "@compute @workgroup_size(1)" ,
3885
+ _ => unreachable ! ( ) ,
3886
+ } ;
3887
+ no_validation_error (
3888
+ & format ! (
3889
+ "
3890
+ {stage_attr}
3891
+ fn main() {{
3892
+ subgroupBallot();
3893
+ }}
3894
+ "
3895
+ ) ,
3896
+ Capabilities :: SUBGROUP ,
3897
+ ) ;
3898
+ }
3899
+
3900
+ // ...in vertex shaders require both [`Capabilities::SUBGROUP`] and
3901
+ // [`Capabilities::SUBGROUP_VERTEX_STAGE`]`. (But note that
3902
+ // `create_validator` automatically sets `Capabilities::SUBGROUP` whenever
3903
+ // `Features::SUBGROUP_VERTEX` is available.)
3904
+ for cap in [ Capabilities :: SUBGROUP , Capabilities :: SUBGROUP_VERTEX_STAGE ] {
3905
+ check_validation ! {
3906
+ "
3907
+ @vertex
3908
+ fn main() -> @builtin(position) vec4<f32> {{
3909
+ subgroupBallot();
3910
+ return vec4();
3911
+ }}
3912
+ " :
3913
+ Err ( _) ,
3914
+ cap
3915
+ }
3916
+ }
3917
+ no_validation_error (
3918
+ "
3919
+ @vertex
3920
+ fn main() -> @builtin(position) vec4<f32> {{
3921
+ subgroupBallot();
3922
+ return vec4();
3923
+ }}
3924
+ " ,
3925
+ Capabilities :: SUBGROUP | Capabilities :: SUBGROUP_VERTEX_STAGE ,
3926
+ ) ;
3927
+
3928
+ // Subgroup barriers...
3929
+
3930
+ // ...require both SUBGROUP and SUBGROUP_BARRIER.
3931
+ for cap in [ Capabilities :: SUBGROUP , Capabilities :: SUBGROUP_BARRIER ] {
3932
+ check_validation ! {
3933
+ r#"
3934
+ @compute @workgroup_size(1)
3935
+ fn main() {
3936
+ subgroupBarrier();
3937
+ }
3938
+ "# :
3939
+ Err ( naga:: valid:: ValidationError :: EntryPoint {
3940
+ stage: naga:: ShaderStage :: Compute ,
3941
+ source: naga:: valid:: EntryPointError :: Function (
3942
+ naga:: valid:: FunctionError :: MissingCapability ( required_caps)
3943
+ ) ,
3944
+ ..
3945
+ } ) if * required_caps == Capabilities :: SUBGROUP | Capabilities :: SUBGROUP_BARRIER ,
3946
+ cap
3947
+ }
3948
+ }
3949
+
3950
+ // ...are never supported in vertex shaders.
3951
+ check_validation ! {
3952
+ r#"
3953
+ @vertex
3954
+ fn main() -> @builtin(position) vec4<f32> {
3955
+ subgroupBarrier();
3956
+ return vec4();
3957
+ }
3958
+ "# :
3959
+ Err ( naga:: valid:: ValidationError :: EntryPoint {
3960
+ stage: naga:: ShaderStage :: Vertex ,
3961
+ source: naga:: valid:: EntryPointError :: ForbiddenStageOperations ,
3962
+ ..
3963
+ } ) ,
3964
+ Capabilities :: SUBGROUP | Capabilities :: SUBGROUP_BARRIER | Capabilities :: SUBGROUP_VERTEX_STAGE
3965
+ }
3966
+
3967
+ // ...are never supported in fragment shaders.
3968
+ check_validation ! {
3969
+ r#"
3970
+ @fragment
3971
+ fn main() {
3972
+ subgroupBarrier();
3973
+ }
3974
+ "# :
3975
+ Err ( naga:: valid:: ValidationError :: EntryPoint {
3976
+ stage: naga:: ShaderStage :: Fragment ,
3977
+ source: naga:: valid:: EntryPointError :: ForbiddenStageOperations ,
3978
+ ..
3979
+ } ) ,
3980
+ Capabilities :: SUBGROUP | Capabilities :: SUBGROUP_BARRIER
3981
+ }
3982
+
3983
+ // The `subgroup_id` built-in...
3984
+
3985
+ // ...in compute shaders requires [`Capabilities::SUBGROUP`]`.
3986
+ check_one_validation ! {
3987
+ "
3988
+ @compute @workgroup_size(1)
3989
+ fn main(@builtin(subgroup_id) subgroup_id: u32) {{
3990
+ }}
3991
+ " ,
3992
+ Err ( naga:: valid:: ValidationError :: EntryPoint {
3993
+ stage: naga:: ShaderStage :: Compute ,
3994
+ source: naga:: valid:: EntryPointError :: Argument (
3995
+ _,
3996
+ naga:: valid:: VaryingError :: UnsupportedCapability ( Capabilities :: SUBGROUP )
3997
+ ) ,
3998
+ ..
3999
+ } )
4000
+ }
4001
+
4002
+ // ...in compute shaders requires *only* [`Capabilities::SUBGROUP`]`.
4003
+ no_validation_error (
4004
+ "
4005
+ @compute @workgroup_size(1)
4006
+ fn main(@builtin(subgroup_id) subgroup_id: u32) {{
4007
+ }}
4008
+ " ,
4009
+ Capabilities :: SUBGROUP ,
4010
+ ) ;
4011
+ }
4012
+
3837
4013
#[ test]
3838
4014
fn subgroup_invalid_broadcast ( ) {
3839
4015
check_validation ! {
0 commit comments