Repository: bitshifter/glam-rs
Pull request #255 (2021-11-13 21:54:34)

Add "cuda" feature for enabling cuda-native alignment requirements on *Vec2 and *Vec4
CUDA prefers specific alignments for Vec2 and Vec4 types in order to use more efficient memory loads. This PR adds a "cuda" feature that enables those alignments using `cfg_attr` in order that glam can be used to generate efficient PTX code. 

This is currently a draft as the changes are somehow affecting DAffine2 and causing some of those tests to fail, where as far as I can see that type shouldn't be affected, but it's hard for me to trace back through all the macro invocations to understand where it's getting affected.

bitshifter: The reason it is failing is due to the intersection of `cuda` and `scalar-math` features. The `scalar-math` feature disables SIMD and thus the SIMD alignment. Ideally your changes should work with `scalar-math` as well, which will involve a bit more work.

The reason it's failing in the lint step is because clippy is run with `--all-feature` which will enable both `cuda` and `scalar-math`.

You should also add the following to `FEATURE_SETS` in `build_and_test_features`:

```sh
"std cuda"
"std scalar-math cuda"
```

It shouldn't be necessary to test `cuda` with any other glam features, just `std` and with and without `scalar-math`.


bitshifter: The compile fail is easily fixed: 

```diff
@@ -491,7 +491,10 @@ impl_affine2_traits!(
     DerefTargetF64
 );
 
-#[cfg(any(feature = "scalar-math", target_arch = "spriv"))]
+#[cfg(all(
+    not(feature = "cuda"),
+    any(feature = "scalar-math", target_arch = "spriv")
+))]
 mod const_test_affine2 {
     const_assert_eq!(
         core::mem::align_of::<f32>(),
```

After fixing that there is a test failure with `--features=cuda`:

```
failures:

---- daffine2::test_affine2_fmt stdout ----
thread 'daffine2::test_affine2_fmt' panicked at 'assertion failed: `(left == right)`
  left: `"[[5, 6], [1, 2], [3, 4]]"`,
 right: `"[[1, 2], [3, 4], [5, 6]]"`', tests/affine2.rs:213:5
```

Which is quite strange. I suspect it's to do with `Deref`, but I would have thought making alignment `8` would not change layout of any glam types, so I'm not sure what's going on there.
bitshifter: The problem is that `Mat2` and `DMat2` are not aligned the same as `Vec2` and `DVec2`, this is because matrices are composed of inner types which aren't `cuda` aligned. In some places `Mat2` and `DMat2` use `Deref` with a target of `Colums2<Vec2>` or `Columns2<DVec2>` but these are not following the same alignment rules as `Vec2` and `DVec2` which results in undefined behaviour. It can be fixed, with the right combination of `#[cfg]` blocks, I already deal with this problem for `scalar-math`, but it will be messy.

The reason why glam does all this stuff is explained (hopefully) in https://github.com/bitshifter/glam-rs/blob/main/ARCHITECTURE.md.

Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 56bee06..ece9997 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,6 +33,9 @@ transform-types = []
 # libm is required when building no_std
 libm = ["num-traits/libm"]
 
+# align types to match CUDA requirements
+cuda = []
+
 [dependencies]
 approx = { version = "0.5", optional = true, default-features = false }
 bytemuck = { version = "1.5", optional = true, default-features = false }
