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}