wgpu_types/
render.rs

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