1use core::{cmp::Ordering, fmt};
2
3pub const FIRST_INSTANCE_BINDING: &str = "naga_vs_first_instance";
5
6pub const SUPPORTED_CORE_VERSIONS: &[u16] = &[140, 150, 330, 400, 410, 420, 430, 440, 450, 460];
8pub const SUPPORTED_ES_VERSIONS: &[u16] = &[300, 310, 320];
10
11#[derive(Debug, Copy, Clone, PartialEq)]
13#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
14#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
15pub enum Version {
16 Desktop(u16),
18 Embedded { version: u16, is_webgl: bool },
20}
21
22impl Version {
23 pub const fn new_gles(version: u16) -> Self {
25 Self::Embedded {
26 version,
27 is_webgl: false,
28 }
29 }
30
31 pub const fn is_es(&self) -> bool {
33 match *self {
34 Version::Desktop(_) => false,
35 Version::Embedded { .. } => true,
36 }
37 }
38
39 pub const fn is_webgl(&self) -> bool {
41 match *self {
42 Version::Desktop(_) => false,
43 Version::Embedded { is_webgl, .. } => is_webgl,
44 }
45 }
46
47 pub fn is_supported(&self) -> bool {
54 match *self {
55 Version::Desktop(v) => SUPPORTED_CORE_VERSIONS.contains(&v),
56 Version::Embedded { version: v, .. } => SUPPORTED_ES_VERSIONS.contains(&v),
57 }
58 }
59
60 pub fn supports_io_locations(&self) -> bool {
61 *self >= Version::Desktop(330) || *self >= Version::new_gles(300)
62 }
63
64 pub fn supports_explicit_locations(&self) -> bool {
71 *self >= Version::Desktop(420) || *self >= Version::new_gles(310)
72 }
73
74 pub fn supports_early_depth_test(&self) -> bool {
75 *self >= Version::Desktop(130) || *self >= Version::new_gles(310)
76 }
77
78 pub fn supports_std140_layout(&self) -> bool {
79 *self >= Version::Desktop(140) || *self >= Version::new_gles(300)
80 }
81
82 pub fn supports_std430_layout(&self) -> bool {
83 *self >= Version::Desktop(400) || *self >= Version::new_gles(310)
85 }
86
87 pub fn supports_fma_function(&self) -> bool {
88 *self >= Version::Desktop(400) || *self >= Version::new_gles(320)
89 }
90
91 pub fn supports_integer_functions(&self) -> bool {
92 *self >= Version::Desktop(400) || *self >= Version::new_gles(310)
93 }
94
95 pub fn supports_frexp_function(&self) -> bool {
96 *self >= Version::Desktop(400) || *self >= Version::new_gles(310)
97 }
98
99 pub fn supports_derivative_control(&self) -> bool {
100 *self >= Version::Desktop(450)
101 }
102
103 pub fn supports_pack_unpack_4x8(&self) -> bool {
110 *self >= Version::Desktop(400) || *self >= Version::new_gles(310)
111 }
112 pub fn supports_pack_unpack_snorm_2x16(&self) -> bool {
113 *self >= Version::Desktop(420) || *self >= Version::new_gles(300)
114 }
115 pub fn supports_pack_unpack_unorm_2x16(&self) -> bool {
116 *self >= Version::Desktop(400) || *self >= Version::new_gles(300)
117 }
118
119 pub fn supports_pack_unpack_half_2x16(&self) -> bool {
124 *self >= Version::Desktop(420) || *self >= Version::new_gles(300)
125 }
126}
127
128impl PartialOrd for Version {
129 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
130 match (*self, *other) {
131 (Version::Desktop(x), Version::Desktop(y)) => Some(x.cmp(&y)),
132 (Version::Embedded { version: x, .. }, Version::Embedded { version: y, .. }) => {
133 Some(x.cmp(&y))
134 }
135 _ => None,
136 }
137 }
138}
139
140impl fmt::Display for Version {
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 match *self {
143 Version::Desktop(v) => write!(f, "{v} core"),
144 Version::Embedded { version: v, .. } => write!(f, "{v} es"),
145 }
146 }
147}
148
149pub type BindingMap = alloc::collections::BTreeMap<crate::ResourceBinding, u8>;
151
152#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
154#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
155#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
156pub enum GlslScalarKind {
157 Sint,
158 Uint,
159 Float,
160}
161
162#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
164#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
165#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
166pub enum GlslVectorSize {
167 Bi = 2,
168 Tri = 3,
169 Quad = 4,
170}
171impl GlslVectorSize {
172 pub fn alignment(&self) -> u32 {
173 match self {
174 Self::Bi => 2,
175 Self::Tri | Self::Quad => 4,
176 }
177 }
178}
179
180#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
182#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
183#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
184pub struct GlslScalar {
185 pub kind: GlslScalarKind,
186 pub width: u8,
187}
188
189impl GlslScalar {
190 pub const F32: Self = Self {
191 kind: GlslScalarKind::Float,
192 width: 4,
193 };
194 pub const I32: Self = Self {
195 kind: GlslScalarKind::Sint,
196 width: 4,
197 };
198 pub const U32: Self = Self {
199 kind: GlslScalarKind::Uint,
200 width: 4,
201 };
202}
203
204#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
206#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
207#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
208pub enum GlslUniformType {
209 Scalar(GlslScalar),
210 Vector {
211 size: GlslVectorSize,
212 scalar: GlslScalar,
213 },
214 Matrix {
215 columns: GlslVectorSize,
216 rows: GlslVectorSize,
217 scalar: GlslScalar,
218 },
219}
220impl GlslUniformType {
221 pub fn size(&self) -> u32 {
222 match self {
223 Self::Scalar(scalar) => scalar.width as u32,
224 Self::Vector { size, scalar } => *size as u32 * scalar.width as u32,
225 Self::Matrix {
227 columns,
228 rows,
229 scalar,
230 } => rows.alignment() * scalar.width as u32 * *columns as u32,
231 }
232 }
233}