Skip to content

Commit 0080c43

Browse files
Firestar99LegNeato
authored andcommitted
subgroup cluster ops: add safety docs, const assert preconditions
1 parent 6bcf4d1 commit 0080c43

13 files changed

+175
-11
lines changed

crates/spirv-std/src/arch/subgroup.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(clippy::missing_safety_doc)]
2-
31
#[cfg(target_arch = "spirv")]
42
use crate::arch::barrier;
53
use crate::float::Float;
@@ -792,6 +790,16 @@ macro_rules! macro_subgroup_op_clustered {
792790
pub unsafe fn $name<const CLUSTER_SIZE: u32, I: VectorOrScalar<Scalar = $scalar>>(
793791
value: I,
794792
) -> I {
793+
const {
794+
assert!(CLUSTER_SIZE >= 1, "`ClusterSize` must be at least 1");
795+
assert!(
796+
CLUSTER_SIZE.is_power_of_two(),
797+
"`ClusterSize` must be a power of 2"
798+
);
799+
// Cannot be verified with static assertions:
800+
// `ClusterSize` must not be greater than the size of the group
801+
}
802+
795803
let mut result = I::default();
796804

797805
unsafe {
@@ -843,6 +851,9 @@ The type of `value` must be the same as Result Type.
843851
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
844852
845853
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
854+
855+
# Safety
856+
* `ClusterSize` must not be greater than the size of the group
846857
");
847858
macro_subgroup_op!(impl Float, "OpGroupNonUniformFAdd", subgroup_f_add, GroupOperation::Reduce, subgroup_inclusive_f_add, GroupOperation::InclusiveScan, subgroup_exclusive_f_add, GroupOperation::ExclusiveScan; r"
848859
A floating point add group operation of all `value` operands contributed by active invocations in the group.
@@ -871,6 +882,9 @@ The type of `value` must be the same as Result Type. The method used to perform
871882
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
872883
873884
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
885+
886+
# Safety
887+
* `ClusterSize` must not be greater than the size of the group
874888
");
875889

876890
// mul
@@ -901,6 +915,9 @@ The type of `value` must be the same as Result Type.
901915
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
902916
903917
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
918+
919+
# Safety
920+
* `ClusterSize` must not be greater than the size of the group
904921
");
905922
macro_subgroup_op!(impl Float, "OpGroupNonUniformFMul", subgroup_f_mul, GroupOperation::Reduce, subgroup_inclusive_f_mul, GroupOperation::InclusiveScan, subgroup_exclusive_f_mul, GroupOperation::ExclusiveScan; r"
906923
A floating point multiply group operation of all `value` operands contributed by active invocations in the group.
@@ -929,6 +946,9 @@ The type of `value` must be the same as Result Type. The method used to perform
929946
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
930947
931948
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
949+
950+
# Safety
951+
* `ClusterSize` must not be greater than the size of the group
932952
");
933953

934954
// min
@@ -959,6 +979,9 @@ The type of `value` must be the same as Result Type.
959979
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
960980
961981
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
982+
983+
# Safety
984+
* `ClusterSize` must not be greater than the size of the group
962985
");
963986
macro_subgroup_op!(impl UnsignedInteger, "OpGroupNonUniformUMin", subgroup_u_min, GroupOperation::Reduce, subgroup_inclusive_u_min, GroupOperation::InclusiveScan, subgroup_exclusive_u_min, GroupOperation::ExclusiveScan; r"
964987
An unsigned integer minimum group operation of all `value` operands contributed by active invocations in the group.
@@ -987,6 +1010,9 @@ The type of `value` must be the same as Result Type.
9871010
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
9881011
9891012
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1013+
1014+
# Safety
1015+
* `ClusterSize` must not be greater than the size of the group
9901016
");
9911017
macro_subgroup_op!(impl Float, "OpGroupNonUniformFMin", subgroup_f_min, GroupOperation::Reduce, subgroup_inclusive_f_min, GroupOperation::InclusiveScan, subgroup_exclusive_f_min, GroupOperation::ExclusiveScan; r"
9921018
A floating point minimum group operation of all `value` operands contributed by active invocations in the group.
@@ -1015,6 +1041,9 @@ The type of `value` must be the same as Result Type. The method used to perform
10151041
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
10161042
10171043
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1044+
1045+
# Safety
1046+
* `ClusterSize` must not be greater than the size of the group
10181047
");
10191048

10201049
// max
@@ -1045,6 +1074,9 @@ The type of `value` must be the same as Result Type.
10451074
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
10461075
10471076
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1077+
1078+
# Safety
1079+
* `ClusterSize` must not be greater than the size of the group
10481080
");
10491081
macro_subgroup_op!(impl UnsignedInteger, "OpGroupNonUniformUMax", subgroup_u_max, GroupOperation::Reduce, subgroup_inclusive_u_max, GroupOperation::InclusiveScan, subgroup_exclusive_u_max, GroupOperation::ExclusiveScan; r"
10501082
An unsigned integer maximum group operation of all `value` operands contributed by active invocations in the group.
@@ -1073,6 +1105,9 @@ The type of `value` must be the same as Result Type.
10731105
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
10741106
10751107
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1108+
1109+
# Safety
1110+
* `ClusterSize` must not be greater than the size of the group
10761111
");
10771112
macro_subgroup_op!(impl Float, "OpGroupNonUniformFMax", subgroup_f_max, GroupOperation::Reduce, subgroup_inclusive_f_max, GroupOperation::InclusiveScan, subgroup_exclusive_f_max, GroupOperation::ExclusiveScan; r"
10781113
A floating point maximum group operation of all `value` operands contributed by active invocations in by group.
@@ -1099,6 +1134,9 @@ The identity I for Operation is -INF.
10991134
The type of `value` must be the same as Result Type. The method used to perform the group operation on the contributed Value(s) from active invocations is implementation defined. From the set of Value(s) provided by active invocations within a subgroup, if for any two Values one of them is a NaN, the other is chosen. If all Value(s) that are used by the current invocation are NaN, then the result is an undefined value.
11001135
11011136
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1137+
1138+
# Safety
1139+
* `ClusterSize` must not be greater than the size of the group
11021140
");
11031141

11041142
// and
@@ -1129,6 +1167,9 @@ The type of `value` must be the same as Result Type.
11291167
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
11301168
11311169
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1170+
1171+
# Safety
1172+
* `ClusterSize` must not be greater than the size of the group
11321173
");
11331174

11341175
// or
@@ -1159,6 +1200,9 @@ The type of `value` must be the same as Result Type.
11591200
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
11601201
11611202
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1203+
1204+
# Safety
1205+
* `ClusterSize` must not be greater than the size of the group
11621206
");
11631207

11641208
// xor
@@ -1189,6 +1233,9 @@ The type of `value` must be the same as Result Type.
11891233
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
11901234
11911235
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1236+
1237+
# Safety
1238+
* `ClusterSize` must not be greater than the size of the group
11921239
");
11931240

11941241
// logical and
@@ -1219,6 +1266,9 @@ The type of `value` must be the same as Result Type.
12191266
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
12201267
12211268
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1269+
1270+
# Safety
1271+
* `ClusterSize` must not be greater than the size of the group
12221272
");
12231273

12241274
// logical or
@@ -1249,6 +1299,9 @@ The type of `value` must be the same as Result Type.
12491299
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
12501300
12511301
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1302+
1303+
# Safety
1304+
* `ClusterSize` must not be greater than the size of the group
12521305
");
12531306

12541307
// logical xor
@@ -1279,6 +1332,9 @@ The type of `value` must be the same as Result Type.
12791332
ClusterSize is the size of cluster to use. ClusterSize must be a scalar of integer type, whose Signedness operand is 0. ClusterSize must come from a constant instruction. Behavior is undefined unless ClusterSize is at least 1 and a power of 2. If ClusterSize is greater than the size of the group, executing this instruction results in undefined behavior.
12801333
12811334
Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`.
1335+
1336+
# Safety
1337+
* `ClusterSize` must not be greater than the size of the group
12821338
");
12831339

12841340
/// Result is the `value` of the invocation within the quad with a quad index equal to `index`.

tests/compiletests/ui/arch/subgroup/subgroup_ballot.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
%1 = OpFunction %2 None %3
22
%4 = OpFunctionParameter %2
33
%5 = OpLabel
4-
OpLine %6 375 8
4+
OpLine %6 373 8
55
%7 = OpGroupNonUniformBallot %8 %9 %4
6-
OpLine %6 414 8
6+
OpLine %6 412 8
77
%10 = OpGroupNonUniformInverseBallot %2 %9 %7
88
OpNoLine
99
OpReturnValue %10

tests/compiletests/ui/arch/subgroup/subgroup_ballot_bit_count.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%1 = OpFunction %2 None %3
22
%4 = OpFunctionParameter %5
33
%6 = OpLabel
4-
OpLine %7 514 0
4+
OpLine %7 512 0
55
%8 = OpGroupNonUniformBallotBitCount %2 %9 Reduce %4
66
OpNoLine
77
OpReturnValue %8

tests/compiletests/ui/arch/subgroup/subgroup_broadcast_first.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%1 = OpFunction %2 None %3
22
%4 = OpFunctionParameter %2
33
%5 = OpLabel
4-
OpLine %6 342 8
4+
OpLine %6 340 8
55
%7 = OpGroupNonUniformBroadcastFirst %2 %8 %4
66
OpNoLine
77
OpReturnValue %7
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// build-pass
2+
// compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model
3+
4+
use glam::UVec3;
5+
use spirv_std::arch::{GroupOperation, SubgroupMask};
6+
use spirv_std::spirv;
7+
8+
unsafe fn subgroup_test_fail(value: u32) -> u32 {
9+
spirv_std::arch::subgroup_clustered_i_add::<0, _>(value)
10+
}
11+
12+
#[spirv(compute(threads(32, 1, 1)))]
13+
pub fn main(#[spirv(local_invocation_id)] local_invocation_id: UVec3) {
14+
unsafe {
15+
subgroup_test_fail(local_invocation_id.x);
16+
}
17+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>::{constant#0}` failed
2+
--> /home/firestar99/workspace/frameworks/rust-gpu/crates/spirv-std/src/arch/subgroup.rs:840:1
3+
|
4+
840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r"
5+
841 | | An integer add group operation of all `value` operands contributed by active invocations in the group.
6+
842 | |
7+
843 | | Result Type must be a scalar or vector of integer type.
8+
... |
9+
856 | | * `ClusterSize` must not be greater than the size of the group
10+
857 | | ");
11+
| |__^ the evaluated program panicked at '`ClusterSize` must be at least 1', /home/firestar99/workspace/frameworks/rust-gpu/crates/spirv-std/src/arch/subgroup.rs:840:1
12+
|
13+
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info)
14+
15+
note: erroneous constant encountered
16+
--> /home/firestar99/workspace/frameworks/rust-gpu/crates/spirv-std/src/arch/subgroup.rs:840:1
17+
|
18+
840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r"
19+
841 | | An integer add group operation of all `value` operands contributed by active invocations in the group.
20+
842 | |
21+
843 | | Result Type must be a scalar or vector of integer type.
22+
... |
23+
856 | | * `ClusterSize` must not be greater than the size of the group
24+
857 | | ");
25+
| |__^
26+
|
27+
= note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info)
28+
29+
note: the above error was encountered while instantiating `fn spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>`
30+
--> $DIR/subgroup_cluster_size_0_fail.rs:9:5
31+
|
32+
9 | spirv_std::arch::subgroup_clustered_i_add::<0, _>(value)
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
35+
error: aborting due to 1 previous error
36+
37+
For more information about this error, try `rustc --explain E0080`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// build-pass
2+
// compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model
3+
4+
use glam::UVec3;
5+
use spirv_std::arch::{GroupOperation, SubgroupMask};
6+
use spirv_std::spirv;
7+
8+
unsafe fn subgroup_test_fail(value: u32) -> u32 {
9+
spirv_std::arch::subgroup_clustered_i_add::<5, _>(value)
10+
}
11+
12+
#[spirv(compute(threads(32, 1, 1)))]
13+
pub fn main(#[spirv(local_invocation_id)] local_invocation_id: UVec3) {
14+
unsafe {
15+
subgroup_test_fail(local_invocation_id.x);
16+
}
17+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>::{constant#0}` failed
2+
--> /home/firestar99/workspace/frameworks/rust-gpu/crates/spirv-std/src/arch/subgroup.rs:840:1
3+
|
4+
840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r"
5+
841 | | An integer add group operation of all `value` operands contributed by active invocations in the group.
6+
842 | |
7+
843 | | Result Type must be a scalar or vector of integer type.
8+
... |
9+
856 | | * `ClusterSize` must not be greater than the size of the group
10+
857 | | ");
11+
| |__^ the evaluated program panicked at '`ClusterSize` must be a power of 2', /home/firestar99/workspace/frameworks/rust-gpu/crates/spirv-std/src/arch/subgroup.rs:840:1
12+
|
13+
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info)
14+
15+
note: erroneous constant encountered
16+
--> /home/firestar99/workspace/frameworks/rust-gpu/crates/spirv-std/src/arch/subgroup.rs:840:1
17+
|
18+
840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r"
19+
841 | | An integer add group operation of all `value` operands contributed by active invocations in the group.
20+
842 | |
21+
843 | | Result Type must be a scalar or vector of integer type.
22+
... |
23+
856 | | * `ClusterSize` must not be greater than the size of the group
24+
857 | | ");
25+
| |__^
26+
|
27+
= note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info)
28+
29+
note: the above error was encountered while instantiating `fn spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>`
30+
--> $DIR/subgroup_cluster_size_non_power_of_two_fail.rs:9:5
31+
|
32+
9 | spirv_std::arch::subgroup_clustered_i_add::<5, _>(value)
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
35+
error: aborting due to 1 previous error
36+
37+
For more information about this error, try `rustc --explain E0080`.

tests/compiletests/ui/arch/subgroup/subgroup_elect.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
%1 = OpFunction %2 None %3
22
%4 = OpLabel
3-
OpLine %5 172 8
3+
OpLine %5 170 8
44
%6 = OpGroupNonUniformElect %2 %7
55
OpNoLine
66
OpReturnValue %6

tests/compiletests/ui/arch/subgroup/subgroup_i_add_clustered.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
%1 = OpFunction %2 None %3
22
%4 = OpFunctionParameter %2
33
%5 = OpLabel
4-
OpLine %6 832 0
4+
OpLine %6 840 0
55
%7 = OpGroupNonUniformIAdd %2 %8 ClusteredReduce %4 %9
66
OpNoLine
77
OpReturnValue %7

0 commit comments

Comments
 (0)