naga/proc/overloads/
constructor_set.rs

1//! A set of type constructors, represented as a bitset.
2
3use crate::ir;
4use crate::proc::overloads::one_bits_iter::OneBitsIter;
5
6bitflags::bitflags! {
7    /// A set of type constructors.
8    #[derive(Copy, Clone, Debug, PartialEq)]
9    pub(crate) struct ConstructorSet: u16 {
10        const SCALAR = 1 << 0;
11        const VEC2 = 1 << 1;
12        const VEC3 = 1 << 2;
13        const VEC4 = 1 << 3;
14        const MAT2X2 = 1 << 4;
15        const MAT2X3 = 1 << 5;
16        const MAT2X4 = 1 << 6;
17        const MAT3X2 = 1 << 7;
18        const MAT3X3 = 1 << 8;
19        const MAT3X4 = 1 << 9;
20        const MAT4X2 = 1 << 10;
21        const MAT4X3 = 1 << 11;
22        const MAT4X4 = 1 << 12;
23
24        const VECN = Self::VEC2.bits()
25            | Self::VEC3.bits()
26            | Self::VEC4.bits();
27    }
28}
29
30impl ConstructorSet {
31    /// Return the single-member set containing `inner`'s constructor.
32    pub const fn singleton(inner: &ir::TypeInner) -> ConstructorSet {
33        use ir::TypeInner as Ti;
34        use ir::VectorSize as Vs;
35        match *inner {
36            Ti::Scalar(_) => Self::SCALAR,
37            Ti::Vector { size, scalar: _ } => match size {
38                Vs::Bi => Self::VEC2,
39                Vs::Tri => Self::VEC3,
40                Vs::Quad => Self::VEC4,
41            },
42            Ti::Matrix {
43                columns,
44                rows,
45                scalar: _,
46            } => match (columns, rows) {
47                (Vs::Bi, Vs::Bi) => Self::MAT2X2,
48                (Vs::Bi, Vs::Tri) => Self::MAT2X3,
49                (Vs::Bi, Vs::Quad) => Self::MAT2X4,
50                (Vs::Tri, Vs::Bi) => Self::MAT3X2,
51                (Vs::Tri, Vs::Tri) => Self::MAT3X3,
52                (Vs::Tri, Vs::Quad) => Self::MAT3X4,
53                (Vs::Quad, Vs::Bi) => Self::MAT4X2,
54                (Vs::Quad, Vs::Tri) => Self::MAT4X3,
55                (Vs::Quad, Vs::Quad) => Self::MAT4X4,
56            },
57            _ => Self::empty(),
58        }
59    }
60
61    pub const fn is_singleton(self) -> bool {
62        self.bits().is_power_of_two()
63    }
64
65    /// Return an iterator over this set's members.
66    ///
67    /// Members are produced as singleton, in order from most general to least.
68    pub fn members(self) -> impl Iterator<Item = ConstructorSet> {
69        OneBitsIter::new(self.bits() as u64).map(|bit| Self::from_bits(bit as u16).unwrap())
70    }
71
72    /// Return the size of the sole element of `self`.
73    ///
74    /// # Panics
75    ///
76    /// Panic if `self` is not a singleton.
77    pub fn size(self) -> ConstructorSize {
78        use ir::VectorSize as Vs;
79        use ConstructorSize as Cs;
80
81        match self {
82            ConstructorSet::SCALAR => Cs::Scalar,
83            ConstructorSet::VEC2 => Cs::Vector(Vs::Bi),
84            ConstructorSet::VEC3 => Cs::Vector(Vs::Tri),
85            ConstructorSet::VEC4 => Cs::Vector(Vs::Quad),
86            ConstructorSet::MAT2X2 => Cs::Matrix {
87                columns: Vs::Bi,
88                rows: Vs::Bi,
89            },
90            ConstructorSet::MAT2X3 => Cs::Matrix {
91                columns: Vs::Bi,
92                rows: Vs::Tri,
93            },
94            ConstructorSet::MAT2X4 => Cs::Matrix {
95                columns: Vs::Bi,
96                rows: Vs::Quad,
97            },
98            ConstructorSet::MAT3X2 => Cs::Matrix {
99                columns: Vs::Tri,
100                rows: Vs::Bi,
101            },
102            ConstructorSet::MAT3X3 => Cs::Matrix {
103                columns: Vs::Tri,
104                rows: Vs::Tri,
105            },
106            ConstructorSet::MAT3X4 => Cs::Matrix {
107                columns: Vs::Tri,
108                rows: Vs::Quad,
109            },
110            ConstructorSet::MAT4X2 => Cs::Matrix {
111                columns: Vs::Quad,
112                rows: Vs::Bi,
113            },
114            ConstructorSet::MAT4X3 => Cs::Matrix {
115                columns: Vs::Quad,
116                rows: Vs::Tri,
117            },
118            ConstructorSet::MAT4X4 => Cs::Matrix {
119                columns: Vs::Quad,
120                rows: Vs::Quad,
121            },
122            _ => unreachable!("ConstructorSet was not a singleton"),
123        }
124    }
125}
126
127/// The sizes a member of [`ConstructorSet`] might have.
128#[derive(Clone, Copy)]
129pub enum ConstructorSize {
130    /// The constructor is [`SCALAR`].
131    ///
132    /// [`SCALAR`]: ConstructorSet::SCALAR
133    Scalar,
134
135    /// The constructor is `VECN` for some `N`.
136    Vector(ir::VectorSize),
137
138    /// The constructor is `MATCXR` for some `C` and `R`.
139    Matrix {
140        columns: ir::VectorSize,
141        rows: ir::VectorSize,
142    },
143}
144
145impl ConstructorSize {
146    /// Construct a [`TypeInner`] for a type with this size and the given `scalar`.
147    ///
148    /// [`TypeInner`]: ir::TypeInner
149    pub const fn to_inner(self, scalar: ir::Scalar) -> ir::TypeInner {
150        match self {
151            Self::Scalar => ir::TypeInner::Scalar(scalar),
152            Self::Vector(size) => ir::TypeInner::Vector { size, scalar },
153            Self::Matrix { columns, rows } => ir::TypeInner::Matrix {
154                columns,
155                rows,
156                scalar,
157            },
158        }
159    }
160}
161
162macro_rules! constructor_set {
163    ( $( $constr:ident )|* ) => {
164        {
165            use $crate::proc::overloads::constructor_set::ConstructorSet;
166            ConstructorSet::empty()
167                $(
168                    .union(ConstructorSet::$constr)
169                )*
170        }
171    }
172}
173
174pub(in crate::proc::overloads) use constructor_set;