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