1#![allow(dead_code)] #[cfg(feature = "dot-out")]
7pub mod dot;
8#[cfg(feature = "glsl-out")]
9pub mod glsl;
10#[cfg(feature = "hlsl-out")]
11pub mod hlsl;
12#[cfg(feature = "msl-out")]
13pub mod msl;
14#[cfg(feature = "spv-out")]
15pub mod spv;
16#[cfg(feature = "wgsl-out")]
17pub mod wgsl;
18
19#[cfg(any(
20 feature = "hlsl-out",
21 feature = "msl-out",
22 feature = "spv-out",
23 feature = "glsl-out"
24))]
25pub mod pipeline_constants;
26
27pub const COMPONENTS: &[char] = &['x', 'y', 'z', 'w'];
29pub const INDENT: &str = " ";
31pub const BAKE_PREFIX: &str = "_e";
33
34pub type NeedBakeExpressions = crate::FastHashSet<crate::Handle<crate::Expression>>;
36
37pub type PipelineConstants = std::collections::HashMap<String, f64>;
45
46#[derive(Clone, Copy)]
48pub struct Level(pub usize);
49
50impl Level {
51 const fn next(&self) -> Self {
52 Level(self.0 + 1)
53 }
54}
55
56impl std::fmt::Display for Level {
57 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
58 (0..self.0).try_for_each(|_| formatter.write_str(INDENT))
59 }
60}
61
62pub enum FunctionType {
78 Function(crate::Handle<crate::Function>),
80 EntryPoint(crate::proc::EntryPointIndex),
85}
86
87impl FunctionType {
88 pub fn is_compute_entry_point(&self, module: &crate::Module) -> bool {
90 match *self {
91 FunctionType::EntryPoint(index) => {
92 module.entry_points[index as usize].stage == crate::ShaderStage::Compute
93 }
94 FunctionType::Function(_) => false,
95 }
96 }
97}
98
99pub struct FunctionCtx<'a> {
101 pub ty: FunctionType,
103 pub info: &'a crate::valid::FunctionInfo,
105 pub expressions: &'a crate::Arena<crate::Expression>,
107 pub named_expressions: &'a crate::NamedExpressions,
109}
110
111impl FunctionCtx<'_> {
112 pub fn resolve_type<'a>(
114 &'a self,
115 handle: crate::Handle<crate::Expression>,
116 types: &'a crate::UniqueArena<crate::Type>,
117 ) -> &'a crate::TypeInner {
118 self.info[handle].ty.inner_with(types)
119 }
120
121 pub const fn name_key(
123 &self,
124 local: crate::Handle<crate::LocalVariable>,
125 ) -> crate::proc::NameKey {
126 match self.ty {
127 FunctionType::Function(handle) => crate::proc::NameKey::FunctionLocal(handle, local),
128 FunctionType::EntryPoint(idx) => crate::proc::NameKey::EntryPointLocal(idx, local),
129 }
130 }
131
132 pub const fn argument_key(&self, arg: u32) -> crate::proc::NameKey {
137 match self.ty {
138 FunctionType::Function(handle) => crate::proc::NameKey::FunctionArgument(handle, arg),
139 FunctionType::EntryPoint(ep_index) => {
140 crate::proc::NameKey::EntryPointArgument(ep_index, arg)
141 }
142 }
143 }
144
145 pub fn is_fixed_function_input(
147 &self,
148 mut expression: crate::Handle<crate::Expression>,
149 module: &crate::Module,
150 ) -> Option<crate::BuiltIn> {
151 let ep_function = match self.ty {
152 FunctionType::Function(_) => return None,
153 FunctionType::EntryPoint(ep_index) => &module.entry_points[ep_index as usize].function,
154 };
155 let mut built_in = None;
156 loop {
157 match self.expressions[expression] {
158 crate::Expression::FunctionArgument(arg_index) => {
159 return match ep_function.arguments[arg_index as usize].binding {
160 Some(crate::Binding::BuiltIn(bi)) => Some(bi),
161 _ => built_in,
162 };
163 }
164 crate::Expression::AccessIndex { base, index } => {
165 match *self.resolve_type(base, &module.types) {
166 crate::TypeInner::Struct { ref members, .. } => {
167 if let Some(crate::Binding::BuiltIn(bi)) =
168 members[index as usize].binding
169 {
170 built_in = Some(bi);
171 }
172 }
173 _ => return None,
174 }
175 expression = base;
176 }
177 _ => return None,
178 }
179 }
180 }
181}
182
183impl crate::Expression {
184 pub const fn bake_ref_count(&self) -> usize {
193 match *self {
194 crate::Expression::Access { .. } | crate::Expression::AccessIndex { .. } => usize::MAX,
196 crate::Expression::ImageSample { .. } | crate::Expression::ImageLoad { .. } => 1,
198 crate::Expression::Derivative { .. } => 1,
200 crate::Expression::Load { .. } => 1,
204 _ => 2,
206 }
207 }
208}
209
210pub const fn binary_operation_str(op: crate::BinaryOperator) -> &'static str {
212 use crate::BinaryOperator as Bo;
213 match op {
214 Bo::Add => "+",
215 Bo::Subtract => "-",
216 Bo::Multiply => "*",
217 Bo::Divide => "/",
218 Bo::Modulo => "%",
219 Bo::Equal => "==",
220 Bo::NotEqual => "!=",
221 Bo::Less => "<",
222 Bo::LessEqual => "<=",
223 Bo::Greater => ">",
224 Bo::GreaterEqual => ">=",
225 Bo::And => "&",
226 Bo::ExclusiveOr => "^",
227 Bo::InclusiveOr => "|",
228 Bo::LogicalAnd => "&&",
229 Bo::LogicalOr => "||",
230 Bo::ShiftLeft => "<<",
231 Bo::ShiftRight => ">>",
232 }
233}
234
235const fn vector_size_str(size: crate::VectorSize) -> &'static str {
237 match size {
238 crate::VectorSize::Bi => "2",
239 crate::VectorSize::Tri => "3",
240 crate::VectorSize::Quad => "4",
241 }
242}
243
244impl crate::TypeInner {
245 pub const fn is_handle(&self) -> bool {
247 match *self {
248 crate::TypeInner::Image { .. } | crate::TypeInner::Sampler { .. } => true,
249 _ => false,
250 }
251 }
252}
253
254impl crate::Statement {
255 pub const fn is_terminator(&self) -> bool {
259 match *self {
260 crate::Statement::Break
261 | crate::Statement::Continue
262 | crate::Statement::Return { .. }
263 | crate::Statement::Kill => true,
264 _ => false,
265 }
266 }
267}
268
269bitflags::bitflags! {
270 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
279 pub struct RayFlag: u32 {
280 const OPAQUE = 0x01;
281 const NO_OPAQUE = 0x02;
282 const TERMINATE_ON_FIRST_HIT = 0x04;
283 const SKIP_CLOSEST_HIT_SHADER = 0x08;
284 const CULL_BACK_FACING = 0x10;
285 const CULL_FRONT_FACING = 0x20;
286 const CULL_OPAQUE = 0x40;
287 const CULL_NO_OPAQUE = 0x80;
288 const SKIP_TRIANGLES = 0x100;
289 const SKIP_AABBS = 0x200;
290 }
291}
292
293#[repr(u32)]
295pub enum RayIntersectionType {
296 Triangle = 1,
297 BoundingBox = 4,
298}