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