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 5 use 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))] 10 pub 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 29 bitflags!( 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 50 impl Default for ColorMask { default() -> Self51 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))] 62 pub 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))] 88 pub 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 104 impl 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))] 131 pub 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 138 impl 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))] 175 pub struct ColorBlendDesc { 176 /// Color write mask. 177 pub mask: ColorMask, 178 /// Blend state, if enabled. 179 pub blend: Option<BlendState>, 180 } 181 182 impl 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))] 194 pub 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 201 impl 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))] 226 pub 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))] 248 pub 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 259 impl Default for StencilFace { default() -> StencilFace260 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))] 273 pub 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 280 impl<T: Copy> Sided<T> { 281 /// Create a new `Sided` structure with both `front` and `back` holding 282 /// the same value. new(value: T) -> Self283 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. 293 pub 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))] 302 pub 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 314 impl Default for StencilTest { default() -> Self315 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))] 328 pub 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 337 impl DepthStencilDesc { 338 /// Returns true if the descriptor assumes the depth attachment. uses_depth(&self) -> bool339 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. uses_stencil(&self) -> bool343 pub fn uses_stencil(&self) -> bool { 344 self.stencil.is_some() 345 } 346 } 347 348 bitflags!( 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 ); 360