Skip to main content

wgsl_types/builtin/
mod.rs

1//! Implementation and type-checking of built-in functions, constructors and operators.
2//!
3//! ### Warning
4//!
5//! Some functions are still TODO and are documented as such.
6//!
7//! ### Functions
8//!
9//! See [`call_builtin_fn`]/[`type_builtin_fn`] Individual functions in module [`call`].
10//!
11//! ### Constructors
12//!
13//! See [`call_ctor`]/[`type_ctor`]. Individual functions in module [`ctor`].
14//!
15//! ### Operators
16//!
17//! See [`call_unary_op`]/[`type_unary_op`] and [`call_binary_op`]/[`type_binary_op`].
18//! Individual operators are implemented on the [`Instance`] and [`Type`] types directly
19//! with the `op_*` functions.
20
21pub mod call;
22pub mod ctor;
23
24mod call_ty;
25mod ops;
26mod ops_ty;
27
28pub use call_ty::type_builtin_fn;
29pub use ctor::{is_ctor, struct_ctor, type_ctor, typecheck_struct_ctor};
30pub use ops_ty::{type_binary_op, type_unary_op};
31
32pub(crate) use call_ty::*;
33pub(crate) use ops::Compwise;
34
35use itertools::Itertools;
36
37#[cfg(feature = "naga-ext")]
38use crate::tplt::AccelerationStructureTags;
39use crate::{
40    CallSignature, Error, Instance, ShaderStage,
41    syntax::{BinaryOperator, UnaryOperator},
42    tplt::{
43        ArrayTemplate, AtomicTemplate, BitcastTemplate, MatTemplate, PtrTemplate, TextureTemplate,
44        TpltParam, VecTemplate,
45    },
46    ty::{SamplerType, TextureType, Ty, Type},
47};
48
49type E = Error;
50
51/// Call a built-in function.
52///
53/// The arguments must be [loaded][Type::loaded].
54///
55/// Includes built-in constructors and zero-value constructors, *except* the struct
56/// zero-value constructor, since it requires knowledge of the struct type.
57/// See [`call_ctor`] or [`Instance::zero_value`] for that.
58///
59/// Some functions are still TODO, see [`call`] for the list of functions and statuses.
60pub fn call_builtin_fn(
61    name: &str,
62    tplt: Option<&[TpltParam]>,
63    args: &[Instance],
64    stage: ShaderStage,
65) -> Result<Option<Instance>, E> {
66    match (name, tplt, args) {
67        // constructors
68        ("array", Some(t), []) => Instance::zero_value(&ArrayTemplate::parse(t)?.ty()),
69        ("array", Some(t), a) => {
70            let tplt = ArrayTemplate::parse(t)?;
71            ctor::array_t(
72                &tplt.inner_ty(),
73                tplt.n().ok_or(E::TemplateArgs("array"))?,
74                a,
75            )
76        }
77        ("array", None, a) => ctor::array(a),
78        ("bool", None, []) => Instance::zero_value(&Type::Bool),
79        ("bool", None, [a1]) => ctor::bool(a1),
80        ("i32", None, []) => Instance::zero_value(&Type::I32),
81        ("i32", None, [a1]) => ctor::i32(a1),
82        ("u32", None, []) => Instance::zero_value(&Type::U32),
83        ("u32", None, [a1]) => ctor::u32(a1),
84        ("f32", None, []) => Instance::zero_value(&Type::F32),
85        ("f32", None, [a1]) => ctor::f32(a1, stage),
86        ("f16", None, []) => Instance::zero_value(&Type::F16),
87        ("f16", None, [a1]) => ctor::f16(a1, stage),
88        ("mat2x2", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(2, 2)),
89        ("mat2x2", Some(t), a) => ctor::mat_t(2, 2, MatTemplate::parse(t)?.inner_ty(), a, stage),
90        ("mat2x2", None, a) => ctor::mat(2, 2, a),
91        ("mat2x3", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(2, 3)),
92        ("mat2x3", Some(t), a) => ctor::mat_t(2, 3, MatTemplate::parse(t)?.inner_ty(), a, stage),
93        ("mat2x3", None, a) => ctor::mat(2, 3, a),
94        ("mat2x4", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(2, 4)),
95        ("mat2x4", Some(t), a) => ctor::mat_t(2, 4, MatTemplate::parse(t)?.inner_ty(), a, stage),
96        ("mat2x4", None, a) => ctor::mat(2, 4, a),
97        ("mat3x2", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(3, 2)),
98        ("mat3x2", Some(t), a) => ctor::mat_t(3, 2, MatTemplate::parse(t)?.inner_ty(), a, stage),
99        ("mat3x2", None, a) => ctor::mat(3, 2, a),
100        ("mat3x3", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(3, 3)),
101        ("mat3x3", Some(t), a) => ctor::mat_t(3, 3, MatTemplate::parse(t)?.inner_ty(), a, stage),
102        ("mat3x3", None, a) => ctor::mat(3, 3, a),
103        ("mat3x4", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(3, 4)),
104        ("mat3x4", Some(t), a) => ctor::mat_t(3, 4, MatTemplate::parse(t)?.inner_ty(), a, stage),
105        ("mat3x4", None, a) => ctor::mat(3, 4, a),
106        ("mat4x2", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(4, 2)),
107        ("mat4x2", Some(t), a) => ctor::mat_t(4, 2, MatTemplate::parse(t)?.inner_ty(), a, stage),
108        ("mat4x2", None, a) => ctor::mat(4, 2, a),
109        ("mat4x3", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(4, 3)),
110        ("mat4x3", Some(t), a) => ctor::mat_t(4, 3, MatTemplate::parse(t)?.inner_ty(), a, stage),
111        ("mat4x3", None, a) => ctor::mat(4, 3, a),
112        ("mat4x4", Some(t), []) => Instance::zero_value(&MatTemplate::parse(t)?.ty(4, 4)),
113        ("mat4x4", Some(t), a) => ctor::mat_t(4, 4, MatTemplate::parse(t)?.inner_ty(), a, stage),
114        ("mat4x4", None, a) => ctor::mat(4, 4, a),
115        ("vec2", Some(t), []) => Instance::zero_value(&VecTemplate::parse(t)?.ty(2)),
116        ("vec2", Some(t), a) => ctor::vec_t(2, VecTemplate::parse(t)?.inner_ty(), a, stage),
117        ("vec2", None, a) => ctor::vec(2, a),
118        ("vec3", Some(t), []) => Instance::zero_value(&VecTemplate::parse(t)?.ty(3)),
119        ("vec3", Some(t), a) => ctor::vec_t(3, VecTemplate::parse(t)?.inner_ty(), a, stage),
120        ("vec3", None, a) => ctor::vec(3, a),
121        ("vec4", Some(t), []) => Instance::zero_value(&VecTemplate::parse(t)?.ty(4)),
122        ("vec4", Some(t), a) => ctor::vec_t(4, VecTemplate::parse(t)?.inner_ty(), a, stage),
123        ("vec4", None, a) => ctor::vec(4, a),
124        #[cfg(feature = "naga-ext")]
125        ("i64", None, []) => Instance::zero_value(&Type::I64),
126        #[cfg(feature = "naga-ext")]
127        ("i64", None, [a1]) => ctor::i64(a1),
128        #[cfg(feature = "naga-ext")]
129        ("u64", None, []) => Instance::zero_value(&Type::U64),
130        #[cfg(feature = "naga-ext")]
131        ("u64", None, [a1]) => ctor::u64(a1),
132        #[cfg(feature = "naga-ext")]
133        ("f64", None, []) => Instance::zero_value(&Type::F64),
134        #[cfg(feature = "naga-ext")]
135        ("f64", None, [a1]) => ctor::f64(a1, stage),
136        // bitcast
137        ("bitcast", Some(t), [a1]) => call::bitcast_t(BitcastTemplate::parse(t)?.ty(), a1),
138        // logical
139        ("all", None, [a]) => call::all(a),
140        ("any", None, [a]) => call::any(a),
141        ("select", None, [a1, a2, a3]) => call::select(a1, a2, a3),
142        // array
143        ("arrayLength", None, [a]) => call::arrayLength(a),
144        // numeric
145        ("abs", None, [a]) => call::abs(a),
146        ("acos", None, [a]) => call::acos(a),
147        ("acosh", None, [a]) => call::acosh(a),
148        ("asin", None, [a]) => call::asin(a),
149        ("asinh", None, [a]) => call::asinh(a),
150        ("atan", None, [a]) => call::atan(a),
151        ("atanh", None, [a]) => call::atanh(a),
152        ("atan2", None, [a1, a2]) => call::atan2(a1, a2),
153        ("ceil", None, [a]) => call::ceil(a),
154        ("clamp", None, [a1, a2, a3]) => call::clamp(a1, a2, a3),
155        ("cos", None, [a]) => call::cos(a),
156        ("cosh", None, [a]) => call::cosh(a),
157        ("countLeadingZeros", None, [a]) => call::countLeadingZeros(a),
158        ("countOneBits", None, [a]) => call::countOneBits(a),
159        ("countTrailingZeros", None, [a]) => call::countTrailingZeros(a),
160        ("cross", None, [a1, a2]) => call::cross(a1, a2, stage),
161        ("degrees", None, [a]) => call::degrees(a),
162        ("determinant", None, [a]) => call::determinant(a),
163        ("distance", None, [a1, a2]) => call::distance(a1, a2, stage),
164        ("dot", None, [a1, a2]) => call::dot(a1, a2, stage),
165        ("dot4U8Packed", None, [a1, a2]) => call::dot4U8Packed(a1, a2),
166        ("dot4I8Packed", None, [a1, a2]) => call::dot4I8Packed(a1, a2),
167        ("exp", None, [a]) => call::exp(a),
168        ("exp2", None, [a]) => call::exp2(a),
169        ("extractBits", None, [a1, a2, a3]) => call::extractBits(a1, a2, a3),
170        ("faceForward", None, [a1, a2, a3]) => call::faceForward(a1, a2, a3),
171        ("firstLeadingBit", None, [a]) => call::firstLeadingBit(a),
172        ("firstTrailingBit", None, [a]) => call::firstTrailingBit(a),
173        ("floor", None, [a]) => call::floor(a),
174        ("fma", None, [a1, a2, a3]) => call::fma(a1, a2, a3),
175        ("fract", None, [a]) => call::fract(a, stage),
176        ("frexp", None, [a]) => call::frexp(a),
177        ("insertBits", None, [a1, a2, a3, a4]) => call::insertBits(a1, a2, a3, a4),
178        ("inverseSqrt", None, [a]) => call::inverseSqrt(a),
179        ("ldexp", None, [a1, a2]) => call::ldexp(a1, a2),
180        ("length", None, [a]) => call::length(a),
181        ("log", None, [a]) => call::log(a),
182        ("log2", None, [a]) => call::log2(a),
183        ("max", None, [a1, a2]) => call::max(a1, a2),
184        ("min", None, [a1, a2]) => call::min(a1, a2),
185        ("mix", None, [a1, a2, a3]) => call::mix(a1, a2, a3, stage),
186        ("modf", None, [a]) => call::modf(a),
187        ("normalize", None, [a]) => call::normalize(a, stage),
188        ("pow", None, [a1, a2]) => call::pow(a1, a2),
189        ("quantizeToF16", None, [a]) => call::quantizeToF16(a),
190        ("radians", None, [a]) => call::radians(a),
191        ("reflect", None, [a1, a2]) => call::reflect(a1, a2),
192        ("refract", None, [a1, a2, a3]) => call::refract(a1, a2, a3),
193        ("reverseBits", None, [a]) => call::reverseBits(a),
194        ("round", None, [a]) => call::round(a),
195        ("saturate", None, [a]) => call::saturate(a),
196        ("sign", None, [a]) => call::sign(a),
197        ("sin", None, [a]) => call::sin(a),
198        ("sinh", None, [a]) => call::sinh(a),
199        ("smoothstep", None, [a1, a2, a3]) => call::smoothstep(a1, a2, a3),
200        ("sqrt", None, [a]) => call::sqrt(a),
201        ("step", None, [a1, a2]) => call::step(a1, a2),
202        ("tan", None, [a]) => call::tan(a),
203        ("tanh", None, [a]) => call::tanh(a),
204        ("transpose", None, [a]) => call::transpose(a),
205        ("trunc", None, [a]) => call::trunc(a),
206        // atomic
207        ("atomicLoad", None, [a]) => call::atomicLoad(a),
208        ("atomicStore", None, [a1, a2]) => {
209            call::atomicStore(a1, a2)?;
210            return Ok(None);
211        }
212        ("atomicAdd", None, [a1, a2]) => call::atomicAdd(a1, a2),
213        ("atomicSub", None, [a1, a2]) => call::atomicSub(a1, a2),
214        ("atomicMax", None, [a1, a2]) => call::atomicMax(a1, a2),
215        ("atomicMin", None, [a1, a2]) => call::atomicMin(a1, a2),
216        ("atomicAnd", None, [a1, a2]) => call::atomicAnd(a1, a2),
217        ("atomicOr", None, [a1, a2]) => call::atomicOr(a1, a2),
218        ("atomicXor", None, [a1, a2]) => call::atomicXor(a1, a2),
219        ("atomicExchange", None, [a1, a2]) => call::atomicExchange(a1, a2),
220        ("atomicCompareExchangeWeak", None, [a1, a2, a3]) => {
221            call::atomicCompareExchangeWeak(a1, a2, a3)
222        }
223        // packing
224        ("pack4x8snorm", None, [a]) => call::pack4x8snorm(a),
225        ("pack4x8unorm", None, [a]) => call::pack4x8unorm(a),
226        ("pack4xI8", None, [a]) => call::pack4xI8(a),
227        ("pack4xU8", None, [a]) => call::pack4xU8(a),
228        ("pack4xI8Clamp", None, [a]) => call::pack4xI8Clamp(a),
229        ("pack4xU8Clamp", None, [a]) => call::pack4xU8Clamp(a),
230        ("pack2x16snorm", None, [a]) => call::pack2x16snorm(a),
231        ("pack2x16unorm", None, [a]) => call::pack2x16unorm(a),
232        ("pack2x16float", None, [a]) => call::pack2x16float(a),
233        ("unpack4x8snorm", None, [a]) => call::unpack4x8snorm(a),
234        ("unpack4x8unorm", None, [a]) => call::unpack4x8unorm(a),
235        ("unpack4xI8", None, [a]) => call::unpack4xI8(a),
236        ("unpack4xU8", None, [a]) => call::unpack4xU8(a),
237        ("unpack2x16snorm", None, [a]) => call::unpack2x16snorm(a),
238        ("unpack2x16unorm", None, [a]) => call::unpack2x16unorm(a),
239        ("unpack2x16float", None, [a]) => call::unpack2x16float(a),
240        // synchronization
241        // barrier primitives are no-op on the cpu
242        ("storageBarrier", None, []) => return Ok(None),
243        ("textureBarrier", None, []) => return Ok(None),
244        ("workgroupBarrier", None, []) => return Ok(None),
245        _ => Err(E::Signature(CallSignature {
246            name: name.to_string(),
247            tplt: tplt.map(|tplt| tplt.to_vec()),
248            args: args.iter().map(|a| a.ty()).collect_vec(),
249        })),
250    }
251    .map(Option::Some)
252}
253
254/// Call a constructor.
255///
256/// The arguments must be [loaded][Type::loaded].
257pub fn call_ctor(ty: &Type, args: &[Instance], stage: ShaderStage) -> Result<Instance, E> {
258    match (ty, args) {
259        (_, []) => Instance::zero_value(ty),
260        (Type::Bool, [a1]) => ctor::bool(a1),
261        (Type::I32, [a1]) => ctor::i32(a1),
262        (Type::U32, [a1]) => ctor::u32(a1),
263        (Type::F32, [a1]) => ctor::f32(a1, stage),
264        (Type::F16, [a1]) => ctor::f16(a1, stage),
265        (Type::Struct(ty), a) => struct_ctor(ty, a).map(Instance::from),
266        (Type::Array(ty, n), a) => ctor::array_t(ty, n.unwrap_or(a.len()), a),
267        (Type::Vec(n, ty), a) => ctor::vec_t(*n as usize, ty, a, stage),
268        (Type::Mat(c, r, ty), a) => ctor::mat_t(*c as usize, *r as usize, ty, a, stage),
269        (
270            Type::AbstractInt
271            | Type::AbstractFloat
272            | Type::Atomic(_)
273            | Type::Ptr(_, _, _)
274            | Type::Ref(_, _, _)
275            | Type::Texture(_)
276            | Type::Sampler(_)
277            | Type::Unknown,
278            _,
279        ) => Err(E::NotConstructible(ty.clone())),
280        #[cfg(feature = "naga-ext")]
281        (Type::I64 | Type::U64 | Type::F64, _) => Err(E::Todo(
282            "naga 64-bit literal constructors not implemented".to_string(),
283        )),
284        #[cfg(feature = "naga-ext")]
285        (Type::BindingArray(_, _), _) => Err(E::NotConstructible(ty.clone())),
286        (Type::Bool | Type::I32 | Type::U32 | Type::F32 | Type::F16, _) => {
287            Err(E::Signature(CallSignature {
288                name: ty.to_string(),
289                tplt: None,
290                args: args.iter().map(|a| a.ty()).collect_vec(),
291            }))
292        }
293        #[cfg(feature = "naga-ext")]
294        (Type::RayQuery(_) | Type::AccelerationStructure(_), _) => {
295            Err(E::NotConstructible(ty.clone()))
296        }
297    }
298}
299
300/// Call a binary operator.
301///
302/// The arguments must be [loaded][Type::loaded].
303///
304/// In practice, `&&` and `||` operators are short-circuiting. Calling these operators here
305/// does not perform short-circuiting, as `lhs` and `rhs` are already computed.
306pub fn call_binary_op(
307    op: BinaryOperator,
308    lhs: &Instance,
309    rhs: &Instance,
310    stage: ShaderStage,
311) -> Result<Instance, E> {
312    match op {
313        BinaryOperator::ShortCircuitOr => lhs.op_or(rhs),
314        BinaryOperator::ShortCircuitAnd => lhs.op_and(rhs),
315        BinaryOperator::Addition => lhs.op_add(rhs, stage),
316        BinaryOperator::Subtraction => lhs.op_sub(rhs, stage),
317        BinaryOperator::Multiplication => lhs.op_mul(rhs, stage),
318        BinaryOperator::Division => lhs.op_div(rhs, stage),
319        BinaryOperator::Remainder => lhs.op_rem(rhs, stage),
320        BinaryOperator::Equality => lhs.op_eq(rhs),
321        BinaryOperator::Inequality => lhs.op_ne(rhs),
322        BinaryOperator::LessThan => lhs.op_lt(rhs),
323        BinaryOperator::LessThanEqual => lhs.op_le(rhs),
324        BinaryOperator::GreaterThan => lhs.op_gt(rhs),
325        BinaryOperator::GreaterThanEqual => lhs.op_ge(rhs),
326        BinaryOperator::BitwiseOr => lhs.op_bitor(rhs),
327        BinaryOperator::BitwiseAnd => lhs.op_bitand(rhs),
328        BinaryOperator::BitwiseXor => lhs.op_bitxor(rhs),
329        BinaryOperator::ShiftLeft => lhs.op_shl(rhs, stage),
330        BinaryOperator::ShiftRight => lhs.op_shr(rhs, stage),
331    }
332}
333
334/// Call a unary operator.
335///
336/// The arguments must be [loaded][Type::loaded].
337pub fn call_unary_op(operator: UnaryOperator, operand: &Instance) -> Result<Instance, E> {
338    match operator {
339        UnaryOperator::LogicalNegation => operand.op_not(),
340        UnaryOperator::Negation => operand.op_neg(),
341        UnaryOperator::BitwiseComplement => operand.op_bitnot(),
342        UnaryOperator::AddressOf => operand.op_ref(),
343        UnaryOperator::Indirection => operand.op_deref(),
344    }
345}
346
347/// Constructs a builtin type.
348///
349/// Includes all builtin types such as `vec3<f32>`,
350/// but does not include their predeclared aliases (`vec3f`).
351pub fn builtin_type(name: &str, tplt: Option<&[TpltParam]>) -> Result<Type, E> {
352    if let Some(t) = tplt {
353        match name {
354            "array" => Ok(ArrayTemplate::parse(t)?.ty()),
355            #[cfg(feature = "naga-ext")]
356            "binding_array" => Ok(crate::tplt::BindingArrayTemplate::parse(t)?.ty()),
357            "vec2" => Ok(VecTemplate::parse(t)?.ty(2)),
358            "vec3" => Ok(VecTemplate::parse(t)?.ty(3)),
359            "vec4" => Ok(VecTemplate::parse(t)?.ty(4)),
360            "mat2x2" => Ok(MatTemplate::parse(t)?.ty(2, 2)),
361            "mat2x3" => Ok(MatTemplate::parse(t)?.ty(2, 3)),
362            "mat2x4" => Ok(MatTemplate::parse(t)?.ty(2, 4)),
363            "mat3x2" => Ok(MatTemplate::parse(t)?.ty(3, 2)),
364            "mat3x3" => Ok(MatTemplate::parse(t)?.ty(3, 3)),
365            "mat3x4" => Ok(MatTemplate::parse(t)?.ty(3, 4)),
366            "mat4x2" => Ok(MatTemplate::parse(t)?.ty(4, 2)),
367            "mat4x3" => Ok(MatTemplate::parse(t)?.ty(4, 3)),
368            "mat4x4" => Ok(MatTemplate::parse(t)?.ty(4, 4)),
369            "ptr" => Ok(PtrTemplate::parse(t)?.ty()),
370            "atomic" => Ok(AtomicTemplate::parse(t)?.ty()),
371            "texture_1d"
372            | "texture_2d"
373            | "texture_2d_array"
374            | "texture_3d"
375            | "texture_cube"
376            | "texture_cube_array"
377            | "texture_multisampled_2d"
378            | "texture_storage_1d"
379            | "texture_storage_2d"
380            | "texture_storage_2d_array"
381            | "texture_storage_3d" => Ok(Type::Texture(TextureTemplate::parse(name, t)?.ty())),
382
383            #[cfg(feature = "naga-ext")]
384            "texture_1d_array" | "texture_storage_1d_array" | "texture_multisampled_2d_array" => {
385                Ok(Type::Texture(TextureTemplate::parse(name, t)?.ty()))
386            }
387            #[cfg(feature = "naga-ext")]
388            "ray_query" => Ok(Type::RayQuery(None)),
389            #[cfg(feature = "naga-ext")]
390            // requires enable extensions
391            "acceleration_structure" => Ok(Type::AccelerationStructure(Some(
392                AccelerationStructureTags::parse(t)?,
393            ))),
394
395            _ => Err(E::UnexpectedTemplate(name.to_string())),
396        }
397    }
398    // builtin types without a template
399    else {
400        match name {
401            "bool" => Ok(Type::Bool),
402            "__AbstractInt" => Ok(Type::AbstractInt),
403            "__AbstractFloat" => Ok(Type::AbstractFloat),
404            "i32" => Ok(Type::I32),
405            "u32" => Ok(Type::U32),
406            "f32" => Ok(Type::F32),
407            "f16" => Ok(Type::F16),
408            "texture_depth_multisampled_2d" => Ok(Type::Texture(TextureType::DepthMultisampled2D)),
409            "texture_external" => Ok(Type::Texture(TextureType::External)),
410            "texture_depth_2d" => Ok(Type::Texture(TextureType::Depth2D)),
411            "texture_depth_2d_array" => Ok(Type::Texture(TextureType::Depth2DArray)),
412            "texture_depth_cube" => Ok(Type::Texture(TextureType::DepthCube)),
413            "texture_depth_cube_array" => Ok(Type::Texture(TextureType::DepthCubeArray)),
414            "sampler" => Ok(Type::Sampler(SamplerType::Sampler)),
415            "sampler_comparison" => Ok(Type::Sampler(SamplerType::SamplerComparison)),
416
417            #[cfg(feature = "naga-ext")]
418            "i64" => Ok(Type::I64),
419            #[cfg(feature = "naga-ext")]
420            "u64" => Ok(Type::U64),
421            #[cfg(feature = "naga-ext")]
422            "f64" => Ok(Type::F64),
423            #[cfg(feature = "naga-ext")]
424            "ray_query" => Ok(Type::RayQuery(Default::default())),
425            #[cfg(feature = "naga-ext")]
426            "acceleration_structure" => Ok(Type::AccelerationStructure(Default::default())),
427
428            // Better error messages
429            "array" => Err(E::MissingTemplate("array")),
430            "binding_array" => Err(E::MissingTemplate("binding_array")),
431            "vec2" => Err(E::MissingTemplate("vec2")),
432            "vec3" => Err(E::MissingTemplate("vec3")),
433            "vec4" => Err(E::MissingTemplate("vec4")),
434            "mat2x2" => Err(E::MissingTemplate("mat2x2")),
435            "mat2x3" => Err(E::MissingTemplate("mat2x3")),
436            "mat2x4" => Err(E::MissingTemplate("mat2x4")),
437            "mat3x2" => Err(E::MissingTemplate("mat3x2")),
438            "mat3x3" => Err(E::MissingTemplate("mat3x3")),
439            "mat3x4" => Err(E::MissingTemplate("mat3x4")),
440            "mat4x2" => Err(E::MissingTemplate("mat4x2")),
441            "mat4x3" => Err(E::MissingTemplate("mat4x3")),
442            "mat4x4" => Err(E::MissingTemplate("mat4x4")),
443            "ptr" => Err(E::MissingTemplate("ptr")),
444            "atomic" => Err(E::MissingTemplate("atomic")),
445            "texture_1d" => Err(E::MissingTemplate("texture_1d")),
446            "texture_2d" => Err(E::MissingTemplate("texture_2d")),
447            "texture_2d_array" => Err(E::MissingTemplate("texture_2d_array")),
448            "texture_3d" => Err(E::MissingTemplate("texture_3d")),
449            "texture_cube" => Err(E::MissingTemplate("texture_cube")),
450            "texture_cube_array" => Err(E::MissingTemplate("texture_cube_array")),
451            "texture_multisampled_2d" => Err(E::MissingTemplate("texture_multisampled_2d")),
452            "texture_storage_1d" => Err(E::MissingTemplate("texture_storage_1d")),
453            "texture_storage_2d" => Err(E::MissingTemplate("texture_storage_2d")),
454            "texture_storage_2d_array" => Err(E::MissingTemplate("texture_storage_2d_array")),
455            "texture_storage_3d" => Err(E::MissingTemplate("texture_storage_3d")),
456            #[cfg(feature = "naga-ext")]
457            "texture_1d_array" => Err(E::MissingTemplate("texture_1d_array")),
458            #[cfg(feature = "naga-ext")]
459            "texture_storage_1d_array" => Err(E::MissingTemplate("texture_storage_1d_array")),
460            #[cfg(feature = "naga-ext")]
461            "texture_multisampled_2d_array" => {
462                Err(E::MissingTemplate("texture_multisampled_2d_array"))
463            }
464
465            _ => Err(E::UnknownType(name.to_string())),
466        }
467    }
468}