diff --git a/src/affine2.rs b/src/affine2.rs
index c819302..40d4b50 100644
--- a/src/affine2.rs
+++ b/src/affine2.rs
@@ -9,6 +9,7 @@ macro_rules! define_affine2_struct {
     ($affine2:ident, $matrix:ident, $column:ident) => {
         /// A 2D affine transform, which can represent translation, rotation, scaling and shear.
         #[derive(Copy, Clone)]
+        #[repr(C)]
         pub struct $affine2 {
             pub matrix2: $matrix,
             pub translation: $column,
@@ -491,7 +492,10 @@ impl_affine2_traits!(
     DerefTargetF64
 );
 
-#[cfg(any(feature = "scalar-math", target_arch = "spriv"))]
+#[cfg(all(
+    not(feature = "cuda"),
+    any(feature = "scalar-math", target_arch = "spriv")
+))]
 mod const_test_affine2 {
     const_assert_eq!(
         core::mem::align_of::<f32>(),
@@ -506,6 +510,7 @@ mod const_test_affine2 {
     const_assert_eq!(32, core::mem::size_of::<super::Affine2>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_daffine2 {
     const_assert_eq!(
         core::mem::align_of::<f64>(),
@@ -513,3 +518,9 @@ mod const_test_daffine2 {
     );
     const_assert_eq!(48, core::mem::size_of::<super::DAffine2>());
 }
+
+#[cfg(feature = "cuda")]
+mod const_test_daffine2 {
+    const_assert_eq!(16, core::mem::align_of::<super::DAffine2>());
+    const_assert_eq!(48, core::mem::size_of::<super::DAffine2>());
+}
diff --git a/src/affine3.rs b/src/affine3.rs
index 7018871..eff87d9 100644
--- a/src/affine3.rs
+++ b/src/affine3.rs
@@ -12,6 +12,7 @@ macro_rules! define_affine3_struct {
         /// The type is composed of a 3x3 matrix containing a linear transformation (e.g. scale,
         /// rotation, shear, reflection) and a 3D vector translation.
         #[derive(Copy, Clone)]
+        #[repr(C)]
         pub struct $affine3 {
             pub matrix3: $matrix,
             pub translation: $column,
diff --git a/src/mat2.rs b/src/mat2.rs
index 2cd705b..4971a1b 100644
--- a/src/mat2.rs
+++ b/src/mat2.rs
@@ -330,7 +330,13 @@ type InnerF32 = crate::core::storage::Columns2<XY<f32>>;
     not(any(feature = "scalar-math", target_arch = "spriv")),
     repr(align(16))
 )]
-#[cfg_attr(any(feature = "scalar-math", target_arch = "spriv"), repr(transparent))]
+#[cfg_attr(
+    all(
+        not(feature = "cuda"),
+        any(feature = "scalar-math", target_arch = "spriv")
+    ),
+    repr(transparent)
+)]
 pub struct Mat2(pub(crate) InnerF32);
 
 impl Mat2 {
@@ -353,7 +359,8 @@ type InnerF64 = crate::core::storage::Columns2<XY<f64>>;
 
 /// A 2x2 column major matrix.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(feature = "cuda", repr(align(16)))]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
 pub struct DMat2(pub(crate) InnerF64);
 
 impl DMat2 {
@@ -387,6 +394,7 @@ mod const_test_mat2 {
     const_assert_eq!(16, core::mem::size_of::<super::Mat2>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_dmat2 {
     const_assert_eq!(
         core::mem::align_of::<f64>(),
@@ -394,3 +402,12 @@ mod const_test_dmat2 {
     );
     const_assert_eq!(32, core::mem::size_of::<super::DMat2>());
 }
+
+#[cfg(feature = "cuda")]
+mod const_test_dmat2 {
+    const_assert_eq!(
+        core::mem::align_of::<super::DVec2>(),
+        core::mem::align_of::<super::DMat2>()
+    );
+    const_assert_eq!(32, core::mem::size_of::<super::DMat2>());
+}
diff --git a/src/mat4.rs b/src/mat4.rs
index 98fd002..7fad170 100644
--- a/src/mat4.rs
+++ b/src/mat4.rs
@@ -775,7 +775,14 @@ type InnerF32 = Columns4<XYZW<f32>>;
     not(any(feature = "scalar-math", target_arch = "spriv")),
     repr(align(16))
 )]
-#[cfg_attr(any(feature = "scalar-math", target_arch = "spriv"), repr(transparent))]
+#[cfg_attr(feature = "cuda", repr(align(16)))]
+#[cfg_attr(
+    all(
+        not(feature = "cuda"),
+        any(feature = "scalar-math", target_arch = "spriv")
+    ),
+    repr(transparent)
+)]
 pub struct Mat4(pub(crate) InnerF32);
 // define_mat4_struct!(Mat4, InnerF32);
 
@@ -875,7 +882,10 @@ impl DMat4 {
 }
 impl_mat4_traits!(f64, dmat4, DMat4, DVec4);
 
-#[cfg(any(feature = "scalar-math", target_arch = "spriv"))]
+#[cfg(all(
+    not(feature = "cuda"),
+    any(feature = "scalar-math", target_arch = "spriv")
+))]
 mod const_test_mat4 {
     const_assert_eq!(
         core::mem::align_of::<f32>(),
@@ -884,7 +894,13 @@ mod const_test_mat4 {
     const_assert_eq!(64, core::mem::size_of::<super::Mat4>());
 }
 
-#[cfg(not(any(feature = "scalar-math", target_arch = "spriv")))]
+#[cfg(feature = "cuda")]
+mod const_test_mat4 {
+    const_assert_eq!(16, core::mem::align_of::<super::Mat4>());
+    const_assert_eq!(64, core::mem::size_of::<super::Mat4>());
+}
+
+#[cfg(not(any(feature = "scalar-math", target_arch = "spriv", feature = "cuda")))]
 mod const_test_mat4 {
     const_assert_eq!(16, core::mem::align_of::<super::Mat4>());
     const_assert_eq!(64, core::mem::size_of::<super::Mat4>());
diff --git a/src/vec2.rs b/src/vec2.rs
index 26f5637..e799bed 100644
--- a/src/vec2.rs
+++ b/src/vec2.rs
@@ -182,7 +182,8 @@ type XYF32 = XY<f32>;
 
 /// A 2-dimensional vector.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(feature = "cuda", repr(C, align(8)))]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
 pub struct Vec2(pub(crate) XYF32);
 
 impl Vec2 {
@@ -197,7 +198,8 @@ type XYF64 = XY<f64>;
 
 /// A 2-dimensional vector.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(feature = "cuda", repr(C, align(16)))]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
 pub struct DVec2(pub(crate) XYF64);
 
 impl DVec2 {
@@ -212,7 +214,8 @@ type XYI32 = XY<i32>;
 
 /// A 2-dimensional vector.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(feature = "cuda", repr(C, align(8)))]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
 pub struct IVec2(pub(crate) XYI32);
 
 impl IVec2 {
@@ -242,7 +245,8 @@ type XYU32 = XY<u32>;
 
 /// A 2-dimensional vector.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(feature = "cuda", repr(C, align(8)))]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
 pub struct UVec2(pub(crate) XYU32);
 
 impl UVec2 {
@@ -268,6 +272,7 @@ impl_vecn_scalar_bit_op_traits!(UVec2, u32, XYU32);
 
 impl_vecn_bit_op_traits!(UVec2, XYU32);
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_vec2 {
     const_assert_eq!(
         core::mem::align_of::<f32>(),
@@ -276,6 +281,7 @@ mod const_test_vec2 {
     const_assert_eq!(8, core::mem::size_of::<super::Vec2>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_dvec2 {
     const_assert_eq!(
         core::mem::align_of::<f64>(),
@@ -284,6 +290,7 @@ mod const_test_dvec2 {
     const_assert_eq!(16, core::mem::size_of::<super::DVec2>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_ivec2 {
     const_assert_eq!(
         core::mem::align_of::<i32>(),
@@ -292,6 +299,7 @@ mod const_test_ivec2 {
     const_assert_eq!(8, core::mem::size_of::<super::IVec2>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_uvec2 {
     const_assert_eq!(
         core::mem::align_of::<u32>(),
@@ -299,3 +307,27 @@ mod const_test_uvec2 {
     );
     const_assert_eq!(8, core::mem::size_of::<super::UVec2>());
 }
+
+#[cfg(feature = "cuda")]
+mod const_test_vec2 {
+    const_assert_eq!(8, core::mem::align_of::<super::Vec2>());
+    const_assert_eq!(8, core::mem::size_of::<super::Vec2>());
+}
+
+#[cfg(feature = "cuda")]
+mod const_test_dvec2 {
+    const_assert_eq!(16, core::mem::align_of::<super::DVec2>());
+    const_assert_eq!(16, core::mem::size_of::<super::DVec2>());
+}
+
+#[cfg(feature = "cuda")]
+mod const_test_ivec2 {
+    const_assert_eq!(8, core::mem::align_of::<super::IVec2>());
+    const_assert_eq!(8, core::mem::size_of::<super::IVec2>());
+}
+
+#[cfg(feature = "cuda")]
+mod const_test_uvec2 {
+    const_assert_eq!(8, core::mem::align_of::<super::UVec2>());
+    const_assert_eq!(8, core::mem::size_of::<super::UVec2>());
+}
diff --git a/src/vec4.rs b/src/vec4.rs
index 2792f83..2738528 100644
--- a/src/vec4.rs
+++ b/src/vec4.rs
@@ -246,10 +246,17 @@ type XYZWF32 = v128;
 /// This type uses 16 byte aligned SIMD vector type for storage on supported platforms.
 #[derive(Clone, Copy)]
 #[cfg_attr(
-    not(any(feature = "scalar-math", target_arch = "spriv")),
+    not(any(feature = "scalar-math", target_arch = "spriv", feature = "cuda")),
     repr(align(16))
 )]
-#[cfg_attr(any(feature = "scalar-math", target_arch = "spriv"), repr(transparent))]
+#[cfg_attr(
+    all(
+        any(feature = "scalar-math", target_arch = "spriv"),
+        not(feature = "cuda")
+    ),
+    repr(transparent)
+)]
+#[cfg_attr(feature = "cuda", repr(C, align(16)))]
 pub struct Vec4(pub(crate) XYZWF32);
 
 #[cfg(any(
@@ -293,7 +300,8 @@ type XYZWF64 = XYZW<f64>;
 
 /// A 4-dimensional vector.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
+#[cfg_attr(feature = "cuda", repr(C, align(16)))]
 pub struct DVec4(pub(crate) XYZWF64);
 
 impl DVec4 {
@@ -308,7 +316,8 @@ type XYZWI32 = XYZW<i32>;
 
 /// A 4-dimensional vector.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
+#[cfg_attr(feature = "cuda", repr(C, align(16)))]
 pub struct IVec4(pub(crate) XYZWI32);
 
 impl IVec4 {
@@ -338,7 +347,8 @@ type XYZWU32 = XYZW<u32>;
 
 /// A 4-dimensional vector.
 #[derive(Clone, Copy)]
-#[repr(transparent)]
+#[cfg_attr(not(feature = "cuda"), repr(transparent))]
+#[cfg_attr(feature = "cuda", repr(C, align(16)))]
 pub struct UVec4(pub(crate) XYZWU32);
 
 impl UVec4 {
@@ -385,7 +395,10 @@ mod tests {
     }
 }
 
-#[cfg(any(feature = "scalar-math", target_arch = "spriv"))]
+#[cfg(all(
+    any(feature = "scalar-math", target_arch = "spriv"),
+    not(feature = "cuda")
+))]
 mod const_test_vec4 {
     const_assert_eq!(
         core::mem::align_of::<f32>(),
@@ -394,12 +407,16 @@ mod const_test_vec4 {
     const_assert_eq!(16, core::mem::size_of::<super::Vec4>());
 }
 
-#[cfg(not(any(feature = "scalar-math", target_arch = "spriv")))]
+#[cfg(any(
+    not(any(feature = "scalar-math", target_arch = "spriv")),
+    feature = "cuda"
+))]
 mod const_test_vec4 {
     const_assert_eq!(16, core::mem::align_of::<super::Vec4>());
     const_assert_eq!(16, core::mem::size_of::<super::Vec4>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_dvec4 {
     const_assert_eq!(
         core::mem::align_of::<f64>(),
@@ -408,6 +425,7 @@ mod const_test_dvec4 {
     const_assert_eq!(32, core::mem::size_of::<super::DVec4>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_ivec4 {
     const_assert_eq!(
         core::mem::align_of::<i32>(),
@@ -416,6 +434,7 @@ mod const_test_ivec4 {
     const_assert_eq!(16, core::mem::size_of::<super::IVec4>());
 }
 
+#[cfg(not(feature = "cuda"))]
 mod const_test_uvec4 {
     const_assert_eq!(
         core::mem::align_of::<u32>(),
@@ -423,3 +442,21 @@ mod const_test_uvec4 {
     );
     const_assert_eq!(16, core::mem::size_of::<super::UVec4>());
 }
+
+#[cfg(feature = "cuda")]
+mod const_test_dvec4 {
+    const_assert_eq!(16, core::mem::align_of::<super::DVec4>());
+    const_assert_eq!(32, core::mem::size_of::<super::DVec4>());
+}
+
+#[cfg(feature = "cuda")]
+mod const_test_ivec4 {
+    const_assert_eq!(16, core::mem::align_of::<super::IVec4>());
+    const_assert_eq!(16, core::mem::size_of::<super::IVec4>());
+}
+
+#[cfg(feature = "cuda")]
+mod const_test_uvec4 {
+    const_assert_eq!(16, core::mem::align_of::<super::UVec4>());
+    const_assert_eq!(16, core::mem::size_of::<super::UVec4>());
+}


Test patch:
diff --git a/tests/affine2.rs b/tests/affine2.rs
index 772d8c0..35424a1 100644
--- a/tests/affine2.rs
+++ b/tests/affine2.rs
@@ -169,6 +169,9 @@ mod affine2 {
         if cfg!(not(feature = "scalar-math")) {
             assert_eq!(32, mem::size_of::<Affine2>());
             assert_eq!(16, mem::align_of::<Affine2>());
+        } else if cfg!(feature = "cuda") {
+            assert_eq!(24, mem::size_of::<Affine2>());
+            assert_eq!(8, mem::align_of::<Affine2>());
         } else {
             assert_eq!(24, mem::size_of::<Affine2>());
             assert_eq!(4, mem::align_of::<Affine2>());
@@ -196,11 +199,19 @@ mod daffine2 {
         }
     }
 
+    #[cfg(not(feature = "cuda"))]
     glam_test!(test_align, {
         use std::mem;
         assert_eq!(48, mem::size_of::<DAffine2>());
         assert_eq!(mem::align_of::<f64>(), mem::align_of::<DAffine2>());
     });
 
+    #[cfg(feature = "cuda")]
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(48, mem::size_of::<DAffine2>());
+        assert_eq!(16, mem::align_of::<DAffine2>());
+    });
+
     impl_affine2_tests!(f64, DAffine2, DVec2);
 }
diff --git a/tests/mat2.rs b/tests/mat2.rs
index 42e0a81..0c7de78 100644
--- a/tests/mat2.rs
+++ b/tests/mat2.rs
@@ -246,6 +246,7 @@ mod mat2 {
     impl_mat2_tests!(f32, const_mat2, mat2, Mat2, Mat3, vec2, Vec2);
 }
 
+#[cfg(not(feature = "cuda"))]
 mod dmat2 {
     use super::support::deg;
     use glam::{const_dmat2, dmat2, dvec2, swizzles::*, DMat2, DMat3, DVec2};
@@ -258,3 +259,17 @@ mod dmat2 {
 
     impl_mat2_tests!(f64, const_dmat2, dmat2, DMat2, DMat3, dvec2, DVec2);
 }
+
+#[cfg(feature = "cuda")]
+mod dmat2 {
+    use super::support::deg;
+    use glam::{const_dmat2, dmat2, dvec2, swizzles::*, DMat2, DMat3, DVec2};
+
+    glam_test!(test_align, {
+        use std::mem;
+        assert_eq!(32, mem::size_of::<DMat2>());
+        assert_eq!(mem::align_of::<DVec2>(), mem::align_of::<DMat2>());
+    });
+
+    impl_mat2_tests!(f64, const_dmat2, dmat2, DMat2, DMat3, dvec2, DVec2);
+}
diff --git a/tests/mat4.rs b/tests/mat4.rs
index 2737b2e..ba07d7c 100644
--- a/tests/mat4.rs
+++ b/tests/mat4.rs
@@ -663,7 +663,7 @@ mod mat4 {
     glam_test!(test_align, {
         use std::mem;
         assert_eq!(64, mem::size_of::<Mat4>());
-        if cfg!(feature = "scalar-math") {
+        if cfg!(all(feature = "scalar-math", not(feature = "cuda"))) {
             assert_eq!(4, mem::align_of::<Mat4>());
         } else {
             assert_eq!(16, mem::align_of::<Mat4>());
diff --git a/tests/vec2.rs b/tests/vec2.rs
index c385ed2..c5f1ad3 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -798,7 +798,10 @@ mod vec2 {
     glam_test!(test_align, {
         use core::mem;
         assert_eq!(8, mem::size_of::<Vec2>());
+        #[cfg(not(feature = "cuda"))]
         assert_eq!(4, mem::align_of::<Vec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(8, mem::align_of::<Vec2>());
         assert_eq!(2, mem::size_of::<BVec2>());
         assert_eq!(1, mem::align_of::<BVec2>());
     });
@@ -831,7 +834,10 @@ mod dvec2 {
     glam_test!(test_align, {
         use core::mem;
         assert_eq!(16, mem::size_of::<DVec2>());
+        #[cfg(not(feature = "cuda"))]
         assert_eq!(mem::align_of::<f64>(), mem::align_of::<DVec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<DVec2>());
         assert_eq!(2, mem::size_of::<BVec2>());
         assert_eq!(1, mem::align_of::<BVec2>());
     });
@@ -845,7 +851,10 @@ mod ivec2 {
     glam_test!(test_align, {
         use core::mem;
         assert_eq!(8, mem::size_of::<IVec2>());
+        #[cfg(not(feature = "cuda"))]
         assert_eq!(4, mem::align_of::<IVec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(8, mem::align_of::<IVec2>());
         assert_eq!(2, mem::size_of::<BVec2>());
         assert_eq!(1, mem::align_of::<BVec2>());
     });
@@ -866,7 +875,10 @@ mod uvec2 {
     glam_test!(test_align, {
         use core::mem;
         assert_eq!(8, mem::size_of::<UVec2>());
+        #[cfg(not(feature = "cuda"))]
         assert_eq!(4, mem::align_of::<UVec2>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(8, mem::align_of::<UVec2>());
         assert_eq!(2, mem::size_of::<BVec2>());
         assert_eq!(1, mem::align_of::<BVec2>());
     });
diff --git a/tests/vec4.rs b/tests/vec4.rs
index 6a8c960..0bd4215 100644
--- a/tests/vec4.rs
+++ b/tests/vec4.rs
@@ -972,7 +972,7 @@ mod vec4 {
     glam_test!(test_align, {
         use std::mem;
         assert_eq!(16, mem::size_of::<Vec4>());
-        if cfg!(not(feature = "scalar-math")) {
+        if cfg!(any(not(feature = "scalar-math"), feature = "cuda")) {
             assert_eq!(16, mem::align_of::<Vec4>());
         } else {
             assert_eq!(4, mem::align_of::<Vec4>());
@@ -1092,7 +1092,10 @@ mod dvec4 {
     glam_test!(test_align, {
         use std::mem;
         assert_eq!(32, mem::size_of::<DVec4>());
+        #[cfg(not(feature = "cuda"))]
         assert_eq!(mem::align_of::<f64>(), mem::align_of::<DVec4>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<DVec4>());
         assert_eq!(4, mem::size_of::<BVec4>());
         assert_eq!(1, mem::align_of::<BVec4>());
     });
@@ -1106,7 +1109,10 @@ mod ivec4 {
     glam_test!(test_align, {
         use std::mem;
         assert_eq!(16, mem::size_of::<IVec4>());
+        #[cfg(not(feature = "cuda"))]
         assert_eq!(4, mem::align_of::<IVec4>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<IVec4>());
         assert_eq!(4, mem::size_of::<BVec4>());
         assert_eq!(1, mem::align_of::<BVec4>());
     });
@@ -1127,7 +1133,10 @@ mod uvec4 {
     glam_test!(test_align, {
         use std::mem;
         assert_eq!(16, mem::size_of::<UVec4>());
+        #[cfg(not(feature = "cuda"))]
         assert_eq!(4, mem::align_of::<UVec4>());
+        #[cfg(feature = "cuda")]
+        assert_eq!(16, mem::align_of::<UVec4>());
         assert_eq!(4, mem::size_of::<BVec4>());
         assert_eq!(1, mem::align_of::<BVec4>());
     });