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