gfx_hal/pso/
output_merger.rs

1//! Output Merger (OM) stage description.
2//! The final stage in a pipeline that creates pixel colors from
3//! the input shader results, depth/stencil information, etc.
4
5use crate::pso::{graphics::StencilValue, State};
6
7/// A pixel-wise comparison function.
8#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
9#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10pub enum Comparison {
11    /// `false`
12    Never = 0,
13    /// `x < y`
14    Less = 1,
15    /// `x == y`
16    Equal = 2,
17    /// `x <= y`
18    LessEqual = 3,
19    /// `x > y`
20    Greater = 4,
21    /// `x != y`
22    NotEqual = 5,
23    /// `x >= y`
24    GreaterEqual = 6,
25    /// `true`
26    Always = 7,
27}
28
29bitflags!(
30    /// Target output color mask.
31    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
32    pub struct ColorMask: u8 {
33        /// Red mask
34        const RED     = 0x1;
35        /// Green mask
36        const GREEN   = 0x2;
37        /// Blue mask
38        const BLUE    = 0x4;
39        /// Alpha channel mask
40        const ALPHA   = 0x8;
41        /// Mask for RGB channels
42        const COLOR   = 0x7;
43        /// Mask all channels
44        const ALL     = 0xF;
45        /// Mask no channels.
46        const NONE    = 0x0;
47    }
48);
49
50impl Default for ColorMask {
51    fn default() -> Self {
52        Self::ALL
53    }
54}
55
56/// Defines the possible blending factors.
57/// During blending, the source or destination fragment may be
58/// multiplied by a factor to produce the final result.
59#[allow(missing_docs)]
60#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62pub enum Factor {
63    Zero = 0,
64    One = 1,
65    SrcColor = 2,
66    OneMinusSrcColor = 3,
67    DstColor = 4,
68    OneMinusDstColor = 5,
69    SrcAlpha = 6,
70    OneMinusSrcAlpha = 7,
71    DstAlpha = 8,
72    OneMinusDstAlpha = 9,
73    ConstColor = 10,
74    OneMinusConstColor = 11,
75    ConstAlpha = 12,
76    OneMinusConstAlpha = 13,
77    SrcAlphaSaturate = 14,
78    Src1Color = 15,
79    OneMinusSrc1Color = 16,
80    Src1Alpha = 17,
81    OneMinusSrc1Alpha = 18,
82}
83
84/// Blending operations.
85#[allow(missing_docs)]
86#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
87#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
88pub enum BlendOp {
89    /// Adds source and destination.
90    /// Source and destination are multiplied by factors before addition.
91    Add { src: Factor, dst: Factor },
92    /// Subtracts destination from source.
93    /// Source and destination are multiplied by factors before subtraction.
94    Sub { src: Factor, dst: Factor },
95    /// Subtracts source from destination.
96    /// Source and destination are multiplied by factors before subtraction.
97    RevSub { src: Factor, dst: Factor },
98    /// Component-wise minimum value of source and destination.
99    Min,
100    /// Component-wise maximum value of source and destination.
101    Max,
102}
103
104impl BlendOp {
105    /// Replace the destination value with the source.
106    pub const REPLACE: Self = BlendOp::Add {
107        src: Factor::One,
108        dst: Factor::Zero,
109    };
110    /// Add the source and destination together.
111    pub const ADD: Self = BlendOp::Add {
112        src: Factor::One,
113        dst: Factor::One,
114    };
115    /// Alpha blend the source and destination together.
116    pub const ALPHA: Self = BlendOp::Add {
117        src: Factor::SrcAlpha,
118        dst: Factor::OneMinusSrcAlpha,
119    };
120    /// Alpha blend a premultiplied-alpha source with the destination.
121    pub const PREMULTIPLIED_ALPHA: Self = BlendOp::Add {
122        src: Factor::One,
123        dst: Factor::OneMinusSrcAlpha,
124    };
125}
126
127/// Specifies whether to use blending, and if so,
128/// which operations to use for color and alpha channels.
129#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
130#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
131pub struct BlendState {
132    /// The blend operation to use for the color channels.
133    pub color: BlendOp,
134    /// The blend operation to use for the alpha channel.
135    pub alpha: BlendOp,
136}
137
138impl BlendState {
139    /// Replace the color.
140    pub const REPLACE: Self = BlendState {
141        color: BlendOp::REPLACE,
142        alpha: BlendOp::REPLACE,
143    };
144    /// Additive blending.
145    pub const ADD: Self = BlendState {
146        color: BlendOp::ADD,
147        alpha: BlendOp::ADD,
148    };
149    /// Multiplicative blending.
150    pub const MULTIPLY: Self = BlendState {
151        color: BlendOp::Add {
152            src: Factor::Zero,
153            dst: Factor::SrcColor,
154        },
155        alpha: BlendOp::Add {
156            src: Factor::Zero,
157            dst: Factor::SrcAlpha,
158        },
159    };
160    /// Alpha blending.
161    pub const ALPHA: Self = BlendState {
162        color: BlendOp::ALPHA,
163        alpha: BlendOp::PREMULTIPLIED_ALPHA,
164    };
165    /// Pre-multiplied alpha blending.
166    pub const PREMULTIPLIED_ALPHA: Self = BlendState {
167        color: BlendOp::PREMULTIPLIED_ALPHA,
168        alpha: BlendOp::PREMULTIPLIED_ALPHA,
169    };
170}
171
172/// PSO color target descriptor.
173#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
174#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
175pub struct ColorBlendDesc {
176    /// Color write mask.
177    pub mask: ColorMask,
178    /// Blend state, if enabled.
179    pub blend: Option<BlendState>,
180}
181
182impl ColorBlendDesc {
183    /// Empty blend descriptor just writes out the color without blending.
184    // this can be used because `Default::default()` isn't a const function...
185    pub const EMPTY: Self = ColorBlendDesc {
186        mask: ColorMask::ALL,
187        blend: None,
188    };
189}
190
191/// Depth test state.
192#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
193#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
194pub struct DepthTest {
195    /// Comparison function to use.
196    pub fun: Comparison,
197    /// Specify whether to write to the depth buffer or not.
198    pub write: bool,
199}
200
201impl DepthTest {
202    /// A depth test that always fails.
203    pub const FAIL: Self = DepthTest {
204        fun: Comparison::Never,
205        write: false,
206    };
207    /// A depth test that always succeeds but doesn't
208    /// write to the depth buffer
209    // DOC TODO: Not a terribly helpful description there...
210    pub const PASS_TEST: Self = DepthTest {
211        fun: Comparison::Always,
212        write: false,
213    };
214    /// A depth test that always succeeds and writes its result
215    /// to the depth buffer.
216    pub const PASS_WRITE: Self = DepthTest {
217        fun: Comparison::Always,
218        write: true,
219    };
220}
221
222/// The operation to use for stencil masking.
223#[repr(u8)]
224#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
225#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
226pub enum StencilOp {
227    /// Keep the current value in the stencil buffer (no change).
228    Keep = 0,
229    /// Set the value in the stencil buffer to zero.
230    Zero = 1,
231    /// Set the stencil buffer value to `reference` from `StencilFace`.
232    Replace = 2,
233    /// Increment the stencil buffer value, clamping to its maximum value.
234    IncrementClamp = 3,
235    /// Decrement the stencil buffer value, clamping to its minimum value.
236    DecrementClamp = 4,
237    /// Bitwise invert the current value in the stencil buffer.
238    Invert = 5,
239    /// Increment the stencil buffer value, wrapping around to 0 on overflow.
240    IncrementWrap = 6,
241    /// Decrement the stencil buffer value, wrapping around to the maximum value on overflow.
242    DecrementWrap = 7,
243}
244
245/// Complete stencil state for a given side of a face.
246#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
247#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
248pub struct StencilFace {
249    /// Comparison function to use to determine if the stencil test passes.
250    pub fun: Comparison,
251    /// What operation to do if the stencil test fails.
252    pub op_fail: StencilOp,
253    /// What operation to do if the stencil test passes but the depth test fails.
254    pub op_depth_fail: StencilOp,
255    /// What operation to do if both the depth and stencil test pass.
256    pub op_pass: StencilOp,
257}
258
259impl Default for StencilFace {
260    fn default() -> StencilFace {
261        StencilFace {
262            fun: Comparison::Never,
263            op_fail: StencilOp::Keep,
264            op_depth_fail: StencilOp::Keep,
265            op_pass: StencilOp::Keep,
266        }
267    }
268}
269
270/// A generic struct holding the properties of two sides of a polygon.
271#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
272#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
273pub struct Sided<T> {
274    /// Information about the front face.
275    pub front: T,
276    /// Information about the back face.
277    pub back: T,
278}
279
280impl<T: Copy> Sided<T> {
281    /// Create a new `Sided` structure with both `front` and `back` holding
282    /// the same value.
283    pub fn new(value: T) -> Self {
284        Sided {
285            front: value,
286            back: value,
287        }
288    }
289}
290
291/// Pair of stencil values that could be either baked into a graphics pipeline
292/// or provided dynamically.
293pub type StencilValues = State<Sided<StencilValue>>;
294
295/// Defines a stencil test. Stencil testing is an operation
296/// performed to cull fragments;
297/// the new fragment is tested against the value held in the
298/// stencil buffer, and if the test fails the fragment is
299/// discarded.
300#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
301#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
302pub struct StencilTest {
303    /// Operations for stencil faces.
304    pub faces: Sided<StencilFace>,
305    /// Masks that are ANDd with both the stencil buffer value and the reference value when they
306    /// are read before doing the stencil test.
307    pub read_masks: StencilValues,
308    /// Mask that are ANDd with the stencil value before writing to the stencil buffer.
309    pub write_masks: StencilValues,
310    /// The reference values used for stencil tests.
311    pub reference_values: StencilValues,
312}
313
314impl Default for StencilTest {
315    fn default() -> Self {
316        StencilTest {
317            faces: Sided::default(),
318            read_masks: State::Static(Sided::new(!0)),
319            write_masks: State::Static(Sided::new(!0)),
320            reference_values: State::Static(Sided::new(0)),
321        }
322    }
323}
324
325/// PSO depth-stencil target descriptor.
326#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
327#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
328pub struct DepthStencilDesc {
329    /// Optional depth testing/writing.
330    pub depth: Option<DepthTest>,
331    /// Enable depth bounds testing.
332    pub depth_bounds: bool,
333    /// Stencil test/write.
334    pub stencil: Option<StencilTest>,
335}
336
337impl DepthStencilDesc {
338    /// Returns true if the descriptor assumes the depth attachment.
339    pub fn uses_depth(&self) -> bool {
340        self.depth.is_some() || self.depth_bounds
341    }
342    /// Returns true if the descriptor assumes the stencil attachment.
343    pub fn uses_stencil(&self) -> bool {
344        self.stencil.is_some()
345    }
346}
347
348bitflags!(
349    /// Face.
350    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
351    pub struct Face: u32 {
352        /// Empty face. TODO: remove when constexpr are stabilized to use empty()
353        const NONE = 0x0;
354        /// Front face.
355        const FRONT = 0x1;
356        /// Back face.
357        const BACK = 0x2;
358    }
359);