wgpu_types/
render.rs

1//! Types for configuring render passes and render pipelines (except for vertex attributes).
2
3use bytemuck::{Pod, Zeroable};
4use macro_rules_attribute::derive;
5
6#[cfg(any(feature = "serde", test))]
7use serde::{Deserialize, Serialize};
8
9use crate::{link_to_wgpu_docs, ConstDefault, LoadOpDontCare};
10
11#[cfg(doc)]
12use crate::{Features, TextureFormat};
13
14/// Alpha blend factor.
15///
16/// Corresponds to [WebGPU `GPUBlendFactor`](
17/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendfactor). Values using `Src1`
18/// require [`Features::DUAL_SOURCE_BLENDING`] and can only be used with the first
19/// render target.
20///
21/// For further details on how the blend factors are applied, see the analogous
22/// functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Blending#Blending_Parameters>.
23#[repr(C)]
24#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
27pub enum BlendFactor {
28    /// 0.0
29    Zero = 0,
30    /// 1.0
31    One = 1,
32    /// S.component
33    Src = 2,
34    /// 1.0 - S.component
35    OneMinusSrc = 3,
36    /// S.alpha
37    SrcAlpha = 4,
38    /// 1.0 - S.alpha
39    OneMinusSrcAlpha = 5,
40    /// D.component
41    Dst = 6,
42    /// 1.0 - D.component
43    OneMinusDst = 7,
44    /// D.alpha
45    DstAlpha = 8,
46    /// 1.0 - D.alpha
47    OneMinusDstAlpha = 9,
48    /// min(S.alpha, 1.0 - D.alpha)
49    SrcAlphaSaturated = 10,
50    /// Constant
51    Constant = 11,
52    /// 1.0 - Constant
53    OneMinusConstant = 12,
54    /// S1.component
55    Src1 = 13,
56    /// 1.0 - S1.component
57    OneMinusSrc1 = 14,
58    /// S1.alpha
59    Src1Alpha = 15,
60    /// 1.0 - S1.alpha
61    OneMinusSrc1Alpha = 16,
62}
63
64impl BlendFactor {
65    /// Returns `true` if the blend factor references the second blend source.
66    ///
67    /// Note that the usage of those blend factors require [`Features::DUAL_SOURCE_BLENDING`].
68    #[must_use]
69    pub fn uses_second_blend_source(&self) -> bool {
70        match self {
71            BlendFactor::Src1
72            | BlendFactor::OneMinusSrc1
73            | BlendFactor::Src1Alpha
74            | BlendFactor::OneMinusSrc1Alpha => true,
75            _ => false,
76        }
77    }
78
79    /// Returns `true` if the blend factor references the source alpha.
80    #[must_use]
81    pub fn uses_source_alpha(&self) -> bool {
82        match self {
83            BlendFactor::SrcAlpha
84            | BlendFactor::OneMinusSrcAlpha
85            | BlendFactor::SrcAlphaSaturated
86            | BlendFactor::Src1Alpha
87            | BlendFactor::OneMinusSrc1Alpha => true,
88            _ => false,
89        }
90    }
91}
92
93/// Alpha blend operation.
94///
95/// Corresponds to [WebGPU `GPUBlendOperation`](
96/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendoperation).
97///
98/// For further details on how the blend operations are applied, see
99/// the analogous functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Blending#Blend_Equations>.
100#[repr(C)]
101#[derive(Copy, Clone, Debug, ConstDefault!, Hash, Eq, PartialEq)]
102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
103#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
104pub enum BlendOperation {
105    /// Src + Dst
106    #[custom(default)]
107    Add = 0,
108    /// Src - Dst
109    Subtract = 1,
110    /// Dst - Src
111    ReverseSubtract = 2,
112    /// min(Src, Dst)
113    Min = 3,
114    /// max(Src, Dst)
115    Max = 4,
116}
117
118/// Describes a blend component of a [`BlendState`].
119///
120/// Corresponds to [WebGPU `GPUBlendComponent`](
121/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendcomponent).
122#[repr(C)]
123#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
125#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
126pub struct BlendComponent {
127    /// Multiplier for the source, which is produced by the fragment shader.
128    pub src_factor: BlendFactor,
129    /// Multiplier for the destination, which is stored in the target.
130    pub dst_factor: BlendFactor,
131    /// The binary operation applied to the source and destination,
132    /// multiplied by their respective factors.
133    pub operation: BlendOperation,
134}
135
136impl BlendComponent {
137    /// Default blending state that replaces destination with the source.
138    pub const REPLACE: Self = Self {
139        src_factor: BlendFactor::One,
140        dst_factor: BlendFactor::Zero,
141        operation: BlendOperation::Add,
142    };
143
144    /// Blend state of `(1 * src) + ((1 - src_alpha) * dst)`.
145    pub const OVER: Self = Self {
146        src_factor: BlendFactor::One,
147        dst_factor: BlendFactor::OneMinusSrcAlpha,
148        operation: BlendOperation::Add,
149    };
150
151    /// Returns true if the state relies on the constant color, which is
152    /// set independently on a render command encoder.
153    #[must_use]
154    pub fn uses_constant(&self) -> bool {
155        match (self.src_factor, self.dst_factor) {
156            (BlendFactor::Constant, _)
157            | (BlendFactor::OneMinusConstant, _)
158            | (_, BlendFactor::Constant)
159            | (_, BlendFactor::OneMinusConstant) => true,
160            (_, _) => false,
161        }
162    }
163}
164
165impl Default for BlendComponent {
166    fn default() -> Self {
167        Self::REPLACE
168    }
169}
170
171/// Describe the blend state of a render pipeline,
172/// within [`ColorTargetState`].
173///
174/// Corresponds to [WebGPU `GPUBlendState`](
175/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendstate).
176#[repr(C)]
177#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
178#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
179#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
180pub struct BlendState {
181    /// Color equation.
182    pub color: BlendComponent,
183    /// Alpha equation.
184    pub alpha: BlendComponent,
185}
186
187impl BlendState {
188    /// Blend mode that does no color blending, just overwrites the output with the contents of the shader.
189    pub const REPLACE: Self = Self {
190        color: BlendComponent::REPLACE,
191        alpha: BlendComponent::REPLACE,
192    };
193
194    /// Blend mode that does standard alpha blending with non-premultiplied alpha.
195    pub const ALPHA_BLENDING: Self = Self {
196        color: BlendComponent {
197            src_factor: BlendFactor::SrcAlpha,
198            dst_factor: BlendFactor::OneMinusSrcAlpha,
199            operation: BlendOperation::Add,
200        },
201        alpha: BlendComponent::OVER,
202    };
203
204    /// Blend mode that does standard alpha blending with premultiplied alpha.
205    pub const PREMULTIPLIED_ALPHA_BLENDING: Self = Self {
206        color: BlendComponent::OVER,
207        alpha: BlendComponent::OVER,
208    };
209
210    /// Blend mode that does standard additive blending.
211    pub const ADDITIVE: Self = Self {
212        color: BlendComponent {
213            src_factor: BlendFactor::One,
214            dst_factor: BlendFactor::One,
215            operation: BlendOperation::Add,
216        },
217        alpha: BlendComponent {
218            src_factor: BlendFactor::One,
219            dst_factor: BlendFactor::One,
220            operation: BlendOperation::Add,
221        },
222    };
223}
224
225/// Describes the color state of a render pipeline.
226///
227/// Corresponds to [WebGPU `GPUColorTargetState`](
228/// https://gpuweb.github.io/gpuweb/#dictdef-gpucolortargetstate).
229#[repr(C)]
230#[derive(Clone, Debug, PartialEq, Eq, Hash)]
231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
232#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
233pub struct ColorTargetState {
234    /// The [`TextureFormat`] of the image that this pipeline will render to. Must match the format
235    /// of the corresponding color attachment in [`CommandEncoder::begin_render_pass`][CEbrp]
236    ///
237    #[doc = link_to_wgpu_docs!(["CEbrp"]: "struct.CommandEncoder.html#method.begin_render_pass")]
238    pub format: crate::TextureFormat,
239    /// The blending that is used for this pipeline.
240    #[cfg_attr(feature = "serde", serde(default))]
241    pub blend: Option<BlendState>,
242    /// Mask which enables/disables writes to different color/alpha channel.
243    #[cfg_attr(feature = "serde", serde(default))]
244    pub write_mask: ColorWrites,
245}
246
247impl From<crate::TextureFormat> for ColorTargetState {
248    fn from(format: crate::TextureFormat) -> Self {
249        Self {
250            format,
251            blend: None,
252            write_mask: ColorWrites::ALL,
253        }
254    }
255}
256
257/// Color write mask. Disabled color channels will not be written to.
258///
259/// Corresponds to [WebGPU `GPUColorWriteFlags`](
260/// https://gpuweb.github.io/gpuweb/#typedefdef-gpucolorwriteflags).
261#[repr(transparent)]
262#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
263#[cfg_attr(feature = "serde", serde(transparent))]
264#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
265pub struct ColorWrites(u32);
266
267bitflags::bitflags! {
268    impl ColorWrites: u32 {
269        /// Do not write any channels
270        const NONE = 0;
271        /// Enable red channel writes
272        const RED = 1 << 0;
273        /// Enable green channel writes
274        const GREEN = 1 << 1;
275        /// Enable blue channel writes
276        const BLUE = 1 << 2;
277        /// Enable alpha channel writes
278        const ALPHA = 1 << 3;
279        /// Enable red, green, and blue channel writes
280        const COLOR = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits();
281        /// Enable writes to all channels.
282        const ALL = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits() | Self::ALPHA.bits();
283    }
284}
285
286impl Default for ColorWrites {
287    fn default() -> Self {
288        Self::ALL
289    }
290}
291
292/// Primitive type the input mesh is composed of.
293///
294/// Corresponds to [WebGPU `GPUPrimitiveTopology`](
295/// https://gpuweb.github.io/gpuweb/#enumdef-gpuprimitivetopology).
296#[repr(C)]
297#[derive(Copy, Clone, Debug, ConstDefault!, Hash, Eq, PartialEq)]
298#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
299#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
300pub enum PrimitiveTopology {
301    /// Vertex data is a list of points. Each vertex is a new point.
302    PointList = 0,
303    /// Vertex data is a list of lines. Each pair of vertices composes a new line.
304    ///
305    /// Vertices `0 1 2 3` create two lines `0 1` and `2 3`
306    LineList = 1,
307    /// Vertex data is a strip of lines. Each set of two adjacent vertices form a line.
308    ///
309    /// Vertices `0 1 2 3` create three lines `0 1`, `1 2`, and `2 3`.
310    LineStrip = 2,
311    /// Vertex data is a list of triangles. Each set of 3 vertices composes a new triangle.
312    ///
313    /// Vertices `0 1 2 3 4 5` create two triangles `0 1 2` and `3 4 5`
314    #[custom(default)]
315    TriangleList = 3,
316    /// Vertex data is a triangle strip. Each set of three adjacent vertices form a triangle.
317    ///
318    /// Vertices `0 1 2 3 4 5` create four triangles `0 1 2`, `2 1 3`, `2 3 4`, and `4 3 5`
319    TriangleStrip = 4,
320}
321
322impl PrimitiveTopology {
323    /// Returns true for strip topologies.
324    #[must_use]
325    pub fn is_strip(&self) -> bool {
326        match *self {
327            Self::PointList | Self::LineList | Self::TriangleList => false,
328            Self::LineStrip | Self::TriangleStrip => true,
329        }
330    }
331
332    /// Returns true for triangle topologies.
333    #[must_use]
334    pub fn is_triangles(&self) -> bool {
335        match *self {
336            Self::TriangleList | Self::TriangleStrip => true,
337            Self::PointList | Self::LineList | Self::LineStrip => false,
338        }
339    }
340}
341
342/// Vertex winding order which classifies the "front" face of a triangle.
343///
344/// Corresponds to [WebGPU `GPUFrontFace`](
345/// https://gpuweb.github.io/gpuweb/#enumdef-gpufrontface).
346#[repr(C)]
347#[derive(Copy, Clone, Debug, ConstDefault!, PartialEq, Eq, Hash)]
348#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
349#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
350pub enum FrontFace {
351    /// Triangles with vertices in counter clockwise order are considered the front face.
352    ///
353    /// This is the default with right handed coordinate spaces.
354    #[custom(default)]
355    Ccw = 0,
356    /// Triangles with vertices in clockwise order are considered the front face.
357    ///
358    /// This is the default with left handed coordinate spaces.
359    Cw = 1,
360}
361
362/// Face of a vertex.
363///
364/// Corresponds to [WebGPU `GPUCullMode`](
365/// https://gpuweb.github.io/gpuweb/#enumdef-gpucullmode),
366/// except that the `"none"` value is represented using `Option<Face>` instead.
367#[repr(C)]
368#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
370#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
371pub enum Face {
372    /// Front face
373    Front = 0,
374    /// Back face
375    Back = 1,
376}
377
378/// Type of drawing mode for polygons
379#[repr(C)]
380#[derive(Copy, Clone, Debug, ConstDefault!, PartialEq, Eq, Hash)]
381#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
382#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
383pub enum PolygonMode {
384    /// Polygons are filled
385    #[custom(default)]
386    Fill = 0,
387    /// Polygons are drawn as line segments
388    Line = 1,
389    /// Polygons are drawn as points
390    Point = 2,
391}
392
393/// Describes the state of primitive assembly and rasterization in a render pipeline.
394///
395/// Corresponds to [WebGPU `GPUPrimitiveState`](
396/// https://gpuweb.github.io/gpuweb/#dictdef-gpuprimitivestate).
397#[repr(C)]
398#[derive(Clone, Copy, Debug, ConstDefault!, PartialEq, Eq, Hash)]
399#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
400#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
401pub struct PrimitiveState {
402    /// The primitive topology used to interpret vertices.
403    pub topology: PrimitiveTopology,
404    /// When drawing strip topologies with indices, this is the required format for the index buffer.
405    /// This has no effect on non-indexed or non-strip draws.
406    ///
407    /// This is required for indexed drawing with strip topology and must match index buffer format, as primitive restart is always enabled
408    /// in all backends and individual strips will be separated
409    /// with the index value `0xFFFF` when using `Uint16`, or `0xFFFFFFFF` when using `Uint32`.
410    #[cfg_attr(feature = "serde", serde(default))]
411    pub strip_index_format: Option<IndexFormat>,
412    /// The face to consider the front for the purpose of culling and stencil operations.
413    #[cfg_attr(feature = "serde", serde(default))]
414    pub front_face: FrontFace,
415    /// The face culling mode.
416    #[cfg_attr(feature = "serde", serde(default))]
417    pub cull_mode: Option<Face>,
418    /// If set to true, the polygon depth is not clipped to 0-1 before rasterization.
419    ///
420    /// Enabling this requires [`Features::DEPTH_CLIP_CONTROL`] to be enabled.
421    #[cfg_attr(feature = "serde", serde(default))]
422    pub unclipped_depth: bool,
423    /// Controls the way each polygon is rasterized. Can be either `Fill` (default), `Line` or `Point`
424    ///
425    /// Setting this to `Line` requires [`Features::POLYGON_MODE_LINE`] to be enabled.
426    ///
427    /// Setting this to `Point` requires [`Features::POLYGON_MODE_POINT`] to be enabled.
428    #[cfg_attr(feature = "serde", serde(default))]
429    pub polygon_mode: PolygonMode,
430    /// If set to true, the primitives are rendered with conservative overestimation. I.e. any rastered pixel touched by it is filled.
431    /// Only valid for `[PolygonMode::Fill`]!
432    ///
433    /// Enabling this requires [`Features::CONSERVATIVE_RASTERIZATION`] to be enabled.
434    pub conservative: bool,
435}
436
437/// Describes the multi-sampling state of a render pipeline.
438///
439/// Corresponds to [WebGPU `GPUMultisampleState`](
440/// https://gpuweb.github.io/gpuweb/#dictdef-gpumultisamplestate).
441#[repr(C)]
442#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
443#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
444#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
445pub struct MultisampleState {
446    /// The number of samples calculated per pixel (for MSAA). For non-multisampled textures,
447    /// this should be `1`
448    pub count: u32,
449    /// Bitmask that restricts the samples of a pixel modified by this pipeline. All samples
450    /// can be enabled using the value `!0`
451    pub mask: u64,
452    /// When enabled, produces another sample mask per pixel based on the alpha output value, that
453    /// is ANDed with the sample mask and the primitive coverage to restrict the set of samples
454    /// affected by a primitive.
455    ///
456    /// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
457    /// is guaranteed to be all 1-s.
458    pub alpha_to_coverage_enabled: bool,
459}
460
461impl MultisampleState {
462    /// This function is identical to [`Default::default()`] except that it is a `const fn`.
463    pub const fn default() -> Self {
464        MultisampleState {
465            count: 1,
466            mask: !0,
467            alpha_to_coverage_enabled: false,
468        }
469    }
470}
471
472impl Default for MultisampleState {
473    fn default() -> Self {
474        Self::default() // call inherent function
475    }
476}
477
478/// Format of indices used with pipeline.
479///
480/// Corresponds to [WebGPU `GPUIndexFormat`](
481/// https://gpuweb.github.io/gpuweb/#enumdef-gpuindexformat).
482#[repr(C)]
483#[derive(Copy, Clone, Debug, ConstDefault!, Hash, Eq, PartialEq)]
484#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
485#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
486pub enum IndexFormat {
487    /// Indices are 16 bit unsigned integers.
488    Uint16 = 0,
489    /// Indices are 32 bit unsigned integers.
490    #[custom(default)]
491    Uint32 = 1,
492}
493
494impl IndexFormat {
495    /// Returns the size in bytes of the index format
496    pub fn byte_size(&self) -> u32 {
497        match self {
498            IndexFormat::Uint16 => 2,
499            IndexFormat::Uint32 => 4,
500        }
501    }
502}
503
504/// Operation to perform on the stencil value.
505///
506/// Corresponds to [WebGPU `GPUStencilOperation`](
507/// https://gpuweb.github.io/gpuweb/#enumdef-gpustenciloperation).
508#[repr(C)]
509#[derive(Copy, Clone, Debug, ConstDefault!, Hash, Eq, PartialEq)]
510#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
511#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
512pub enum StencilOperation {
513    /// Keep stencil value unchanged.
514    #[custom(default)]
515    Keep = 0,
516    /// Set stencil value to zero.
517    Zero = 1,
518    /// Replace stencil value with value provided in most recent call to
519    /// [`RenderPass::set_stencil_reference`][RPssr].
520    ///
521    #[doc = link_to_wgpu_docs!(["RPssr"]: "struct.RenderPass.html#method.set_stencil_reference")]
522    Replace = 2,
523    /// Bitwise inverts stencil value.
524    Invert = 3,
525    /// Increments stencil value by one, clamping on overflow.
526    IncrementClamp = 4,
527    /// Decrements stencil value by one, clamping on underflow.
528    DecrementClamp = 5,
529    /// Increments stencil value by one, wrapping on overflow.
530    IncrementWrap = 6,
531    /// Decrements stencil value by one, wrapping on underflow.
532    DecrementWrap = 7,
533}
534
535/// Describes stencil state in a render pipeline.
536///
537/// If you are not using stencil state, set this to [`StencilFaceState::IGNORE`].
538///
539/// Corresponds to [WebGPU `GPUStencilFaceState`](
540/// https://gpuweb.github.io/gpuweb/#dictdef-gpustencilfacestate).
541#[repr(C)]
542#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
544#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
545pub struct StencilFaceState {
546    /// Comparison function that determines if the fail_op or pass_op is used on the stencil buffer.
547    pub compare: CompareFunction,
548    /// Operation that is performed when stencil test fails.
549    pub fail_op: StencilOperation,
550    /// Operation that is performed when depth test fails but stencil test succeeds.
551    pub depth_fail_op: StencilOperation,
552    /// Operation that is performed when stencil test success.
553    pub pass_op: StencilOperation,
554}
555
556impl StencilFaceState {
557    /// Ignore the stencil state for the face.
558    pub const IGNORE: Self = StencilFaceState {
559        compare: CompareFunction::Always,
560        fail_op: StencilOperation::Keep,
561        depth_fail_op: StencilOperation::Keep,
562        pass_op: StencilOperation::Keep,
563    };
564
565    /// Returns true if the face state uses the reference value for testing or operation.
566    #[must_use]
567    pub fn needs_ref_value(&self) -> bool {
568        self.compare.needs_ref_value()
569            || self.fail_op == StencilOperation::Replace
570            || self.depth_fail_op == StencilOperation::Replace
571            || self.pass_op == StencilOperation::Replace
572    }
573
574    /// Returns true if the face state doesn't mutate the target values.
575    #[must_use]
576    pub fn is_read_only(&self) -> bool {
577        self.pass_op == StencilOperation::Keep
578            && self.depth_fail_op == StencilOperation::Keep
579            && self.fail_op == StencilOperation::Keep
580    }
581}
582
583impl crate::macros::ConstDefaultHelper for StencilFaceState {
584    const DEFAULT: Self = Self::IGNORE;
585}
586impl Default for StencilFaceState {
587    /// Returns [`StencilFaceState::IGNORE`] as the default.
588    fn default() -> Self {
589        Self::IGNORE
590    }
591}
592
593/// Comparison function used for depth and stencil operations.
594///
595/// Corresponds to [WebGPU `GPUCompareFunction`](
596/// https://gpuweb.github.io/gpuweb/#enumdef-gpucomparefunction).
597#[repr(C)]
598#[derive(Copy, Clone, Debug, ConstDefault!, Hash, Eq, PartialEq)]
599#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
600#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
601pub enum CompareFunction {
602    /// Function never passes
603    Never = 1,
604    /// Function passes if new value less than existing value
605    Less = 2,
606    /// Function passes if new value is equal to existing value. When using
607    /// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
608    /// output as `@invariant` to prevent artifacting.
609    Equal = 3,
610    /// Function passes if new value is less than or equal to existing value
611    LessEqual = 4,
612    /// Function passes if new value is greater than existing value
613    Greater = 5,
614    /// Function passes if new value is not equal to existing value. When using
615    /// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
616    /// output as `@invariant` to prevent artifacting.
617    NotEqual = 6,
618    /// Function passes if new value is greater than or equal to existing value
619    GreaterEqual = 7,
620    /// Function always passes
621    #[custom(default)]
622    Always = 8,
623}
624
625impl CompareFunction {
626    /// Returns true if the comparison depends on the reference value.
627    #[must_use]
628    pub fn needs_ref_value(self) -> bool {
629        match self {
630            Self::Never | Self::Always => false,
631            _ => true,
632        }
633    }
634}
635
636/// State of the stencil operation (fixed-pipeline stage).
637///
638/// For use in [`DepthStencilState`].
639///
640/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
641/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
642#[repr(C)]
643#[derive(Clone, Debug, ConstDefault!, PartialEq, Eq, Hash)]
644#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
645pub struct StencilState {
646    /// Front face mode.
647    pub front: StencilFaceState,
648    /// Back face mode.
649    pub back: StencilFaceState,
650    /// Stencil values are AND'd with this mask when reading and writing from the stencil buffer. Only low 8 bits are used.
651    pub read_mask: u32,
652    /// Stencil values are AND'd with this mask when writing to the stencil buffer. Only low 8 bits are used.
653    pub write_mask: u32,
654}
655
656impl StencilState {
657    /// Returns true if the stencil test is enabled.
658    #[must_use]
659    pub fn is_enabled(&self) -> bool {
660        (self.front != StencilFaceState::IGNORE || self.back != StencilFaceState::IGNORE)
661            && (self.read_mask != 0 || self.write_mask != 0)
662    }
663    /// Returns true if the state doesn't mutate the target values.
664    #[must_use]
665    pub fn is_read_only(&self, cull_mode: Option<Face>) -> bool {
666        // The rules are defined in step 7 of the "Device timeline initialization steps"
667        // subsection of the "Render Pipeline Creation" section of WebGPU
668        // (link to the section: https://gpuweb.github.io/gpuweb/#render-pipeline-creation)
669
670        if self.write_mask == 0 {
671            return true;
672        }
673
674        let front_ro = cull_mode == Some(Face::Front) || self.front.is_read_only();
675        let back_ro = cull_mode == Some(Face::Back) || self.back.is_read_only();
676
677        front_ro && back_ro
678    }
679    /// Returns true if the stencil state uses the reference value for testing.
680    #[must_use]
681    pub fn needs_ref_value(&self) -> bool {
682        self.front.needs_ref_value() || self.back.needs_ref_value()
683    }
684}
685
686/// Describes the biasing setting for the depth target.
687///
688/// For use in [`DepthStencilState`].
689///
690/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
691/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
692#[repr(C)]
693#[derive(Clone, Copy, Debug, ConstDefault!)]
694#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
695pub struct DepthBiasState {
696    /// Constant depth biasing factor, in basic units of the depth format.
697    pub constant: i32,
698    /// Slope depth biasing factor.
699    pub slope_scale: f32,
700    /// Depth bias clamp value (absolute).
701    pub clamp: f32,
702}
703
704impl DepthBiasState {
705    /// Returns true if the depth biasing is enabled.
706    #[must_use]
707    pub fn is_enabled(&self) -> bool {
708        self.constant != 0 || self.slope_scale != 0.0
709    }
710}
711
712impl core::hash::Hash for DepthBiasState {
713    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
714        self.constant.hash(state);
715        self.slope_scale.to_bits().hash(state);
716        self.clamp.to_bits().hash(state);
717    }
718}
719
720impl PartialEq for DepthBiasState {
721    fn eq(&self, other: &Self) -> bool {
722        (self.constant == other.constant)
723            && (self.slope_scale.to_bits() == other.slope_scale.to_bits())
724            && (self.clamp.to_bits() == other.clamp.to_bits())
725    }
726}
727
728impl Eq for DepthBiasState {}
729
730/// Operation to perform to the output attachment at the start of a render pass.
731///
732/// Corresponds to [WebGPU `GPULoadOp`](https://gpuweb.github.io/gpuweb/#enumdef-gpuloadop),
733/// plus the corresponding clearValue.
734#[repr(u8)]
735#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
736#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
737#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
738pub enum LoadOp<V> {
739    /// Loads the specified value for this attachment into the render pass.
740    ///
741    /// On some GPU hardware (primarily mobile), "clear" is significantly cheaper
742    /// because it avoids loading data from main memory into tile-local memory.
743    ///
744    /// On other GPU hardware, there isn’t a significant difference.
745    ///
746    /// As a result, it is recommended to use "clear" rather than "load" in cases
747    /// where the initial value doesn’t matter
748    /// (e.g. the render target will be cleared using a skybox).
749    Clear(V) = 0,
750    /// Loads the existing value for this attachment into the render pass.
751    Load = 1,
752    /// The render target has undefined contents at the start of the render pass.
753    /// This may lead to undefined behavior if you read from the any of the
754    /// render target pixels without first writing to them.
755    ///
756    /// Blending also becomes undefined behavior if the source
757    /// pixels are undefined.
758    ///
759    /// This is the fastest option on all GPUs if you always overwrite all pixels
760    /// in the render target after this load operation.
761    ///
762    /// Backends that don't support `DontCare` internally, will pick a different (unspecified)
763    /// load op instead.
764    ///
765    /// # Safety
766    ///
767    /// - All pixels in the render target must be written to before
768    ///   any read or a [`StoreOp::Store`] occurs.
769    #[cfg_attr(feature = "serde", serde(skip))] // unsafe to use, so cannot be (de)serialized
770    DontCare(LoadOpDontCare) = 2,
771}
772
773impl<V> LoadOp<V> {
774    /// Returns true if variants are same (ignoring clear value)
775    pub fn eq_variant<T>(&self, other: LoadOp<T>) -> bool {
776        matches!(
777            (self, other),
778            (LoadOp::Clear(_), LoadOp::Clear(_))
779                | (LoadOp::Load, LoadOp::Load)
780                | (LoadOp::DontCare(_), LoadOp::DontCare(_))
781        )
782    }
783}
784
785impl<V: Default> Default for LoadOp<V> {
786    fn default() -> Self {
787        Self::Clear(Default::default())
788    }
789}
790
791/// Operation to perform to the output attachment at the end of a render pass.
792///
793/// Corresponds to [WebGPU `GPUStoreOp`](https://gpuweb.github.io/gpuweb/#enumdef-gpustoreop).
794#[repr(C)]
795#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, ConstDefault!)]
796#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
797#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
798pub enum StoreOp {
799    /// Stores the resulting value of the render pass for this attachment.
800    #[custom(default)]
801    Store = 0,
802    /// Discards the resulting value of the render pass for this attachment.
803    ///
804    /// The attachment will be treated as uninitialized afterwards.
805    /// (If only either Depth or Stencil texture-aspects is set to `Discard`,
806    /// the respective other texture-aspect will be preserved.)
807    ///
808    /// This can be significantly faster on tile-based render hardware.
809    ///
810    /// Prefer this if the attachment is not read by subsequent passes.
811    Discard = 1,
812}
813
814/// Pair of load and store operations for an attachment aspect.
815///
816/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
817/// separate `loadOp` and `storeOp` fields are used instead.
818#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
819#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
820pub struct Operations<V> {
821    /// How data should be read through this attachment.
822    pub load: LoadOp<V>,
823    /// Whether data will be written to through this attachment.
824    ///
825    /// Note that resolve textures (if specified) are always written to,
826    /// regardless of this setting.
827    pub store: StoreOp,
828}
829
830impl<V: Default> Default for Operations<V> {
831    #[inline]
832    fn default() -> Self {
833        Self {
834            load: LoadOp::<V>::default(),
835            store: StoreOp::default(),
836        }
837    }
838}
839
840/// Describes the depth/stencil state in a render pipeline.
841///
842/// Corresponds to [WebGPU `GPUDepthStencilState`](
843/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
844#[repr(C)]
845#[derive(Clone, Debug, Hash, PartialEq, Eq)]
846#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
847pub struct DepthStencilState {
848    /// Format of the depth/stencil buffer, must be special depth format. Must match the format
849    /// of the depth/stencil attachment in [`CommandEncoder::begin_render_pass`][CEbrp].
850    ///
851    #[doc = link_to_wgpu_docs!(["CEbrp"]: "struct.CommandEncoder.html#method.begin_render_pass")]
852    pub format: crate::TextureFormat,
853    /// Whether to write updated depth values to the depth attachment.
854    ///
855    /// If `format` is a depth or depth/stencil format, then this must be `Some`.
856    /// Otherwise, specifying `None` is preferred, but `Some(false)` is also
857    /// accepted.
858    pub depth_write_enabled: Option<bool>,
859    /// Comparison function used to compare depth values in the depth test.
860    ///
861    /// If `depth_write_enabled` is `Some(true)` or if `depth_fail_op` for either
862    /// stencil face is not `Keep`, then this must be `Some`. Otherwise, specifying
863    /// `None` is preferred, but `Some(CompareFunction::Always)` is also accepted.
864    pub depth_compare: Option<CompareFunction>,
865    /// Stencil state.
866    #[cfg_attr(feature = "serde", serde(default))]
867    pub stencil: StencilState,
868    /// Depth bias state.
869    #[cfg_attr(feature = "serde", serde(default))]
870    pub bias: DepthBiasState,
871}
872
873impl DepthStencilState {
874    /// Construct `DepthStencilState` for a stencil operation with no depth operation.
875    ///
876    /// Panics if `format` does not have a stencil aspect.
877    pub fn stencil(format: crate::TextureFormat, stencil: StencilState) -> DepthStencilState {
878        assert!(
879            format.has_stencil_aspect(),
880            "{format:?} is not a stencil format"
881        );
882        DepthStencilState {
883            format,
884            depth_write_enabled: None,
885            depth_compare: None,
886            stencil,
887            bias: DepthBiasState::default(),
888        }
889    }
890
891    /// Returns true if the depth testing is enabled.
892    #[must_use]
893    pub fn is_depth_enabled(&self) -> bool {
894        self.depth_compare.unwrap_or_default() != CompareFunction::Always
895            || self.depth_write_enabled.unwrap_or_default()
896    }
897
898    /// Returns true if the state doesn't mutate the depth buffer.
899    #[must_use]
900    pub fn is_depth_read_only(&self) -> bool {
901        !self.depth_write_enabled.unwrap_or_default()
902    }
903
904    /// Returns true if the state doesn't mutate the stencil.
905    #[must_use]
906    pub fn is_stencil_read_only(&self, cull_mode: Option<Face>) -> bool {
907        self.stencil.is_read_only(cull_mode)
908    }
909
910    /// Returns true if the state doesn't mutate either depth or stencil of the target.
911    #[must_use]
912    pub fn is_read_only(&self, cull_mode: Option<Face>) -> bool {
913        self.is_depth_read_only() && self.is_stencil_read_only(cull_mode)
914    }
915}
916
917/// Describes the depth/stencil attachment for render bundles.
918///
919/// Corresponds to a portion of [WebGPU `GPURenderBundleEncoderDescriptor`](
920/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundleencoderdescriptor).
921#[repr(C)]
922#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
923#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
924pub struct RenderBundleDepthStencil {
925    /// Format of the attachment.
926    pub format: crate::TextureFormat,
927    /// If the depth aspect of the depth stencil attachment is going to be written to.
928    ///
929    /// This must match the [`RenderPassDepthStencilAttachment::depth_ops`] of the renderpass this render bundle is executed in.
930    /// If `depth_ops` is `Some(..)` this must be false. If it is `None` this must be true.
931    ///
932    #[doc = link_to_wgpu_docs!(["`RenderPassDepthStencilAttachment::depth_ops`"]: "struct.RenderPassDepthStencilAttachment.html#structfield.depth_ops")]
933    pub depth_read_only: bool,
934
935    /// If the stencil aspect of the depth stencil attachment is going to be written to.
936    ///
937    /// This must match the [`RenderPassDepthStencilAttachment::stencil_ops`] of the renderpass this render bundle is executed in.
938    /// If `depth_ops` is `Some(..)` this must be false. If it is `None` this must be true.
939    ///
940    #[doc = link_to_wgpu_docs!(["`RenderPassDepthStencilAttachment::stencil_ops`"]: "struct.RenderPassDepthStencilAttachment.html#structfield.stencil_ops")]
941    pub stencil_read_only: bool,
942}
943
944/// Describes a [`RenderBundle`](../wgpu/struct.RenderBundle.html).
945///
946/// Corresponds to [WebGPU `GPURenderBundleDescriptor`](
947/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundledescriptor).
948#[repr(C)]
949#[derive(Clone, Debug, PartialEq, Eq, Hash)]
950#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
951pub struct RenderBundleDescriptor<L> {
952    /// Debug label of the render bundle encoder. This will show up in graphics debuggers for easy identification.
953    pub label: L,
954}
955
956impl<L> RenderBundleDescriptor<L> {
957    /// Takes a closure and maps the label of the render bundle descriptor into another.
958    #[must_use]
959    pub fn map_label<'a, K>(&'a self, fun: impl FnOnce(&'a L) -> K) -> RenderBundleDescriptor<K> {
960        RenderBundleDescriptor {
961            label: fun(&self.label),
962        }
963    }
964}
965
966impl<T> Default for RenderBundleDescriptor<Option<T>> {
967    fn default() -> Self {
968        Self { label: None }
969    }
970}
971
972/// Argument buffer layout for `draw_indirect` commands.
973#[repr(C)]
974#[derive(Copy, Clone, Debug, ConstDefault!, Pod, Zeroable)]
975pub struct DrawIndirectArgs {
976    /// The number of vertices to draw.
977    pub vertex_count: u32,
978    /// The number of instances to draw.
979    pub instance_count: u32,
980    /// The Index of the first vertex to draw.
981    pub first_vertex: u32,
982    /// The instance ID of the first instance to draw.
983    ///
984    /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
985    pub first_instance: u32,
986}
987
988impl DrawIndirectArgs {
989    /// Returns the bytes representation of the struct, ready to be written in a buffer.
990    #[must_use]
991    pub fn as_bytes(&self) -> &[u8] {
992        bytemuck::bytes_of(self)
993    }
994}
995
996/// Argument buffer layout for `draw_indexed_indirect` commands.
997#[repr(C)]
998#[derive(Copy, Clone, Debug, ConstDefault!, Pod, Zeroable)]
999pub struct DrawIndexedIndirectArgs {
1000    /// The number of indices to draw.
1001    pub index_count: u32,
1002    /// The number of instances to draw.
1003    pub instance_count: u32,
1004    /// The first index within the index buffer.
1005    pub first_index: u32,
1006    /// The value added to the vertex index before indexing into the vertex buffer.
1007    pub base_vertex: i32,
1008    /// The instance ID of the first instance to draw.
1009    ///
1010    /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
1011    pub first_instance: u32,
1012}
1013
1014impl DrawIndexedIndirectArgs {
1015    /// Returns the bytes representation of the struct, ready to be written in a buffer.
1016    #[must_use]
1017    pub fn as_bytes(&self) -> &[u8] {
1018        bytemuck::bytes_of(self)
1019    }
1020}
1021
1022/// Argument buffer layout for `dispatch_workgroups_indirect` commands.
1023#[repr(C)]
1024#[derive(Copy, Clone, Debug, ConstDefault!, Pod, Zeroable)]
1025pub struct DispatchIndirectArgs {
1026    /// The number of work groups in X dimension.
1027    pub x: u32,
1028    /// The number of work groups in Y dimension.
1029    pub y: u32,
1030    /// The number of work groups in Z dimension.
1031    pub z: u32,
1032}
1033
1034impl DispatchIndirectArgs {
1035    /// Returns the bytes representation of the struct, ready to be written into a buffer.
1036    #[must_use]
1037    pub fn as_bytes(&self) -> &[u8] {
1038        bytemuck::bytes_of(self)
1039    }
1040}