diff --git a/crates/spirv-builder/src/test/basic.rs b/crates/spirv-builder/src/test/basic.rs index 144111c31c..475fdc90cd 100644 --- a/crates/spirv-builder/src/test/basic.rs +++ b/crates/spirv-builder/src/test/basic.rs @@ -563,6 +563,31 @@ OpFunctionEnd", ); } +#[test] +fn any() { + val(r#" + +#[allow(unused_attributes)] +#[spirv(fragment)] +pub fn main() { + let vector = glam::BVec2::new(true, false); + assert!(arch::any(vector)); +} +"#); +} + +#[test] +fn all() { + val(r#" +#[allow(unused_attributes)] +#[spirv(fragment)] +pub fn main() { + let vector = glam::BVec2::new(true, true); + assert!(arch::all(vector)); +} +"#); +} + #[test] fn image_read() { val(r#" diff --git a/crates/spirv-std/src/arch.rs b/crates/spirv-std/src/arch.rs index 7e1e540c51..deb289754b 100644 --- a/crates/spirv-std/src/arch.rs +++ b/crates/spirv-std/src/arch.rs @@ -5,6 +5,72 @@ //! no additional safety checks beyond type-checking. use crate::{scalar::Scalar, vector::Vector}; +/// Result is true if any component of `vector` is true, otherwise result is +/// false. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpAny")] +#[inline] +pub fn any, const N: usize>(vector: V) -> bool { + let mut result = false; + + unsafe { + asm! { + // Types & Constants + "%bool = OpTypeBool", + "%u8 = OpTypeInt 8 0", + "%u8_0 = OpConstant %u8 0", + "%u8_1 = OpConstant %u8 1", + "%glam_vec_type = OpTypeVector %u8 {len}", + "%bool_vec_type = OpTypeVector %bool {len}", + "%false_vec = OpConstantNull %glam_vec_type", + // Code + "%vector = OpLoad %glam_vec_type {vector}", + "%bool_vec = OpINotEqual %bool_vec_type %vector %false_vec", + "%result = OpAny %bool %bool_vec", + "%boolean = OpSelect %u8 %result %u8_1 %u8_0", + "OpStore {result} %boolean", + vector = in(reg) &vector, + len = const N, + result = in(reg) &mut result + } + } + + result +} + +/// Result is true if all components of `vector` is true, otherwise result is +/// false. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpAll")] +#[inline] +pub fn all, const N: usize>(vector: V) -> bool { + let mut result = false; + + unsafe { + asm! { + // Types & Constants + "%bool = OpTypeBool", + "%u8 = OpTypeInt 8 0", + "%u8_0 = OpConstant %u8 0", + "%u8_1 = OpConstant %u8 1", + "%glam_vec_type = OpTypeVector %u8 {len}", + "%bool_vec_type = OpTypeVector %bool {len}", + "%false_vec = OpConstantNull %glam_vec_type", + // Code + "%vector = OpLoad %glam_vec_type {vector}", + "%bool_vec = OpINotEqual %bool_vec_type %vector %false_vec", + "%result = OpAll %bool %bool_vec", + "%boolean = OpSelect %u8 %result %u8_1 %u8_0", + "OpStore {element} %boolean", + vector = in(reg) &vector, + len = const N, + element = in(reg) &mut result + } + } + + result +} + /// Extract a single, dynamically selected, component of a vector. /// /// # Safety @@ -13,7 +79,10 @@ use crate::{scalar::Scalar, vector::Vector}; #[spirv_std_macros::gpu_only] #[doc(alias = "OpVectorExtractDynamic")] #[inline] -pub unsafe fn vector_extract_dynamic>(vector: V, index: usize) -> T { +pub unsafe fn vector_extract_dynamic, const N: usize>( + vector: V, + index: usize, +) -> T { let mut result = T::default(); asm! { @@ -37,7 +106,7 @@ pub unsafe fn vector_extract_dynamic>(vector: V, index: #[spirv_std_macros::gpu_only] #[doc(alias = "OpVectorInsertDynamic")] #[inline] -pub unsafe fn vector_insert_dynamic>( +pub unsafe fn vector_insert_dynamic, const N: usize>( vector: V, index: usize, element: T, diff --git a/crates/spirv-std/src/textures.rs b/crates/spirv-std/src/textures.rs index ad99e48a2a..f8e54497a8 100644 --- a/crates/spirv-std/src/textures.rs +++ b/crates/spirv-std/src/textures.rs @@ -64,11 +64,11 @@ pub struct StorageImage2d { impl StorageImage2d { /// Read a texel from an image without a sampler. #[spirv_std_macros::gpu_only] - pub fn read(&self, coordinate: V) -> V2 + pub fn read(&self, coordinate: V) -> V2 where I: Integer, - V: Vector, - V2: Vector, + V: Vector, + V2: Vector, { let mut result = V2::default(); @@ -89,11 +89,11 @@ impl StorageImage2d { /// Write a texel to an image without a sampler. #[spirv_std_macros::gpu_only] - pub fn write(&self, coordinate: V, texels: V2) + pub fn write(&self, coordinate: V, texels: V2) where I: Integer, - V: Vector, - V2: Vector, + V: Vector, + V2: Vector, { unsafe { asm! { diff --git a/crates/spirv-std/src/vector.rs b/crates/spirv-std/src/vector.rs index cb2382068b..9a0e6f314f 100644 --- a/crates/spirv-std/src/vector.rs +++ b/crates/spirv-std/src/vector.rs @@ -1,16 +1,19 @@ /// Abstract trait representing a SPIR-V vector type. -pub trait Vector: crate::sealed::Sealed + Default {} +pub trait Vector: + crate::sealed::Sealed + Default +{ +} -impl Vector for glam::BVec2 {} -impl Vector for glam::BVec3 {} -impl Vector for glam::BVec4 {} -impl Vector for glam::Vec2 {} -impl Vector for glam::Vec3 {} -impl Vector for glam::Vec3A {} -impl Vector for glam::Vec4 {} -impl Vector for glam::UVec2 {} -impl Vector for glam::UVec3 {} -impl Vector for glam::UVec4 {} -impl Vector for glam::IVec2 {} -impl Vector for glam::IVec3 {} -impl Vector for glam::IVec4 {} +impl Vector for glam::BVec2 {} +impl Vector for glam::BVec3 {} +impl Vector for glam::BVec4 {} +impl Vector for glam::Vec2 {} +impl Vector for glam::Vec3 {} +impl Vector for glam::Vec3A {} +impl Vector for glam::Vec4 {} +impl Vector for glam::UVec2 {} +impl Vector for glam::UVec3 {} +impl Vector for glam::UVec4 {} +impl Vector for glam::IVec2 {} +impl Vector for glam::IVec3 {} +impl Vector for glam::IVec4 {}