1#![cfg_attr(not(feature = "std"), no_std)]
84#![cfg_attr(docsrs, feature(doc_cfg))]
85
86pub type Int = i32;
88pub type Uint = u32;
90pub type Float = f32;
92pub type Double = f64;
94
95#[repr(transparent)]
97#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
98pub struct Bool(u32);
99
100impl Bool {
101 pub fn new(value: bool) -> Self {
102 Self(value as u32)
103 }
104}
105
106impl From<Bool> for bool {
107 fn from(other: Bool) -> Self {
108 other.0 != 0
109 }
110}
111
112impl From<bool> for Bool {
113 fn from(other: bool) -> Self {
114 Self(other as u32)
115 }
116}
117
118#[cfg(feature = "bytemuck")]
119unsafe impl bytemuck::Zeroable for Bool {}
120#[cfg(feature = "bytemuck")]
121unsafe impl bytemuck::Pod for Bool {}
122
123macro_rules! define_vectors {
124 ( $(( $name:ident, $mint_name:ident, $prim:ident * $count:literal, align: $align:literal, size: $size:literal ),)* ) => {
125 $(
126 define_vectors!(@impl
127 $name,
128 mint::$mint_name<$prim>,
129 $prim,
130 $count,
131 $align,
132 concat!(
133 "Vector of ", stringify!($count), " `", stringify!($prim), "` values. ",
134 "Has size ", stringify!($size), " and alignment ", stringify!($align), "."
135 ),
136 concat!(
137 "Construct a `", stringify!($name), "` from any type which is convertable into a ",
138 "`mint::", stringify!($mint_name), "<", stringify!($prim), ">`."
139 )
140 );
141 )*
142 };
143
144 (@impl $name:ident, $mint_type:ty, $ty:ty, $count:literal, $align:literal, $doc:expr, $mint_doc:expr) => {
145 #[doc = $doc]
146 #[repr(C, align($align))]
147 #[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
148 pub struct $name {
149 pub inner: [$ty; $count],
150 }
151
152 #[cfg(feature = "bytemuck")]
153 unsafe impl bytemuck::Zeroable for $name {}
154 #[cfg(feature = "bytemuck")]
155 unsafe impl bytemuck::Pod for $name {}
156
157 impl $name {
158 #[inline(always)]
159 pub fn new(inner: [$ty; $count]) -> Self {
160 Self {
161 inner,
162 }
163 }
164
165 #[cfg(feature = "mint")]
166 #[cfg_attr(docsrs, doc(cfg(feature = "mint")))]
167 #[doc = $mint_doc]
168 #[inline(always)]
169 pub fn from_mint<T: Into<$mint_type>>(value: T) -> Self {
170 Self::from(value.into())
171 }
172 }
173
174 #[cfg(feature = "mint")]
175 impl From<$mint_type> for $name {
176 #[inline(always)]
177 fn from(other: $mint_type) -> Self {
178 let inner: [$ty; $count] = other.into();
180
181 Self { inner }
182 }
183 }
184
185 impl From<[$ty; $count]> for $name {
186 #[inline(always)]
187 fn from(inner: [$ty; $count]) -> Self {
188 Self {
189 inner,
190 }
191 }
192 }
193
194 #[cfg(feature = "mint")]
195 impl From<$name> for $mint_type {
196 #[inline(always)]
197 fn from(other: $name) -> Self {
198 other.inner.into()
199 }
200 }
201
202 impl From<$name> for [$ty; $count] {
203 #[inline(always)]
204 fn from(other: $name) -> Self {
205 other.inner
206 }
207 }
208 };
209}
210
211define_vectors! {
212 (Vec2, Vector2, f32 * 2, align: 8, size: 8),
213 (Vec3, Vector3, f32 * 3, align: 16, size: 12),
214 (Vec4, Vector4, f32 * 4, align: 16, size: 16),
215 (DVec2, Vector2, f64 * 2, align: 16, size: 16),
216 (DVec3, Vector3, f64 * 3, align: 32, size: 24),
217 (DVec4, Vector4, f64 * 4, align: 32, size: 32),
218 (UVec2, Vector2, u32 * 2, align: 8, size: 8),
219 (UVec3, Vector3, u32 * 3, align: 16, size: 12),
220 (UVec4, Vector4, u32 * 4, align: 16, size: 16),
221 (IVec2, Vector2, i32 * 2, align: 8, size: 8),
222 (IVec3, Vector3, i32 * 3, align: 16, size: 12),
223 (IVec4, Vector4, i32 * 4, align: 16, size: 16),
224 (BVec2, Vector2, Bool * 2, align: 8, size: 8),
225 (BVec3, Vector3, Bool * 3, align: 16, size: 12),
226 (BVec4, Vector4, Bool * 4, align: 16, size: 16),
227}
228
229macro_rules! define_matrices {
230 ( $(( $name:ident, $mint_name:ident, $prim_ty:ty, $row_ty:ty, $rows:literal * $cols:literal, align: $align:literal, size: $size:literal, pad: $pad:literal, [$($idx:literal),*] ),)* ) => {
231 $(
232 define_matrices!(@impl
233 $name,
234 mint::$mint_name<$prim_ty>,
235 $align,
236 $prim_ty,
237 $row_ty,
238 $rows,
239 $cols,
240 $pad,
241 [$( $idx ),*],
242 concat!(
243 "Matrix of `", stringify!($prim_ty), "` values with ", stringify!($rows), " rows and ", stringify!($cols), " columns. ",
244 "Has size ", stringify!($size), " and alignment ", stringify!($align), "."
245 ),
246 concat!(
247 "Construct a `", stringify!($name), "` from any type which is convertable into a ",
248 "`mint::", stringify!($mint_name), "<", stringify!($prim_ty), ">`."
249 )
250 );
251 )*
252 };
253
254 (@impl $name:ident, $mint_type:ty, $align:literal, $inner_ty:ty, $ty:ty, $count_x:literal, $count_y:literal, $padding:literal, [$( $idx:literal ),*], $doc:expr, $mint_doc:expr) => {
255 #[doc = $doc]
256 #[repr(C, align($align))]
257 #[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
258 pub struct $name {
259 pub inner: [$ty; $count_y],
260 _padding: [u8; $padding],
261 }
262
263 #[cfg(feature = "bytemuck")]
264 unsafe impl bytemuck::Zeroable for $name {}
265 #[cfg(feature = "bytemuck")]
266 unsafe impl bytemuck::Pod for $name {}
267
268 impl $name {
269 #[inline(always)]
270 pub fn new(inner: [$ty; $count_y]) -> Self {
271 Self { inner, _padding: [0; $padding] }
272 }
273
274 #[cfg(feature = "mint")]
275 #[cfg_attr(docsrs, doc(cfg(feature = "mint")))]
276 #[doc = $mint_doc]
277 #[inline(always)]
278 pub fn from_mint<T: Into<$mint_type>>(value: T) -> Self {
279 Self::from(value.into())
280 }
281 }
282
283 #[cfg(feature = "mint")]
284 impl From<$mint_type> for $name {
285 #[inline(always)]
286 fn from(other: $mint_type) -> Self {
287 let as_arr: [$inner_ty; $count_x * $count_y] = other.into();
289 as_arr.into()
290 }
291 }
292
293 impl From<[$ty; $count_y]> for $name {
294 #[inline(always)]
295 fn from(inner: [$ty; $count_y]) -> Self {
296 Self { inner, _padding: [0; $padding] }
297 }
298 }
299
300 impl From<[$inner_ty; $count_x * $count_y]> for $name {
301 #[inline(always)]
302 fn from(inner: [$inner_ty; $count_x * $count_y]) -> Self {
303 let d2: [[$inner_ty; $count_x]; $count_y] = unsafe { core::mem::transmute(inner) };
304 Self {
305 inner: [$(<$ty>::from(d2[$idx])),*],
306 _padding: [0; $padding],
307 }
308 }
309 }
310
311 impl From<[[$inner_ty; $count_x]; $count_y]> for $name {
312 #[inline(always)]
313 fn from(inner: [[$inner_ty; $count_x]; $count_y]) -> Self {
314 Self {
315 inner: [$(<$ty>::from(inner[$idx])),*],
316 _padding: [0; $padding],
317 }
318 }
319 }
320
321 #[cfg(feature = "mint")]
322 impl From<$name> for $mint_type {
323 #[inline(always)]
324 fn from(other: $name) -> Self {
325 let as_arr = <[[$inner_ty; $count_x]; $count_y]>::from(other);
326 as_arr.into()
327 }
328 }
329
330 impl From<$name> for [$ty; $count_y] {
331 #[inline(always)]
332 fn from(other: $name) -> Self {
333 other.inner
334 }
335 }
336
337 impl From<$name> for [$inner_ty; $count_x * $count_y] {
338 #[inline(always)]
339 fn from(other: $name) -> Self {
340 let d2: [[$inner_ty; $count_x]; $count_y] = [$(<[$inner_ty; $count_x]>::from(other.inner[$idx])),*];
341 unsafe { core::mem::transmute(d2) }
342 }
343 }
344
345 impl From<$name> for [[$inner_ty; $count_x]; $count_y] {
346 #[inline(always)]
347 fn from(other: $name) -> Self {
348 [$(<[$inner_ty; $count_x]>::from(other.inner[$idx])),*]
349 }
350 }
351 };
352}
353
354define_matrices! {
355 (Mat2x2, ColumnMatrix2, f32, Vec2, 2 * 2, align: 8, size: 16, pad: 0, [0, 1]),
356 (Mat2x3, ColumnMatrix2x3, f32, Vec2, 2 * 3, align: 8, size: 32, pad: 8, [0, 1, 2]),
357 (Mat2x4, ColumnMatrix2x4, f32, Vec2, 2 * 4, align: 8, size: 32, pad: 0, [0, 1, 2, 3]),
358
359 (Mat3x2, ColumnMatrix3x2, f32, Vec3, 3 * 2, align: 16, size: 32, pad: 4, [0, 1]),
360 (Mat3x3, ColumnMatrix3, f32, Vec3, 3 * 3, align: 16, size: 48, pad: 4, [0, 1, 2]),
361 (Mat3x4, ColumnMatrix3x4, f32, Vec3, 3 * 4, align: 16, size: 64, pad: 4, [0, 1, 2, 3]),
362
363 (Mat4x2, ColumnMatrix4x2, f32, Vec4, 4 * 2, align: 16, size: 32, pad: 0, [0, 1]),
364 (Mat4x3, ColumnMatrix4x3, f32, Vec4, 4 * 3, align: 16, size: 48, pad: 0, [0, 1, 2]),
365 (Mat4x4, ColumnMatrix4, f32, Vec4, 4 * 4, align: 16, size: 64, pad: 0, [0, 1, 2, 3]),
366
367 (DMat2x2, ColumnMatrix2, f64, DVec2, 2 * 2, align: 16, size: 32, pad: 0, [0, 1]),
368 (DMat2x3, ColumnMatrix2x3, f64, DVec2, 2 * 3, align: 16, size: 48, pad: 0, [0, 1, 2]),
369 (DMat2x4, ColumnMatrix2x4, f64, DVec2, 2 * 4, align: 16, size: 64, pad: 0, [0, 1, 2, 3]),
370
371 (DMat3x2, ColumnMatrix3x2, f64, DVec3, 3 * 2, align: 32, size: 64, pad: 0, [0, 1]),
372 (DMat3x3, ColumnMatrix3, f64, DVec3, 3 * 3, align: 32, size: 96, pad: 0, [0, 1, 2]),
373 (DMat3x4, ColumnMatrix3x4, f64, DVec3, 3 * 4, align: 32, size: 128, pad: 0, [0, 1, 2, 3]),
374
375 (DMat4x2, ColumnMatrix4x2, f64, DVec4, 4 * 2, align: 32, size: 64, pad: 0, [0, 1]),
376 (DMat4x3, ColumnMatrix4x3, f64, DVec4, 4 * 3, align: 32, size: 96, pad: 0, [0, 1, 2]),
377 (DMat4x4, ColumnMatrix4, f64, DVec4, 4 * 4, align: 32, size: 128, pad: 0, [0, 1, 2, 3]),
378}
379
380pub type Mat2 = Mat2x2;
382pub type Mat3 = Mat3x3;
384pub type Mat4 = Mat4x4;
386pub type DMat2 = DMat2x2;
388pub type DMat3 = DMat3x3;
390pub type DMat4 = DMat4x4;
392
393#[repr(C, align(16))]
414#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
415pub struct ArrayMember<T>(pub T);
416
417#[cfg(feature = "bytemuck")]
418unsafe impl<T: bytemuck::Zeroable> bytemuck::Zeroable for ArrayMember<T> {}
419#[cfg(feature = "bytemuck")]
420unsafe impl<T: bytemuck::Pod> bytemuck::Pod for ArrayMember<T> {}
421
422#[repr(C, align(256))]
486#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
487pub struct DynamicOffsetMember<T>(pub T);
488
489#[cfg(feature = "bytemuck")]
490unsafe impl<T: bytemuck::Zeroable> bytemuck::Zeroable for DynamicOffsetMember<T> {}
491#[cfg(feature = "bytemuck")]
492unsafe impl<T: bytemuck::Pod> bytemuck::Pod for DynamicOffsetMember<T> {}
493
494pub mod padding {
496 macro_rules! define_padding {
497 ($name:ident, $count:literal <- $doc:literal) => {
498 #[doc = $doc]
499 #[repr(C)]
500 #[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
501 pub struct $name {
502 _padding: [u8; $count],
503 }
504
505 #[cfg(feature = "bytemuck")]
506 unsafe impl bytemuck::Zeroable for $name {}
507 #[cfg(feature = "bytemuck")]
508 unsafe impl bytemuck::Pod for $name {}
509
510 impl $name {
511 #[inline(always)]
512 pub fn new() -> Self {
513 Self::default()
514 }
515 }
516 };
517 }
518
519 define_padding!(Pad1Float, 4 <- "Padding the size of a single float/uint/int. 4 bytes.");
520 define_padding!(Pad2Float, 8 <- "Padding the size of two floats/uints/ints. 8 bytes.");
521 define_padding!(Pad3Float, 12 <- "Padding the size of three floats/uints/ints. 12 bytes.");
522 define_padding!(Pad4Float, 16 <- "Padding the size of four floats/uints/ints. 16 bytes.");
523 define_padding!(Pad1Double, 8 <- "Padding the size of a single double. 8 bytes.");
524 define_padding!(Pad2Double, 16 <- "Padding the size of two doubles. 16 bytes.");
525 define_padding!(Pad3Double, 24 <- "Padding the size of three doubles. 24 bytes.");
526 define_padding!(Pad4Double, 32 <- "Padding the size of four doubles. 32 bytes.");
527}
528
529#[cfg(test)]
530mod test {
531 use crate::*;
532 use core::mem::size_of;
533 use glsl_layout::AsStd140;
534 use std::ptr::null;
535
536 #[repr(C)]
537 struct Test1 {
538 a: Vec3,
539 b: u32,
540 }
541
542 #[repr(C)]
543 struct Test2 {
544 a: std140::vec3,
545 b: std140::uint,
546 }
547
548 #[derive(AsStd140)]
549 struct Test3 {
550 a: glsl_layout::vec3,
551 b: glsl_layout::int,
552 }
553
554 type Test3U = <Test3 as AsStd140>::Std140;
555
556 #[test]
557 fn sizes() {
558 assert_eq!((&unsafe { &*null::<Test3U>() }.b) as *const i32 as usize, 12);
559 assert_eq!(size_of::<Test3U>(), 16);
560 }
561}