diff --git a/crates/spirv-std/src/arch/subgroup.rs b/crates/spirv-std/src/arch/subgroup.rs index 1a2af74245..660c9ee5f3 100644 --- a/crates/spirv-std/src/arch/subgroup.rs +++ b/crates/spirv-std/src/arch/subgroup.rs @@ -1,5 +1,3 @@ -#![allow(clippy::missing_safety_doc)] - #[cfg(target_arch = "spirv")] use crate::arch::barrier; use crate::float::Float; @@ -54,9 +52,7 @@ pub enum GroupOperation { PartitionedExclusiveScanNV = 8, } -/// Only usable if the extension GL_KHR_shader_subgroup_basic is enabled. -/// -/// The function subgroupBarrier() enforces that all active invocations within a +/// The function `subgroupBarrier()` enforces that all active invocations within a /// subgroup must execute this function before any are allowed to continue their /// execution, and the results of any memory stores performed using coherent /// variables performed prior to the call will be visible to any future @@ -67,7 +63,7 @@ pub enum GroupOperation { #[spirv_std_macros::gpu_only] #[doc(alias = "subgroupBarrier")] #[inline] -pub unsafe fn subgroup_barrier() { +pub fn subgroup_barrier() { unsafe { barrier::control_barrier::< SUBGROUP, @@ -82,9 +78,7 @@ pub unsafe fn subgroup_barrier() { } } -/// Only usable if the extension GL_KHR_shader_subgroup_basic is enabled. -/// -/// The function subgroupMemoryBarrier() enforces the ordering of all memory +/// The function `subgroupMemoryBarrier()` enforces the ordering of all memory /// transactions issued within a single shader invocation, as viewed by other /// invocations in the same subgroup. /// @@ -92,7 +86,7 @@ pub unsafe fn subgroup_barrier() { #[spirv_std_macros::gpu_only] #[doc(alias = "subgroupMemoryBarrier")] #[inline] -pub unsafe fn subgroup_memory_barrier() { +pub fn subgroup_memory_barrier() { unsafe { barrier::memory_barrier::< SUBGROUP, @@ -106,9 +100,7 @@ pub unsafe fn subgroup_memory_barrier() { } } -/// Only usable if the extension GL_KHR_shader_subgroup_basic is enabled. -/// -/// The function subgroupMemoryBarrierBuffer() enforces the ordering of all +/// The function `subgroupMemoryBarrierBuffer()` enforces the ordering of all /// memory transactions to buffer variables issued within a single shader /// invocation, as viewed by other invocations in the same subgroup. /// @@ -116,7 +108,7 @@ pub unsafe fn subgroup_memory_barrier() { #[spirv_std_macros::gpu_only] #[doc(alias = "subgroupMemoryBarrierBuffer")] #[inline] -pub unsafe fn subgroup_memory_barrier_buffer() { +pub fn subgroup_memory_barrier_buffer() { unsafe { barrier::memory_barrier::< SUBGROUP, @@ -125,9 +117,7 @@ pub unsafe fn subgroup_memory_barrier_buffer() { } } -/// Only usable if the extension GL_KHR_shader_subgroup_basic is enabled. -/// -/// The function subgroupMemoryBarrierShared() enforces the ordering of all +/// The function `subgroupMemoryBarrierShared()` enforces the ordering of all /// memory transactions to shared variables issued within a single shader /// invocation, as viewed by other invocations in the same subgroup. /// @@ -137,7 +127,7 @@ pub unsafe fn subgroup_memory_barrier_buffer() { #[spirv_std_macros::gpu_only] #[doc(alias = "subgroupMemoryBarrierShared")] #[inline] -pub unsafe fn subgroup_memory_barrier_shared() { +pub fn subgroup_memory_barrier_shared() { unsafe { barrier::memory_barrier::< SUBGROUP, @@ -146,9 +136,7 @@ pub unsafe fn subgroup_memory_barrier_shared() { } } -/// Only usable if the extension GL_KHR_shader_subgroup_basic is enabled. -/// -/// The function subgroupMemoryBarrierImage() enforces the ordering of all +/// The function `subgroupMemoryBarrierImage()` enforces the ordering of all /// memory transactions to images issued within a single shader invocation, as /// viewed by other invocations in the same subgroup. /// @@ -156,7 +144,7 @@ pub unsafe fn subgroup_memory_barrier_shared() { #[spirv_std_macros::gpu_only] #[doc(alias = "subgroupMemoryBarrierImage")] #[inline] -pub unsafe fn subgroup_memory_barrier_image() { +pub fn subgroup_memory_barrier_image() { unsafe { barrier::memory_barrier::< SUBGROUP, @@ -175,7 +163,7 @@ pub unsafe fn subgroup_memory_barrier_image() { #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformElect")] #[inline] -pub unsafe fn subgroup_elect() -> bool { +pub fn subgroup_elect() -> bool { let mut result = false; unsafe { @@ -193,19 +181,19 @@ pub unsafe fn subgroup_elect() -> bool { result } -/// Evaluates a predicate for all active invocations in the group, resulting in true if predicate evaluates to true for all active invocations in the group, otherwise the result is false. +/// Evaluates a `predicate` for all active invocations in the group, resulting in true if `predicate` evaluates to true for all active invocations in the group, otherwise the result is false. /// /// Result Type must be a Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// Predicate must be a Boolean type. +/// `predicate` must be a Boolean type. /// /// Requires Capability `GroupNonUniformVote`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformAll")] #[inline] -pub unsafe fn subgroup_all(predicate: bool) -> bool { +pub fn subgroup_all(predicate: bool) -> bool { let mut result = false; unsafe { @@ -225,19 +213,19 @@ pub unsafe fn subgroup_all(predicate: bool) -> bool { result } -/// Evaluates a predicate for all active invocations in the group, resulting in true if predicate evaluates to true for any active invocation in the group, otherwise the result is false. +/// Evaluates a `predicate` for all active invocations in the group, resulting in true if `predicate` evaluates to true for any active invocation in the group, otherwise the result is false. /// /// Result Type must be a Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// Predicate must be a Boolean type. +/// `predicate` must be a Boolean type. /// /// Requires Capability `GroupNonUniformVote`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformAny")] #[inline] -pub unsafe fn subgroup_any(predicate: bool) -> bool { +pub fn subgroup_any(predicate: bool) -> bool { let mut result = false; unsafe { @@ -257,19 +245,19 @@ pub unsafe fn subgroup_any(predicate: bool) -> bool { result } -/// Evaluates a value for all active invocations in the group. The result is true if Value is equal for all active invocations in the group. Otherwise, the result is false. +/// Evaluates a `value` for all active invocations in the group. The result is true if `value` is equal for all active invocations in the group. Otherwise, the result is false. /// /// Result Type must be a Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// Value must be a scalar or vector of floating-point type, integer type, or Boolean type. The compare operation is based on this type, and if it is a floating-point type, an ordered-and-equal compare is used. +/// `value` must be a scalar or vector of floating-point type, integer type, or Boolean type. The compare operation is based on this type, and if it is a floating-point type, an ordered-and-equal compare is used. /// /// Requires Capability `GroupNonUniformVote`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformAllEqual")] #[inline] -pub unsafe fn subgroup_all_equal(value: T) -> bool { +pub fn subgroup_all_equal(value: T) -> bool { let mut result = false; unsafe { @@ -289,21 +277,26 @@ pub unsafe fn subgroup_all_equal(value: T) -> bool { result } -/// Result is the Value of the invocation identified by the id Id to all active invocations in the group. +/// Result is the `value` of the invocation identified by the id `id` to all active invocations in the group. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// -/// Id must be a scalar of integer type, whose Signedness operand is 0. +/// `id` must be a scalar of integer type, whose Signedness operand is 0. /// -/// Before version 1.5, Id must come from a constant instruction. Starting with version 1.5, this restriction is lifted. However, behavior is undefined when Id is not dynamically uniform. +/// Before version 1.5, `id` must come from a constant instruction. Starting with version 1.5, this restriction is lifted. However, behavior is undefined when `id` is not dynamically uniform. /// -/// The resulting value is undefined if Id is an inactive invocation, or is greater than or equal to the size of the group. +/// The resulting value is undefined if `id` is an inactive invocation, or is greater than or equal to the size of the group. /// /// Requires Capability `GroupNonUniformBallot`. +/// +/// # Safety +/// * `id` must not be dynamically uniform +/// * before 1.5: `id` must be constant +/// * Result is undefined if `id` is an inactive invocation or out of bounds #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformBroadcast")] #[inline] @@ -328,19 +321,19 @@ pub unsafe fn subgroup_broadcast(value: T, id: u32) -> T { result } -/// Result is the Value of the invocation from the active invocation with the lowest id in the group to all active invocations in the group. +/// Result is the `value` of the invocation from the active invocation with the lowest id in the group to all active invocations in the group. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// /// Requires Capability `GroupNonUniformBallot`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformBroadcastFirst")] #[inline] -pub unsafe fn subgroup_broadcast_first(value: T) -> T { +pub fn subgroup_broadcast_first(value: T) -> T { let mut result = T::default(); unsafe { @@ -359,7 +352,7 @@ pub unsafe fn subgroup_broadcast_first(value: T) -> T { result } -/// Result is a bitfield value combining the Predicate value from all invocations in the group that execute the same dynamic instance of this instruction. The bit is set to one if the corresponding invocation is active and the Predicate for that invocation evaluated to true; otherwise, it is set to zero. +/// Result is a bitfield value combining the `predicate` value from all invocations in the group that execute the same dynamic instance of this instruction. The bit is set to one if the corresponding invocation is active and the `predicate` for that invocation evaluated to true; otherwise, it is set to zero. /// /// Result Type must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. /// @@ -367,13 +360,13 @@ pub unsafe fn subgroup_broadcast_first(value: T) -> T { /// /// Execution is a Scope that identifies the group of invocations affected by this command. /// -/// Predicate must be a Boolean type. +/// `predicate` must be a Boolean type. /// /// Requires Capability `GroupNonUniformBallot`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformBallot")] #[inline] -pub unsafe fn subgroup_ballot(predicate: bool) -> SubgroupMask { +pub fn subgroup_ballot(predicate: bool) -> SubgroupMask { let mut result = SubgroupMask::default(); unsafe { @@ -393,23 +386,26 @@ pub unsafe fn subgroup_ballot(predicate: bool) -> SubgroupMask { result } -/// Evaluates a value for all active invocations in the group, resulting in true if the bit in Value for the corresponding invocation is set to one, otherwise the result is false. +/// Evaluates a `value` for all active invocations in the group, resulting in true if the bit in `value` for the corresponding invocation is set to one, otherwise the result is false. /// /// Result Type must be a Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// Value must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. +/// `value` must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. /// -/// Behavior is undefined unless Value is the same for all invocations that execute the same dynamic instance of this instruction. +/// Behavior is undefined unless `value` is the same for all invocations that execute the same dynamic instance of this instruction. /// -/// Value is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. +/// `value` is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. /// /// Requires Capability `GroupNonUniformBallot`. +/// +/// # Safety +/// * `value` must be the same for all dynamic instances of this instruction #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformInverseBallot")] #[inline] -pub unsafe fn subgroup_inverse_ballot(subgroup_mask: SubgroupMask) -> bool { +pub unsafe fn subgroup_inverse_ballot(value: SubgroupMask) -> bool { let mut result = false; unsafe { @@ -417,11 +413,11 @@ pub unsafe fn subgroup_inverse_ballot(subgroup_mask: SubgroupMask) -> bool { "%bool = OpTypeBool", "%u32 = OpTypeInt 32 0", "%subgroup = OpConstant %u32 {subgroup}", - "%subgroup_mask = OpLoad _ {subgroup_mask}", - "%result = OpGroupNonUniformInverseBallot %bool %subgroup %subgroup_mask", + "%value = OpLoad _ {value}", + "%result = OpGroupNonUniformInverseBallot %bool %subgroup %value", "OpStore {result} %result", subgroup = const SUBGROUP, - subgroup_mask = in(reg) &subgroup_mask, + value = in(reg) &value, result = in(reg) &mut result, } } @@ -429,25 +425,29 @@ pub unsafe fn subgroup_inverse_ballot(subgroup_mask: SubgroupMask) -> bool { result } -/// Evaluates a value for all active invocations in the group, resulting in true if the bit in Value that corresponds to Index is set to one, otherwise the result is false. +/// Evaluates a value for all active invocations in the group, resulting in true if the bit in `value` that corresponds to `index` is set to one, otherwise the result is false. /// /// Result Type must be a Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// Value must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. +/// `value` must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. /// -/// Value is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. +/// `value` is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. /// -/// Index must be a scalar of integer type, whose Signedness operand is 0. +/// `index` must be a scalar of integer type, whose Signedness operand is 0. /// -/// The resulting value is undefined if Index is greater than or equal to the size of the group. +/// The resulting value is undefined if `index` is greater than or equal to the size of the group. /// /// Requires Capability `GroupNonUniformBallot`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if `id` is out of bounds #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformBallotBitExtract")] #[inline] -pub unsafe fn subgroup_ballot_bit_extract(subgroup_mask: SubgroupMask, id: u32) -> bool { +pub fn subgroup_ballot_bit_extract(value: SubgroupMask, index: u32) -> bool { let mut result = false; unsafe { @@ -455,13 +455,13 @@ pub unsafe fn subgroup_ballot_bit_extract(subgroup_mask: SubgroupMask, id: u32) "%bool = OpTypeBool", "%u32 = OpTypeInt 32 0", "%subgroup = OpConstant %u32 {subgroup}", - "%subgroup_mask = OpLoad _ {subgroup_mask}", - "%id = OpLoad _ {id}", - "%result = OpGroupNonUniformBallotBitExtract %bool %subgroup %subgroup_mask %id", + "%value = OpLoad _ {value}", + "%index = OpLoad _ {index}", + "%result = OpGroupNonUniformBallotBitExtract %bool %subgroup %value %index", "OpStore {result} %result", subgroup = const SUBGROUP, - subgroup_mask = in(reg) &subgroup_mask, - id = in(reg) &id, + value = in(reg) &value, + index = in(reg) &index, result = in(reg) &mut result, } } @@ -471,7 +471,7 @@ pub unsafe fn subgroup_ballot_bit_extract(subgroup_mask: SubgroupMask, id: u32) macro_rules! macro_subgroup_ballot_bit_count { ($name:ident, $group_op:expr) => { - /// Result is the number of bits that are set to 1 in Value, considering only the bits in Value required to represent all bits of the group's invocations. + /// Result is the number of bits that are set to 1 in `value`, considering only the bits in `value` required to represent all bits of the group's invocations. /// /// Result Type must be a scalar of integer type, whose Signedness operand is 0. /// @@ -479,27 +479,27 @@ macro_rules! macro_subgroup_ballot_bit_count { /// /// The identity I for Operation is 0. /// - /// Value must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. + /// `value` must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. /// - /// Value is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. + /// `value` is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. /// /// Requires Capability `GroupNonUniformBallot`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformBallotBitCount")] #[inline] - pub unsafe fn $name(subgroup_mask: SubgroupMask) -> u32 { + pub fn $name(value: SubgroupMask) -> u32 { let mut result = 0; unsafe { asm! { "%u32 = OpTypeInt 32 0", "%subgroup = OpConstant %u32 {subgroup}", - "%subgroup_mask = OpLoad _ {subgroup_mask}", - "%result = OpGroupNonUniformBallotBitCount %u32 %subgroup {groupop} %subgroup_mask", + "%value = OpLoad _ {value}", + "%result = OpGroupNonUniformBallotBitCount %u32 %subgroup {groupop} %value", "OpStore {result} %result", subgroup = const SUBGROUP, groupop = const ($group_op as u32), - subgroup_mask = in(reg) &subgroup_mask, + value = in(reg) &value, result = in(reg) &mut result, } } @@ -519,32 +519,36 @@ macro_subgroup_ballot_bit_count!( GroupOperation::ExclusiveScan ); -/// Find the least significant bit set to 1 in Value, considering only the bits in Value required to represent all bits of the group's invocations. If none of the considered bits is set to 1, the resulting value is undefined. +/// Find the least significant bit set to 1 in `value`, considering only the bits in `value` required to represent all bits of the group's invocations. If none of the considered bits is set to 1, the resulting value is undefined. /// /// Result Type must be a scalar of integer type, whose Signedness operand is 0. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// Value must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. +/// `value` must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. /// -/// Value is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. +/// `value` is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. /// /// Requires Capability `GroupNonUniformBallot`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if `id` is an inactive invocation or out of bounds #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformBallotFindLSB")] #[inline] -pub unsafe fn subgroup_ballot_find_lsb(subgroup_mask: SubgroupMask) -> u32 { +pub fn subgroup_ballot_find_lsb(value: SubgroupMask) -> u32 { let mut result = 0; unsafe { asm! { "%u32 = OpTypeInt 32 0", "%subgroup = OpConstant %u32 {subgroup}", - "%subgroup_mask = OpLoad _ {subgroup_mask}", - "%result = OpGroupNonUniformBallotFindLSB %u32 %subgroup %subgroup_mask", + "%value = OpLoad _ {value}", + "%result = OpGroupNonUniformBallotFindLSB %u32 %subgroup %value", "OpStore {result} %result", subgroup = const SUBGROUP, - subgroup_mask = in(reg) &subgroup_mask, + value = in(reg) &value, result = in(reg) &mut result, } } @@ -552,32 +556,32 @@ pub unsafe fn subgroup_ballot_find_lsb(subgroup_mask: SubgroupMask) -> u32 { result } -/// Find the most significant bit set to 1 in Value, considering only the bits in Value required to represent all bits of the group's invocations. If none of the considered bits is set to 1, the resulting value is undefined. +/// Find the most significant bit set to 1 in `value`, considering only the bits in `value` required to represent all bits of the group's invocations. If none of the considered bits is set to 1, the resulting value is undefined. /// /// Result Type must be a scalar of integer type, whose Signedness operand is 0. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// Value must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. +/// `value` must be a vector of four components of integer type scalar, whose Width operand is 32 and whose Signedness operand is 0. /// -/// Value is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. +/// `value` is a set of bitfields where the first invocation is represented in the lowest bit of the first vector component and the last (up to the size of the group) is the higher bit number of the last bitmask needed to represent all bits of the group invocations. /// /// Requires Capability `GroupNonUniformBallot`. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformBallotFindMSB")] #[inline] -pub unsafe fn subgroup_ballot_find_msb(subgroup_mask: SubgroupMask) -> u32 { +pub fn subgroup_ballot_find_msb(value: SubgroupMask) -> u32 { let mut result = 0; unsafe { asm! { "%u32 = OpTypeInt 32 0", "%subgroup = OpConstant %u32 {subgroup}", - "%subgroup_mask = OpLoad _ {subgroup_mask}", - "%result = OpGroupNonUniformBallotFindMSB %u32 %subgroup %subgroup_mask", + "%value = OpLoad _ {value}", + "%result = OpGroupNonUniformBallotFindMSB %u32 %subgroup %value", "OpStore {result} %result", subgroup = const SUBGROUP, - subgroup_mask = in(reg) &subgroup_mask, + value = in(reg) &value, result = in(reg) &mut result, } } @@ -585,23 +589,27 @@ pub unsafe fn subgroup_ballot_find_msb(subgroup_mask: SubgroupMask) -> u32 { result } -/// Result is the Value of the invocation identified by the id Id. +/// Result is the `value` of the invocation identified by the id `id`. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// -/// Id must be a scalar of integer type, whose Signedness operand is 0. +/// `id` must be a scalar of integer type, whose Signedness operand is 0. /// -/// The resulting value is undefined if Id is an inactive invocation, or is greater than or equal to the size of the group. +/// The resulting value is undefined if `id` is an inactive invocation, or is greater than or equal to the size of the group. /// /// Requires Capability `GroupNonUniformShuffle`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if `id` is an inactive invocation or out of bounds #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformShuffle")] #[inline] -pub unsafe fn subgroup_shuffle(value: T, id: u32) -> T { +pub fn subgroup_shuffle(value: T, id: u32) -> T { let mut result = T::default(); unsafe { @@ -622,23 +630,27 @@ pub unsafe fn subgroup_shuffle(value: T, id: u32) -> T { result } -/// Result is the Value of the invocation identified by the current invocation’s id within the group xor’ed with Mask. +/// Result is the `value` of the invocation identified by the current invocation’s id within the group xor’ed with Mask. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// /// Mask must be a scalar of integer type, whose Signedness operand is 0. /// /// The resulting value is undefined if current invocation’s id within the group xor’ed with Mask is an inactive invocation, or is greater than or equal to the size of the group. /// /// Requires Capability `GroupNonUniformShuffle`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if current invocation’s id within the group xor’ed with `mask` is an inactive invocation or out of bounds #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformShuffleXor")] #[inline] -pub unsafe fn subgroup_shuffle_xor(value: T, mask: u32) -> T { +pub fn subgroup_shuffle_xor(value: T, mask: u32) -> T { let mut result = T::default(); unsafe { @@ -659,23 +671,27 @@ pub unsafe fn subgroup_shuffle_xor(value: T, mask: u32) -> T result } -/// Result is the Value of the invocation identified by the current invocation’s id within the group - Delta. +/// Result is the `value` of the invocation identified by the current invocation’s id within the group - Delta. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// /// Delta must be a scalar of integer type, whose Signedness operand is 0. /// /// Delta is treated as unsigned and the resulting value is undefined if Delta is greater than the current invocation’s id within the group or if the selected lane is inactive. /// /// Requires Capability `GroupNonUniformShuffleRelative`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if `delta` is greater than the current invocation’s id within the group or if the selected lane is inactive #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformShuffleUp")] #[inline] -pub unsafe fn subgroup_shuffle_up(value: T, delta: u32) -> T { +pub fn subgroup_shuffle_up(value: T, delta: u32) -> T { let mut result = T::default(); unsafe { @@ -696,23 +712,27 @@ pub unsafe fn subgroup_shuffle_up(value: T, delta: u32) -> T result } -/// Result is the Value of the invocation identified by the current invocation’s id within the group + Delta. +/// Result is the `value` of the invocation identified by the current invocation’s id within the group + Delta. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// /// Delta must be a scalar of integer type, whose Signedness operand is 0. /// /// Delta is treated as unsigned and the resulting value is undefined if Delta is greater than or equal to the size of the group, or if the current invocation’s id within the group + Delta is either an inactive invocation or greater than or equal to the size of the group. /// /// Requires Capability `GroupNonUniformShuffleRelative`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if `delta` is greater than or equal to the size of the group, or if the current invocation’s id within the group + `delta` is either an inactive invocation or greater than or equal to the size of the group. #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformShuffleDown")] #[inline] -pub unsafe fn subgroup_shuffle_down(value: T, delta: u32) -> T { +pub fn subgroup_shuffle_down(value: T, delta: u32) -> T { let mut result = T::default(); unsafe { @@ -739,7 +759,7 @@ macro_rules! macro_subgroup_op { #[spirv_std_macros::gpu_only] #[doc(alias = $asm_op)] #[inline] - pub unsafe fn $name>( + pub fn $name>( value: I, ) -> I { let mut result = I::default(); @@ -770,6 +790,16 @@ macro_rules! macro_subgroup_op_clustered { pub unsafe fn $name>( value: I, ) -> I { + const { + assert!(CLUSTER_SIZE >= 1, "`ClusterSize` must be at least 1"); + assert!( + CLUSTER_SIZE.is_power_of_two(), + "`ClusterSize` must be a power of 2" + ); + // Cannot be verified with static assertions: + // `ClusterSize` must not be greater than the size of the group + } + let mut result = I::default(); unsafe { @@ -795,7 +825,7 @@ macro_rules! macro_subgroup_op_clustered { // add macro_subgroup_op!(impl Integer, "OpGroupNonUniformIAdd", subgroup_i_add, GroupOperation::Reduce, subgroup_inclusive_i_add, GroupOperation::InclusiveScan, subgroup_exclusive_i_add, GroupOperation::ExclusiveScan; r" -An integer add group operation of all Value operands contributed by active invocations in the group. +An integer add group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. @@ -803,27 +833,30 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" -An integer add group operation of all Value operands contributed by active invocations in the group. +An integer add group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); macro_subgroup_op!(impl Float, "OpGroupNonUniformFAdd", subgroup_f_add, GroupOperation::Reduce, subgroup_inclusive_f_add, GroupOperation::InclusiveScan, subgroup_exclusive_f_add, GroupOperation::ExclusiveScan; r" -A floating point add group operation of all Value operands contributed by active invocations in the group. +A floating point add group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of floating-point type. @@ -831,29 +864,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 0. -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. +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. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Float, "OpGroupNonUniformFAdd", subgroup_clustered_f_add; r" -A floating point add group operation of all Value operands contributed by active invocations in the group. +A floating point add group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of floating-point type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. -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. +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. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // mul macro_subgroup_op!(impl Integer, "OpGroupNonUniformIMul", subgroup_i_mul, GroupOperation::Reduce, subgroup_inclusive_i_mul, GroupOperation::InclusiveScan, subgroup_exclusive_i_mul, GroupOperation::ExclusiveScan; r" -An integer multiply group operation of all Value operands contributed by active invocations in the group. +An integer multiply group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. @@ -861,27 +897,30 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 1. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIMul", subgroup_clustered_i_mul; r" -An integer multiply group operation of all Value operands contributed by active invocations in the group. +An integer multiply group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 1. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 1. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); macro_subgroup_op!(impl Float, "OpGroupNonUniformFMul", subgroup_f_mul, GroupOperation::Reduce, subgroup_inclusive_f_mul, GroupOperation::InclusiveScan, subgroup_exclusive_f_mul, GroupOperation::ExclusiveScan; r" -A floating point multiply group operation of all Value operands contributed by active invocations in the group. +A floating point multiply group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of floating-point type. @@ -889,29 +928,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 1. -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. +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. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Float, "OpGroupNonUniformFMul", subgroup_clustered_f_mul; r" -A floating point multiply group operation of all Value operands contributed by active invocations in the group. +A floating point multiply group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of floating-point type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 1. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 1. If Operation is ClusteredReduce, `ClusterSize` must be present. -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. +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. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // min macro_subgroup_op!(impl SignedInteger, "OpGroupNonUniformSMin", subgroup_s_min, GroupOperation::Reduce, subgroup_inclusive_s_min, GroupOperation::InclusiveScan, subgroup_exclusive_s_min, GroupOperation::ExclusiveScan; r" -A signed integer minimum group operation of all Value operands contributed by active invocations in the group. +A signed integer minimum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. @@ -919,27 +961,30 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is INT_MAX. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl SignedInteger, "OpGroupNonUniformSMin", subgroup_clustered_s_min; r" -A signed integer minimum group operation of all Value operands contributed by active invocations in the group. +A signed integer minimum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is INT_MAX. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is INT_MAX. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); macro_subgroup_op!(impl UnsignedInteger, "OpGroupNonUniformUMin", subgroup_u_min, GroupOperation::Reduce, subgroup_inclusive_u_min, GroupOperation::InclusiveScan, subgroup_exclusive_u_min, GroupOperation::ExclusiveScan; r" -An unsigned integer minimum group operation of all Value operands contributed by active invocations in the group. +An unsigned integer minimum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type, whose Signedness operand is 0. @@ -947,27 +992,30 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is UINT_MAX. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl UnsignedInteger, "OpGroupNonUniformUMin", subgroup_clustered_u_min; r" -An unsigned integer minimum group operation of all Value operands contributed by active invocations in the group. +An unsigned integer minimum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type, whose Signedness operand is 0. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is UINT_MAX. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is UINT_MAX. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); macro_subgroup_op!(impl Float, "OpGroupNonUniformFMin", subgroup_f_min, GroupOperation::Reduce, subgroup_inclusive_f_min, GroupOperation::InclusiveScan, subgroup_exclusive_f_min, GroupOperation::ExclusiveScan; r" -A floating point minimum group operation of all Value operands contributed by active invocations in the group. +A floating point minimum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of floating-point type. @@ -975,29 +1023,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is +INF. -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. +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. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Float, "OpGroupNonUniformFMin", subgroup_clustered_f_min; r" -A floating point minimum group operation of all Value operands contributed by active invocations in the group. +A floating point minimum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of floating-point type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is +INF. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is +INF. If Operation is ClusteredReduce, `ClusterSize` must be present. -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. +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. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // max macro_subgroup_op!(impl SignedInteger, "OpGroupNonUniformSMax", subgroup_s_max, GroupOperation::Reduce, subgroup_inclusive_s_max, GroupOperation::InclusiveScan, subgroup_exclusive_s_max, GroupOperation::ExclusiveScan; r" -A signed integer maximum group operation of all Value operands contributed by active invocations in the group. +A signed integer maximum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. @@ -1005,27 +1056,30 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is INT_MIN. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl SignedInteger, "OpGroupNonUniformSMax", subgroup_clustered_s_max; r" -A signed integer maximum group operation of all Value operands contributed by active invocations in the group. +A signed integer maximum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is INT_MIN. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is INT_MIN. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); macro_subgroup_op!(impl UnsignedInteger, "OpGroupNonUniformUMax", subgroup_u_max, GroupOperation::Reduce, subgroup_inclusive_u_max, GroupOperation::InclusiveScan, subgroup_exclusive_u_max, GroupOperation::ExclusiveScan; r" -An unsigned integer maximum group operation of all Value operands contributed by active invocations in the group. +An unsigned integer maximum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type, whose Signedness operand is 0. @@ -1033,27 +1087,30 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl UnsignedInteger, "OpGroupNonUniformUMax", subgroup_clustered_u_max; r" -An unsigned integer maximum group operation of all Value operands contributed by active invocations in the group. +An unsigned integer maximum group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type, whose Signedness operand is 0. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); macro_subgroup_op!(impl Float, "OpGroupNonUniformFMax", subgroup_f_max, GroupOperation::Reduce, subgroup_inclusive_f_max, GroupOperation::InclusiveScan, subgroup_exclusive_f_max, GroupOperation::ExclusiveScan; r" -A floating point maximum group operation of all Value operands contributed by active invocations in by group. +A floating point maximum group operation of all `value` operands contributed by active invocations in by group. Result Type must be a scalar or vector of floating-point type. @@ -1061,12 +1118,12 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is -INF. -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. +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. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Float, "OpGroupNonUniformFMax", subgroup_clustered_f_max; r" -A floating point maximum group operation of all Value operands contributed by active invocations in by group. +A floating point maximum group operation of all `value` operands contributed by active invocations in by group. Result Type must be a scalar or vector of floating-point type. @@ -1074,14 +1131,17 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is -INF. -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. +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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // and macro_subgroup_op!(impl Integer, "OpGroupNonUniformBitwiseAnd", subgroup_and, GroupOperation::Reduce, subgroup_inclusive_and, GroupOperation::InclusiveScan, subgroup_exclusive_and, GroupOperation::ExclusiveScan; r" -A bitwise and group operation of all Value operands contributed by active invocations in the group. +A bitwise and group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. @@ -1089,29 +1149,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is ~0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformBitwiseAnd", subgroup_clustered_and; r" -A bitwise and group operation of all Value operands contributed by active invocations in the group. +A bitwise and group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is ~0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is ~0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // or macro_subgroup_op!(impl Integer, "OpGroupNonUniformBitwiseOr", subgroup_or, GroupOperation::Reduce, subgroup_inclusive_or, GroupOperation::InclusiveScan, subgroup_exclusive_or, GroupOperation::ExclusiveScan; r" -A bitwise or group operation of all Value operands contributed by active invocations in the group. +A bitwise or group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. @@ -1119,29 +1182,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformBitwiseOr", subgroup_clustered_or; r" -A bitwise or group operation of all Value operands contributed by active invocations in the group. +A bitwise or group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // xor macro_subgroup_op!(impl Integer, "OpGroupNonUniformBitwiseXor", subgroup_xor, GroupOperation::Reduce, subgroup_inclusive_xor, GroupOperation::InclusiveScan, subgroup_exclusive_xor, GroupOperation::ExclusiveScan; r" -A bitwise xor group operation of all Value operands contributed by active invocations in the group. +A bitwise xor group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. @@ -1149,29 +1215,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformBitwiseXor", subgroup_clustered_xor; r" -A bitwise xor group operation of all Value operands contributed by active invocations in the group. +A bitwise xor group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // logical and macro_subgroup_op!(bool, "OpGroupNonUniformLogicalAnd", subgroup_logical_and, GroupOperation::Reduce, subgroup_inclusive_logical_and, GroupOperation::InclusiveScan, subgroup_exclusive_logical_and, GroupOperation::ExclusiveScan; r" -A logical and group operation of all Value operands contributed by active invocations in the group. +A logical and group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of Boolean type. @@ -1179,29 +1248,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is ~0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(bool, "OpGroupNonUniformLogicalAnd", subgroup_clustered_logical_and; r" -A logical and group operation of all Value operands contributed by active invocations in the group. +A logical and group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of Boolean type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is ~0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is ~0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // logical or macro_subgroup_op!(bool, "OpGroupNonUniformLogicalOr", subgroup_logical_or, GroupOperation::Reduce, subgroup_inclusive_logical_or, GroupOperation::InclusiveScan, subgroup_exclusive_logical_or, GroupOperation::ExclusiveScan; r" -A logical or group operation of all Value operands contributed by active invocations in the group. +A logical or group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of Boolean type. @@ -1209,29 +1281,32 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(bool, "OpGroupNonUniformLogicalOr", subgroup_clustered_logical_or; r" -A logical or group operation of all Value operands contributed by active invocations in the group. +A logical or group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of Boolean type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); // logical xor macro_subgroup_op!(bool, "OpGroupNonUniformLogicalXor", subgroup_logical_xor, GroupOperation::Reduce, subgroup_inclusive_logical_xor, GroupOperation::InclusiveScan, subgroup_exclusive_logical_xor, GroupOperation::ExclusiveScan; r" -A logical xor group operation of all Value operands contributed by active invocations in the group. +A logical xor group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of Boolean type. @@ -1239,45 +1314,52 @@ Execution is a Scope that identifies the group of invocations affected by this c The identity I for Operation is 0. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. Requires Capability `GroupNonUniformArithmetic`. "); macro_subgroup_op_clustered!(bool, "OpGroupNonUniformLogicalXor", subgroup_clustered_logical_xor; r" -A logical xor group operation of all Value operands contributed by active invocations in the group. +A logical xor group operation of all `value` operands contributed by active invocations in the group. Result Type must be a scalar or vector of Boolean type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, ClusterSize must be present. +The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. -The type of Value must be the same as Result Type. +The type of `value` must be the same as Result Type. -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. +`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. Requires Capability `GroupNonUniformArithmetic` and `GroupNonUniformClustered`. + +# Safety +* `ClusterSize` must not be greater than the size of the group "); -/// Result is the Value of the invocation within the quad with a quad index equal to Index. +/// Result is the `value` of the invocation within the quad with a quad index equal to `index`. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope, but has no effect on the behavior of this instruction. It must be Subgroup. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// -/// Index must be a scalar of integer type, whose Signedness operand is 0. +/// `index` must be a scalar of integer type, whose Signedness operand is 0. /// -/// Before version 1.5, Index must come from a constant instruction. Starting with version 1.5, Index must be dynamically uniform. +/// Before version 1.5, `index` must come from a constant instruction. Starting with version 1.5, `index` must be dynamically uniform. /// -/// If the value of Index is greater than or equal to 4, or refers to an inactive invocation, the resulting value is undefined. +/// If the value of `index` is greater than or equal to 4, or refers to an inactive invocation, the resulting value is undefined. /// /// Requires Capability `GroupNonUniformQuad`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if the value of `index` is greater than or equal to 4, or refers to an inactive invocation #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformQuadBroadcast")] #[inline] -pub unsafe fn subgroup_quad_broadcast(value: T, id: u32) -> T { +pub fn subgroup_quad_broadcast(value: T, index: u32) -> T { let mut result = T::default(); unsafe { @@ -1285,12 +1367,12 @@ pub unsafe fn subgroup_quad_broadcast(value: T, id: u32) -> T "%u32 = OpTypeInt 32 0", "%subgroup = OpConstant %u32 {subgroup}", "%value = OpLoad _ {value}", - "%id = OpLoad _ {id}", - "%result = OpGroupNonUniformQuadBroadcast _ %subgroup %value %id", + "%index = OpLoad _ {index}", + "%result = OpGroupNonUniformQuadBroadcast _ %subgroup %value %index", "OpStore {result} %result", subgroup = const SUBGROUP, value = in(reg) &value, - id = in(reg) &id, + index = in(reg) &index, result = in(reg) &mut result, } } @@ -1304,7 +1386,7 @@ pub unsafe fn subgroup_quad_broadcast(value: T, id: u32) -> T /// /// Direction must come from a constant instruction. /// -/// The value returned in Result is the value provided to Value by another invocation in the same quad scope instance. The invocation providing this value is determined according to Direction. +/// The value returned in Result is the value provided to `value` by another invocation in the same quad scope instance. The invocation providing this `value` is determined according to Direction. /// /// Requires Capability `GroupNonUniformQuad`. pub enum QuadDirection { @@ -1322,13 +1404,13 @@ pub enum QuadDirection { Diagonal = 2, } -/// Swap the Value of the invocation within the quad with another invocation in the quad using Direction. +/// Swap the `value` of the invocation within the quad with another invocation in the quad using Direction. /// /// Result Type must be a scalar or vector of floating-point type, integer type, or Boolean type. /// /// Execution is a Scope, but has no effect on the behavior of this instruction. It must be Subgroup. /// -/// The type of Value must be the same as Result Type. +/// The type of `value` must be the same as Result Type. /// /// Direction is the kind of swap to perform. /// @@ -1336,7 +1418,7 @@ pub enum QuadDirection { /// /// Direction must come from a constant instruction. /// -/// The value returned in Result is the value provided to Value by another invocation in the same quad scope instance. The invocation providing this value is determined according to Direction. +/// The value returned in Result is the value provided to `value` by another invocation in the same quad scope instance. The invocation providing this `value` is determined according to Direction. /// /// A Direction of 0 indicates a horizontal swap; /// - Invocations with quad indices of 0 and 1 swap values @@ -1350,13 +1432,17 @@ pub enum QuadDirection { /// /// Direction must be one of the above values. /// -/// If an active invocation reads Value from an inactive invocation, the resulting value is undefined. +/// If an active invocation reads `value` from an inactive invocation, the resulting value is undefined. /// /// Requires Capability `GroupNonUniformQuad`. +/// +/// # Safety +/// * This function is safe +/// * Result is undefined if an active invocation reads `value` from an inactive invocation #[spirv_std_macros::gpu_only] #[doc(alias = "OpGroupNonUniformQuadSwap")] #[inline] -pub unsafe fn subgroup_quad_swap(value: T) -> T { +pub fn subgroup_quad_swap(value: T) -> T { let mut result = T::default(); unsafe { diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_ballot.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_ballot.stderr index 2d7b71e12c..9ce9546076 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_ballot.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_ballot.stderr @@ -1,9 +1,9 @@ %1 = OpFunction %2 None %3 %4 = OpFunctionParameter %2 %5 = OpLabel -OpLine %6 380 8 +OpLine %6 373 8 %7 = OpGroupNonUniformBallot %8 %9 %4 -OpLine %6 416 8 +OpLine %6 412 8 %10 = OpGroupNonUniformInverseBallot %2 %9 %7 OpNoLine OpReturnValue %10 diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_broadcast_first.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_broadcast_first.stderr index 6836a0fd14..a6ffcdb8a4 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_broadcast_first.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_broadcast_first.stderr @@ -1,7 +1,7 @@ %1 = OpFunction %2 None %3 %4 = OpFunctionParameter %2 %5 = OpLabel -OpLine %6 347 8 +OpLine %6 340 8 %7 = OpGroupNonUniformBroadcastFirst %2 %8 %4 OpNoLine OpReturnValue %7 diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs new file mode 100644 index 0000000000..4fec2a3db5 --- /dev/null +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs @@ -0,0 +1,18 @@ +// build-pass +// compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model +// normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" + +use glam::UVec3; +use spirv_std::arch::{GroupOperation, SubgroupMask}; +use spirv_std::spirv; + +unsafe fn subgroup_test_fail(value: u32) -> u32 { + spirv_std::arch::subgroup_clustered_i_add::<0, _>(value) +} + +#[spirv(compute(threads(32, 1, 1)))] +pub fn main(#[spirv(local_invocation_id)] local_invocation_id: UVec3) { + unsafe { + subgroup_test_fail(local_invocation_id.x); + } +} diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr new file mode 100644 index 0000000000..db4905f35d --- /dev/null +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr @@ -0,0 +1,37 @@ +error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>::{constant#0}` failed + --> $SPIRV_STD_SRC/arch/subgroup.rs:840:1 + | +840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" +841 | | An integer add group operation of all `value` operands contributed by active invocations in the group. +842 | | +843 | | Result Type must be a scalar or vector of integer type. +... | +856 | | * `ClusterSize` must not be greater than the size of the group +857 | | "); + | |__^ the evaluated program panicked at '`ClusterSize` must be at least 1', $SPIRV_STD_SRC/arch/subgroup.rs:840:1 + | + = 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) + +note: erroneous constant encountered + --> $SPIRV_STD_SRC/arch/subgroup.rs:840:1 + | +840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" +841 | | An integer add group operation of all `value` operands contributed by active invocations in the group. +842 | | +843 | | Result Type must be a scalar or vector of integer type. +... | +856 | | * `ClusterSize` must not be greater than the size of the group +857 | | "); + | |__^ + | + = note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: the above error was encountered while instantiating `fn spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>` + --> $DIR/subgroup_cluster_size_0_fail.rs:10:5 + | +10 | spirv_std::arch::subgroup_clustered_i_add::<0, _>(value) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs new file mode 100644 index 0000000000..9184cc25b1 --- /dev/null +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs @@ -0,0 +1,18 @@ +// build-pass +// compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model +// normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" + +use glam::UVec3; +use spirv_std::arch::{GroupOperation, SubgroupMask}; +use spirv_std::spirv; + +unsafe fn subgroup_test_fail(value: u32) -> u32 { + spirv_std::arch::subgroup_clustered_i_add::<5, _>(value) +} + +#[spirv(compute(threads(32, 1, 1)))] +pub fn main(#[spirv(local_invocation_id)] local_invocation_id: UVec3) { + unsafe { + subgroup_test_fail(local_invocation_id.x); + } +} diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr new file mode 100644 index 0000000000..5442b482b9 --- /dev/null +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr @@ -0,0 +1,37 @@ +error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>::{constant#0}` failed + --> $SPIRV_STD_SRC/arch/subgroup.rs:840:1 + | +840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" +841 | | An integer add group operation of all `value` operands contributed by active invocations in the group. +842 | | +843 | | Result Type must be a scalar or vector of integer type. +... | +856 | | * `ClusterSize` must not be greater than the size of the group +857 | | "); + | |__^ the evaluated program panicked at '`ClusterSize` must be a power of 2', $SPIRV_STD_SRC/arch/subgroup.rs:840:1 + | + = 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) + +note: erroneous constant encountered + --> $SPIRV_STD_SRC/arch/subgroup.rs:840:1 + | +840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" +841 | | An integer add group operation of all `value` operands contributed by active invocations in the group. +842 | | +843 | | Result Type must be a scalar or vector of integer type. +... | +856 | | * `ClusterSize` must not be greater than the size of the group +857 | | "); + | |__^ + | + = note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: the above error was encountered while instantiating `fn spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>` + --> $DIR/subgroup_cluster_size_non_power_of_two_fail.rs:10:5 + | +10 | spirv_std::arch::subgroup_clustered_i_add::<5, _>(value) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_elect.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_elect.stderr index 0cbeb7590b..4bfef562f7 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_elect.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_elect.stderr @@ -1,6 +1,6 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 182 8 +OpLine %5 170 8 %6 = OpGroupNonUniformElect %2 %7 OpNoLine OpReturnValue %6 diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_clustered.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_clustered.stderr index d88cfd3296..710c976877 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_clustered.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_clustered.stderr @@ -1,7 +1,7 @@ %1 = OpFunction %2 None %3 %4 = OpFunctionParameter %2 %5 = OpLabel -OpLine %6 810 0 +OpLine %6 840 0 %7 = OpGroupNonUniformIAdd %2 %8 ClusteredReduce %4 %9 OpNoLine OpReturnValue %7 diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_exclusive_scan.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_exclusive_scan.stderr index ca83820bf0..da708505b8 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_exclusive_scan.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_exclusive_scan.stderr @@ -1,7 +1,7 @@ %1 = OpFunction %2 None %3 %4 = OpFunctionParameter %2 %5 = OpLabel -OpLine %6 797 0 +OpLine %6 827 0 %7 = OpGroupNonUniformIAdd %2 %8 ExclusiveScan %4 OpNoLine OpReturnValue %7 diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_inclusive_scan.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_inclusive_scan.stderr index 93048426c1..684d46dec0 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_inclusive_scan.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_inclusive_scan.stderr @@ -1,7 +1,7 @@ %1 = OpFunction %2 None %3 %4 = OpFunctionParameter %2 %5 = OpLabel -OpLine %6 797 0 +OpLine %6 827 0 %7 = OpGroupNonUniformIAdd %2 %8 InclusiveScan %4 OpNoLine OpReturnValue %7 diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_reduce.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_reduce.stderr index f382189af7..9430d3452d 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_i_add_reduce.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_i_add_reduce.stderr @@ -1,7 +1,7 @@ %1 = OpFunction %2 None %3 %4 = OpFunctionParameter %2 %5 = OpLabel -OpLine %6 797 0 +OpLine %6 827 0 %7 = OpGroupNonUniformIAdd %2 %8 Reduce %4 OpNoLine OpReturnValue %7