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