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