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