From 4fdd48d6ef6b7eec2f26992befd9eebe7d165b2d Mon Sep 17 00:00:00 2001 From: BeastLe9enD Date: Fri, 7 Apr 2023 03:59:48 +0200 Subject: [PATCH 1/2] Add vector or scalar traits --- crates/spirv-std/src/float.rs | 43 +++++++++++++-- crates/spirv-std/src/integer.rs | 96 +++++++++++++++++++++++++-------- crates/spirv-std/src/number.rs | 38 +++++++++---- crates/spirv-std/src/scalar.rs | 55 +++++++++++++++---- 4 files changed, 184 insertions(+), 48 deletions(-) diff --git a/crates/spirv-std/src/float.rs b/crates/spirv-std/src/float.rs index 0a685b2468..fa25ddbd06 100644 --- a/crates/spirv-std/src/float.rs +++ b/crates/spirv-std/src/float.rs @@ -9,17 +9,50 @@ use core::arch::asm; /// # Safety /// Implementing this trait on non-primitive-float types breaks assumptions of other unsafe code, /// and should not be done. -pub unsafe trait Float: num_traits::Float + crate::scalar::Scalar + Default { +pub unsafe trait Float: num_traits::Float + crate::scalar::Scalar { /// Width of the float, in bits. const WIDTH: usize; } -unsafe impl Float for f32 { - const WIDTH: usize = 32; +/// Abstract trait representing a SPIR-V floating point type. It may also be a vector type. +/// +/// # Safety +/// Implementing this trait on non-primitive-float types breaks assumptions of other unsafe code, +/// and should not be done. +pub unsafe trait FloatVector: crate::scalar::ScalarVector { + /// Width of the float, in bits. + const WIDTH: usize; +} + +macro_rules! impl_floats { + (unsafe impl Float for $($typ:ty)*;) => { + $( + unsafe impl Float for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + } + + unsafe impl FloatVector for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + } + )* + }; + + (unsafe impl FloatVector for $($typ:ty)*;) => { + $( + unsafe impl FloatVector for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + } + )* + }; + + ($(unsafe impl $trait:ident for $($typ:ty)*;)+) => { + $(impl_floats!(unsafe impl $trait for $($typ)*;);)+ + }; } -unsafe impl Float for f64 { - const WIDTH: usize = 64; +impl_floats! { + unsafe impl Float for f32 f64; + unsafe impl FloatVector for glam::Vec2 glam::Vec3 glam::Vec4 glam::DVec2 glam::DVec3 glam::DVec4; } /// Converts two f32 values (floats) into two f16 values (halfs). The result is a u32, with the low diff --git a/crates/spirv-std/src/integer.rs b/crates/spirv-std/src/integer.rs index 083bae617a..1aa324ce79 100644 --- a/crates/spirv-std/src/integer.rs +++ b/crates/spirv-std/src/integer.rs @@ -12,41 +12,93 @@ pub unsafe trait Integer: num_traits::PrimInt + crate::scalar::Scalar { const SIGNED: bool; } +/// Abstract trait representing any SPIR-V integer type. It may also be a vector type. +/// +/// # Safety +/// Implementing this trait on non-primitive-integer types breaks assumptions of other unsafe code, +/// and should not be done. +pub unsafe trait IntegerVector: crate::scalar::ScalarVector { + /// Width of the integer, in bits. + const WIDTH: usize; + /// If the integer is signed: true means signed, false means unsigned. + const SIGNED: bool; +} + /// A trait for being generic over signed integer types. pub trait SignedInteger: Integer {} +/// A trait for being generic over signed integer types. It may also be a vector type. +pub trait SignedIntegerVector: IntegerVector {} + /// A trait for being generic over unsigned integer types. pub trait UnsignedInteger: Integer {} +/// A trait for being generic over unsigned integer types. It may also be a vector type. +pub trait UnsignedIntegerVector: IntegerVector {} macro_rules! impl_numbers { - (impl UnsignedInteger for $typ:ty;) => { - unsafe impl Integer for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = false; - } + (impl UnsignedInteger for $($typ:ty)*;) => { + $( + unsafe impl Integer for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = false; + } + + unsafe impl IntegerVector for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = false; + } + + impl UnsignedInteger for $typ {} + impl UnsignedIntegerVector for $typ {} + )* + }; + + (impl UnsignedIntegerVector for $($typ:ty)*;) => { + $( + unsafe impl IntegerVector for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = false; + } - impl UnsignedInteger for $typ {} + impl UnsignedIntegerVector for $typ {} + )* }; - (impl SignedInteger for $typ:ty;) => { - unsafe impl Integer for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = true; - } - impl SignedInteger for $typ {} + (impl SignedInteger for $($typ:ty)*;) => { + $( + unsafe impl Integer for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = true; + } + + unsafe impl IntegerVector for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = true; + } + + impl SignedInteger for $typ {} + impl SignedIntegerVector for $typ {} + )* }; - ($(impl $trait:ident for $typ:ty;)+) => { - $(impl_numbers!(impl $trait for $typ;);)+ + + (impl SignedIntegerVector for $($typ:ty)*;) => { + $( + unsafe impl IntegerVector for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = true; + } + + impl SignedIntegerVector for $typ {} + )* }; + ($(impl $trait:ident for $($typ:ty)*;)+) => { + $(impl_numbers!(impl $trait for $($typ)*;);)+ + }; } impl_numbers! { - impl UnsignedInteger for u8; - impl UnsignedInteger for u16; - impl UnsignedInteger for u32; - impl UnsignedInteger for u64; - impl SignedInteger for i8; - impl SignedInteger for i16; - impl SignedInteger for i32; - impl SignedInteger for i64; + impl UnsignedInteger for u8 u16 u32 u64; + impl UnsignedIntegerVector for glam::UVec2 glam::UVec3 glam::UVec4; + impl SignedInteger for i8 i16 i32 i64; + impl SignedIntegerVector for glam::IVec2 glam::IVec3 glam::IVec4; } diff --git a/crates/spirv-std/src/number.rs b/crates/spirv-std/src/number.rs index 20a195da1e..db07b1dbf1 100644 --- a/crates/spirv-std/src/number.rs +++ b/crates/spirv-std/src/number.rs @@ -3,13 +3,31 @@ /// Abstract trait representing a SPIR-V integer or floating-point type. pub trait Number: crate::scalar::Scalar {} -impl Number for u8 {} -impl Number for u16 {} -impl Number for u32 {} -impl Number for u64 {} -impl Number for i8 {} -impl Number for i16 {} -impl Number for i32 {} -impl Number for i64 {} -impl Number for f32 {} -impl Number for f64 {} +/// Abstract trait representing a SPIR-V integer or floating-point type. It may also be a vector type. +pub trait NumberVector: crate::scalar::ScalarVector {} + +macro_rules! impl_numbers { + (unsafe impl Number for $($typ:ty)*;) => { + $( + impl Number for $typ {} + impl NumberVector for $typ {} + )* + }; + + (unsafe impl NumberVector for $($typ:ty)*;) => { + $( + impl NumberVector for $typ {} + )* + }; + + ($(unsafe impl $trait:ident for $($typ:ty)*;)+) => { + $(impl_numbers!(unsafe impl $trait for $($typ)*;);)+ + }; +} + +impl_numbers! { + unsafe impl Number for u8 u16 u32 u64 i8 i16 i32 i64 f32 f64; + unsafe impl NumberVector for glam::Vec2 glam::DVec2 glam::UVec2 glam::IVec2; + unsafe impl NumberVector for glam::Vec3 glam::DVec3 glam::UVec3 glam::IVec3; + unsafe impl NumberVector for glam::Vec4 glam::DVec4 glam::UVec4 glam::IVec4; +} diff --git a/crates/spirv-std/src/scalar.rs b/crates/spirv-std/src/scalar.rs index 34d1f5db8c..9fb72b1ae4 100644 --- a/crates/spirv-std/src/scalar.rs +++ b/crates/spirv-std/src/scalar.rs @@ -7,14 +7,47 @@ /// not be done. pub unsafe trait Scalar: Copy + Default + crate::sealed::Sealed {} -unsafe impl Scalar for bool {} -unsafe impl Scalar for f32 {} -unsafe impl Scalar for f64 {} -unsafe impl Scalar for u8 {} -unsafe impl Scalar for u16 {} -unsafe impl Scalar for u32 {} -unsafe impl Scalar for u64 {} -unsafe impl Scalar for i8 {} -unsafe impl Scalar for i16 {} -unsafe impl Scalar for i32 {} -unsafe impl Scalar for i64 {} +/// Abstract trait representing a SPIR-V scalar type. It may also be a vector type. +/// +/// # Safety +/// Implementing this trait on non-scalar types breaks assumptions of other unsafe code, and should +/// not be done. +pub unsafe trait ScalarVector: Copy + Default { + /// Dimension of the vector, 1 if it is a scalar + const DIM: usize; +} + +macro_rules! impl_scalars { + (unsafe impl Scalar for $($typ:ty)*;) => { + $( + unsafe impl Scalar for $typ {} + unsafe impl ScalarVector for $typ { + const DIM: usize = 1; + } + )* + }; + + (unsafe impl ScalarVector, $num: literal for $($typ:ty)*;) => { + $( + unsafe impl ScalarVector for $typ { + const DIM: usize = $num; + } + )* + }; +} + +impl_scalars! { + unsafe impl Scalar for bool f32 f64 u8 u16 u32 u64 i8 i16 i32 i64; +} + +impl_scalars! { + unsafe impl ScalarVector, 2 for glam::BVec2 glam::Vec2 glam::DVec2 glam::UVec2 glam::IVec2; +} + +impl_scalars! { + unsafe impl ScalarVector, 3 for glam::BVec3 glam::Vec3 glam::DVec3 glam::UVec3 glam::IVec3; +} + +impl_scalars! { + unsafe impl ScalarVector, 4 for glam::BVec4 glam::Vec4 glam::DVec4 glam::UVec4 glam::IVec4; +} From ee3af29b2d890ea9f59347c5997e6d0451a95832 Mon Sep 17 00:00:00 2001 From: BeastLe9enD Date: Fri, 7 Apr 2023 20:57:50 +0200 Subject: [PATCH 2/2] Add ScalarOrVector type --- crates/spirv-std/src/float.rs | 43 ++------------- crates/spirv-std/src/integer.rs | 96 ++++++++------------------------- crates/spirv-std/src/number.rs | 38 ++++--------- crates/spirv-std/src/scalar.rs | 55 ++++--------------- crates/spirv-std/src/vector.rs | 53 ++++++++++++++++++ 5 files changed, 101 insertions(+), 184 deletions(-) diff --git a/crates/spirv-std/src/float.rs b/crates/spirv-std/src/float.rs index fa25ddbd06..0a685b2468 100644 --- a/crates/spirv-std/src/float.rs +++ b/crates/spirv-std/src/float.rs @@ -9,50 +9,17 @@ use core::arch::asm; /// # Safety /// Implementing this trait on non-primitive-float types breaks assumptions of other unsafe code, /// and should not be done. -pub unsafe trait Float: num_traits::Float + crate::scalar::Scalar { +pub unsafe trait Float: num_traits::Float + crate::scalar::Scalar + Default { /// Width of the float, in bits. const WIDTH: usize; } -/// Abstract trait representing a SPIR-V floating point type. It may also be a vector type. -/// -/// # Safety -/// Implementing this trait on non-primitive-float types breaks assumptions of other unsafe code, -/// and should not be done. -pub unsafe trait FloatVector: crate::scalar::ScalarVector { - /// Width of the float, in bits. - const WIDTH: usize; -} - -macro_rules! impl_floats { - (unsafe impl Float for $($typ:ty)*;) => { - $( - unsafe impl Float for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - } - - unsafe impl FloatVector for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - } - )* - }; - - (unsafe impl FloatVector for $($typ:ty)*;) => { - $( - unsafe impl FloatVector for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - } - )* - }; - - ($(unsafe impl $trait:ident for $($typ:ty)*;)+) => { - $(impl_floats!(unsafe impl $trait for $($typ)*;);)+ - }; +unsafe impl Float for f32 { + const WIDTH: usize = 32; } -impl_floats! { - unsafe impl Float for f32 f64; - unsafe impl FloatVector for glam::Vec2 glam::Vec3 glam::Vec4 glam::DVec2 glam::DVec3 glam::DVec4; +unsafe impl Float for f64 { + const WIDTH: usize = 64; } /// Converts two f32 values (floats) into two f16 values (halfs). The result is a u32, with the low diff --git a/crates/spirv-std/src/integer.rs b/crates/spirv-std/src/integer.rs index 1aa324ce79..083bae617a 100644 --- a/crates/spirv-std/src/integer.rs +++ b/crates/spirv-std/src/integer.rs @@ -12,93 +12,41 @@ pub unsafe trait Integer: num_traits::PrimInt + crate::scalar::Scalar { const SIGNED: bool; } -/// Abstract trait representing any SPIR-V integer type. It may also be a vector type. -/// -/// # Safety -/// Implementing this trait on non-primitive-integer types breaks assumptions of other unsafe code, -/// and should not be done. -pub unsafe trait IntegerVector: crate::scalar::ScalarVector { - /// Width of the integer, in bits. - const WIDTH: usize; - /// If the integer is signed: true means signed, false means unsigned. - const SIGNED: bool; -} - /// A trait for being generic over signed integer types. pub trait SignedInteger: Integer {} -/// A trait for being generic over signed integer types. It may also be a vector type. -pub trait SignedIntegerVector: IntegerVector {} - /// A trait for being generic over unsigned integer types. pub trait UnsignedInteger: Integer {} -/// A trait for being generic over unsigned integer types. It may also be a vector type. -pub trait UnsignedIntegerVector: IntegerVector {} macro_rules! impl_numbers { - (impl UnsignedInteger for $($typ:ty)*;) => { - $( - unsafe impl Integer for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = false; - } - - unsafe impl IntegerVector for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = false; - } - - impl UnsignedInteger for $typ {} - impl UnsignedIntegerVector for $typ {} - )* - }; - - (impl UnsignedIntegerVector for $($typ:ty)*;) => { - $( - unsafe impl IntegerVector for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = false; - } + (impl UnsignedInteger for $typ:ty;) => { + unsafe impl Integer for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = false; + } - impl UnsignedIntegerVector for $typ {} - )* + impl UnsignedInteger for $typ {} }; + (impl SignedInteger for $typ:ty;) => { + unsafe impl Integer for $typ { + const WIDTH: usize = core::mem::size_of::<$typ>() * 8; + const SIGNED: bool = true; + } - (impl SignedInteger for $($typ:ty)*;) => { - $( - unsafe impl Integer for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = true; - } - - unsafe impl IntegerVector for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = true; - } - - impl SignedInteger for $typ {} - impl SignedIntegerVector for $typ {} - )* + impl SignedInteger for $typ {} }; - - (impl SignedIntegerVector for $($typ:ty)*;) => { - $( - unsafe impl IntegerVector for $typ { - const WIDTH: usize = core::mem::size_of::<$typ>() * 8; - const SIGNED: bool = true; - } - - impl SignedIntegerVector for $typ {} - )* + ($(impl $trait:ident for $typ:ty;)+) => { + $(impl_numbers!(impl $trait for $typ;);)+ }; - ($(impl $trait:ident for $($typ:ty)*;)+) => { - $(impl_numbers!(impl $trait for $($typ)*;);)+ - }; } impl_numbers! { - impl UnsignedInteger for u8 u16 u32 u64; - impl UnsignedIntegerVector for glam::UVec2 glam::UVec3 glam::UVec4; - impl SignedInteger for i8 i16 i32 i64; - impl SignedIntegerVector for glam::IVec2 glam::IVec3 glam::IVec4; + impl UnsignedInteger for u8; + impl UnsignedInteger for u16; + impl UnsignedInteger for u32; + impl UnsignedInteger for u64; + impl SignedInteger for i8; + impl SignedInteger for i16; + impl SignedInteger for i32; + impl SignedInteger for i64; } diff --git a/crates/spirv-std/src/number.rs b/crates/spirv-std/src/number.rs index db07b1dbf1..20a195da1e 100644 --- a/crates/spirv-std/src/number.rs +++ b/crates/spirv-std/src/number.rs @@ -3,31 +3,13 @@ /// Abstract trait representing a SPIR-V integer or floating-point type. pub trait Number: crate::scalar::Scalar {} -/// Abstract trait representing a SPIR-V integer or floating-point type. It may also be a vector type. -pub trait NumberVector: crate::scalar::ScalarVector {} - -macro_rules! impl_numbers { - (unsafe impl Number for $($typ:ty)*;) => { - $( - impl Number for $typ {} - impl NumberVector for $typ {} - )* - }; - - (unsafe impl NumberVector for $($typ:ty)*;) => { - $( - impl NumberVector for $typ {} - )* - }; - - ($(unsafe impl $trait:ident for $($typ:ty)*;)+) => { - $(impl_numbers!(unsafe impl $trait for $($typ)*;);)+ - }; -} - -impl_numbers! { - unsafe impl Number for u8 u16 u32 u64 i8 i16 i32 i64 f32 f64; - unsafe impl NumberVector for glam::Vec2 glam::DVec2 glam::UVec2 glam::IVec2; - unsafe impl NumberVector for glam::Vec3 glam::DVec3 glam::UVec3 glam::IVec3; - unsafe impl NumberVector for glam::Vec4 glam::DVec4 glam::UVec4 glam::IVec4; -} +impl Number for u8 {} +impl Number for u16 {} +impl Number for u32 {} +impl Number for u64 {} +impl Number for i8 {} +impl Number for i16 {} +impl Number for i32 {} +impl Number for i64 {} +impl Number for f32 {} +impl Number for f64 {} diff --git a/crates/spirv-std/src/scalar.rs b/crates/spirv-std/src/scalar.rs index 9fb72b1ae4..34d1f5db8c 100644 --- a/crates/spirv-std/src/scalar.rs +++ b/crates/spirv-std/src/scalar.rs @@ -7,47 +7,14 @@ /// not be done. pub unsafe trait Scalar: Copy + Default + crate::sealed::Sealed {} -/// Abstract trait representing a SPIR-V scalar type. It may also be a vector type. -/// -/// # Safety -/// Implementing this trait on non-scalar types breaks assumptions of other unsafe code, and should -/// not be done. -pub unsafe trait ScalarVector: Copy + Default { - /// Dimension of the vector, 1 if it is a scalar - const DIM: usize; -} - -macro_rules! impl_scalars { - (unsafe impl Scalar for $($typ:ty)*;) => { - $( - unsafe impl Scalar for $typ {} - unsafe impl ScalarVector for $typ { - const DIM: usize = 1; - } - )* - }; - - (unsafe impl ScalarVector, $num: literal for $($typ:ty)*;) => { - $( - unsafe impl ScalarVector for $typ { - const DIM: usize = $num; - } - )* - }; -} - -impl_scalars! { - unsafe impl Scalar for bool f32 f64 u8 u16 u32 u64 i8 i16 i32 i64; -} - -impl_scalars! { - unsafe impl ScalarVector, 2 for glam::BVec2 glam::Vec2 glam::DVec2 glam::UVec2 glam::IVec2; -} - -impl_scalars! { - unsafe impl ScalarVector, 3 for glam::BVec3 glam::Vec3 glam::DVec3 glam::UVec3 glam::IVec3; -} - -impl_scalars! { - unsafe impl ScalarVector, 4 for glam::BVec4 glam::Vec4 glam::DVec4 glam::UVec4 glam::IVec4; -} +unsafe impl Scalar for bool {} +unsafe impl Scalar for f32 {} +unsafe impl Scalar for f64 {} +unsafe impl Scalar for u8 {} +unsafe impl Scalar for u16 {} +unsafe impl Scalar for u32 {} +unsafe impl Scalar for u64 {} +unsafe impl Scalar for i8 {} +unsafe impl Scalar for i16 {} +unsafe impl Scalar for i32 {} +unsafe impl Scalar for i64 {} diff --git a/crates/spirv-std/src/vector.rs b/crates/spirv-std/src/vector.rs index 4377086a67..3073ba067c 100644 --- a/crates/spirv-std/src/vector.rs +++ b/crates/spirv-std/src/vector.rs @@ -1,5 +1,7 @@ //! Traits related to vectors. +use crate::scalar::Scalar; + /// Abstract trait representing a SPIR-V vector type. /// /// # Safety @@ -23,3 +25,54 @@ unsafe impl Vector for glam::UVec4 {} unsafe impl Vector for glam::IVec2 {} unsafe impl Vector for glam::IVec3 {} unsafe impl Vector for glam::IVec4 {} + +/// Abstract trait representing a SPIR-V scalar or vector type. +/// +/// # Safety +/// Implementing this trait on non-simd-vector/scalar types breaks assumptions of other unsafe code, and +/// should not be done. +pub unsafe trait ScalarOrVector { + /// The scalar type + type Scalar; + + /// The dimension of the vector, or 1 if it is a scalar + const DIM: usize; +} + +unsafe impl ScalarOrVector for S { + type Scalar = S; + const DIM: usize = 1; +} + +macro_rules! impl_vector_or_scalar { + ($(for $scalar_ty:ty, $dim: literal: unsafe impl ScalarOrVector for $typ:ty;)+) => { + $( + unsafe impl ScalarOrVector for $typ { + type Scalar = $scalar_ty; + const DIM: usize = $dim; + } + )+ + } +} + +impl_vector_or_scalar! { + for bool, 2: unsafe impl ScalarOrVector for glam::BVec2; + for bool, 3: unsafe impl ScalarOrVector for glam::BVec3; + for bool, 4: unsafe impl ScalarOrVector for glam::BVec4; + + for f32, 2: unsafe impl ScalarOrVector for glam::Vec2; + for f32, 3: unsafe impl ScalarOrVector for glam::Vec3; + for f32, 4: unsafe impl ScalarOrVector for glam::Vec4; + + for f64, 2: unsafe impl ScalarOrVector for glam::DVec2; + for f64, 3: unsafe impl ScalarOrVector for glam::DVec3; + for f64, 4: unsafe impl ScalarOrVector for glam::DVec4; + + for u32, 2: unsafe impl ScalarOrVector for glam::UVec2; + for u32, 3: unsafe impl ScalarOrVector for glam::UVec3; + for u32, 4: unsafe impl ScalarOrVector for glam::UVec4; + + for i32, 2: unsafe impl ScalarOrVector for glam::IVec2; + for i32, 3: unsafe impl ScalarOrVector for glam::IVec3; + for i32, 4: unsafe impl ScalarOrVector for glam::IVec4; +}