naga/front/
type_gen.rs

1/*!
2Type generators.
3*/
4
5use crate::{arena::Handle, span::Span};
6
7impl crate::Module {
8    /// Populate this module's [`SpecialTypes::ray_desc`] type.
9    ///
10    /// [`SpecialTypes::ray_desc`] is the type of the [`descriptor`] operand of
11    /// an [`Initialize`] [`RayQuery`] statement. In WGSL, it is a struct type
12    /// referred to as `RayDesc`.
13    ///
14    /// Backends consume values of this type to drive platform APIs, so if you
15    /// change any its fields, you must update the backends to match. Look for
16    /// backend code dealing with [`RayQueryFunction::Initialize`].
17    ///
18    /// [`SpecialTypes::ray_desc`]: crate::SpecialTypes::ray_desc
19    /// [`descriptor`]: crate::RayQueryFunction::Initialize::descriptor
20    /// [`Initialize`]: crate::RayQueryFunction::Initialize
21    /// [`RayQuery`]: crate::Statement::RayQuery
22    /// [`RayQueryFunction::Initialize`]: crate::RayQueryFunction::Initialize
23    pub fn generate_ray_desc_type(&mut self) -> Handle<crate::Type> {
24        if let Some(handle) = self.special_types.ray_desc {
25            return handle;
26        }
27
28        let ty_flag = self.types.insert(
29            crate::Type {
30                name: None,
31                inner: crate::TypeInner::Scalar(crate::Scalar::U32),
32            },
33            Span::UNDEFINED,
34        );
35        let ty_scalar = self.types.insert(
36            crate::Type {
37                name: None,
38                inner: crate::TypeInner::Scalar(crate::Scalar::F32),
39            },
40            Span::UNDEFINED,
41        );
42        let ty_vector = self.types.insert(
43            crate::Type {
44                name: None,
45                inner: crate::TypeInner::Vector {
46                    size: crate::VectorSize::Tri,
47                    scalar: crate::Scalar::F32,
48                },
49            },
50            Span::UNDEFINED,
51        );
52
53        let handle = self.types.insert(
54            crate::Type {
55                name: Some("RayDesc".to_string()),
56                inner: crate::TypeInner::Struct {
57                    members: vec![
58                        crate::StructMember {
59                            name: Some("flags".to_string()),
60                            ty: ty_flag,
61                            binding: None,
62                            offset: 0,
63                        },
64                        crate::StructMember {
65                            name: Some("cull_mask".to_string()),
66                            ty: ty_flag,
67                            binding: None,
68                            offset: 4,
69                        },
70                        crate::StructMember {
71                            name: Some("tmin".to_string()),
72                            ty: ty_scalar,
73                            binding: None,
74                            offset: 8,
75                        },
76                        crate::StructMember {
77                            name: Some("tmax".to_string()),
78                            ty: ty_scalar,
79                            binding: None,
80                            offset: 12,
81                        },
82                        crate::StructMember {
83                            name: Some("origin".to_string()),
84                            ty: ty_vector,
85                            binding: None,
86                            offset: 16,
87                        },
88                        crate::StructMember {
89                            name: Some("dir".to_string()),
90                            ty: ty_vector,
91                            binding: None,
92                            offset: 32,
93                        },
94                    ],
95                    span: 48,
96                },
97            },
98            Span::UNDEFINED,
99        );
100
101        self.special_types.ray_desc = Some(handle);
102        handle
103    }
104
105    /// Populate this module's [`SpecialTypes::ray_intersection`] type.
106    ///
107    /// [`SpecialTypes::ray_intersection`] is the type of a
108    /// `RayQueryGetIntersection` expression. In WGSL, it is a struct type
109    /// referred to as `RayIntersection`.
110    ///
111    /// Backends construct values of this type based on platform APIs, so if you
112    /// change any its fields, you must update the backends to match. Look for
113    /// the backend's handling for [`Expression::RayQueryGetIntersection`].
114    ///
115    /// [`SpecialTypes::ray_intersection`]: crate::SpecialTypes::ray_intersection
116    /// [`Expression::RayQueryGetIntersection`]: crate::Expression::RayQueryGetIntersection
117    pub fn generate_ray_intersection_type(&mut self) -> Handle<crate::Type> {
118        if let Some(handle) = self.special_types.ray_intersection {
119            return handle;
120        }
121
122        let ty_flag = self.types.insert(
123            crate::Type {
124                name: None,
125                inner: crate::TypeInner::Scalar(crate::Scalar::U32),
126            },
127            Span::UNDEFINED,
128        );
129        let ty_scalar = self.types.insert(
130            crate::Type {
131                name: None,
132                inner: crate::TypeInner::Scalar(crate::Scalar::F32),
133            },
134            Span::UNDEFINED,
135        );
136        let ty_barycentrics = self.types.insert(
137            crate::Type {
138                name: None,
139                inner: crate::TypeInner::Vector {
140                    size: crate::VectorSize::Bi,
141                    scalar: crate::Scalar::F32,
142                },
143            },
144            Span::UNDEFINED,
145        );
146        let ty_bool = self.types.insert(
147            crate::Type {
148                name: None,
149                inner: crate::TypeInner::Scalar(crate::Scalar::BOOL),
150            },
151            Span::UNDEFINED,
152        );
153        let ty_transform = self.types.insert(
154            crate::Type {
155                name: None,
156                inner: crate::TypeInner::Matrix {
157                    columns: crate::VectorSize::Quad,
158                    rows: crate::VectorSize::Tri,
159                    scalar: crate::Scalar::F32,
160                },
161            },
162            Span::UNDEFINED,
163        );
164
165        let handle = self.types.insert(
166            crate::Type {
167                name: Some("RayIntersection".to_string()),
168                inner: crate::TypeInner::Struct {
169                    members: vec![
170                        crate::StructMember {
171                            name: Some("kind".to_string()),
172                            ty: ty_flag,
173                            binding: None,
174                            offset: 0,
175                        },
176                        crate::StructMember {
177                            name: Some("t".to_string()),
178                            ty: ty_scalar,
179                            binding: None,
180                            offset: 4,
181                        },
182                        crate::StructMember {
183                            name: Some("instance_custom_index".to_string()),
184                            ty: ty_flag,
185                            binding: None,
186                            offset: 8,
187                        },
188                        crate::StructMember {
189                            name: Some("instance_id".to_string()),
190                            ty: ty_flag,
191                            binding: None,
192                            offset: 12,
193                        },
194                        crate::StructMember {
195                            name: Some("sbt_record_offset".to_string()),
196                            ty: ty_flag,
197                            binding: None,
198                            offset: 16,
199                        },
200                        crate::StructMember {
201                            name: Some("geometry_index".to_string()),
202                            ty: ty_flag,
203                            binding: None,
204                            offset: 20,
205                        },
206                        crate::StructMember {
207                            name: Some("primitive_index".to_string()),
208                            ty: ty_flag,
209                            binding: None,
210                            offset: 24,
211                        },
212                        crate::StructMember {
213                            name: Some("barycentrics".to_string()),
214                            ty: ty_barycentrics,
215                            binding: None,
216                            offset: 28,
217                        },
218                        crate::StructMember {
219                            name: Some("front_face".to_string()),
220                            ty: ty_bool,
221                            binding: None,
222                            offset: 36,
223                        },
224                        crate::StructMember {
225                            name: Some("object_to_world".to_string()),
226                            ty: ty_transform,
227                            binding: None,
228                            offset: 48,
229                        },
230                        crate::StructMember {
231                            name: Some("world_to_object".to_string()),
232                            ty: ty_transform,
233                            binding: None,
234                            offset: 112,
235                        },
236                    ],
237                    span: 176,
238                },
239            },
240            Span::UNDEFINED,
241        );
242
243        self.special_types.ray_intersection = Some(handle);
244        handle
245    }
246
247    /// Populate this module's [`SpecialTypes::predeclared_types`] type and return the handle.
248    ///
249    /// [`SpecialTypes::predeclared_types`]: crate::SpecialTypes::predeclared_types
250    pub fn generate_predeclared_type(
251        &mut self,
252        special_type: crate::PredeclaredType,
253    ) -> Handle<crate::Type> {
254        use std::fmt::Write;
255
256        if let Some(value) = self.special_types.predeclared_types.get(&special_type) {
257            return *value;
258        }
259
260        let ty = match special_type {
261            crate::PredeclaredType::AtomicCompareExchangeWeakResult(scalar) => {
262                let bool_ty = self.types.insert(
263                    crate::Type {
264                        name: None,
265                        inner: crate::TypeInner::Scalar(crate::Scalar::BOOL),
266                    },
267                    Span::UNDEFINED,
268                );
269                let scalar_ty = self.types.insert(
270                    crate::Type {
271                        name: None,
272                        inner: crate::TypeInner::Scalar(scalar),
273                    },
274                    Span::UNDEFINED,
275                );
276
277                crate::Type {
278                    name: Some(format!(
279                        "__atomic_compare_exchange_result<{:?},{}>",
280                        scalar.kind, scalar.width,
281                    )),
282                    inner: crate::TypeInner::Struct {
283                        members: vec![
284                            crate::StructMember {
285                                name: Some("old_value".to_string()),
286                                ty: scalar_ty,
287                                binding: None,
288                                offset: 0,
289                            },
290                            crate::StructMember {
291                                name: Some("exchanged".to_string()),
292                                ty: bool_ty,
293                                binding: None,
294                                offset: scalar.width as u32,
295                            },
296                        ],
297                        span: scalar.width as u32 * 2,
298                    },
299                }
300            }
301            crate::PredeclaredType::ModfResult { size, width } => {
302                let float_ty = self.types.insert(
303                    crate::Type {
304                        name: None,
305                        inner: crate::TypeInner::Scalar(crate::Scalar::float(width)),
306                    },
307                    Span::UNDEFINED,
308                );
309
310                let (member_ty, second_offset) = if let Some(size) = size {
311                    let vec_ty = self.types.insert(
312                        crate::Type {
313                            name: None,
314                            inner: crate::TypeInner::Vector {
315                                size,
316                                scalar: crate::Scalar::float(width),
317                            },
318                        },
319                        Span::UNDEFINED,
320                    );
321                    (vec_ty, size as u32 * width as u32)
322                } else {
323                    (float_ty, width as u32)
324                };
325
326                let mut type_name = "__modf_result_".to_string();
327                if let Some(size) = size {
328                    let _ = write!(type_name, "vec{}_", size as u8);
329                }
330                let _ = write!(type_name, "f{}", width * 8);
331
332                crate::Type {
333                    name: Some(type_name),
334                    inner: crate::TypeInner::Struct {
335                        members: vec![
336                            crate::StructMember {
337                                name: Some("fract".to_string()),
338                                ty: member_ty,
339                                binding: None,
340                                offset: 0,
341                            },
342                            crate::StructMember {
343                                name: Some("whole".to_string()),
344                                ty: member_ty,
345                                binding: None,
346                                offset: second_offset,
347                            },
348                        ],
349                        span: second_offset * 2,
350                    },
351                }
352            }
353            crate::PredeclaredType::FrexpResult { size, width } => {
354                let float_ty = self.types.insert(
355                    crate::Type {
356                        name: None,
357                        inner: crate::TypeInner::Scalar(crate::Scalar::float(width)),
358                    },
359                    Span::UNDEFINED,
360                );
361
362                let int_ty = self.types.insert(
363                    crate::Type {
364                        name: None,
365                        inner: crate::TypeInner::Scalar(crate::Scalar {
366                            kind: crate::ScalarKind::Sint,
367                            width,
368                        }),
369                    },
370                    Span::UNDEFINED,
371                );
372
373                let (fract_member_ty, exp_member_ty, second_offset) = if let Some(size) = size {
374                    let vec_float_ty = self.types.insert(
375                        crate::Type {
376                            name: None,
377                            inner: crate::TypeInner::Vector {
378                                size,
379                                scalar: crate::Scalar::float(width),
380                            },
381                        },
382                        Span::UNDEFINED,
383                    );
384                    let vec_int_ty = self.types.insert(
385                        crate::Type {
386                            name: None,
387                            inner: crate::TypeInner::Vector {
388                                size,
389                                scalar: crate::Scalar {
390                                    kind: crate::ScalarKind::Sint,
391                                    width,
392                                },
393                            },
394                        },
395                        Span::UNDEFINED,
396                    );
397                    (vec_float_ty, vec_int_ty, size as u32 * width as u32)
398                } else {
399                    (float_ty, int_ty, width as u32)
400                };
401
402                let mut type_name = "__frexp_result_".to_string();
403                if let Some(size) = size {
404                    let _ = write!(type_name, "vec{}_", size as u8);
405                }
406                let _ = write!(type_name, "f{}", width * 8);
407
408                crate::Type {
409                    name: Some(type_name),
410                    inner: crate::TypeInner::Struct {
411                        members: vec![
412                            crate::StructMember {
413                                name: Some("fract".to_string()),
414                                ty: fract_member_ty,
415                                binding: None,
416                                offset: 0,
417                            },
418                            crate::StructMember {
419                                name: Some("exp".to_string()),
420                                ty: exp_member_ty,
421                                binding: None,
422                                offset: second_offset,
423                            },
424                        ],
425                        span: second_offset * 2,
426                    },
427                }
428            }
429        };
430
431        let handle = self.types.insert(ty, Span::UNDEFINED);
432        self.special_types
433            .predeclared_types
434            .insert(special_type, handle);
435        handle
436    }
437}