From 27ea9ec126f255176c68813cec1e62c986ddd645 Mon Sep 17 00:00:00 2001 From: Gymore Date: Fri, 28 May 2021 20:52:12 +0200 Subject: [PATCH 1/3] Implement `Zeroable` and `Pod` for every color types Affected types: `Rgb`, `Luma`, `Hsl`, `Hsluv`, `Hsv`, `Hwb`, `Lab`, `Lch`, `Lchuv`, `Luv`, `Xyz`, `Yxy` as well as their `Alpha` variant. --- palette/Cargo.toml | 4 ++ palette/src/alpha/alpha.rs | 104 +++++++++++++++++++++++++++++++++++++ palette/src/hsl.rs | 16 ++++++ palette/src/hsluv.rs | 16 ++++++ palette/src/hsv.rs | 16 ++++++ palette/src/hues.rs | 5 ++ palette/src/hwb.rs | 16 ++++++ palette/src/lab.rs | 16 ++++++ palette/src/lch.rs | 16 ++++++ palette/src/lchuv.rs | 16 ++++++ palette/src/luma/luma.rs | 16 ++++++ palette/src/luv.rs | 16 ++++++ palette/src/rgb/rgb.rs | 16 ++++++ palette/src/xyz.rs | 16 ++++++ palette/src/yxy.rs | 16 ++++++ 15 files changed, 305 insertions(+) diff --git a/palette/Cargo.toml b/palette/Cargo.toml index 4fdd48d09..d90409794 100644 --- a/palette/Cargo.toml +++ b/palette/Cargo.toml @@ -48,6 +48,10 @@ version = "1" features = ["serde_derive"] optional = true +[dependencies.bytemuck] +version = "1" +optional = true + [dev-dependencies] csv = "1" lazy_static = "1" diff --git a/palette/src/alpha/alpha.rs b/palette/src/alpha/alpha.rs index f52cc9cb4..78f252c32 100644 --- a/palette/src/alpha/alpha.rs +++ b/palette/src/alpha/alpha.rs @@ -2,6 +2,8 @@ use core::fmt; use core::ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; use approx::{AbsDiffEq, RelativeEq, UlpsEq}; +#[cfg(feature = "bytemuck")] +use bytemuck::{Pod, Zeroable}; #[cfg(feature = "random")] use rand::distributions::uniform::{SampleBorrow, SampleUniform, Uniform, UniformSampler}; #[cfg(feature = "random")] @@ -583,6 +585,108 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl Zeroable for Alpha {} + +// The `Pod` trait may only be implemented for `Alpha` if both `C` and `T` are +// `Pod` AND if they also have the similar memory alignment requirements. + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + S: crate::rgb::RgbStandard, + T: Component + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + S: crate::luma::LumaStandard, + T: Component + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + S: crate::rgb::RgbStandard, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + Wp: crate::white_point::WhitePoint, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + S: crate::rgb::RgbStandard, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + S: crate::rgb::RgbStandard, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + Wp: crate::white_point::WhitePoint, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + Wp: crate::white_point::WhitePoint, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + Wp: crate::white_point::WhitePoint, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + Wp: crate::white_point::WhitePoint, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + Wp: crate::white_point::WhitePoint, + T: crate::FloatComponent + Pod, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl Pod for Alpha, T> +where + Wp: crate::white_point::WhitePoint, + T: crate::FloatComponent + Pod, +{ +} + #[cfg(test)] mod test { use crate::encoding::Srgb; diff --git a/palette/src/hsl.rs b/palette/src/hsl.rs index 57774b3c2..3b5678935 100644 --- a/palette/src/hsl.rs +++ b/palette/src/hsl.rs @@ -811,6 +811,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Hsl +where + S: RgbStandard, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Hsl +where + S: RgbStandard, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Hsl; diff --git a/palette/src/hsluv.rs b/palette/src/hsluv.rs index eaad058b1..c325d0f53 100644 --- a/palette/src/hsluv.rs +++ b/palette/src/hsluv.rs @@ -553,6 +553,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Hsluv +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Hsluv +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Hsluv; diff --git a/palette/src/hsv.rs b/palette/src/hsv.rs index 1e0c176d2..6dc8118eb 100644 --- a/palette/src/hsv.rs +++ b/palette/src/hsv.rs @@ -825,6 +825,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Hsv +where + S: RgbStandard, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Hsv +where + S: RgbStandard, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Hsv; diff --git a/palette/src/hues.rs b/palette/src/hues.rs index 9b96e8d68..fc660b8b3 100644 --- a/palette/src/hues.rs +++ b/palette/src/hues.rs @@ -259,6 +259,11 @@ macro_rules! make_hues { $name(rng.gen() * from_f64(360.0)) } } + + #[cfg(feature = "bytemuck")] + unsafe impl bytemuck::Zeroable for $name {} + #[cfg(feature = "bytemuck")] + unsafe impl bytemuck::Pod for $name {} )+) } diff --git a/palette/src/hwb.rs b/palette/src/hwb.rs index e4d17752f..0092324dd 100644 --- a/palette/src/hwb.rs +++ b/palette/src/hwb.rs @@ -764,6 +764,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Hwb +where + S: RgbStandard, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Hwb +where + S: RgbStandard, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Hwb; diff --git a/palette/src/lab.rs b/palette/src/lab.rs index 5e1a837d1..9824558ae 100644 --- a/palette/src/lab.rs +++ b/palette/src/lab.rs @@ -814,6 +814,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Lab +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Lab +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Lab; diff --git a/palette/src/lch.rs b/palette/src/lch.rs index bf757d683..db3ce7899 100644 --- a/palette/src/lch.rs +++ b/palette/src/lch.rs @@ -722,6 +722,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Lch +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Lch +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use crate::white_point::D65; diff --git a/palette/src/lchuv.rs b/palette/src/lchuv.rs index 774733a30..c98c20a36 100644 --- a/palette/src/lchuv.rs +++ b/palette/src/lchuv.rs @@ -563,6 +563,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Lchuv +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Lchuv +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use crate::white_point::D65; diff --git a/palette/src/luma/luma.rs b/palette/src/luma/luma.rs index ee3a4c101..1af2221f3 100644 --- a/palette/src/luma/luma.rs +++ b/palette/src/luma/luma.rs @@ -876,6 +876,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Luma +where + S: LumaStandard, + T: Component + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Luma +where + S: LumaStandard, + T: Component + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use crate::encoding::Srgb; diff --git a/palette/src/luv.rs b/palette/src/luv.rs index 9fb3b4682..854b549c4 100644 --- a/palette/src/luv.rs +++ b/palette/src/luv.rs @@ -674,6 +674,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Luv +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Luv +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Luv; diff --git a/palette/src/rgb/rgb.rs b/palette/src/rgb/rgb.rs index 5e53a9d78..4abe0c3d8 100644 --- a/palette/src/rgb/rgb.rs +++ b/palette/src/rgb/rgb.rs @@ -1236,6 +1236,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Rgb +where + S: RgbStandard, + T: Component + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Rgb +where + S: RgbStandard, + T: Component + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use core::str::FromStr; diff --git a/palette/src/xyz.rs b/palette/src/xyz.rs index c6ad8ff95..fa4391b67 100644 --- a/palette/src/xyz.rs +++ b/palette/src/xyz.rs @@ -824,6 +824,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Xyz +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Xyz +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Xyz; diff --git a/palette/src/yxy.rs b/palette/src/yxy.rs index 5e91e36f9..adf31d180 100644 --- a/palette/src/yxy.rs +++ b/palette/src/yxy.rs @@ -752,6 +752,22 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Yxy +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Zeroable, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Yxy +where + Wp: WhitePoint, + T: FloatComponent + bytemuck::Pod, +{ +} + #[cfg(test)] mod test { use super::Yxy; From 409d9c85a1f42b5230cce34e5988daa57f28202a Mon Sep 17 00:00:00 2001 From: Gymore Date: Fri, 28 May 2021 20:54:15 +0200 Subject: [PATCH 2/3] Implement `Zeroable` and `Pod` for `Packed` This requires `Packed` to be `Copy` regardless of whether `C` is `Copy`. --- palette/src/rgb/packed.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/palette/src/rgb/packed.rs b/palette/src/rgb/packed.rs index 24331a7a8..567ac5916 100644 --- a/palette/src/rgb/packed.rs +++ b/palette/src/rgb/packed.rs @@ -58,7 +58,7 @@ use crate::Pixel; /// assert_eq!(colors[0].color, 0x7F0080); /// assert_eq!(colors[1].color, 0x60BBCC); /// ``` -#[derive(Copy, Clone, Debug, PartialEq, Eq, Pixel)] +#[derive(Debug, PartialEq, Eq, Pixel)] #[palette(palette_internal)] #[repr(C)] pub struct Packed { @@ -72,6 +72,14 @@ pub struct Packed { pub channel_order: PhantomData, } +impl Copy for Packed {} + +impl Clone for Packed { + fn clone(&self) -> Self { + *self + } +} + /// Splits and combines RGB(A) types with some channel ordering. Channels may be /// ordered as `Abgr`, `Argb`, `Bgra`, or `Rgba`. pub trait RgbChannels { @@ -159,6 +167,11 @@ where } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for Packed {} +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for Packed {} + #[cfg(test)] mod test { use crate::rgb::packed::channels::{Abgr, Argb, Bgra, Rgba}; From 627739ff0b5acb1a3d15bf3566f15f1efee00122 Mon Sep 17 00:00:00 2001 From: Gymore Date: Sat, 29 May 2021 13:33:41 +0200 Subject: [PATCH 3/3] Implement `bytemuck::Pod` and `bytemuck::Zeroable` for both `Alpha` and `PreAlpha` --- palette/src/alpha/alpha.rs | 105 ++++----------------------------- palette/src/blend/pre_alpha.rs | 18 ++++++ 2 files changed, 29 insertions(+), 94 deletions(-) diff --git a/palette/src/alpha/alpha.rs b/palette/src/alpha/alpha.rs index 78f252c32..87e742463 100644 --- a/palette/src/alpha/alpha.rs +++ b/palette/src/alpha/alpha.rs @@ -2,8 +2,6 @@ use core::fmt; use core::ops::{Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; use approx::{AbsDiffEq, RelativeEq, UlpsEq}; -#[cfg(feature = "bytemuck")] -use bytemuck::{Pod, Zeroable}; #[cfg(feature = "random")] use rand::distributions::uniform::{SampleBorrow, SampleUniform, Uniform, UniformSampler}; #[cfg(feature = "random")] @@ -586,104 +584,23 @@ where } #[cfg(feature = "bytemuck")] -unsafe impl Zeroable for Alpha {} - -// The `Pod` trait may only be implemented for `Alpha` if both `C` and `T` are -// `Pod` AND if they also have the similar memory alignment requirements. - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - S: crate::rgb::RgbStandard, - T: Component + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - S: crate::luma::LumaStandard, - T: Component + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - S: crate::rgb::RgbStandard, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - Wp: crate::white_point::WhitePoint, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - S: crate::rgb::RgbStandard, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - S: crate::rgb::RgbStandard, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - Wp: crate::white_point::WhitePoint, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - Wp: crate::white_point::WhitePoint, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - Wp: crate::white_point::WhitePoint, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> -where - Wp: crate::white_point::WhitePoint, - T: crate::FloatComponent + Pod, -{ -} - -#[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> +unsafe impl bytemuck::Zeroable for Alpha where - Wp: crate::white_point::WhitePoint, - T: crate::FloatComponent + Pod, + C: bytemuck::Zeroable, + T: bytemuck::Zeroable, { } +// Safety: +// It is a requirement of `Pixel` that the in-memory representation of +// `C` is made of `T`s. +// Because `T` is `Pod`, `Alpha` is `Pod` as well because no internal +// padding can be introduced during monomorphization. #[cfg(feature = "bytemuck")] -unsafe impl Pod for Alpha, T> +unsafe impl bytemuck::Pod for Alpha where - Wp: crate::white_point::WhitePoint, - T: crate::FloatComponent + Pod, + T: bytemuck::Pod, + C: bytemuck::Pod + Pixel, { } diff --git a/palette/src/blend/pre_alpha.rs b/palette/src/blend/pre_alpha.rs index ac08a8520..109599ea7 100644 --- a/palette/src/blend/pre_alpha.rs +++ b/palette/src/blend/pre_alpha.rs @@ -389,6 +389,24 @@ impl DerefMut for PreAlpha { } } +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Zeroable for PreAlpha +where + C: bytemuck::Zeroable, + T: Float + bytemuck::Zeroable, +{ +} + +// Safety: +// See `Alpha`'s implementation of `Pod`. +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for PreAlpha +where + C: bytemuck::Pod + Pixel, + T: Float + bytemuck::Pod, +{ +} + #[cfg(test)] #[cfg(feature = "serializing")] mod test {