1use mtl_foundation::UInteger;
19
20#[repr(C, packed)]
24#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
25pub struct Origin {
26 pub x: UInteger,
27 pub y: UInteger,
28 pub z: UInteger,
29}
30
31impl Origin {
32 #[inline]
34 pub const fn new(x: UInteger, y: UInteger, z: UInteger) -> Self {
35 Self { x, y, z }
36 }
37
38 #[inline]
42 pub const fn make(x: UInteger, y: UInteger, z: UInteger) -> Self {
43 Self::new(x, y, z)
44 }
45}
46
47#[repr(C, packed)]
51#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
52pub struct Size {
53 pub width: UInteger,
54 pub height: UInteger,
55 pub depth: UInteger,
56}
57
58impl Size {
59 #[inline]
61 pub const fn new(width: UInteger, height: UInteger, depth: UInteger) -> Self {
62 Self {
63 width,
64 height,
65 depth,
66 }
67 }
68
69 #[inline]
73 pub const fn make(width: UInteger, height: UInteger, depth: UInteger) -> Self {
74 Self::new(width, height, depth)
75 }
76}
77
78#[repr(C, packed)]
82#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
83pub struct Region {
84 pub origin: Origin,
85 pub size: Size,
86}
87
88impl Region {
89 #[inline]
91 pub const fn new(origin: Origin, size: Size) -> Self {
92 Self { origin, size }
93 }
94
95 #[inline]
99 pub const fn new_1d(x: UInteger, width: UInteger) -> Self {
100 Self {
101 origin: Origin::new(x, 0, 0),
102 size: Size::new(width, 1, 1),
103 }
104 }
105
106 #[inline]
110 pub const fn new_2d(x: UInteger, y: UInteger, width: UInteger, height: UInteger) -> Self {
111 Self {
112 origin: Origin::new(x, y, 0),
113 size: Size::new(width, height, 1),
114 }
115 }
116
117 #[inline]
121 pub const fn new_3d(
122 x: UInteger,
123 y: UInteger,
124 z: UInteger,
125 width: UInteger,
126 height: UInteger,
127 depth: UInteger,
128 ) -> Self {
129 Self {
130 origin: Origin::new(x, y, z),
131 size: Size::new(width, height, depth),
132 }
133 }
134
135 #[inline]
139 pub const fn make_1d(x: UInteger, width: UInteger) -> Self {
140 Self::new_1d(x, width)
141 }
142
143 #[inline]
147 pub const fn make_2d(x: UInteger, y: UInteger, width: UInteger, height: UInteger) -> Self {
148 Self::new_2d(x, y, width, height)
149 }
150
151 #[inline]
155 pub const fn make_3d(
156 x: UInteger,
157 y: UInteger,
158 z: UInteger,
159 width: UInteger,
160 height: UInteger,
161 depth: UInteger,
162 ) -> Self {
163 Self::new_3d(x, y, z, width, height, depth)
164 }
165}
166
167#[repr(C, packed)]
171#[derive(Copy, Clone, Debug, Default, PartialEq)]
172pub struct SamplePosition {
173 pub x: f32,
174 pub y: f32,
175}
176
177impl SamplePosition {
178 #[inline]
180 pub const fn new(x: f32, y: f32) -> Self {
181 Self { x, y }
182 }
183
184 #[inline]
188 pub const fn make(x: f32, y: f32) -> Self {
189 Self::new(x, y)
190 }
191}
192
193pub type Coordinate2D = SamplePosition;
197
198#[repr(C, packed)]
202#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
203pub struct ResourceID {
204 pub _impl: u64,
205}
206
207impl ResourceID {
208 #[inline]
210 pub const fn new(value: u64) -> Self {
211 Self { _impl: value }
212 }
213}
214
215#[repr(C, packed)]
219#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
220pub struct ScissorRect {
221 pub x: UInteger,
222 pub y: UInteger,
223 pub width: UInteger,
224 pub height: UInteger,
225}
226
227impl ScissorRect {
228 #[inline]
230 pub const fn new(x: UInteger, y: UInteger, width: UInteger, height: UInteger) -> Self {
231 Self {
232 x,
233 y,
234 width,
235 height,
236 }
237 }
238}
239
240#[repr(C, packed)]
244#[derive(Copy, Clone, Debug, Default, PartialEq)]
245pub struct Viewport {
246 pub origin_x: f64,
247 pub origin_y: f64,
248 pub width: f64,
249 pub height: f64,
250 pub znear: f64,
251 pub zfar: f64,
252}
253
254impl Viewport {
255 #[inline]
257 pub const fn new(
258 origin_x: f64,
259 origin_y: f64,
260 width: f64,
261 height: f64,
262 znear: f64,
263 zfar: f64,
264 ) -> Self {
265 Self {
266 origin_x,
267 origin_y,
268 width,
269 height,
270 znear,
271 zfar,
272 }
273 }
274}
275
276#[repr(C, packed)]
280#[derive(Copy, Clone, Debug, Default, PartialEq)]
281pub struct ClearColor {
282 pub red: f64,
283 pub green: f64,
284 pub blue: f64,
285 pub alpha: f64,
286}
287
288impl ClearColor {
289 #[inline]
291 pub const fn new(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
292 Self {
293 red,
294 green,
295 blue,
296 alpha,
297 }
298 }
299
300 #[inline]
304 pub const fn make(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
305 Self::new(red, green, blue, alpha)
306 }
307}
308
309#[repr(C, packed)]
313#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
314pub struct DrawPrimitivesIndirectArguments {
315 pub vertex_count: u32,
316 pub instance_count: u32,
317 pub vertex_start: u32,
318 pub base_instance: u32,
319}
320
321#[repr(C, packed)]
325#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
326pub struct DrawIndexedPrimitivesIndirectArguments {
327 pub index_count: u32,
328 pub instance_count: u32,
329 pub index_start: u32,
330 pub base_vertex: i32,
331 pub base_instance: u32,
332}
333
334#[repr(C, packed)]
338#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
339pub struct VertexAmplificationViewMapping {
340 pub viewport_array_index_offset: u32,
341 pub render_target_array_index_offset: u32,
342}
343
344#[repr(C, packed)]
348#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
349pub struct DrawPatchIndirectArguments {
350 pub patch_count: u32,
351 pub instance_count: u32,
352 pub patch_start: u32,
353 pub base_instance: u32,
354}
355
356#[repr(C, packed)]
360#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
361pub struct QuadTessellationFactorsHalf {
362 pub edge_tessellation_factor: [u16; 4],
363 pub inside_tessellation_factor: [u16; 2],
364}
365
366#[repr(C, packed)]
370#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
371pub struct TriangleTessellationFactorsHalf {
372 pub edge_tessellation_factor: [u16; 3],
373 pub inside_tessellation_factor: u16,
374}
375
376use crate::enums::{AccelerationStructureInstanceOptions, MotionBorderMode};
381
382#[repr(C, packed)]
386#[derive(Copy, Clone, Debug, Default, PartialEq)]
387pub struct PackedFloat3 {
388 pub x: f32,
389 pub y: f32,
390 pub z: f32,
391}
392
393impl PackedFloat3 {
394 #[inline]
396 pub const fn new(x: f32, y: f32, z: f32) -> Self {
397 Self { x, y, z }
398 }
399
400 #[inline]
402 pub const fn from_array(arr: [f32; 3]) -> Self {
403 Self {
404 x: arr[0],
405 y: arr[1],
406 z: arr[2],
407 }
408 }
409
410 #[inline]
412 pub const fn to_array(&self) -> [f32; 3] {
413 [self.x, self.y, self.z]
414 }
415}
416
417impl PackedFloat3 {
418 #[inline]
424 pub fn get(&self, idx: usize) -> Option<f32> {
425 match idx {
426 0 => Some(self.x),
427 1 => Some(self.y),
428 2 => Some(self.z),
429 _ => None,
430 }
431 }
432}
433
434#[repr(C, packed)]
440#[derive(Copy, Clone, Debug, Default, PartialEq)]
441pub struct PackedFloat4x3 {
442 pub columns: [PackedFloat3; 4],
443}
444
445impl PackedFloat4x3 {
446 #[inline]
448 pub const fn new(
449 col0: PackedFloat3,
450 col1: PackedFloat3,
451 col2: PackedFloat3,
452 col3: PackedFloat3,
453 ) -> Self {
454 Self {
455 columns: [col0, col1, col2, col3],
456 }
457 }
458
459 #[inline]
461 pub const fn identity() -> Self {
462 Self {
463 columns: [
464 PackedFloat3::new(1.0, 0.0, 0.0),
465 PackedFloat3::new(0.0, 1.0, 0.0),
466 PackedFloat3::new(0.0, 0.0, 1.0),
467 PackedFloat3::new(0.0, 0.0, 0.0),
468 ],
469 }
470 }
471}
472
473impl std::ops::Index<usize> for PackedFloat4x3 {
474 type Output = PackedFloat3;
475 #[inline]
476 fn index(&self, idx: usize) -> &Self::Output {
477 &self.columns[idx]
478 }
479}
480
481impl std::ops::IndexMut<usize> for PackedFloat4x3 {
482 #[inline]
483 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
484 &mut self.columns[idx]
485 }
486}
487
488#[repr(C, packed)]
492#[derive(Copy, Clone, Debug, Default, PartialEq)]
493pub struct AxisAlignedBoundingBox {
494 pub min: PackedFloat3,
495 pub max: PackedFloat3,
496}
497
498impl AxisAlignedBoundingBox {
499 #[inline]
501 pub const fn new(min: PackedFloat3, max: PackedFloat3) -> Self {
502 Self { min, max }
503 }
504
505 #[inline]
507 pub const fn from_point(p: PackedFloat3) -> Self {
508 Self { min: p, max: p }
509 }
510}
511
512#[repr(C, packed)]
516#[derive(Copy, Clone, Debug, Default, PartialEq)]
517pub struct PackedFloatQuaternion {
518 pub x: f32,
519 pub y: f32,
520 pub z: f32,
521 pub w: f32,
522}
523
524impl PackedFloatQuaternion {
525 #[inline]
527 pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
528 Self { x, y, z, w }
529 }
530
531 #[inline]
533 pub const fn identity() -> Self {
534 Self {
535 x: 0.0,
536 y: 0.0,
537 z: 0.0,
538 w: 1.0,
539 }
540 }
541
542 #[inline]
544 pub const fn from_array(arr: [f32; 4]) -> Self {
545 Self {
546 x: arr[0],
547 y: arr[1],
548 z: arr[2],
549 w: arr[3],
550 }
551 }
552
553 #[inline]
555 pub const fn to_array(&self) -> [f32; 4] {
556 [self.x, self.y, self.z, self.w]
557 }
558}
559
560impl PackedFloatQuaternion {
561 #[inline]
567 pub fn get(&self, idx: usize) -> Option<f32> {
568 match idx {
569 0 => Some(self.x),
570 1 => Some(self.y),
571 2 => Some(self.z),
572 3 => Some(self.w),
573 _ => None,
574 }
575 }
576}
577
578#[repr(C, packed)]
582#[derive(Copy, Clone, Debug, Default, PartialEq)]
583pub struct ComponentTransform {
584 pub scale: PackedFloat3,
585 pub shear: PackedFloat3,
586 pub pivot: PackedFloat3,
587 pub rotation: PackedFloatQuaternion,
588 pub translation: PackedFloat3,
589}
590
591impl ComponentTransform {
592 #[inline]
594 pub const fn identity() -> Self {
595 Self {
596 scale: PackedFloat3::new(1.0, 1.0, 1.0),
597 shear: PackedFloat3::new(0.0, 0.0, 0.0),
598 pivot: PackedFloat3::new(0.0, 0.0, 0.0),
599 rotation: PackedFloatQuaternion::identity(),
600 translation: PackedFloat3::new(0.0, 0.0, 0.0),
601 }
602 }
603}
604
605#[repr(C, packed)]
613#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
614pub struct AccelerationStructureSizes {
615 pub acceleration_structure_size: UInteger,
616 pub build_scratch_buffer_size: UInteger,
617 pub refit_scratch_buffer_size: UInteger,
618}
619
620#[repr(C, packed)]
624#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
625pub struct SizeAndAlign {
626 pub size: UInteger,
627 pub align: UInteger,
628}
629
630#[repr(C, packed)]
638#[derive(Copy, Clone, Debug, PartialEq)]
639pub struct AccelerationStructureInstanceDescriptor {
640 pub transformation_matrix: PackedFloat4x3,
641 pub options: AccelerationStructureInstanceOptions,
642 pub mask: u32,
643 pub intersection_function_table_offset: u32,
644 pub acceleration_structure_index: u32,
645}
646
647impl Default for AccelerationStructureInstanceDescriptor {
648 fn default() -> Self {
649 Self {
650 transformation_matrix: PackedFloat4x3::identity(),
651 options: AccelerationStructureInstanceOptions::NONE,
652 mask: 0xFFFFFFFF,
653 intersection_function_table_offset: 0,
654 acceleration_structure_index: 0,
655 }
656 }
657}
658
659#[repr(C, packed)]
663#[derive(Copy, Clone, Debug, PartialEq)]
664pub struct AccelerationStructureUserIDInstanceDescriptor {
665 pub transformation_matrix: PackedFloat4x3,
666 pub options: AccelerationStructureInstanceOptions,
667 pub mask: u32,
668 pub intersection_function_table_offset: u32,
669 pub acceleration_structure_index: u32,
670 pub user_id: u32,
671}
672
673impl Default for AccelerationStructureUserIDInstanceDescriptor {
674 fn default() -> Self {
675 Self {
676 transformation_matrix: PackedFloat4x3::identity(),
677 options: AccelerationStructureInstanceOptions::NONE,
678 mask: 0xFFFFFFFF,
679 intersection_function_table_offset: 0,
680 acceleration_structure_index: 0,
681 user_id: 0,
682 }
683 }
684}
685
686#[repr(C, packed)]
690#[derive(Copy, Clone, Debug, PartialEq)]
691pub struct AccelerationStructureMotionInstanceDescriptor {
692 pub options: AccelerationStructureInstanceOptions,
693 pub mask: u32,
694 pub intersection_function_table_offset: u32,
695 pub acceleration_structure_index: u32,
696 pub user_id: u32,
697 pub motion_transforms_start_index: u32,
698 pub motion_transforms_count: u32,
699 pub motion_start_border_mode: MotionBorderMode,
700 pub motion_end_border_mode: MotionBorderMode,
701 pub motion_start_time: f32,
702 pub motion_end_time: f32,
703}
704
705impl Default for AccelerationStructureMotionInstanceDescriptor {
706 fn default() -> Self {
707 Self {
708 options: AccelerationStructureInstanceOptions::NONE,
709 mask: 0xFFFFFFFF,
710 intersection_function_table_offset: 0,
711 acceleration_structure_index: 0,
712 user_id: 0,
713 motion_transforms_start_index: 0,
714 motion_transforms_count: 0,
715 motion_start_border_mode: MotionBorderMode::CLAMP,
716 motion_end_border_mode: MotionBorderMode::CLAMP,
717 motion_start_time: 0.0,
718 motion_end_time: 1.0,
719 }
720 }
721}
722
723#[repr(C, packed)]
727#[derive(Copy, Clone, Debug, PartialEq)]
728pub struct IndirectAccelerationStructureInstanceDescriptor {
729 pub transformation_matrix: PackedFloat4x3,
730 pub options: AccelerationStructureInstanceOptions,
731 pub mask: u32,
732 pub intersection_function_table_offset: u32,
733 pub user_id: u32,
734 pub acceleration_structure_id: ResourceID,
735}
736
737impl Default for IndirectAccelerationStructureInstanceDescriptor {
738 fn default() -> Self {
739 Self {
740 transformation_matrix: PackedFloat4x3::identity(),
741 options: AccelerationStructureInstanceOptions::NONE,
742 mask: 0xFFFFFFFF,
743 intersection_function_table_offset: 0,
744 user_id: 0,
745 acceleration_structure_id: ResourceID::default(),
746 }
747 }
748}
749
750#[repr(C, packed)]
754#[derive(Copy, Clone, Debug, PartialEq)]
755pub struct IndirectAccelerationStructureMotionInstanceDescriptor {
756 pub options: AccelerationStructureInstanceOptions,
757 pub mask: u32,
758 pub intersection_function_table_offset: u32,
759 pub user_id: u32,
760 pub acceleration_structure_id: ResourceID,
761 pub motion_transforms_start_index: u32,
762 pub motion_transforms_count: u32,
763 pub motion_start_border_mode: MotionBorderMode,
764 pub motion_end_border_mode: MotionBorderMode,
765 pub motion_start_time: f32,
766 pub motion_end_time: f32,
767}
768
769impl Default for IndirectAccelerationStructureMotionInstanceDescriptor {
770 fn default() -> Self {
771 Self {
772 options: AccelerationStructureInstanceOptions::NONE,
773 mask: 0xFFFFFFFF,
774 intersection_function_table_offset: 0,
775 user_id: 0,
776 acceleration_structure_id: ResourceID::default(),
777 motion_transforms_start_index: 0,
778 motion_transforms_count: 0,
779 motion_start_border_mode: MotionBorderMode::CLAMP,
780 motion_end_border_mode: MotionBorderMode::CLAMP,
781 motion_start_time: 0.0,
782 motion_end_time: 1.0,
783 }
784 }
785}
786
787#[cfg(test)]
788mod tests {
789 use super::*;
790
791 #[test]
792 fn test_origin_size() {
793 assert_eq!(
794 std::mem::size_of::<Origin>(),
795 3 * std::mem::size_of::<UInteger>()
796 );
797 }
798
799 #[test]
800 fn test_size_size() {
801 assert_eq!(
802 std::mem::size_of::<Size>(),
803 3 * std::mem::size_of::<UInteger>()
804 );
805 }
806
807 #[test]
808 fn test_region_size() {
809 assert_eq!(
810 std::mem::size_of::<Region>(),
811 6 * std::mem::size_of::<UInteger>()
812 );
813 }
814
815 #[test]
816 fn test_sample_position_size() {
817 assert_eq!(std::mem::size_of::<SamplePosition>(), 2 * 4);
818 }
819
820 #[test]
821 fn test_resource_id_size() {
822 assert_eq!(std::mem::size_of::<ResourceID>(), 8);
823 }
824
825 #[test]
826 fn test_scissor_rect_size() {
827 assert_eq!(
828 std::mem::size_of::<ScissorRect>(),
829 4 * std::mem::size_of::<UInteger>()
830 );
831 }
832
833 #[test]
834 fn test_viewport_size() {
835 assert_eq!(std::mem::size_of::<Viewport>(), 6 * 8);
836 }
837
838 #[test]
839 fn test_clear_color_size() {
840 assert_eq!(std::mem::size_of::<ClearColor>(), 4 * 8);
841 }
842
843 #[test]
844 fn test_origin_make() {
845 let origin = Origin::make(1, 2, 3);
846 let x = { origin.x };
847 let y = { origin.y };
848 let z = { origin.z };
849 assert_eq!(x, 1);
850 assert_eq!(y, 2);
851 assert_eq!(z, 3);
852 }
853
854 #[test]
855 fn test_region_make_2d() {
856 let region = Region::make_2d(10, 20, 100, 200);
857 let ox = { region.origin.x };
858 let oy = { region.origin.y };
859 let oz = { region.origin.z };
860 let sw = { region.size.width };
861 let sh = { region.size.height };
862 let sd = { region.size.depth };
863 assert_eq!(ox, 10);
864 assert_eq!(oy, 20);
865 assert_eq!(oz, 0);
866 assert_eq!(sw, 100);
867 assert_eq!(sh, 200);
868 assert_eq!(sd, 1);
869 }
870
871 #[test]
874 fn test_packed_float3_size() {
875 assert_eq!(std::mem::size_of::<PackedFloat3>(), 12); }
877
878 #[test]
879 fn test_packed_float4x3_size() {
880 assert_eq!(std::mem::size_of::<PackedFloat4x3>(), 48); }
882
883 #[test]
884 fn test_axis_aligned_bounding_box_size() {
885 assert_eq!(std::mem::size_of::<AxisAlignedBoundingBox>(), 24); }
887
888 #[test]
889 fn test_packed_float_quaternion_size() {
890 assert_eq!(std::mem::size_of::<PackedFloatQuaternion>(), 16); }
892
893 #[test]
894 fn test_component_transform_size() {
895 assert_eq!(std::mem::size_of::<ComponentTransform>(), 64);
897 }
898
899 #[test]
900 fn test_acceleration_structure_sizes_size() {
901 assert_eq!(
902 std::mem::size_of::<AccelerationStructureSizes>(),
903 3 * std::mem::size_of::<UInteger>()
904 );
905 }
906
907 #[test]
908 fn test_size_and_align_size() {
909 assert_eq!(
910 std::mem::size_of::<SizeAndAlign>(),
911 2 * std::mem::size_of::<UInteger>()
912 );
913 }
914
915 #[test]
916 fn test_acceleration_structure_instance_descriptor_size() {
917 assert_eq!(
919 std::mem::size_of::<AccelerationStructureInstanceDescriptor>(),
920 64
921 );
922 }
923
924 #[test]
925 fn test_acceleration_structure_user_id_instance_descriptor_size() {
926 assert_eq!(
928 std::mem::size_of::<AccelerationStructureUserIDInstanceDescriptor>(),
929 68
930 );
931 }
932
933 #[test]
934 fn test_packed_float3_new() {
935 let v = PackedFloat3::new(1.0, 2.0, 3.0);
936 let x = { v.x };
937 let y = { v.y };
938 let z = { v.z };
939 assert_eq!(x, 1.0);
940 assert_eq!(y, 2.0);
941 assert_eq!(z, 3.0);
942 }
943
944 #[test]
945 fn test_packed_float4x3_identity() {
946 let m = PackedFloat4x3::identity();
947 let c0x = { m.columns[0].x };
949 let c0y = { m.columns[0].y };
950 let c0z = { m.columns[0].z };
951 assert_eq!(c0x, 1.0);
952 assert_eq!(c0y, 0.0);
953 assert_eq!(c0z, 0.0);
954 let c3x = { m.columns[3].x };
956 let c3y = { m.columns[3].y };
957 let c3z = { m.columns[3].z };
958 assert_eq!(c3x, 0.0);
959 assert_eq!(c3y, 0.0);
960 assert_eq!(c3z, 0.0);
961 }
962
963 #[test]
964 fn test_packed_float_quaternion_identity() {
965 let q = PackedFloatQuaternion::identity();
966 let x = { q.x };
967 let y = { q.y };
968 let z = { q.z };
969 let w = { q.w };
970 assert_eq!(x, 0.0);
971 assert_eq!(y, 0.0);
972 assert_eq!(z, 0.0);
973 assert_eq!(w, 1.0);
974 }
975}