naga/ir/
mod.rs

1/*!
2The Intermediate Representation shared by all frontends and backends.
3
4The central structure of the IR, and the crate, is [`Module`]. A `Module` contains:
5
6- [`Function`]s, which have arguments, a return type, local variables, and a body,
7
8- [`EntryPoint`]s, which are specialized functions that can serve as the entry
9  point for pipeline stages like vertex shading or fragment shading,
10
11- [`Constant`]s and [`GlobalVariable`]s used by `EntryPoint`s and `Function`s, and
12
13- [`Type`]s used by the above.
14
15The body of an `EntryPoint` or `Function` is represented using two types:
16
17- An [`Expression`] produces a value, but has no side effects or control flow.
18  `Expressions` include variable references, unary and binary operators, and so
19  on.
20
21- A [`Statement`] can have side effects and structured control flow.
22  `Statement`s do not produce a value, other than by storing one in some
23  designated place. `Statements` include blocks, conditionals, and loops, but also
24  operations that have side effects, like stores and function calls.
25
26`Statement`s form a tree, with pointers into the DAG of `Expression`s.
27
28Restricting side effects to statements simplifies analysis and code generation.
29A Naga backend can generate code to evaluate an `Expression` however and
30whenever it pleases, as long as it is certain to observe the side effects of all
31previously executed `Statement`s.
32
33Many `Statement` variants use the [`Block`] type, which is `Vec<Statement>`,
34with optional span info, representing a series of statements executed in order. The body of an
35`EntryPoint`s or `Function` is a `Block`, and `Statement` has a
36[`Block`][Statement::Block] variant.
37
38## Function Calls
39
40Naga's representation of function calls is unusual. Most languages treat
41function calls as expressions, but because calls may have side effects, Naga
42represents them as a kind of statement, [`Statement::Call`]. If the function
43returns a value, a call statement designates a particular [`Expression::CallResult`]
44expression to represent its return value, for use by subsequent statements and
45expressions.
46
47## `Expression` evaluation time
48
49It is essential to know when an [`Expression`] should be evaluated, because its
50value may depend on previous [`Statement`]s' effects. But whereas the order of
51execution for a tree of `Statement`s is apparent from its structure, it is not
52so clear for `Expressions`, since an expression may be referred to by any number
53of `Statement`s and other `Expression`s.
54
55Naga's rules for when `Expression`s are evaluated are as follows:
56
57-   [`Literal`], [`Constant`], and [`ZeroValue`] expressions are
58    considered to be implicitly evaluated before execution begins.
59
60-   [`FunctionArgument`] and [`LocalVariable`] expressions are considered
61    implicitly evaluated upon entry to the function to which they belong.
62    Function arguments cannot be assigned to, and `LocalVariable` expressions
63    produce a *pointer to* the variable's value (for use with [`Load`] and
64    [`Store`]). Neither varies while the function executes, so it suffices to
65    consider these expressions evaluated once on entry.
66
67-   Similarly, [`GlobalVariable`] expressions are considered implicitly
68    evaluated before execution begins, since their value does not change while
69    code executes, for one of two reasons:
70
71    -   Most `GlobalVariable` expressions produce a pointer to the variable's
72        value, for use with [`Load`] and [`Store`], as `LocalVariable`
73        expressions do. Although the variable's value may change, its address
74        does not.
75
76    -   A `GlobalVariable` expression referring to a global in the
77        [`AddressSpace::Handle`] address space produces the value directly, not
78        a pointer. Such global variables hold opaque types like shaders or
79        images, and cannot be assigned to.
80
81-   A [`CallResult`] expression that is the `result` of a [`Statement::Call`],
82    representing the call's return value, is evaluated when the `Call` statement
83    is executed.
84
85-   Similarly, an [`AtomicResult`] expression that is the `result` of an
86    [`Atomic`] statement, representing the result of the atomic operation, is
87    evaluated when the `Atomic` statement is executed.
88
89-   A [`RayQueryProceedResult`] expression, which is a boolean
90    indicating if the ray query is finished, is evaluated when the
91    [`RayQuery`] statement whose [`Proceed::result`] points to it is
92    executed.
93
94-   All other expressions are evaluated when the (unique) [`Statement::Emit`]
95    statement that covers them is executed.
96
97Now, strictly speaking, not all `Expression` variants actually care when they're
98evaluated. For example, you can evaluate a [`BinaryOperator::Add`] expression
99any time you like, as long as you give it the right operands. It's really only a
100very small set of expressions that are affected by timing:
101
102-   [`Load`], [`ImageSample`], and [`ImageLoad`] expressions are influenced by
103    stores to the variables or images they access, and must execute at the
104    proper time relative to them.
105
106-   [`Derivative`] expressions are sensitive to control flow uniformity: they
107    must not be moved out of an area of uniform control flow into a non-uniform
108    area.
109
110-   More generally, any expression that's used by more than one other expression
111    or statement should probably be evaluated only once, and then stored in a
112    variable to be cited at each point of use.
113
114Naga tries to help back ends handle all these cases correctly in a somewhat
115circuitous way. The [`ModuleInfo`] structure returned by [`Validator::validate`]
116provides a reference count for each expression in each function in the module.
117Naturally, any expression with a reference count of two or more deserves to be
118evaluated and stored in a temporary variable at the point that the `Emit`
119statement covering it is executed. But if we selectively lower the reference
120count threshold to _one_ for the sensitive expression types listed above, so
121that we _always_ generate a temporary variable and save their value, then the
122same code that manages multiply referenced expressions will take care of
123introducing temporaries for time-sensitive expressions as well. The
124`Expression::bake_ref_count` method (private to the back ends) is meant to help
125with this.
126
127## `Expression` scope
128
129Each `Expression` has a *scope*, which is the region of the function within
130which it can be used by `Statement`s and other `Expression`s. It is a validation
131error to use an `Expression` outside its scope.
132
133An expression's scope is defined as follows:
134
135-   The scope of a [`Constant`], [`GlobalVariable`], [`FunctionArgument`] or
136    [`LocalVariable`] expression covers the entire `Function` in which it
137    occurs.
138
139-   The scope of an expression evaluated by an [`Emit`] statement covers the
140    subsequent expressions in that `Emit`, the subsequent statements in the `Block`
141    to which that `Emit` belongs (if any) and their sub-statements (if any).
142
143-   The `result` expression of a [`Call`] or [`Atomic`] statement has a scope
144    covering the subsequent statements in the `Block` in which the statement
145    occurs (if any) and their sub-statements (if any).
146
147For example, this implies that an expression evaluated by some statement in a
148nested `Block` is not available in the `Block`'s parents. Such a value would
149need to be stored in a local variable to be carried upwards in the statement
150tree.
151
152## Constant expressions
153
154A Naga *constant expression* is one of the following [`Expression`]
155variants, whose operands (if any) are also constant expressions:
156- [`Literal`]
157- [`Constant`], for [`Constant`]s
158- [`ZeroValue`], for fixed-size types
159- [`Compose`]
160- [`Access`]
161- [`AccessIndex`]
162- [`Splat`]
163- [`Swizzle`]
164- [`Unary`]
165- [`Binary`]
166- [`Select`]
167- [`Relational`]
168- [`Math`]
169- [`As`]
170
171A constant expression can be evaluated at module translation time.
172
173## Override expressions
174
175A Naga *override expression* is the same as a [constant expression],
176except that it is also allowed to reference other [`Override`]s.
177
178An override expression can be evaluated at pipeline creation time.
179
180[`AtomicResult`]: Expression::AtomicResult
181[`RayQueryProceedResult`]: Expression::RayQueryProceedResult
182[`CallResult`]: Expression::CallResult
183[`Constant`]: Expression::Constant
184[`ZeroValue`]: Expression::ZeroValue
185[`Literal`]: Expression::Literal
186[`Derivative`]: Expression::Derivative
187[`FunctionArgument`]: Expression::FunctionArgument
188[`GlobalVariable`]: Expression::GlobalVariable
189[`ImageLoad`]: Expression::ImageLoad
190[`ImageSample`]: Expression::ImageSample
191[`Load`]: Expression::Load
192[`LocalVariable`]: Expression::LocalVariable
193
194[`Atomic`]: Statement::Atomic
195[`Call`]: Statement::Call
196[`Emit`]: Statement::Emit
197[`Store`]: Statement::Store
198[`RayQuery`]: Statement::RayQuery
199
200[`Proceed::result`]: RayQueryFunction::Proceed::result
201
202[`Validator::validate`]: crate::valid::Validator::validate
203[`ModuleInfo`]: crate::valid::ModuleInfo
204
205[`Literal`]: Expression::Literal
206[`ZeroValue`]: Expression::ZeroValue
207[`Compose`]: Expression::Compose
208[`Access`]: Expression::Access
209[`AccessIndex`]: Expression::AccessIndex
210[`Splat`]: Expression::Splat
211[`Swizzle`]: Expression::Swizzle
212[`Unary`]: Expression::Unary
213[`Binary`]: Expression::Binary
214[`Select`]: Expression::Select
215[`Relational`]: Expression::Relational
216[`Math`]: Expression::Math
217[`As`]: Expression::As
218
219[constant expression]: #constant-expressions
220*/
221
222mod block;
223
224use alloc::{boxed::Box, string::String, vec::Vec};
225
226#[cfg(feature = "arbitrary")]
227use arbitrary::Arbitrary;
228use half::f16;
229#[cfg(feature = "deserialize")]
230use serde::Deserialize;
231#[cfg(feature = "serialize")]
232use serde::Serialize;
233
234use crate::arena::{Arena, Handle, Range, UniqueArena};
235use crate::diagnostic_filter::DiagnosticFilterNode;
236use crate::{FastIndexMap, NamedExpressions};
237
238pub use block::Block;
239
240/// Explicitly allows early depth/stencil tests.
241///
242/// Normally, depth/stencil tests are performed after fragment shading. However, as an optimization,
243/// most drivers will move the depth/stencil tests before fragment shading if this does not
244/// have any observable consequences. This optimization is disabled under the following
245/// circumstances:
246///   - `discard` is called in the fragment shader.
247///   - The fragment shader writes to the depth buffer.
248///   - The fragment shader writes to any storage bindings.
249///
250/// When `EarlyDepthTest` is set, it is allowed to perform an early depth/stencil test even if the
251/// above conditions are not met. When [`EarlyDepthTest::Force`] is used, depth/stencil tests
252/// **must** be performed before fragment shading.
253///
254/// To force early depth/stencil tests in a shader:
255///   - GLSL: `layout(early_fragment_tests) in;`
256///   - HLSL: `Attribute earlydepthstencil`
257///   - SPIR-V: `ExecutionMode EarlyFragmentTests`
258///   - WGSL: `@early_depth_test(force)`
259///
260/// This may also be enabled in a shader by specifying a [`ConservativeDepth`].
261///
262/// For more, see:
263///   - <https://www.khronos.org/opengl/wiki/Early_Fragment_Test#Explicit_specification>
264///   - <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-attributes-earlydepthstencil>
265///   - <https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Execution_Mode>
266#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
267#[cfg_attr(feature = "serialize", derive(Serialize))]
268#[cfg_attr(feature = "deserialize", derive(Deserialize))]
269#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
270pub enum EarlyDepthTest {
271    /// Requires depth/stencil tests to be performed before fragment shading.
272    ///
273    /// This will disable depth/stencil tests after fragment shading, so discarding the fragment
274    /// or overwriting the fragment depth will have no effect.
275    Force,
276
277    /// Allows an additional depth/stencil test to be performed before fragment shading.
278    ///
279    /// It is up to the driver to decide whether early tests are performed. Unlike `Force`, this
280    /// does not disable depth/stencil tests after fragment shading.
281    Allow {
282        /// Specifies restrictions on how the depth value can be modified within the fragment
283        /// shader.
284        ///
285        /// This may be taken into account when deciding whether to perform early tests.
286        conservative: ConservativeDepth,
287    },
288}
289
290/// Enables adjusting depth without disabling early Z.
291///
292/// To use in a shader:
293///   - GLSL: `layout (depth_<greater/less/unchanged/any>) out float gl_FragDepth;`
294///     - `depth_any` option behaves as if the layout qualifier was not present.
295///   - HLSL: `SV_DepthGreaterEqual`/`SV_DepthLessEqual`/`SV_Depth`
296///   - SPIR-V: `ExecutionMode Depth<Greater/Less/Unchanged>`
297///   - WGSL: `@early_depth_test(greater_equal/less_equal/unchanged)`
298///
299/// For more, see:
300///   - <https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_conservative_depth.txt>
301///   - <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics#system-value-semantics>
302///   - <https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Execution_Mode>
303#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
304#[cfg_attr(feature = "serialize", derive(Serialize))]
305#[cfg_attr(feature = "deserialize", derive(Deserialize))]
306#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
307pub enum ConservativeDepth {
308    /// Shader may rewrite depth only with a value greater than calculated.
309    GreaterEqual,
310
311    /// Shader may rewrite depth smaller than one that would have been written without the modification.
312    LessEqual,
313
314    /// Shader may not rewrite depth value.
315    Unchanged,
316}
317
318/// Stage of the programmable pipeline.
319#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
320#[cfg_attr(feature = "serialize", derive(Serialize))]
321#[cfg_attr(feature = "deserialize", derive(Deserialize))]
322#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
323pub enum ShaderStage {
324    /// A vertex shader, in a render pipeline.
325    Vertex,
326
327    /// A task shader, in a mesh render pipeline.
328    Task,
329
330    /// A mesh shader, in a mesh render pipeline.
331    Mesh,
332
333    /// A fragment shader, in a render pipeline.
334    Fragment,
335
336    /// Compute pipeline shader.
337    Compute,
338}
339
340/// Addressing space of variables.
341#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
342#[cfg_attr(feature = "serialize", derive(Serialize))]
343#[cfg_attr(feature = "deserialize", derive(Deserialize))]
344#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
345pub enum AddressSpace {
346    /// Function locals.
347    Function,
348    /// Private data, per invocation, mutable.
349    Private,
350    /// Workgroup shared data, mutable.
351    WorkGroup,
352    /// Uniform buffer data.
353    Uniform,
354    /// Storage buffer data, potentially mutable.
355    Storage { access: StorageAccess },
356    /// Opaque handles, such as samplers and images.
357    Handle,
358
359    /// Push constants.
360    ///
361    /// A [`Module`] may contain at most one [`GlobalVariable`] in
362    /// this address space. Its contents are provided not by a buffer
363    /// but by `SetPushConstant` pass commands, allowing the CPU to
364    /// establish different values for each draw/dispatch.
365    ///
366    /// `PushConstant` variables may not contain `f16` values, even if
367    /// the [`SHADER_FLOAT16`] capability is enabled.
368    ///
369    /// Backends generally place tight limits on the size of
370    /// `PushConstant` variables.
371    ///
372    /// [`SHADER_FLOAT16`]: crate::valid::Capabilities::SHADER_FLOAT16
373    PushConstant,
374    /// Task shader to mesh shader payload
375    TaskPayload,
376}
377
378/// Built-in inputs and outputs.
379#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
380#[cfg_attr(feature = "serialize", derive(Serialize))]
381#[cfg_attr(feature = "deserialize", derive(Deserialize))]
382#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
383pub enum BuiltIn {
384    /// Written in vertex/mesh shaders, read in fragment shaders
385    Position { invariant: bool },
386    /// Read in task, mesh, vertex, and fragment shaders
387    ViewIndex,
388
389    /// Read in vertex shaders
390    BaseInstance,
391    /// Read in vertex shaders
392    BaseVertex,
393    /// Written in vertex & mesh shaders
394    ClipDistance,
395    /// Written in vertex & mesh shaders
396    CullDistance,
397    /// Read in vertex shaders
398    InstanceIndex,
399    /// Written in vertex & mesh shaders
400    PointSize,
401    /// Read in vertex shaders
402    VertexIndex,
403    /// Read in vertex & task shaders, or mesh shaders in pipelines without task shaders
404    DrawID,
405
406    /// Written in fragment shaders
407    FragDepth,
408    /// Read in fragment shaders
409    PointCoord,
410    /// Read in fragment shaders
411    FrontFacing,
412    /// Read in fragment shaders, written in mesh shaders
413    PrimitiveIndex,
414    /// Read in fragment shaders
415    Barycentric,
416    /// Read in fragment shaders
417    SampleIndex,
418    /// Read or written in fragment shaders
419    SampleMask,
420
421    /// Read in compute, task, and mesh shaders
422    GlobalInvocationId,
423    /// Read in compute, task, and mesh shaders
424    LocalInvocationId,
425    /// Read in compute, task, and mesh shaders
426    LocalInvocationIndex,
427    /// Read in compute, task, and mesh shaders
428    WorkGroupId,
429    /// Read in compute, task, and mesh shaders
430    WorkGroupSize,
431    /// Read in compute, task, and mesh shaders
432    NumWorkGroups,
433
434    /// Read in compute, task, and mesh shaders
435    NumSubgroups,
436    /// Read in compute, task, and mesh shaders
437    SubgroupId,
438    /// Read in compute, fragment, task, and mesh shaders
439    SubgroupSize,
440    /// Read in compute, fragment, task, and mesh shaders
441    SubgroupInvocationId,
442
443    /// Written in task shaders
444    MeshTaskSize,
445    /// Written in mesh shaders
446    CullPrimitive,
447    /// Written in mesh shaders
448    PointIndex,
449    /// Written in mesh shaders
450    LineIndices,
451    /// Written in mesh shaders
452    TriangleIndices,
453
454    /// Written to a workgroup variable in mesh shaders
455    VertexCount,
456    /// Written to a workgroup variable in mesh shaders
457    Vertices,
458    /// Written to a workgroup variable in mesh shaders
459    PrimitiveCount,
460    /// Written to a workgroup variable in mesh shaders
461    Primitives,
462}
463
464/// Number of bytes per scalar.
465pub type Bytes = u8;
466
467/// Number of components in a vector.
468#[repr(u8)]
469#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
470#[cfg_attr(feature = "serialize", derive(Serialize))]
471#[cfg_attr(feature = "deserialize", derive(Deserialize))]
472#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
473pub enum VectorSize {
474    /// 2D vector
475    Bi = 2,
476    /// 3D vector
477    Tri = 3,
478    /// 4D vector
479    Quad = 4,
480}
481
482impl VectorSize {
483    pub const MAX: usize = Self::Quad as usize;
484}
485
486impl From<VectorSize> for u8 {
487    fn from(size: VectorSize) -> u8 {
488        size as u8
489    }
490}
491
492impl From<VectorSize> for u32 {
493    fn from(size: VectorSize) -> u32 {
494        size as u32
495    }
496}
497
498/// Primitive type for a scalar.
499#[repr(u8)]
500#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
501#[cfg_attr(feature = "serialize", derive(Serialize))]
502#[cfg_attr(feature = "deserialize", derive(Deserialize))]
503#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
504pub enum ScalarKind {
505    /// Signed integer type.
506    Sint,
507    /// Unsigned integer type.
508    Uint,
509    /// Floating point type.
510    Float,
511    /// Boolean type.
512    Bool,
513
514    /// WGSL abstract integer type.
515    ///
516    /// These are forbidden by validation, and should never reach backends.
517    AbstractInt,
518
519    /// Abstract floating-point type.
520    ///
521    /// These are forbidden by validation, and should never reach backends.
522    AbstractFloat,
523}
524
525/// Characteristics of a scalar type.
526#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
527#[cfg_attr(feature = "serialize", derive(Serialize))]
528#[cfg_attr(feature = "deserialize", derive(Deserialize))]
529#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
530pub struct Scalar {
531    /// How the value's bits are to be interpreted.
532    pub kind: ScalarKind,
533
534    /// This size of the value in bytes.
535    pub width: Bytes,
536}
537
538/// Size of an array.
539#[repr(u8)]
540#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
541#[cfg_attr(feature = "serialize", derive(Serialize))]
542#[cfg_attr(feature = "deserialize", derive(Deserialize))]
543#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
544pub enum ArraySize {
545    /// The array size is constant.
546    Constant(core::num::NonZeroU32),
547    /// The array size is an override-expression.
548    Pending(Handle<Override>),
549    /// The array size can change at runtime.
550    Dynamic,
551}
552
553/// The interpolation qualifier of a binding or struct field.
554#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
555#[cfg_attr(feature = "serialize", derive(Serialize))]
556#[cfg_attr(feature = "deserialize", derive(Deserialize))]
557#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
558pub enum Interpolation {
559    /// The value will be interpolated in a perspective-correct fashion.
560    /// Also known as "smooth" in glsl.
561    Perspective,
562    /// Indicates that linear, non-perspective, correct
563    /// interpolation must be used.
564    /// Also known as "no_perspective" in glsl.
565    Linear,
566    /// Indicates that no interpolation will be performed.
567    Flat,
568}
569
570/// The sampling qualifiers of a binding or struct field.
571#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
572#[cfg_attr(feature = "serialize", derive(Serialize))]
573#[cfg_attr(feature = "deserialize", derive(Deserialize))]
574#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
575pub enum Sampling {
576    /// Interpolate the value at the center of the pixel.
577    Center,
578
579    /// Interpolate the value at a point that lies within all samples covered by
580    /// the fragment within the current primitive. In multisampling, use a
581    /// single value for all samples in the primitive.
582    Centroid,
583
584    /// Interpolate the value at each sample location. In multisampling, invoke
585    /// the fragment shader once per sample.
586    Sample,
587
588    /// Use the value provided by the first vertex of the current primitive.
589    First,
590
591    /// Use the value provided by the first or last vertex of the current primitive. The exact
592    /// choice is implementation-dependent.
593    Either,
594}
595
596/// Member of a user-defined structure.
597// Clone is used only for error reporting and is not intended for end users
598#[derive(Clone, Debug, Eq, Hash, PartialEq)]
599#[cfg_attr(feature = "serialize", derive(Serialize))]
600#[cfg_attr(feature = "deserialize", derive(Deserialize))]
601#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
602pub struct StructMember {
603    pub name: Option<String>,
604    /// Type of the field.
605    pub ty: Handle<Type>,
606    /// For I/O structs, defines the binding.
607    pub binding: Option<Binding>,
608    /// Offset from the beginning from the struct.
609    pub offset: u32,
610}
611
612/// The number of dimensions an image has.
613#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
614#[cfg_attr(feature = "serialize", derive(Serialize))]
615#[cfg_attr(feature = "deserialize", derive(Deserialize))]
616#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
617pub enum ImageDimension {
618    /// 1D image
619    D1,
620    /// 2D image
621    D2,
622    /// 3D image
623    D3,
624    /// Cube map
625    Cube,
626}
627
628bitflags::bitflags! {
629    /// Flags describing an image.
630    #[cfg_attr(feature = "serialize", derive(Serialize))]
631    #[cfg_attr(feature = "deserialize", derive(Deserialize))]
632    #[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
633    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
634    pub struct StorageAccess: u32 {
635        /// Storage can be used as a source for load ops.
636        const LOAD = 0x1;
637        /// Storage can be used as a target for store ops.
638        const STORE = 0x2;
639        /// Storage can be used as a target for atomic ops.
640        const ATOMIC = 0x4;
641    }
642}
643
644/// Image storage format.
645#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
646#[cfg_attr(feature = "serialize", derive(Serialize))]
647#[cfg_attr(feature = "deserialize", derive(Deserialize))]
648#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
649pub enum StorageFormat {
650    // 8-bit formats
651    R8Unorm,
652    R8Snorm,
653    R8Uint,
654    R8Sint,
655
656    // 16-bit formats
657    R16Uint,
658    R16Sint,
659    R16Float,
660    Rg8Unorm,
661    Rg8Snorm,
662    Rg8Uint,
663    Rg8Sint,
664
665    // 32-bit formats
666    R32Uint,
667    R32Sint,
668    R32Float,
669    Rg16Uint,
670    Rg16Sint,
671    Rg16Float,
672    Rgba8Unorm,
673    Rgba8Snorm,
674    Rgba8Uint,
675    Rgba8Sint,
676    Bgra8Unorm,
677
678    // Packed 32-bit formats
679    Rgb10a2Uint,
680    Rgb10a2Unorm,
681    Rg11b10Ufloat,
682
683    // 64-bit formats
684    R64Uint,
685    Rg32Uint,
686    Rg32Sint,
687    Rg32Float,
688    Rgba16Uint,
689    Rgba16Sint,
690    Rgba16Float,
691
692    // 128-bit formats
693    Rgba32Uint,
694    Rgba32Sint,
695    Rgba32Float,
696
697    // Normalized 16-bit per channel formats
698    R16Unorm,
699    R16Snorm,
700    Rg16Unorm,
701    Rg16Snorm,
702    Rgba16Unorm,
703    Rgba16Snorm,
704}
705
706/// Sub-class of the image type.
707#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
708#[cfg_attr(feature = "serialize", derive(Serialize))]
709#[cfg_attr(feature = "deserialize", derive(Deserialize))]
710#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
711pub enum ImageClass {
712    /// Regular sampled image.
713    Sampled {
714        /// Kind of values to sample.
715        kind: ScalarKind,
716        /// Multi-sampled image.
717        ///
718        /// A multi-sampled image holds several samples per texel. Multi-sampled
719        /// images cannot have mipmaps.
720        multi: bool,
721    },
722    /// Depth comparison image.
723    Depth {
724        /// Multi-sampled depth image.
725        multi: bool,
726    },
727    /// External texture.
728    External,
729    /// Storage image.
730    Storage {
731        format: StorageFormat,
732        access: StorageAccess,
733    },
734}
735
736/// A data type declared in the module.
737#[derive(Clone, Debug, Eq, Hash, PartialEq)]
738#[cfg_attr(feature = "serialize", derive(Serialize))]
739#[cfg_attr(feature = "deserialize", derive(Deserialize))]
740#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
741pub struct Type {
742    /// The name of the type, if any.
743    pub name: Option<String>,
744    /// Inner structure that depends on the kind of the type.
745    pub inner: TypeInner,
746}
747
748/// Enum with additional information, depending on the kind of type.
749///
750/// Comparison using `==` is not reliable in the case of [`Pointer`],
751/// [`ValuePointer`], or [`Struct`] variants. For these variants,
752/// use [`TypeInner::non_struct_equivalent`] or [`compare_types`].
753///
754/// [`compare_types`]: crate::proc::compare_types
755/// [`ValuePointer`]: TypeInner::ValuePointer
756/// [`Pointer`]: TypeInner::Pointer
757/// [`Struct`]: TypeInner::Struct
758#[derive(Clone, Debug, Eq, Hash, PartialEq)]
759#[cfg_attr(feature = "serialize", derive(Serialize))]
760#[cfg_attr(feature = "deserialize", derive(Deserialize))]
761#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
762pub enum TypeInner {
763    /// Number of integral or floating-point kind.
764    Scalar(Scalar),
765    /// Vector of numbers.
766    Vector { size: VectorSize, scalar: Scalar },
767    /// Matrix of numbers.
768    Matrix {
769        columns: VectorSize,
770        rows: VectorSize,
771        scalar: Scalar,
772    },
773    /// Atomic scalar.
774    Atomic(Scalar),
775    /// Pointer to another type.
776    ///
777    /// Pointers to scalars and vectors should be treated as equivalent to
778    /// [`ValuePointer`] types. Use either [`TypeInner::non_struct_equivalent`]
779    /// or [`compare_types`] to compare types in a way that treats pointers
780    /// correctly.
781    ///
782    /// ## Pointers to non-`SIZED` types
783    ///
784    /// The `base` type of a pointer may be a non-[`SIZED`] type like a
785    /// dynamically-sized [`Array`], or a [`Struct`] whose last member is a
786    /// dynamically sized array. Such pointers occur as the types of
787    /// [`GlobalVariable`] or [`AccessIndex`] expressions referring to
788    /// dynamically-sized arrays.
789    ///
790    /// However, among pointers to non-`SIZED` types, only pointers to `Struct`s
791    /// are [`DATA`]. Pointers to dynamically sized `Array`s cannot be passed as
792    /// arguments, stored in variables, or held in arrays or structures. Their
793    /// only use is as the types of `AccessIndex` expressions.
794    ///
795    /// [`SIZED`]: crate::valid::TypeFlags::SIZED
796    /// [`DATA`]: crate::valid::TypeFlags::DATA
797    /// [`Array`]: TypeInner::Array
798    /// [`Struct`]: TypeInner::Struct
799    /// [`ValuePointer`]: TypeInner::ValuePointer
800    /// [`GlobalVariable`]: Expression::GlobalVariable
801    /// [`AccessIndex`]: Expression::AccessIndex
802    /// [`compare_types`]: crate::proc::compare_types
803    Pointer {
804        base: Handle<Type>,
805        space: AddressSpace,
806    },
807
808    /// Pointer to a scalar or vector.
809    ///
810    /// A `ValuePointer` type is equivalent to a `Pointer` whose `base` is a
811    /// `Scalar` or `Vector` type. This is for use in [`TypeResolution::Value`]
812    /// variants; see the documentation for [`TypeResolution`] for details.
813    ///
814    /// Use [`TypeInner::non_struct_equivalent`] or [`compare_types`] to compare
815    /// types that could be pointers, to ensure that `Pointer` and
816    /// `ValuePointer` types are recognized as equivalent.
817    ///
818    /// [`TypeResolution`]: crate::proc::TypeResolution
819    /// [`TypeResolution::Value`]: crate::proc::TypeResolution::Value
820    /// [`compare_types`]: crate::proc::compare_types
821    ValuePointer {
822        size: Option<VectorSize>,
823        scalar: Scalar,
824        space: AddressSpace,
825    },
826
827    /// Homogeneous list of elements.
828    ///
829    /// The `base` type must be a [`SIZED`], [`DATA`] type.
830    ///
831    /// ## Dynamically sized arrays
832    ///
833    /// An `Array` is [`SIZED`] unless its `size` is [`Dynamic`].
834    /// Dynamically-sized arrays may only appear in a few situations:
835    ///
836    /// -   They may appear as the type of a [`GlobalVariable`], or as the last
837    ///     member of a [`Struct`].
838    ///
839    /// -   They may appear as the base type of a [`Pointer`]. An
840    ///     [`AccessIndex`] expression referring to a struct's final
841    ///     unsized array member would have such a pointer type. However, such
842    ///     pointer types may only appear as the types of such intermediate
843    ///     expressions. They are not [`DATA`], and cannot be stored in
844    ///     variables, held in arrays or structs, or passed as parameters.
845    ///
846    /// [`SIZED`]: crate::valid::TypeFlags::SIZED
847    /// [`DATA`]: crate::valid::TypeFlags::DATA
848    /// [`Dynamic`]: ArraySize::Dynamic
849    /// [`Struct`]: TypeInner::Struct
850    /// [`Pointer`]: TypeInner::Pointer
851    /// [`AccessIndex`]: Expression::AccessIndex
852    Array {
853        base: Handle<Type>,
854        size: ArraySize,
855        stride: u32,
856    },
857
858    /// User-defined structure.
859    ///
860    /// There must always be at least one member.
861    ///
862    /// A `Struct` type is [`DATA`], and the types of its members must be
863    /// `DATA` as well.
864    ///
865    /// Member types must be [`SIZED`], except for the final member of a
866    /// struct, which may be a dynamically sized [`Array`]. The
867    /// `Struct` type itself is `SIZED` when all its members are `SIZED`.
868    ///
869    /// Two structure types with different names are not equivalent. Because
870    /// this variant does not contain the name, it is not possible to use it
871    /// to compare struct types. Use [`compare_types`] to compare two types
872    /// that may be structs.
873    ///
874    /// [`DATA`]: crate::valid::TypeFlags::DATA
875    /// [`SIZED`]: crate::∅TypeFlags::SIZED
876    /// [`Array`]: TypeInner::Array
877    /// [`compare_types`]: crate::proc::compare_types
878    Struct {
879        members: Vec<StructMember>,
880        //TODO: should this be unaligned?
881        span: u32,
882    },
883    /// Possibly multidimensional array of texels.
884    Image {
885        dim: ImageDimension,
886        arrayed: bool,
887        //TODO: consider moving `multisampled: bool` out
888        class: ImageClass,
889    },
890    /// Can be used to sample values from images.
891    Sampler { comparison: bool },
892
893    /// Opaque object representing an acceleration structure of geometry.
894    AccelerationStructure { vertex_return: bool },
895
896    /// Locally used handle for ray queries.
897    RayQuery { vertex_return: bool },
898
899    /// Array of bindings.
900    ///
901    /// A `BindingArray` represents an array where each element draws its value
902    /// from a separate bound resource. The array's element type `base` may be
903    /// [`Image`], [`Sampler`], or any type that would be permitted for a global
904    /// in the [`Uniform`] or [`Storage`] address spaces. Only global variables
905    /// may be binding arrays; on the host side, their values are provided by
906    /// [`TextureViewArray`], [`SamplerArray`], or [`BufferArray`]
907    /// bindings.
908    ///
909    /// Since each element comes from a distinct resource, a binding array of
910    /// images could have images of varying sizes (but not varying dimensions;
911    /// they must all have the same `Image` type). Or, a binding array of
912    /// buffers could have elements that are dynamically sized arrays, each with
913    /// a different length.
914    ///
915    /// Binding arrays are in the same address spaces as their underlying type.
916    /// As such, referring to an array of images produces an [`Image`] value
917    /// directly (as opposed to a pointer). The only operation permitted on
918    /// `BindingArray` values is indexing, which works transparently: indexing
919    /// a binding array of samplers yields a [`Sampler`], indexing a pointer to the
920    /// binding array of storage buffers produces a pointer to the storage struct.
921    ///
922    /// Unlike textures and samplers, binding arrays are not [`ARGUMENT`], so
923    /// they cannot be passed as arguments to functions.
924    ///
925    /// Naga's WGSL front end supports binding arrays with the type syntax
926    /// `binding_array<T, N>`.
927    ///
928    /// [`Image`]: TypeInner::Image
929    /// [`Sampler`]: TypeInner::Sampler
930    /// [`Uniform`]: AddressSpace::Uniform
931    /// [`Storage`]: AddressSpace::Storage
932    /// [`TextureViewArray`]: https://docs.rs/wgpu/latest/wgpu/enum.BindingResource.html#variant.TextureViewArray
933    /// [`SamplerArray`]: https://docs.rs/wgpu/latest/wgpu/enum.BindingResource.html#variant.SamplerArray
934    /// [`BufferArray`]: https://docs.rs/wgpu/latest/wgpu/enum.BindingResource.html#variant.BufferArray
935    /// [`DATA`]: crate::valid::TypeFlags::DATA
936    /// [`ARGUMENT`]: crate::valid::TypeFlags::ARGUMENT
937    /// [naga#1864]: https://github.com/gfx-rs/naga/issues/1864
938    BindingArray { base: Handle<Type>, size: ArraySize },
939}
940
941#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
942#[cfg_attr(feature = "serialize", derive(Serialize))]
943#[cfg_attr(feature = "deserialize", derive(Deserialize))]
944#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
945pub enum Literal {
946    /// May not be NaN or infinity.
947    F64(f64),
948    /// May not be NaN or infinity.
949    F32(f32),
950    /// May not be NaN or infinity.
951    F16(f16),
952    U32(u32),
953    I32(i32),
954    U64(u64),
955    I64(i64),
956    Bool(bool),
957    AbstractInt(i64),
958    AbstractFloat(f64),
959}
960
961/// Pipeline-overridable constant.
962#[derive(Clone, Debug, PartialEq)]
963#[cfg_attr(feature = "serialize", derive(Serialize))]
964#[cfg_attr(feature = "deserialize", derive(Deserialize))]
965#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
966pub struct Override {
967    pub name: Option<String>,
968    /// Pipeline Constant ID.
969    pub id: Option<u16>,
970    pub ty: Handle<Type>,
971
972    /// The default value of the pipeline-overridable constant.
973    ///
974    /// This [`Handle`] refers to [`Module::global_expressions`], not
975    /// any [`Function::expressions`] arena.
976    pub init: Option<Handle<Expression>>,
977}
978
979/// Constant value.
980#[derive(Clone, Debug, PartialEq)]
981#[cfg_attr(feature = "serialize", derive(Serialize))]
982#[cfg_attr(feature = "deserialize", derive(Deserialize))]
983#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
984pub struct Constant {
985    pub name: Option<String>,
986    pub ty: Handle<Type>,
987
988    /// The value of the constant.
989    ///
990    /// This [`Handle`] refers to [`Module::global_expressions`], not
991    /// any [`Function::expressions`] arena.
992    pub init: Handle<Expression>,
993}
994
995/// Describes how an input/output variable is to be bound.
996#[derive(Clone, Debug, Eq, PartialEq, Hash)]
997#[cfg_attr(feature = "serialize", derive(Serialize))]
998#[cfg_attr(feature = "deserialize", derive(Deserialize))]
999#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1000pub enum Binding {
1001    /// Built-in shader variable.
1002    BuiltIn(BuiltIn),
1003
1004    /// Indexed location.
1005    ///
1006    /// This is a value passed to a [`Fragment`] shader from a [`Vertex`] or
1007    /// [`Mesh`] shader.
1008    ///
1009    /// Values passed from the [`Vertex`] stage to the [`Fragment`] stage must
1010    /// have their `interpolation` defaulted (i.e. not `None`) by the front end
1011    /// as appropriate for that language.
1012    ///
1013    /// For other stages, we permit interpolations even though they're ignored.
1014    /// When a front end is parsing a struct type, it usually doesn't know what
1015    /// stages will be using it for IO, so it's easiest if it can apply the
1016    /// defaults to anything with a `Location` binding, just in case.
1017    ///
1018    /// For anything other than floating-point scalars and vectors, the
1019    /// interpolation must be `Flat`.
1020    ///
1021    /// [`Vertex`]: crate::ShaderStage::Vertex
1022    /// [`Mesh`]: crate::ShaderStage::Mesh
1023    /// [`Fragment`]: crate::ShaderStage::Fragment
1024    Location {
1025        location: u32,
1026        interpolation: Option<Interpolation>,
1027        sampling: Option<Sampling>,
1028
1029        /// Optional `blend_src` index used for dual source blending.
1030        /// See <https://www.w3.org/TR/WGSL/#attribute-blend_src>
1031        blend_src: Option<u32>,
1032
1033        /// Whether the binding is a per-primitive binding for use with mesh shaders.
1034        ///
1035        /// This must be `true` if this binding is a mesh shader primitive output, or such
1036        /// an output's corresponding fragment shader input. It must be `false` otherwise.
1037        ///
1038        /// A stage's outputs must all have unique `location` numbers, regardless of
1039        /// whether they are per-primitive; a mesh shader's per-vertex and per-primitive
1040        /// outputs share the same location numbering space.
1041        ///
1042        /// Per-primitive values are not interpolated at all and are not dependent on the
1043        /// vertices or pixel location. For example, it may be used to store a
1044        /// non-interpolated normal vector.
1045        per_primitive: bool,
1046    },
1047}
1048
1049/// Pipeline binding information for global resources.
1050#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
1051#[cfg_attr(feature = "serialize", derive(Serialize))]
1052#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1053#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1054pub struct ResourceBinding {
1055    /// The bind group index.
1056    pub group: u32,
1057    /// Binding number within the group.
1058    pub binding: u32,
1059}
1060
1061/// Variable defined at module level.
1062#[derive(Clone, Debug, PartialEq)]
1063#[cfg_attr(feature = "serialize", derive(Serialize))]
1064#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1065#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1066pub struct GlobalVariable {
1067    /// Name of the variable, if any.
1068    pub name: Option<String>,
1069    /// How this variable is to be stored.
1070    pub space: AddressSpace,
1071    /// For resources, defines the binding point.
1072    pub binding: Option<ResourceBinding>,
1073    /// The type of this variable.
1074    pub ty: Handle<Type>,
1075    /// Initial value for this variable.
1076    ///
1077    /// This refers to an [`Expression`] in [`Module::global_expressions`].
1078    pub init: Option<Handle<Expression>>,
1079}
1080
1081/// Variable defined at function level.
1082#[derive(Clone, Debug)]
1083#[cfg_attr(feature = "serialize", derive(Serialize))]
1084#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1085#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1086pub struct LocalVariable {
1087    /// Name of the variable, if any.
1088    pub name: Option<String>,
1089    /// The type of this variable.
1090    pub ty: Handle<Type>,
1091    /// Initial value for this variable.
1092    ///
1093    /// This handle refers to an expression in this `LocalVariable`'s function's
1094    /// [`expressions`] arena, but it is required to be an evaluated override
1095    /// expression.
1096    ///
1097    /// [`expressions`]: Function::expressions
1098    pub init: Option<Handle<Expression>>,
1099}
1100
1101/// Operation that can be applied on a single value.
1102#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1103#[cfg_attr(feature = "serialize", derive(Serialize))]
1104#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1105#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1106pub enum UnaryOperator {
1107    Negate,
1108    LogicalNot,
1109    BitwiseNot,
1110}
1111
1112/// Operation that can be applied on two values.
1113///
1114/// ## Arithmetic type rules
1115///
1116/// The arithmetic operations `Add`, `Subtract`, `Multiply`, `Divide`, and
1117/// `Modulo` can all be applied to [`Scalar`] types other than [`Bool`], or
1118/// [`Vector`]s thereof. Both operands must have the same type.
1119///
1120/// `Add` and `Subtract` can also be applied to [`Matrix`] values. Both operands
1121/// must have the same type.
1122///
1123/// `Multiply` supports additional cases:
1124///
1125/// -   A [`Matrix`] or [`Vector`] can be multiplied by a scalar [`Float`],
1126///     either on the left or the right.
1127///
1128/// -   A [`Matrix`] on the left can be multiplied by a [`Vector`] on the right
1129///     if the matrix has as many columns as the vector has components
1130///     (`matCxR * VecC`).
1131///
1132/// -   A [`Vector`] on the left can be multiplied by a [`Matrix`] on the right
1133///     if the matrix has as many rows as the vector has components
1134///     (`VecR * matCxR`).
1135///
1136/// -   Two matrices can be multiplied if the left operand has as many columns
1137///     as the right operand has rows (`matNxR * matCxN`).
1138///
1139/// In all the above `Multiply` cases, the byte widths of the underlying scalar
1140/// types of both operands must be the same.
1141///
1142/// Note that `Multiply` supports mixed vector and scalar operations directly,
1143/// whereas the other arithmetic operations require an explicit [`Splat`] for
1144/// mixed-type use.
1145///
1146/// [`Scalar`]: TypeInner::Scalar
1147/// [`Vector`]: TypeInner::Vector
1148/// [`Matrix`]: TypeInner::Matrix
1149/// [`Float`]: ScalarKind::Float
1150/// [`Bool`]: ScalarKind::Bool
1151/// [`Splat`]: Expression::Splat
1152#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1153#[cfg_attr(feature = "serialize", derive(Serialize))]
1154#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1155#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1156pub enum BinaryOperator {
1157    Add,
1158    Subtract,
1159    Multiply,
1160    Divide,
1161    /// Equivalent of the WGSL's `%` operator or SPIR-V's `OpFRem`
1162    Modulo,
1163    Equal,
1164    NotEqual,
1165    Less,
1166    LessEqual,
1167    Greater,
1168    GreaterEqual,
1169    And,
1170    ExclusiveOr,
1171    InclusiveOr,
1172    LogicalAnd,
1173    LogicalOr,
1174    ShiftLeft,
1175    /// Right shift carries the sign of signed integers only.
1176    ShiftRight,
1177}
1178
1179/// Function on an atomic value.
1180///
1181/// Note: these do not include load/store, which use the existing
1182/// [`Expression::Load`] and [`Statement::Store`].
1183///
1184/// All `Handle<Expression>` values here refer to an expression in
1185/// [`Function::expressions`].
1186#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1187#[cfg_attr(feature = "serialize", derive(Serialize))]
1188#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1189#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1190pub enum AtomicFunction {
1191    Add,
1192    Subtract,
1193    And,
1194    ExclusiveOr,
1195    InclusiveOr,
1196    Min,
1197    Max,
1198    Exchange { compare: Option<Handle<Expression>> },
1199}
1200
1201/// Hint at which precision to compute a derivative.
1202#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1203#[cfg_attr(feature = "serialize", derive(Serialize))]
1204#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1205#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1206pub enum DerivativeControl {
1207    Coarse,
1208    Fine,
1209    None,
1210}
1211
1212/// Axis on which to compute a derivative.
1213#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1214#[cfg_attr(feature = "serialize", derive(Serialize))]
1215#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1216#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1217pub enum DerivativeAxis {
1218    X,
1219    Y,
1220    Width,
1221}
1222
1223/// Built-in shader function for testing relation between values.
1224#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1225#[cfg_attr(feature = "serialize", derive(Serialize))]
1226#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1227#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1228pub enum RelationalFunction {
1229    All,
1230    Any,
1231    IsNan,
1232    IsInf,
1233}
1234
1235/// Built-in shader function for math.
1236#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1237#[cfg_attr(feature = "serialize", derive(Serialize))]
1238#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1239#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1240pub enum MathFunction {
1241    // comparison
1242    Abs,
1243    Min,
1244    Max,
1245    Clamp,
1246    Saturate,
1247    // trigonometry
1248    Cos,
1249    Cosh,
1250    Sin,
1251    Sinh,
1252    Tan,
1253    Tanh,
1254    Acos,
1255    Asin,
1256    Atan,
1257    Atan2,
1258    Asinh,
1259    Acosh,
1260    Atanh,
1261    Radians,
1262    Degrees,
1263    // decomposition
1264    Ceil,
1265    Floor,
1266    Round,
1267    Fract,
1268    Trunc,
1269    Modf,
1270    Frexp,
1271    Ldexp,
1272    // exponent
1273    Exp,
1274    Exp2,
1275    Log,
1276    Log2,
1277    Pow,
1278    // geometry
1279    Dot,
1280    Dot4I8Packed,
1281    Dot4U8Packed,
1282    Outer,
1283    Cross,
1284    Distance,
1285    Length,
1286    Normalize,
1287    FaceForward,
1288    Reflect,
1289    Refract,
1290    // computational
1291    Sign,
1292    Fma,
1293    Mix,
1294    Step,
1295    SmoothStep,
1296    Sqrt,
1297    InverseSqrt,
1298    Inverse,
1299    Transpose,
1300    Determinant,
1301    QuantizeToF16,
1302    // bits
1303    CountTrailingZeros,
1304    CountLeadingZeros,
1305    CountOneBits,
1306    ReverseBits,
1307    ExtractBits,
1308    InsertBits,
1309    FirstTrailingBit,
1310    FirstLeadingBit,
1311    // data packing
1312    Pack4x8snorm,
1313    Pack4x8unorm,
1314    Pack2x16snorm,
1315    Pack2x16unorm,
1316    Pack2x16float,
1317    Pack4xI8,
1318    Pack4xU8,
1319    Pack4xI8Clamp,
1320    Pack4xU8Clamp,
1321    // data unpacking
1322    Unpack4x8snorm,
1323    Unpack4x8unorm,
1324    Unpack2x16snorm,
1325    Unpack2x16unorm,
1326    Unpack2x16float,
1327    Unpack4xI8,
1328    Unpack4xU8,
1329}
1330
1331/// Sampling modifier to control the level of detail.
1332///
1333/// All `Handle<Expression>` values here refer to an expression in
1334/// [`Function::expressions`].
1335#[derive(Clone, Copy, Debug, PartialEq)]
1336#[cfg_attr(feature = "serialize", derive(Serialize))]
1337#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1338#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1339pub enum SampleLevel {
1340    Auto,
1341    Zero,
1342    Exact(Handle<Expression>),
1343    Bias(Handle<Expression>),
1344    Gradient {
1345        x: Handle<Expression>,
1346        y: Handle<Expression>,
1347    },
1348}
1349
1350/// Type of an image query.
1351///
1352/// All `Handle<Expression>` values here refer to an expression in
1353/// [`Function::expressions`].
1354#[derive(Clone, Copy, Debug, PartialEq)]
1355#[cfg_attr(feature = "serialize", derive(Serialize))]
1356#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1357#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1358pub enum ImageQuery {
1359    /// Get the size at the specified level.
1360    ///
1361    /// The return value is a `u32` for 1D images, and a `vecN<u32>`
1362    /// for an image with dimensions N > 2.
1363    Size {
1364        /// If `None`, the base level is considered.
1365        level: Option<Handle<Expression>>,
1366    },
1367    /// Get the number of mipmap levels, a `u32`.
1368    NumLevels,
1369    /// Get the number of array layers, a `u32`.
1370    NumLayers,
1371    /// Get the number of samples, a `u32`.
1372    NumSamples,
1373}
1374
1375/// Component selection for a vector swizzle.
1376#[repr(u8)]
1377#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
1378#[cfg_attr(feature = "serialize", derive(Serialize))]
1379#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1380#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1381pub enum SwizzleComponent {
1382    X = 0,
1383    Y = 1,
1384    Z = 2,
1385    W = 3,
1386}
1387
1388/// The specific behavior of a [`SubgroupGather`] statement.
1389///
1390/// All `Handle<Expression>` values here refer to an expression in
1391/// [`Function::expressions`].
1392///
1393/// [`SubgroupGather`]: Statement::SubgroupGather
1394#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1395#[cfg_attr(feature = "serialize", derive(Serialize))]
1396#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1397#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1398pub enum GatherMode {
1399    /// All gather from the active lane with the smallest index
1400    BroadcastFirst,
1401    /// All gather from the same lane at the index given by the expression
1402    Broadcast(Handle<Expression>),
1403    /// Each gathers from a different lane at the index given by the expression
1404    Shuffle(Handle<Expression>),
1405    /// Each gathers from their lane plus the shift given by the expression
1406    ShuffleDown(Handle<Expression>),
1407    /// Each gathers from their lane minus the shift given by the expression
1408    ShuffleUp(Handle<Expression>),
1409    /// Each gathers from their lane xored with the given by the expression
1410    ShuffleXor(Handle<Expression>),
1411    /// All gather from the same quad lane at the index given by the expression
1412    QuadBroadcast(Handle<Expression>),
1413    /// Each gathers from the opposite quad lane along the given direction
1414    QuadSwap(Direction),
1415}
1416
1417#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1418#[cfg_attr(feature = "serialize", derive(Serialize))]
1419#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1420#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1421pub enum Direction {
1422    X = 0,
1423    Y = 1,
1424    Diagonal = 2,
1425}
1426
1427#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1428#[cfg_attr(feature = "serialize", derive(Serialize))]
1429#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1430#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1431pub enum SubgroupOperation {
1432    All = 0,
1433    Any = 1,
1434    Add = 2,
1435    Mul = 3,
1436    Min = 4,
1437    Max = 5,
1438    And = 6,
1439    Or = 7,
1440    Xor = 8,
1441}
1442
1443#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
1444#[cfg_attr(feature = "serialize", derive(Serialize))]
1445#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1446#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1447pub enum CollectiveOperation {
1448    Reduce = 0,
1449    InclusiveScan = 1,
1450    ExclusiveScan = 2,
1451}
1452
1453bitflags::bitflags! {
1454    /// Memory barrier flags.
1455    #[cfg_attr(feature = "serialize", derive(Serialize))]
1456    #[cfg_attr(feature = "deserialize", derive(Deserialize))]
1457    #[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1458    #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
1459    pub struct Barrier: u32 {
1460        /// Barrier affects all [`AddressSpace::Storage`] accesses.
1461        const STORAGE = 1 << 0;
1462        /// Barrier affects all [`AddressSpace::WorkGroup`] accesses.
1463        const WORK_GROUP = 1 << 1;
1464        /// Barrier synchronizes execution across all invocations within a subgroup that execute this instruction.
1465        const SUB_GROUP = 1 << 2;
1466        /// Barrier synchronizes texture memory accesses in a workgroup.
1467        const TEXTURE = 1 << 3;
1468    }
1469}
1470
1471/// An expression that can be evaluated to obtain a value.
1472///
1473/// This is a Single Static Assignment (SSA) scheme similar to SPIR-V.
1474///
1475/// When an `Expression` variant holds `Handle<Expression>` fields, they refer
1476/// to another expression in the same arena, unless explicitly noted otherwise.
1477/// One `Arena<Expression>` may only refer to a different arena indirectly, via
1478/// [`Constant`] or [`Override`] expressions, which hold handles for their
1479/// respective types.
1480///
1481/// [`Constant`]: Expression::Constant
1482/// [`Override`]: Expression::Override
1483#[derive(Clone, Debug, PartialEq)]
1484#[cfg_attr(feature = "serialize", derive(Serialize))]
1485#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1486#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1487pub enum Expression {
1488    /// Literal.
1489    Literal(Literal),
1490    /// Constant value.
1491    Constant(Handle<Constant>),
1492    /// Pipeline-overridable constant.
1493    Override(Handle<Override>),
1494    /// Zero value of a type.
1495    ZeroValue(Handle<Type>),
1496    /// Composite expression.
1497    Compose {
1498        ty: Handle<Type>,
1499        components: Vec<Handle<Expression>>,
1500    },
1501
1502    /// Array access with a computed index.
1503    ///
1504    /// ## Typing rules
1505    ///
1506    /// The `base` operand must be some composite type: [`Vector`], [`Matrix`],
1507    /// [`Array`], a [`Pointer`] to one of those, or a [`ValuePointer`] with a
1508    /// `size`.
1509    ///
1510    /// The `index` operand must be an integer, signed or unsigned.
1511    ///
1512    /// Indexing a [`Vector`] or [`Array`] produces a value of its element type.
1513    /// Indexing a [`Matrix`] produces a [`Vector`].
1514    ///
1515    /// Indexing a [`Pointer`] to any of the above produces a pointer to the
1516    /// element/component type, in the same [`space`]. In the case of [`Array`],
1517    /// the result is an actual [`Pointer`], but for vectors and matrices, there
1518    /// may not be any type in the arena representing the component's type, so
1519    /// those produce [`ValuePointer`] types equivalent to the appropriate
1520    /// [`Pointer`].
1521    ///
1522    /// ## Dynamic indexing restrictions
1523    ///
1524    /// To accommodate restrictions in some of the shader languages that Naga
1525    /// targets, it is not permitted to subscript a matrix with a dynamically
1526    /// computed index unless that matrix appears behind a pointer. In other
1527    /// words, if the inner type of `base` is [`Matrix`], then `index` must be a
1528    /// constant. But if the type of `base` is a [`Pointer`] to an matrix, then
1529    /// the index may be any expression of integer type.
1530    ///
1531    /// You can use the [`Expression::is_dynamic_index`] method to determine
1532    /// whether a given index expression requires matrix base operands to be
1533    /// behind a pointer.
1534    ///
1535    /// (It would be simpler to always require the use of `AccessIndex` when
1536    /// subscripting matrices that are not behind pointers, but to accommodate
1537    /// existing front ends, Naga also permits `Access`, with a restricted
1538    /// `index`.)
1539    ///
1540    /// [`Vector`]: TypeInner::Vector
1541    /// [`Matrix`]: TypeInner::Matrix
1542    /// [`Array`]: TypeInner::Array
1543    /// [`Pointer`]: TypeInner::Pointer
1544    /// [`space`]: TypeInner::Pointer::space
1545    /// [`ValuePointer`]: TypeInner::ValuePointer
1546    /// [`Float`]: ScalarKind::Float
1547    Access {
1548        base: Handle<Expression>,
1549        index: Handle<Expression>,
1550    },
1551    /// Access the same types as [`Access`], plus [`Struct`] with a known index.
1552    ///
1553    /// [`Access`]: Expression::Access
1554    /// [`Struct`]: TypeInner::Struct
1555    AccessIndex {
1556        base: Handle<Expression>,
1557        index: u32,
1558    },
1559    /// Splat scalar into a vector.
1560    Splat {
1561        size: VectorSize,
1562        value: Handle<Expression>,
1563    },
1564    /// Vector swizzle.
1565    Swizzle {
1566        size: VectorSize,
1567        vector: Handle<Expression>,
1568        pattern: [SwizzleComponent; 4],
1569    },
1570
1571    /// Reference a function parameter, by its index.
1572    ///
1573    /// A `FunctionArgument` expression evaluates to the argument's value.
1574    FunctionArgument(u32),
1575
1576    /// Reference a global variable.
1577    ///
1578    /// If the given `GlobalVariable`'s [`space`] is [`AddressSpace::Handle`],
1579    /// then the variable stores some opaque type like a sampler or an image,
1580    /// and a `GlobalVariable` expression referring to it produces the
1581    /// variable's value directly.
1582    ///
1583    /// For any other address space, a `GlobalVariable` expression produces a
1584    /// pointer to the variable's value. You must use a [`Load`] expression to
1585    /// retrieve its value, or a [`Store`] statement to assign it a new value.
1586    ///
1587    /// [`space`]: GlobalVariable::space
1588    /// [`Load`]: Expression::Load
1589    /// [`Store`]: Statement::Store
1590    GlobalVariable(Handle<GlobalVariable>),
1591
1592    /// Reference a local variable.
1593    ///
1594    /// A `LocalVariable` expression evaluates to a pointer to the variable's value.
1595    /// You must use a [`Load`](Expression::Load) expression to retrieve its value,
1596    /// or a [`Store`](Statement::Store) statement to assign it a new value.
1597    LocalVariable(Handle<LocalVariable>),
1598
1599    /// Load a value indirectly.
1600    ///
1601    /// For [`TypeInner::Atomic`] the result is a corresponding scalar.
1602    /// For other types behind the `pointer<T>`, the result is `T`.
1603    Load { pointer: Handle<Expression> },
1604    /// Sample a point from a sampled or a depth image.
1605    ImageSample {
1606        image: Handle<Expression>,
1607        sampler: Handle<Expression>,
1608        /// If Some(), this operation is a gather operation
1609        /// on the selected component.
1610        gather: Option<SwizzleComponent>,
1611        coordinate: Handle<Expression>,
1612        array_index: Option<Handle<Expression>>,
1613        /// This must be a const-expression.
1614        offset: Option<Handle<Expression>>,
1615        level: SampleLevel,
1616        depth_ref: Option<Handle<Expression>>,
1617        /// Whether the sampling operation should clamp each component of
1618        /// `coordinate` to the range `[half_texel, 1 - half_texel]`, regardless
1619        /// of `sampler`.
1620        clamp_to_edge: bool,
1621    },
1622
1623    /// Load a texel from an image.
1624    ///
1625    /// For most images, this returns a four-element vector of the same
1626    /// [`ScalarKind`] as the image. If the format of the image does not have
1627    /// four components, default values are provided: the first three components
1628    /// (typically R, G, and B) default to zero, and the final component
1629    /// (typically alpha) defaults to one.
1630    ///
1631    /// However, if the image's [`class`] is [`Depth`], then this returns a
1632    /// [`Float`] scalar value.
1633    ///
1634    /// [`ScalarKind`]: ScalarKind
1635    /// [`class`]: TypeInner::Image::class
1636    /// [`Depth`]: ImageClass::Depth
1637    /// [`Float`]: ScalarKind::Float
1638    ImageLoad {
1639        /// The image to load a texel from. This must have type [`Image`]. (This
1640        /// will necessarily be a [`GlobalVariable`] or [`FunctionArgument`]
1641        /// expression, since no other expressions are allowed to have that
1642        /// type.)
1643        ///
1644        /// [`Image`]: TypeInner::Image
1645        /// [`GlobalVariable`]: Expression::GlobalVariable
1646        /// [`FunctionArgument`]: Expression::FunctionArgument
1647        image: Handle<Expression>,
1648
1649        /// The coordinate of the texel we wish to load. This must be a scalar
1650        /// for [`D1`] images, a [`Bi`] vector for [`D2`] images, and a [`Tri`]
1651        /// vector for [`D3`] images. (Array indices, sample indices, and
1652        /// explicit level-of-detail values are supplied separately.) Its
1653        /// component type must be [`Sint`].
1654        ///
1655        /// [`D1`]: ImageDimension::D1
1656        /// [`D2`]: ImageDimension::D2
1657        /// [`D3`]: ImageDimension::D3
1658        /// [`Bi`]: VectorSize::Bi
1659        /// [`Tri`]: VectorSize::Tri
1660        /// [`Sint`]: ScalarKind::Sint
1661        coordinate: Handle<Expression>,
1662
1663        /// The index into an arrayed image. If the [`arrayed`] flag in
1664        /// `image`'s type is `true`, then this must be `Some(expr)`, where
1665        /// `expr` is a [`Sint`] scalar. Otherwise, it must be `None`.
1666        ///
1667        /// [`arrayed`]: TypeInner::Image::arrayed
1668        /// [`Sint`]: ScalarKind::Sint
1669        array_index: Option<Handle<Expression>>,
1670
1671        /// A sample index, for multisampled [`Sampled`] and [`Depth`] images.
1672        ///
1673        /// [`Sampled`]: ImageClass::Sampled
1674        /// [`Depth`]: ImageClass::Depth
1675        sample: Option<Handle<Expression>>,
1676
1677        /// A level of detail, for mipmapped images.
1678        ///
1679        /// This must be present when accessing non-multisampled
1680        /// [`Sampled`] and [`Depth`] images, even if only the
1681        /// full-resolution level is present (in which case the only
1682        /// valid level is zero).
1683        ///
1684        /// [`Sampled`]: ImageClass::Sampled
1685        /// [`Depth`]: ImageClass::Depth
1686        level: Option<Handle<Expression>>,
1687    },
1688
1689    /// Query information from an image.
1690    ImageQuery {
1691        image: Handle<Expression>,
1692        query: ImageQuery,
1693    },
1694    /// Apply an unary operator.
1695    Unary {
1696        op: UnaryOperator,
1697        expr: Handle<Expression>,
1698    },
1699    /// Apply a binary operator.
1700    Binary {
1701        op: BinaryOperator,
1702        left: Handle<Expression>,
1703        right: Handle<Expression>,
1704    },
1705    /// Select between two values based on a condition.
1706    ///
1707    /// Note that, because expressions have no side effects, it is unobservable
1708    /// whether the non-selected branch is evaluated.
1709    Select {
1710        /// Boolean expression
1711        condition: Handle<Expression>,
1712        accept: Handle<Expression>,
1713        reject: Handle<Expression>,
1714    },
1715    /// Compute the derivative on an axis.
1716    Derivative {
1717        axis: DerivativeAxis,
1718        ctrl: DerivativeControl,
1719        expr: Handle<Expression>,
1720    },
1721    /// Call a relational function.
1722    Relational {
1723        fun: RelationalFunction,
1724        argument: Handle<Expression>,
1725    },
1726    /// Call a math function
1727    Math {
1728        fun: MathFunction,
1729        arg: Handle<Expression>,
1730        arg1: Option<Handle<Expression>>,
1731        arg2: Option<Handle<Expression>>,
1732        arg3: Option<Handle<Expression>>,
1733    },
1734    /// Cast a simple type to another kind.
1735    As {
1736        /// Source expression, which can only be a scalar or a vector.
1737        expr: Handle<Expression>,
1738        /// Target scalar kind.
1739        kind: ScalarKind,
1740        /// If provided, converts to the specified byte width.
1741        /// Otherwise, bitcast.
1742        convert: Option<Bytes>,
1743    },
1744    /// Result of calling another function.
1745    CallResult(Handle<Function>),
1746
1747    /// Result of an atomic operation.
1748    ///
1749    /// This expression must be referred to by the [`result`] field of exactly one
1750    /// [`Atomic`][stmt] statement somewhere in the same function. Let `T` be the
1751    /// scalar type contained by the [`Atomic`][type] value that the statement
1752    /// operates on.
1753    ///
1754    /// If `comparison` is `false`, then `ty` must be the scalar type `T`.
1755    ///
1756    /// If `comparison` is `true`, then `ty` must be a [`Struct`] with two members:
1757    ///
1758    /// - A member named `old_value`, whose type is `T`, and
1759    ///
1760    /// - A member named `exchanged`, of type [`BOOL`].
1761    ///
1762    /// [`result`]: Statement::Atomic::result
1763    /// [stmt]: Statement::Atomic
1764    /// [type]: TypeInner::Atomic
1765    /// [`Struct`]: TypeInner::Struct
1766    /// [`BOOL`]: Scalar::BOOL
1767    AtomicResult { ty: Handle<Type>, comparison: bool },
1768
1769    /// Result of a [`WorkGroupUniformLoad`] statement.
1770    ///
1771    /// [`WorkGroupUniformLoad`]: Statement::WorkGroupUniformLoad
1772    WorkGroupUniformLoadResult {
1773        /// The type of the result
1774        ty: Handle<Type>,
1775    },
1776    /// Get the length of an array.
1777    /// The expression must resolve to a pointer to an array with a dynamic size.
1778    ///
1779    /// This doesn't match the semantics of spirv's `OpArrayLength`, which must be passed
1780    /// a pointer to a structure containing a runtime array in its' last field.
1781    ArrayLength(Handle<Expression>),
1782
1783    /// Get the Positions of the triangle hit by the [`RayQuery`]
1784    ///
1785    /// [`RayQuery`]: Statement::RayQuery
1786    RayQueryVertexPositions {
1787        query: Handle<Expression>,
1788        committed: bool,
1789    },
1790
1791    /// Result of a [`Proceed`] [`RayQuery`] statement.
1792    ///
1793    /// [`Proceed`]: RayQueryFunction::Proceed
1794    /// [`RayQuery`]: Statement::RayQuery
1795    RayQueryProceedResult,
1796
1797    /// Return an intersection found by `query`.
1798    ///
1799    /// If `committed` is true, return the committed result available when
1800    RayQueryGetIntersection {
1801        query: Handle<Expression>,
1802        committed: bool,
1803    },
1804
1805    /// Result of a [`SubgroupBallot`] statement.
1806    ///
1807    /// [`SubgroupBallot`]: Statement::SubgroupBallot
1808    SubgroupBallotResult,
1809
1810    /// Result of a [`SubgroupCollectiveOperation`] or [`SubgroupGather`] statement.
1811    ///
1812    /// [`SubgroupCollectiveOperation`]: Statement::SubgroupCollectiveOperation
1813    /// [`SubgroupGather`]: Statement::SubgroupGather
1814    SubgroupOperationResult { ty: Handle<Type> },
1815}
1816
1817/// The value of the switch case.
1818#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1819#[cfg_attr(feature = "serialize", derive(Serialize))]
1820#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1821#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1822pub enum SwitchValue {
1823    I32(i32),
1824    U32(u32),
1825    Default,
1826}
1827
1828/// A case for a switch statement.
1829// Clone is used only for error reporting and is not intended for end users
1830#[derive(Clone, Debug)]
1831#[cfg_attr(feature = "serialize", derive(Serialize))]
1832#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1833#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1834pub struct SwitchCase {
1835    /// Value, upon which the case is considered true.
1836    pub value: SwitchValue,
1837    /// Body of the case.
1838    pub body: Block,
1839    /// If true, the control flow continues to the next case in the list,
1840    /// or default.
1841    pub fall_through: bool,
1842}
1843
1844/// An operation that a [`RayQuery` statement] applies to its [`query`] operand.
1845///
1846/// [`RayQuery` statement]: Statement::RayQuery
1847/// [`query`]: Statement::RayQuery::query
1848#[derive(Clone, Debug)]
1849#[cfg_attr(feature = "serialize", derive(Serialize))]
1850#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1851#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1852pub enum RayQueryFunction {
1853    /// Initialize the `RayQuery` object.
1854    Initialize {
1855        /// The acceleration structure within which this query should search for hits.
1856        ///
1857        /// The expression must be an [`AccelerationStructure`].
1858        ///
1859        /// [`AccelerationStructure`]: TypeInner::AccelerationStructure
1860        acceleration_structure: Handle<Expression>,
1861
1862        #[allow(rustdoc::private_intra_doc_links)]
1863        /// A struct of detailed parameters for the ray query.
1864        ///
1865        /// This expression should have the struct type given in
1866        /// [`SpecialTypes::ray_desc`]. This is available in the WGSL
1867        /// front end as the `RayDesc` type.
1868        descriptor: Handle<Expression>,
1869    },
1870
1871    /// Start or continue the query given by the statement's [`query`] operand.
1872    ///
1873    /// After executing this statement, the `result` expression is a
1874    /// [`Bool`] scalar indicating whether there are more intersection
1875    /// candidates to consider.
1876    ///
1877    /// [`query`]: Statement::RayQuery::query
1878    /// [`Bool`]: ScalarKind::Bool
1879    Proceed {
1880        result: Handle<Expression>,
1881    },
1882
1883    /// Add a candidate generated intersection to be included
1884    /// in the determination of the closest hit for a ray query.
1885    GenerateIntersection {
1886        hit_t: Handle<Expression>,
1887    },
1888
1889    /// Confirm a triangle intersection to be included in the determination of
1890    /// the closest hit for a ray query.
1891    ConfirmIntersection,
1892
1893    Terminate,
1894}
1895
1896//TODO: consider removing `Clone`. It's not valid to clone `Statement::Emit` anyway.
1897/// Instructions which make up an executable block.
1898///
1899/// `Handle<Expression>` and `Range<Expression>` values in `Statement` variants
1900/// refer to expressions in [`Function::expressions`], unless otherwise noted.
1901// Clone is used only for error reporting and is not intended for end users
1902#[derive(Clone, Debug)]
1903#[cfg_attr(feature = "serialize", derive(Serialize))]
1904#[cfg_attr(feature = "deserialize", derive(Deserialize))]
1905#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
1906pub enum Statement {
1907    /// Emit a range of expressions, visible to all statements that follow in this block.
1908    ///
1909    /// See the [module-level documentation][emit] for details.
1910    ///
1911    /// [emit]: index.html#expression-evaluation-time
1912    Emit(Range<Expression>),
1913    /// A block containing more statements, to be executed sequentially.
1914    Block(Block),
1915    /// Conditionally executes one of two blocks, based on the value of the condition.
1916    ///
1917    /// Naga IR does not have "phi" instructions. If you need to use
1918    /// values computed in an `accept` or `reject` block after the `If`,
1919    /// store them in a [`LocalVariable`].
1920    If {
1921        condition: Handle<Expression>, //bool
1922        accept: Block,
1923        reject: Block,
1924    },
1925    /// Conditionally executes one of multiple blocks, based on the value of the selector.
1926    ///
1927    /// Each case must have a distinct [`value`], exactly one of which must be
1928    /// [`Default`]. The `Default` may appear at any position, and covers all
1929    /// values not explicitly appearing in other cases. A `Default` appearing in
1930    /// the midst of the list of cases does not shadow the cases that follow.
1931    ///
1932    /// Some backend languages don't support fallthrough (HLSL due to FXC,
1933    /// WGSL), and may translate fallthrough cases in the IR by duplicating
1934    /// code. However, all backend languages do support cases selected by
1935    /// multiple values, like `case 1: case 2: case 3: { ... }`. This is
1936    /// represented in the IR as a series of fallthrough cases with empty
1937    /// bodies, except for the last.
1938    ///
1939    /// Naga IR does not have "phi" instructions. If you need to use
1940    /// values computed in a [`SwitchCase::body`] block after the `Switch`,
1941    /// store them in a [`LocalVariable`].
1942    ///
1943    /// [`value`]: SwitchCase::value
1944    /// [`body`]: SwitchCase::body
1945    /// [`Default`]: SwitchValue::Default
1946    Switch {
1947        selector: Handle<Expression>,
1948        cases: Vec<SwitchCase>,
1949    },
1950
1951    /// Executes a block repeatedly.
1952    ///
1953    /// Each iteration of the loop executes the `body` block, followed by the
1954    /// `continuing` block.
1955    ///
1956    /// Executing a [`Break`], [`Return`] or [`Kill`] statement exits the loop.
1957    ///
1958    /// A [`Continue`] statement in `body` jumps to the `continuing` block. The
1959    /// `continuing` block is meant to be used to represent structures like the
1960    /// third expression of a C-style `for` loop head, to which `continue`
1961    /// statements in the loop's body jump.
1962    ///
1963    /// The `continuing` block and its substatements must not contain `Return`
1964    /// or `Kill` statements, or any `Break` or `Continue` statements targeting
1965    /// this loop. (It may have `Break` and `Continue` statements targeting
1966    /// loops or switches nested within the `continuing` block.) Expressions
1967    /// emitted in `body` are in scope in `continuing`.
1968    ///
1969    /// If present, `break_if` is an expression which is evaluated after the
1970    /// continuing block. Expressions emitted in `body` or `continuing` are
1971    /// considered to be in scope. If the expression's value is true, control
1972    /// continues after the `Loop` statement, rather than branching back to the
1973    /// top of body as usual. The `break_if` expression corresponds to a "break
1974    /// if" statement in WGSL, or a loop whose back edge is an
1975    /// `OpBranchConditional` instruction in SPIR-V.
1976    ///
1977    /// Naga IR does not have "phi" instructions. If you need to use
1978    /// values computed in a `body` or `continuing` block after the
1979    /// `Loop`, store them in a [`LocalVariable`].
1980    ///
1981    /// [`Break`]: Statement::Break
1982    /// [`Continue`]: Statement::Continue
1983    /// [`Kill`]: Statement::Kill
1984    /// [`Return`]: Statement::Return
1985    /// [`break if`]: Self::Loop::break_if
1986    Loop {
1987        body: Block,
1988        continuing: Block,
1989        break_if: Option<Handle<Expression>>,
1990    },
1991
1992    /// Exits the innermost enclosing [`Loop`] or [`Switch`].
1993    ///
1994    /// A `Break` statement may only appear within a [`Loop`] or [`Switch`]
1995    /// statement. It may not break out of a [`Loop`] from within the loop's
1996    /// `continuing` block.
1997    ///
1998    /// [`Loop`]: Statement::Loop
1999    /// [`Switch`]: Statement::Switch
2000    Break,
2001
2002    /// Skips to the `continuing` block of the innermost enclosing [`Loop`].
2003    ///
2004    /// A `Continue` statement may only appear within the `body` block of the
2005    /// innermost enclosing [`Loop`] statement. It must not appear within that
2006    /// loop's `continuing` block.
2007    ///
2008    /// [`Loop`]: Statement::Loop
2009    Continue,
2010
2011    /// Returns from the function (possibly with a value).
2012    ///
2013    /// `Return` statements are forbidden within the `continuing` block of a
2014    /// [`Loop`] statement.
2015    ///
2016    /// [`Loop`]: Statement::Loop
2017    Return { value: Option<Handle<Expression>> },
2018
2019    /// Aborts the current shader execution.
2020    ///
2021    /// `Kill` statements are forbidden within the `continuing` block of a
2022    /// [`Loop`] statement.
2023    ///
2024    /// [`Loop`]: Statement::Loop
2025    Kill,
2026
2027    /// Synchronize invocations within the work group.
2028    /// The `Barrier` flags control which memory accesses should be synchronized.
2029    /// If empty, this becomes purely an execution barrier.
2030    ControlBarrier(Barrier),
2031
2032    /// Synchronize invocations within the work group.
2033    /// The `Barrier` flags control which memory accesses should be synchronized.
2034    MemoryBarrier(Barrier),
2035
2036    /// Stores a value at an address.
2037    ///
2038    /// For [`TypeInner::Atomic`] type behind the pointer, the value
2039    /// has to be a corresponding scalar.
2040    /// For other types behind the `pointer<T>`, the value is `T`.
2041    ///
2042    /// This statement is a barrier for any operations on the
2043    /// `Expression::LocalVariable` or `Expression::GlobalVariable`
2044    /// that is the destination of an access chain, started
2045    /// from the `pointer`.
2046    Store {
2047        pointer: Handle<Expression>,
2048        value: Handle<Expression>,
2049    },
2050    /// Stores a texel value to an image.
2051    ///
2052    /// The `image`, `coordinate`, and `array_index` fields have the same
2053    /// meanings as the corresponding operands of an [`ImageLoad`] expression;
2054    /// see that documentation for details. Storing into multisampled images or
2055    /// images with mipmaps is not supported, so there are no `level` or
2056    /// `sample` operands.
2057    ///
2058    /// This statement is a barrier for any operations on the corresponding
2059    /// [`Expression::GlobalVariable`] for this image.
2060    ///
2061    /// [`ImageLoad`]: Expression::ImageLoad
2062    ImageStore {
2063        image: Handle<Expression>,
2064        coordinate: Handle<Expression>,
2065        array_index: Option<Handle<Expression>>,
2066        value: Handle<Expression>,
2067    },
2068    /// Atomic function.
2069    Atomic {
2070        /// Pointer to an atomic value.
2071        ///
2072        /// This must be a [`Pointer`] to an [`Atomic`] value. The atomic's
2073        /// scalar type may be [`I32`] or [`U32`].
2074        ///
2075        /// If [`SHADER_INT64_ATOMIC_MIN_MAX`] or [`SHADER_INT64_ATOMIC_ALL_OPS`] are
2076        /// enabled, this may also be [`I64`] or [`U64`].
2077        ///
2078        /// If [`SHADER_FLOAT32_ATOMIC`] is enabled, this may be [`F32`].
2079        ///
2080        /// [`Pointer`]: TypeInner::Pointer
2081        /// [`Atomic`]: TypeInner::Atomic
2082        /// [`I32`]: Scalar::I32
2083        /// [`U32`]: Scalar::U32
2084        /// [`SHADER_INT64_ATOMIC_MIN_MAX`]: crate::valid::Capabilities::SHADER_INT64_ATOMIC_MIN_MAX
2085        /// [`SHADER_INT64_ATOMIC_ALL_OPS`]: crate::valid::Capabilities::SHADER_INT64_ATOMIC_ALL_OPS
2086        /// [`SHADER_FLOAT32_ATOMIC`]: crate::valid::Capabilities::SHADER_FLOAT32_ATOMIC
2087        /// [`I64`]: Scalar::I64
2088        /// [`U64`]: Scalar::U64
2089        /// [`F32`]: Scalar::F32
2090        pointer: Handle<Expression>,
2091
2092        /// Function to run on the atomic value.
2093        ///
2094        /// If [`pointer`] refers to a 64-bit atomic value, then:
2095        ///
2096        /// - The [`SHADER_INT64_ATOMIC_ALL_OPS`] capability allows any [`AtomicFunction`]
2097        ///   value here.
2098        ///
2099        /// - The [`SHADER_INT64_ATOMIC_MIN_MAX`] capability allows
2100        ///   [`AtomicFunction::Min`] and [`AtomicFunction::Max`]
2101        ///   in the [`Storage`] address space here.
2102        ///
2103        /// - If neither of those capabilities are present, then 64-bit scalar
2104        ///   atomics are not allowed.
2105        ///
2106        /// If [`pointer`] refers to a 32-bit floating-point atomic value, then:
2107        ///
2108        /// - The [`SHADER_FLOAT32_ATOMIC`] capability allows [`AtomicFunction::Add`],
2109        ///   [`AtomicFunction::Subtract`], and [`AtomicFunction::Exchange { compare: None }`]
2110        ///   in the [`Storage`] address space here.
2111        ///
2112        /// [`AtomicFunction::Exchange { compare: None }`]: AtomicFunction::Exchange
2113        /// [`pointer`]: Statement::Atomic::pointer
2114        /// [`Storage`]: AddressSpace::Storage
2115        /// [`SHADER_INT64_ATOMIC_MIN_MAX`]: crate::valid::Capabilities::SHADER_INT64_ATOMIC_MIN_MAX
2116        /// [`SHADER_INT64_ATOMIC_ALL_OPS`]: crate::valid::Capabilities::SHADER_INT64_ATOMIC_ALL_OPS
2117        /// [`SHADER_FLOAT32_ATOMIC`]: crate::valid::Capabilities::SHADER_FLOAT32_ATOMIC
2118        fun: AtomicFunction,
2119
2120        /// Value to use in the function.
2121        ///
2122        /// This must be a scalar of the same type as [`pointer`]'s atomic's scalar type.
2123        ///
2124        /// [`pointer`]: Statement::Atomic::pointer
2125        value: Handle<Expression>,
2126
2127        /// [`AtomicResult`] expression representing this function's result.
2128        ///
2129        /// If [`fun`] is [`Exchange { compare: None }`], this must be `Some`,
2130        /// as otherwise that operation would be equivalent to a simple [`Store`]
2131        /// to the atomic.
2132        ///
2133        /// Otherwise, this may be `None` if the return value of the operation is not needed.
2134        ///
2135        /// If `pointer` refers to a 64-bit atomic value, [`SHADER_INT64_ATOMIC_MIN_MAX`]
2136        /// is enabled, and [`SHADER_INT64_ATOMIC_ALL_OPS`] is not, this must be `None`.
2137        ///
2138        /// [`AtomicResult`]: crate::Expression::AtomicResult
2139        /// [`fun`]: Statement::Atomic::fun
2140        /// [`Store`]: Statement::Store
2141        /// [`Exchange { compare: None }`]: AtomicFunction::Exchange
2142        /// [`SHADER_INT64_ATOMIC_MIN_MAX`]: crate::valid::Capabilities::SHADER_INT64_ATOMIC_MIN_MAX
2143        /// [`SHADER_INT64_ATOMIC_ALL_OPS`]: crate::valid::Capabilities::SHADER_INT64_ATOMIC_ALL_OPS
2144        result: Option<Handle<Expression>>,
2145    },
2146    /// Performs an atomic operation on a texel value of an image.
2147    ///
2148    /// Doing atomics on images with mipmaps is not supported, so there is no
2149    /// `level` operand.
2150    ImageAtomic {
2151        /// The image to perform an atomic operation on. This must have type
2152        /// [`Image`]. (This will necessarily be a [`GlobalVariable`] or
2153        /// [`FunctionArgument`] expression, since no other expressions are
2154        /// allowed to have that type.)
2155        ///
2156        /// [`Image`]: TypeInner::Image
2157        /// [`GlobalVariable`]: Expression::GlobalVariable
2158        /// [`FunctionArgument`]: Expression::FunctionArgument
2159        image: Handle<Expression>,
2160
2161        /// The coordinate of the texel we wish to load. This must be a scalar
2162        /// for [`D1`] images, a [`Bi`] vector for [`D2`] images, and a [`Tri`]
2163        /// vector for [`D3`] images. (Array indices, sample indices, and
2164        /// explicit level-of-detail values are supplied separately.) Its
2165        /// component type must be [`Sint`].
2166        ///
2167        /// [`D1`]: ImageDimension::D1
2168        /// [`D2`]: ImageDimension::D2
2169        /// [`D3`]: ImageDimension::D3
2170        /// [`Bi`]: VectorSize::Bi
2171        /// [`Tri`]: VectorSize::Tri
2172        /// [`Sint`]: ScalarKind::Sint
2173        coordinate: Handle<Expression>,
2174
2175        /// The index into an arrayed image. If the [`arrayed`] flag in
2176        /// `image`'s type is `true`, then this must be `Some(expr)`, where
2177        /// `expr` is a [`Sint`] scalar. Otherwise, it must be `None`.
2178        ///
2179        /// [`arrayed`]: TypeInner::Image::arrayed
2180        /// [`Sint`]: ScalarKind::Sint
2181        array_index: Option<Handle<Expression>>,
2182
2183        /// The kind of atomic operation to perform on the texel.
2184        fun: AtomicFunction,
2185
2186        /// The value with which to perform the atomic operation.
2187        value: Handle<Expression>,
2188    },
2189    /// Load uniformly from a uniform pointer in the workgroup address space.
2190    ///
2191    /// Corresponds to the [`workgroupUniformLoad`](https://www.w3.org/TR/WGSL/#workgroupUniformLoad-builtin)
2192    /// built-in function of wgsl, and has the same barrier semantics
2193    WorkGroupUniformLoad {
2194        /// This must be of type [`Pointer`] in the [`WorkGroup`] address space
2195        ///
2196        /// [`Pointer`]: TypeInner::Pointer
2197        /// [`WorkGroup`]: AddressSpace::WorkGroup
2198        pointer: Handle<Expression>,
2199        /// The [`WorkGroupUniformLoadResult`] expression representing this load's result.
2200        ///
2201        /// [`WorkGroupUniformLoadResult`]: Expression::WorkGroupUniformLoadResult
2202        result: Handle<Expression>,
2203    },
2204    /// Calls a function.
2205    ///
2206    /// If the `result` is `Some`, the corresponding expression has to be
2207    /// `Expression::CallResult`, and this statement serves as a barrier for any
2208    /// operations on that expression.
2209    Call {
2210        function: Handle<Function>,
2211        arguments: Vec<Handle<Expression>>,
2212        result: Option<Handle<Expression>>,
2213    },
2214    RayQuery {
2215        /// The [`RayQuery`] object this statement operates on.
2216        ///
2217        /// [`RayQuery`]: TypeInner::RayQuery
2218        query: Handle<Expression>,
2219
2220        /// The specific operation we're performing on `query`.
2221        fun: RayQueryFunction,
2222    },
2223    /// Calculate a bitmask using a boolean from each active thread in the subgroup
2224    SubgroupBallot {
2225        /// The [`SubgroupBallotResult`] expression representing this load's result.
2226        ///
2227        /// [`SubgroupBallotResult`]: Expression::SubgroupBallotResult
2228        result: Handle<Expression>,
2229        /// The value from this thread to store in the ballot
2230        predicate: Option<Handle<Expression>>,
2231    },
2232    /// Gather a value from another active thread in the subgroup
2233    SubgroupGather {
2234        /// Specifies which thread to gather from
2235        mode: GatherMode,
2236        /// The value to broadcast over
2237        argument: Handle<Expression>,
2238        /// The [`SubgroupOperationResult`] expression representing this load's result.
2239        ///
2240        /// [`SubgroupOperationResult`]: Expression::SubgroupOperationResult
2241        result: Handle<Expression>,
2242    },
2243    /// Compute a collective operation across all active threads in the subgroup
2244    SubgroupCollectiveOperation {
2245        /// What operation to compute
2246        op: SubgroupOperation,
2247        /// How to combine the results
2248        collective_op: CollectiveOperation,
2249        /// The value to compute over
2250        argument: Handle<Expression>,
2251        /// The [`SubgroupOperationResult`] expression representing this load's result.
2252        ///
2253        /// [`SubgroupOperationResult`]: Expression::SubgroupOperationResult
2254        result: Handle<Expression>,
2255    },
2256}
2257
2258/// A function argument.
2259#[derive(Clone, Debug)]
2260#[cfg_attr(feature = "serialize", derive(Serialize))]
2261#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2262#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2263pub struct FunctionArgument {
2264    /// Name of the argument, if any.
2265    pub name: Option<String>,
2266    /// Type of the argument.
2267    pub ty: Handle<Type>,
2268    /// For entry points, an argument has to have a binding
2269    /// unless it's a structure.
2270    pub binding: Option<Binding>,
2271}
2272
2273/// A function result.
2274#[derive(Clone, Debug)]
2275#[cfg_attr(feature = "serialize", derive(Serialize))]
2276#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2277#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2278pub struct FunctionResult {
2279    /// Type of the result.
2280    pub ty: Handle<Type>,
2281    /// For entry points, the result has to have a binding
2282    /// unless it's a structure.
2283    pub binding: Option<Binding>,
2284}
2285
2286/// A function defined in the module.
2287#[derive(Debug, Default, Clone)]
2288#[cfg_attr(feature = "serialize", derive(Serialize))]
2289#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2290#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2291pub struct Function {
2292    /// Name of the function, if any.
2293    pub name: Option<String>,
2294    /// Information about function argument.
2295    pub arguments: Vec<FunctionArgument>,
2296    /// The result of this function, if any.
2297    pub result: Option<FunctionResult>,
2298    /// Local variables defined and used in the function.
2299    pub local_variables: Arena<LocalVariable>,
2300    /// Expressions used inside this function.
2301    ///
2302    /// Unless explicitly stated otherwise, if an [`Expression`] is in this
2303    /// arena, then its subexpressions are in this arena too. In other words,
2304    /// every `Handle<Expression>` in this arena refers to an [`Expression`] in
2305    /// this arena too.
2306    ///
2307    /// The main ways this arena refers to [`Module::global_expressions`] are:
2308    ///
2309    /// - [`Constant`], [`Override`], and [`GlobalVariable`] expressions hold
2310    ///   handles for their respective types, whose initializer expressions are
2311    ///   in [`Module::global_expressions`].
2312    ///
2313    /// - Various expressions hold [`Type`] handles, and [`Type`]s may refer to
2314    ///   global expressions, for things like array lengths.
2315    ///
2316    /// An [`Expression`] must occur before all other [`Expression`]s that use
2317    /// its value.
2318    ///
2319    /// [`Constant`]: Expression::Constant
2320    /// [`Override`]: Expression::Override
2321    /// [`GlobalVariable`]: Expression::GlobalVariable
2322    pub expressions: Arena<Expression>,
2323    /// Map of expressions that have associated variable names
2324    pub named_expressions: NamedExpressions,
2325    /// Block of instructions comprising the body of the function.
2326    pub body: Block,
2327    /// The leaf of all diagnostic filter rules tree (stored in [`Module::diagnostic_filters`])
2328    /// parsed on this function.
2329    ///
2330    /// In WGSL, this corresponds to `@diagnostic(…)` attributes.
2331    ///
2332    /// See [`DiagnosticFilterNode`] for details on how the tree is represented and used in
2333    /// validation.
2334    pub diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
2335}
2336
2337/// The main function for a pipeline stage.
2338///
2339/// An [`EntryPoint`] is a [`Function`] that serves as the main function for a
2340/// graphics or compute pipeline stage. For example, an `EntryPoint` whose
2341/// [`stage`] is [`ShaderStage::Vertex`] can serve as a graphics pipeline's
2342/// vertex shader.
2343///
2344/// Since an entry point is called directly by the graphics or compute pipeline,
2345/// not by other WGSL functions, you must specify what the pipeline should pass
2346/// as the entry point's arguments, and what values it will return. For example,
2347/// a vertex shader needs a vertex's attributes as its arguments, but if it's
2348/// used for instanced draw calls, it will also want to know the instance id.
2349/// The vertex shader's return value will usually include an output vertex
2350/// position, and possibly other attributes to be interpolated and passed along
2351/// to a fragment shader.
2352///
2353/// To specify this, the arguments and result of an `EntryPoint`'s [`function`]
2354/// must each have a [`Binding`], or be structs whose members all have
2355/// `Binding`s. This associates every value passed to or returned from the entry
2356/// point with either a [`BuiltIn`] or a [`Location`]:
2357///
2358/// -   A [`BuiltIn`] has special semantics, usually specific to its pipeline
2359///     stage. For example, the result of a vertex shader can include a
2360///     [`BuiltIn::Position`] value, which determines the position of a vertex
2361///     of a rendered primitive. Or, a compute shader might take an argument
2362///     whose binding is [`BuiltIn::WorkGroupSize`], through which the compute
2363///     pipeline would pass the number of invocations in your workgroup.
2364///
2365/// -   A [`Location`] indicates user-defined IO to be passed from one pipeline
2366///     stage to the next. For example, a vertex shader might also produce a
2367///     `uv` texture location as a user-defined IO value.
2368///
2369/// In other words, the pipeline stage's input and output interface are
2370/// determined by the bindings of the arguments and result of the `EntryPoint`'s
2371/// [`function`].
2372///
2373/// [`Function`]: crate::Function
2374/// [`Location`]: Binding::Location
2375/// [`function`]: EntryPoint::function
2376/// [`stage`]: EntryPoint::stage
2377#[derive(Debug, Clone)]
2378#[cfg_attr(feature = "serialize", derive(Serialize))]
2379#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2380#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2381pub struct EntryPoint {
2382    /// Name of this entry point, visible externally.
2383    ///
2384    /// Entry point names for a given `stage` must be distinct within a module.
2385    pub name: String,
2386    /// Shader stage.
2387    pub stage: ShaderStage,
2388    /// Early depth test for fragment stages.
2389    pub early_depth_test: Option<EarlyDepthTest>,
2390    /// Workgroup size for compute stages
2391    pub workgroup_size: [u32; 3],
2392    /// Override expressions for workgroup size in the global_expressions arena
2393    pub workgroup_size_overrides: Option<[Option<Handle<Expression>>; 3]>,
2394    /// The entrance function.
2395    pub function: Function,
2396    /// Information for [`Mesh`] shaders.
2397    ///
2398    /// [`Mesh`]: ShaderStage::Mesh
2399    pub mesh_info: Option<MeshStageInfo>,
2400    /// The unique global variable used as a task payload from task shader to mesh shader
2401    pub task_payload: Option<Handle<GlobalVariable>>,
2402}
2403
2404/// Return types predeclared for the frexp, modf, and atomicCompareExchangeWeak built-in functions.
2405///
2406/// These cannot be spelled in WGSL source.
2407///
2408/// Stored in [`SpecialTypes::predeclared_types`] and created by [`Module::generate_predeclared_type`].
2409#[derive(Debug, PartialEq, Eq, Hash, Clone)]
2410#[cfg_attr(feature = "serialize", derive(Serialize))]
2411#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2412#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2413pub enum PredeclaredType {
2414    AtomicCompareExchangeWeakResult(Scalar),
2415    ModfResult {
2416        size: Option<VectorSize>,
2417        scalar: Scalar,
2418    },
2419    FrexpResult {
2420        size: Option<VectorSize>,
2421        scalar: Scalar,
2422    },
2423}
2424
2425/// Set of special types that can be optionally generated by the frontends.
2426#[derive(Debug, Default, Clone)]
2427#[cfg_attr(feature = "serialize", derive(Serialize))]
2428#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2429#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2430pub struct SpecialTypes {
2431    /// Type for `RayDesc`.
2432    ///
2433    /// Call [`Module::generate_ray_desc_type`] to populate this if
2434    /// needed and return the handle.
2435    pub ray_desc: Option<Handle<Type>>,
2436
2437    /// Type for `RayIntersection`.
2438    ///
2439    /// Call [`Module::generate_ray_intersection_type`] to populate
2440    /// this if needed and return the handle.
2441    pub ray_intersection: Option<Handle<Type>>,
2442
2443    /// Type for `RayVertexReturn`.
2444    ///
2445    /// Call [`Module::generate_vertex_return_type`]
2446    pub ray_vertex_return: Option<Handle<Type>>,
2447
2448    /// Struct containing parameters required by some backends to emit code for
2449    /// [`ImageClass::External`] textures.
2450    ///
2451    /// See `wgpu_core::device::resource::ExternalTextureParams` for the
2452    /// documentation of each field.
2453    ///
2454    /// In WGSL, this type would be:
2455    ///
2456    /// ```ignore
2457    /// struct NagaExternalTextureParams {         // align size offset
2458    ///     yuv_conversion_matrix: mat4x4<f32>,    //    16   64      0
2459    ///     gamut_conversion_matrix: mat3x3<f32>,  //    16   48     64
2460    ///     src_tf: NagaExternalTextureTransferFn, //     4   16    112
2461    ///     dst_tf: NagaExternalTextureTransferFn, //     4   16    128
2462    ///     sample_transform: mat3x2<f32>,         //     8   24    144
2463    ///     load_transform: mat3x2<f32>,           //     8   24    168
2464    ///     size: vec2<u32>,                       //     8    8    192
2465    ///     num_planes: u32,                       //     4    4    200
2466    /// }                            // whole struct:    16  208
2467    /// ```
2468    ///
2469    /// Call [`Module::generate_external_texture_types`] to populate this if
2470    /// needed.
2471    pub external_texture_params: Option<Handle<Type>>,
2472
2473    /// Struct describing a gamma encoding transfer function. Member of
2474    /// `NagaExternalTextureParams`, describing how the backend should perform
2475    /// color space conversion when sampling from [`ImageClass::External`]
2476    /// textures.
2477    ///
2478    /// In WGSL, this type would be:
2479    ///
2480    /// ```ignore
2481    /// struct NagaExternalTextureTransferFn { // align size offset
2482    ///     a: f32,                            //     4    4      0
2483    ///     b: f32,                            //     4    4      4
2484    ///     g: f32,                            //     4    4      8
2485    ///     k: f32,                            //     4    4     12
2486    /// }                         // whole struct:    4   16
2487    /// ```
2488    ///
2489    /// Call [`Module::generate_external_texture_types`] to populate this if
2490    /// needed.
2491    pub external_texture_transfer_function: Option<Handle<Type>>,
2492
2493    /// Types for predeclared wgsl types instantiated on demand.
2494    ///
2495    /// Call [`Module::generate_predeclared_type`] to populate this if
2496    /// needed and return the handle.
2497    pub predeclared_types: FastIndexMap<PredeclaredType, Handle<Type>>,
2498}
2499
2500bitflags::bitflags! {
2501    /// Ray flags used when casting rays.
2502    /// Matching vulkan constants can be found in
2503    /// https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/ray_common/ray_flags_section.txt
2504    #[cfg_attr(feature = "serialize", derive(Serialize))]
2505    #[cfg_attr(feature = "deserialize", derive(Deserialize))]
2506    #[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2507    #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
2508    pub struct RayFlag: u32 {
2509        /// Force all intersections to be treated as opaque.
2510        const FORCE_OPAQUE = 0x1;
2511        /// Force all intersections to be treated as non-opaque.
2512        const FORCE_NO_OPAQUE = 0x2;
2513        /// Stop traversal after the first hit.
2514        const TERMINATE_ON_FIRST_HIT = 0x4;
2515        /// Don't execute the closest hit shader.
2516        const SKIP_CLOSEST_HIT_SHADER = 0x8;
2517        /// Cull back facing geometry.
2518        const CULL_BACK_FACING = 0x10;
2519        /// Cull front facing geometry.
2520        const CULL_FRONT_FACING = 0x20;
2521        /// Cull opaque geometry.
2522        const CULL_OPAQUE = 0x40;
2523        /// Cull non-opaque geometry.
2524        const CULL_NO_OPAQUE = 0x80;
2525        /// Skip triangular geometry.
2526        const SKIP_TRIANGLES = 0x100;
2527        /// Skip axis-aligned bounding boxes.
2528        const SKIP_AABBS = 0x200;
2529    }
2530}
2531
2532/// Type of a ray query intersection.
2533/// Matching vulkan constants can be found in
2534/// <https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/KHR/SPV_KHR_ray_query.asciidoc>
2535/// but the actual values are different for candidate intersections.
2536#[cfg_attr(feature = "serialize", derive(Serialize))]
2537#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2538#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2539#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
2540pub enum RayQueryIntersection {
2541    /// No intersection found.
2542    /// Matches `RayQueryCommittedIntersectionNoneKHR`.
2543    #[default]
2544    None = 0,
2545    /// Intersecting with triangles.
2546    /// Matches `RayQueryCommittedIntersectionTriangleKHR` and `RayQueryCandidateIntersectionTriangleKHR`.
2547    Triangle = 1,
2548    /// Intersecting with generated primitives.
2549    /// Matches `RayQueryCommittedIntersectionGeneratedKHR`.
2550    Generated = 2,
2551    /// Intersecting with Axis Aligned Bounding Boxes.
2552    /// Matches `RayQueryCandidateIntersectionAABBKHR`.
2553    Aabb = 3,
2554}
2555
2556/// Doc comments preceding items.
2557///
2558/// These can be used to generate automated documentation,
2559/// IDE hover information or translate shaders with their context comments.
2560#[derive(Debug, Default, Clone)]
2561#[cfg_attr(feature = "serialize", derive(Serialize))]
2562#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2563#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2564pub struct DocComments {
2565    pub types: FastIndexMap<Handle<Type>, Vec<String>>,
2566    // The key is:
2567    // - key.0: the handle to the Struct
2568    // - key.1: the index of the `StructMember`.
2569    pub struct_members: FastIndexMap<(Handle<Type>, usize), Vec<String>>,
2570    pub entry_points: FastIndexMap<usize, Vec<String>>,
2571    pub functions: FastIndexMap<Handle<Function>, Vec<String>>,
2572    pub constants: FastIndexMap<Handle<Constant>, Vec<String>>,
2573    pub global_variables: FastIndexMap<Handle<GlobalVariable>, Vec<String>>,
2574    // Top level comments, appearing before any space.
2575    pub module: Vec<String>,
2576}
2577
2578/// The output topology for a mesh shader. Note that mesh shaders don't allow things like triangle-strips.
2579#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2580#[cfg_attr(feature = "serialize", derive(Serialize))]
2581#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2582#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2583pub enum MeshOutputTopology {
2584    /// Outputs individual vertices to be rendered as points.
2585    Points,
2586    /// Outputs groups of 2 vertices to be renderedas lines .
2587    Lines,
2588    /// Outputs groups of 3 vertices to be rendered as triangles.
2589    Triangles,
2590}
2591
2592/// Information specific to mesh shader entry points.
2593#[derive(Debug, Clone, PartialEq, Eq)]
2594#[cfg_attr(feature = "serialize", derive(Serialize))]
2595#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2596#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2597#[allow(dead_code)]
2598pub struct MeshStageInfo {
2599    /// The type of primitive outputted.
2600    pub topology: MeshOutputTopology,
2601    /// The maximum number of vertices a mesh shader may output.
2602    pub max_vertices: u32,
2603    /// If pipeline constants are used, the expressions that override `max_vertices`
2604    pub max_vertices_override: Option<Handle<Expression>>,
2605    /// The maximum number of primitives a mesh shader may output.
2606    pub max_primitives: u32,
2607    /// If pipeline constants are used, the expressions that override `max_primitives`
2608    pub max_primitives_override: Option<Handle<Expression>>,
2609    /// The type used by vertex outputs, i.e. what is passed to `setVertex`.
2610    pub vertex_output_type: Handle<Type>,
2611    /// The type used by primitive outputs, i.e. what is passed to `setPrimitive`.
2612    pub primitive_output_type: Handle<Type>,
2613    /// The global variable holding the outputted vertices, primitives, and counts
2614    pub output_variable: Handle<GlobalVariable>,
2615}
2616
2617/// Shader module.
2618///
2619/// A module is a set of constants, global variables and functions, as well as
2620/// the types required to define them.
2621///
2622/// Some functions are marked as entry points, to be used in a certain shader stage.
2623///
2624/// To create a new module, use the `Default` implementation.
2625/// Alternatively, you can load an existing shader using one of the [available front ends].
2626///
2627/// When finished, you can export modules using one of the [available backends].
2628///
2629/// ## Module arenas
2630///
2631/// Most module contents are stored in [`Arena`]s. In a valid module, arena
2632/// elements only refer to prior arena elements. That is, whenever an element in
2633/// some `Arena<T>` contains a `Handle<T>` referring to another element the same
2634/// arena, the handle's referent always precedes the element containing the
2635/// handle.
2636///
2637/// The elements of [`Module::types`] may refer to [`Expression`]s in
2638/// [`Module::global_expressions`], and those expressions may in turn refer back
2639/// to [`Type`]s in [`Module::types`]. In a valid module, there exists an order
2640/// in which all types and global expressions can be visited such that:
2641///
2642/// - types and expressions are visited in the order in which they appear in
2643///   their arenas, and
2644///
2645/// - every element refers only to previously visited elements.
2646///
2647/// This implies that the graph of types and global expressions is acyclic.
2648/// (However, it is a stronger condition: there are cycle-free arrangements of
2649/// types and expressions for which an order like the one described above does
2650/// not exist. Modules arranged in such a way are not valid.)
2651///
2652/// [available front ends]: crate::front
2653/// [available backends]: crate::back
2654#[derive(Debug, Default, Clone)]
2655#[cfg_attr(feature = "serialize", derive(Serialize))]
2656#[cfg_attr(feature = "deserialize", derive(Deserialize))]
2657#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
2658pub struct Module {
2659    /// Arena for the types defined in this module.
2660    ///
2661    /// See the [`Module`] docs for more details about this field.
2662    pub types: UniqueArena<Type>,
2663    /// Dictionary of special type handles.
2664    pub special_types: SpecialTypes,
2665    /// Arena for the constants defined in this module.
2666    pub constants: Arena<Constant>,
2667    /// Arena for the pipeline-overridable constants defined in this module.
2668    pub overrides: Arena<Override>,
2669    /// Arena for the global variables defined in this module.
2670    pub global_variables: Arena<GlobalVariable>,
2671    /// [Constant expressions] and [override expressions] used by this module.
2672    ///
2673    /// If an expression is in this arena, then its subexpressions are in this
2674    /// arena too. In other words, every `Handle<Expression>` in this arena
2675    /// refers to an [`Expression`] in this arena too.
2676    ///
2677    /// See the [`Module`] docs for more details about this field.
2678    ///
2679    /// [Constant expressions]: index.html#constant-expressions
2680    /// [override expressions]: index.html#override-expressions
2681    pub global_expressions: Arena<Expression>,
2682    /// Arena for the functions defined in this module.
2683    ///
2684    /// Each function must appear in this arena strictly before all its callers.
2685    /// Recursion is not supported.
2686    pub functions: Arena<Function>,
2687    /// Entry points.
2688    pub entry_points: Vec<EntryPoint>,
2689    /// Arena for all diagnostic filter rules parsed in this module, including those in functions
2690    /// and statements.
2691    ///
2692    /// This arena contains elements of a _tree_ of diagnostic filter rules. When nodes are built
2693    /// by a front-end, they refer to a parent scope
2694    pub diagnostic_filters: Arena<DiagnosticFilterNode>,
2695    /// The leaf of all diagnostic filter rules tree parsed from directives in this module.
2696    ///
2697    /// In WGSL, this corresponds to `diagnostic(…);` directives.
2698    ///
2699    /// See [`DiagnosticFilterNode`] for details on how the tree is represented and used in
2700    /// validation.
2701    pub diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
2702    /// Doc comments.
2703    pub doc_comments: Option<Box<DocComments>>,
2704}