1 use super::Error;
2 use crate::arena::{Arena, Handle};
3 
make_scalar_inner(kind: crate::ScalarKind, width: crate::Bytes) -> crate::ConstantInner4 fn make_scalar_inner(kind: crate::ScalarKind, width: crate::Bytes) -> crate::ConstantInner {
5     crate::ConstantInner::Scalar {
6         width,
7         value: match kind {
8             crate::ScalarKind::Uint => crate::ScalarValue::Uint(0),
9             crate::ScalarKind::Sint => crate::ScalarValue::Sint(0),
10             crate::ScalarKind::Float => crate::ScalarValue::Float(0.0),
11             crate::ScalarKind::Bool => crate::ScalarValue::Bool(false),
12         },
13     }
14 }
15 
generate_null_constant( ty: Handle<crate::Type>, type_arena: &mut Arena<crate::Type>, constant_arena: &mut Arena<crate::Constant>, ) -> Result<crate::ConstantInner, Error>16 pub fn generate_null_constant(
17     ty: Handle<crate::Type>,
18     type_arena: &mut Arena<crate::Type>,
19     constant_arena: &mut Arena<crate::Constant>,
20 ) -> Result<crate::ConstantInner, Error> {
21     let inner = match type_arena[ty].inner {
22         crate::TypeInner::Scalar { kind, width } => make_scalar_inner(kind, width),
23         crate::TypeInner::Vector { size, kind, width } => {
24             let mut components = Vec::with_capacity(size as usize);
25             for _ in 0..size as usize {
26                 components.push(constant_arena.fetch_or_append(crate::Constant {
27                     name: None,
28                     specialization: None,
29                     inner: make_scalar_inner(kind, width),
30                 }));
31             }
32             crate::ConstantInner::Composite { ty, components }
33         }
34         crate::TypeInner::Matrix {
35             columns,
36             rows,
37             width,
38         } => {
39             let vector_ty = type_arena.fetch_or_append(crate::Type {
40                 name: None,
41                 inner: crate::TypeInner::Vector {
42                     kind: crate::ScalarKind::Float,
43                     size: rows,
44                     width,
45                 },
46             });
47             let vector_inner = generate_null_constant(vector_ty, type_arena, constant_arena)?;
48             let vector_handle = constant_arena.fetch_or_append(crate::Constant {
49                 name: None,
50                 specialization: None,
51                 inner: vector_inner,
52             });
53             crate::ConstantInner::Composite {
54                 ty,
55                 components: vec![vector_handle; columns as usize],
56             }
57         }
58         crate::TypeInner::Struct { ref members, .. } => {
59             let mut components = Vec::with_capacity(members.len());
60             // copy out the types to avoid borrowing `members`
61             let member_tys = members.iter().map(|member| member.ty).collect::<Vec<_>>();
62             for member_ty in member_tys {
63                 let inner = generate_null_constant(member_ty, type_arena, constant_arena)?;
64                 components.push(constant_arena.fetch_or_append(crate::Constant {
65                     name: None,
66                     specialization: None,
67                     inner,
68                 }));
69             }
70             crate::ConstantInner::Composite { ty, components }
71         }
72         crate::TypeInner::Array {
73             base,
74             size: crate::ArraySize::Constant(handle),
75             ..
76         } => {
77             let size = constant_arena[handle]
78                 .to_array_length()
79                 .ok_or(Error::InvalidArraySize(handle))?;
80             let inner = generate_null_constant(base, type_arena, constant_arena)?;
81             let value = constant_arena.fetch_or_append(crate::Constant {
82                 name: None,
83                 specialization: None,
84                 inner,
85             });
86             crate::ConstantInner::Composite {
87                 ty,
88                 components: vec![value; size as usize],
89             }
90         }
91         ref other => {
92             log::warn!("null constant type {:?}", other);
93             return Err(Error::UnsupportedType(ty));
94         }
95     };
96     Ok(inner)
97 }
98 
99 /// Create a default value for an output built-in.
generate_default_built_in( built_in: Option<crate::BuiltIn>, ty: Handle<crate::Type>, type_arena: &mut Arena<crate::Type>, constant_arena: &mut Arena<crate::Constant>, ) -> Result<Handle<crate::Constant>, Error>100 pub fn generate_default_built_in(
101     built_in: Option<crate::BuiltIn>,
102     ty: Handle<crate::Type>,
103     type_arena: &mut Arena<crate::Type>,
104     constant_arena: &mut Arena<crate::Constant>,
105 ) -> Result<Handle<crate::Constant>, Error> {
106     let inner = match built_in {
107         Some(crate::BuiltIn::Position) => {
108             let zero = constant_arena.fetch_or_append(crate::Constant {
109                 name: None,
110                 specialization: None,
111                 inner: crate::ConstantInner::Scalar {
112                     value: crate::ScalarValue::Float(0.0),
113                     width: 4,
114                 },
115             });
116             let one = constant_arena.fetch_or_append(crate::Constant {
117                 name: None,
118                 specialization: None,
119                 inner: crate::ConstantInner::Scalar {
120                     value: crate::ScalarValue::Float(1.0),
121                     width: 4,
122                 },
123             });
124             crate::ConstantInner::Composite {
125                 ty,
126                 components: vec![zero, zero, zero, one],
127             }
128         }
129         Some(crate::BuiltIn::PointSize) => crate::ConstantInner::Scalar {
130             value: crate::ScalarValue::Float(1.0),
131             width: 4,
132         },
133         Some(crate::BuiltIn::FragDepth) => crate::ConstantInner::Scalar {
134             value: crate::ScalarValue::Float(0.0),
135             width: 4,
136         },
137         Some(crate::BuiltIn::SampleMask) => crate::ConstantInner::Scalar {
138             value: crate::ScalarValue::Uint(!0),
139             width: 4,
140         },
141         //Note: `crate::BuiltIn::ClipDistance` is intentionally left for the default path
142         _ => generate_null_constant(ty, type_arena, constant_arena)?,
143     };
144     Ok(constant_arena.fetch_or_append(crate::Constant {
145         name: None,
146         specialization: None,
147         inner,
148     }))
149 }
150