diff --git a/Cargo.lock b/Cargo.lock index f44ff49179..151d7e44bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1004,9 +1004,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.11.3" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d9e5a6410cd46e6bea97123cec5ef1cba14274aad26a1835dd3c9b753ae069" +checksum = "2ad8819b352632f676098176a51e11e324e8cee4c2518dd67e58c36b848438e6" dependencies = [ "num-traits", "version_check", diff --git a/crates/spirv-builder/src/test/basic.rs b/crates/spirv-builder/src/test/basic.rs index 004ef5a790..86e26d5bf3 100644 --- a/crates/spirv-builder/src/test/basic.rs +++ b/crates/spirv-builder/src/test/basic.rs @@ -366,3 +366,17 @@ pub fn create_uninit_and_write() { #[spirv(fragment)] pub fn main() {}"#); } + +#[test] +fn vector_extract_dynamic() { + val(r#" +#[allow(unused_attributes)] +#[spirv(fragment)] +pub fn main() { + let vector = glam::Vec2::new(1.0, 2.0); + let element = unsafe { spirv_std::arch::vector_extract_dynamic(&vector, 1) }; + assert!(2.0 == element); +} +"#); +} + diff --git a/crates/spirv-std/Cargo.toml b/crates/spirv-std/Cargo.toml index 03537f2ab8..902ef67452 100644 --- a/crates/spirv-std/Cargo.toml +++ b/crates/spirv-std/Cargo.toml @@ -8,7 +8,7 @@ repository = "https://github.com/EmbarkStudios/rust-gpu" description = "Standard functions and types for SPIR-V" [dependencies] -glam = { version = "0.11.3", default-features = false, features = ["libm", "scalar-math"] } +glam = { version = "0.12.0", default-features = false, features = ["libm", "scalar-math"] } num-traits = { version = "0.2.14", default-features = false } spirv-std-macros = { path = "../spirv-std-macros" } diff --git a/crates/spirv-std/src/arch.rs b/crates/spirv-std/src/arch.rs new file mode 100644 index 0000000000..f864f278c6 --- /dev/null +++ b/crates/spirv-std/src/arch.rs @@ -0,0 +1,29 @@ +//! SPIR-V Instrinics +//! +//! This module is intended as a low level abstraction over SPIR-V instructions. +//! These functions will typically map to a single instruction, and will perform +//! no additional safety checks beyond type-checking. +use crate::{scalar::Scalar, vector::Vector}; + +/// Extract a single, dynamically selected, component of a vector. +/// +/// # Safety +/// Behavior is undefined if `index`’s value is greater than or equal to the +/// number of components in `vector`. +#[spirv_std_macros::gpu_only] +#[doc(alias = "OpVectorExtractDynamic")] +#[inline] +pub unsafe fn vector_extract_dynamic>(vector: V, index: usize) -> T { + let mut result = T::default(); + + asm! { + "%vector = OpLoad _ {vector}", + "%element = OpVectorExtractDynamic _ %vector {index}", + "OpStore {element} %element", + vector = in(reg) &vector, + index = in(reg) index, + element = in(reg) &mut result + } + + result +} diff --git a/crates/spirv-std/src/lib.rs b/crates/spirv-std/src/lib.rs index 6bba2ba861..fae52dad6e 100644 --- a/crates/spirv-std/src/lib.rs +++ b/crates/spirv-std/src/lib.rs @@ -43,8 +43,12 @@ #[macro_use] pub extern crate spirv_std_macros; +pub mod arch; pub mod derivative; pub mod storage_class; +pub mod scalar; +pub(crate) mod sealed; +pub mod vector; mod textures; pub use glam; diff --git a/crates/spirv-std/src/scalar.rs b/crates/spirv-std/src/scalar.rs new file mode 100644 index 0000000000..9bac2d11aa --- /dev/null +++ b/crates/spirv-std/src/scalar.rs @@ -0,0 +1,7 @@ +/// Abstract trait representing a SPIR-V scalar type. +pub trait Scalar: Copy + Default + crate::sealed::Sealed {} + +impl Scalar for bool {} +impl Scalar for f32 {} +impl Scalar for u32 {} +impl Scalar for i32 {} diff --git a/crates/spirv-std/src/sealed.rs b/crates/spirv-std/src/sealed.rs new file mode 100644 index 0000000000..55c05ddf7d --- /dev/null +++ b/crates/spirv-std/src/sealed.rs @@ -0,0 +1,21 @@ +/// A marker trait used to prevent other traits from being implemented outside +/// of `spirv-std`. +pub trait Sealed {} + +impl Sealed for bool {} +impl Sealed for f32 {} +impl Sealed for u32 {} +impl Sealed for i32 {} +impl Sealed for glam::BVec2 {} +impl Sealed for glam::BVec3 {} +impl Sealed for glam::BVec4 {} +impl Sealed for glam::Vec2 {} +impl Sealed for glam::Vec3 {} +impl Sealed for glam::Vec3A {} +impl Sealed for glam::Vec4 {} +impl Sealed for glam::UVec2 {} +impl Sealed for glam::UVec3 {} +impl Sealed for glam::UVec4 {} +impl Sealed for glam::IVec2 {} +impl Sealed for glam::IVec3 {} +impl Sealed for glam::IVec4 {} diff --git a/crates/spirv-std/src/vector.rs b/crates/spirv-std/src/vector.rs new file mode 100644 index 0000000000..9f866adf23 --- /dev/null +++ b/crates/spirv-std/src/vector.rs @@ -0,0 +1,16 @@ +/// Abstract trait representing a SPIR-V vector type. +pub trait Vector: crate::sealed::Sealed {} + +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 {}