1 // Copyright (c) 2016 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 //! Depth and stencil operations description. 11 //! 12 //! After the fragment shader has finished running, each fragment goes through the depth 13 //! and stencil tests. 14 //! 15 //! The depth test passes of fails depending on how the depth value of each fragment compares 16 //! to the existing depth value in the depth buffer at that fragment's location. Depth values 17 //! are always between 0.0 and 1.0. 18 //! 19 //! The stencil test passes or fails depending on how a reference value compares to the existing 20 //! value in the stencil buffer at each fragment's location. Depending on the outcome of the 21 //! depth and stencil tests, the value of the stencil buffer at that location can be updated. 22 23 use std::ops::Range; 24 use std::u32; 25 26 /// Configuration of the depth and stencil tests. 27 #[derive(Debug, Clone)] 28 pub struct DepthStencil { 29 /// Comparison to use between the depth value of each fragment and the depth value currently 30 /// in the depth buffer. 31 pub depth_compare: Compare, 32 33 /// If `true`, then the value in the depth buffer will be updated when the depth test succeeds. 34 pub depth_write: bool, 35 36 /// Allows you to ask the GPU to exclude fragments that are outside of a certain range. This is 37 /// done in addition to the regular depth test. 38 pub depth_bounds_test: DepthBounds, 39 40 /// Stencil operations to use for points, lines and triangles whose front is facing the user. 41 pub stencil_front: Stencil, 42 43 /// Stencil operations to use for triangles whose back is facing the user. 44 pub stencil_back: Stencil, 45 } 46 47 impl DepthStencil { 48 /// Creates a `DepthStencil` where both the depth and stencil tests are disabled and have 49 /// no effect. 50 #[inline] disabled() -> DepthStencil51 pub fn disabled() -> DepthStencil { 52 DepthStencil { 53 depth_write: false, 54 depth_compare: Compare::Always, 55 depth_bounds_test: DepthBounds::Disabled, 56 stencil_front: Default::default(), 57 stencil_back: Default::default(), 58 } 59 } 60 61 /// Creates a `DepthStencil` with a `Less` depth test, `depth_write` set to true, and stencil 62 /// testing disabled. 63 #[inline] simple_depth_test() -> DepthStencil64 pub fn simple_depth_test() -> DepthStencil { 65 DepthStencil { 66 depth_write: true, 67 depth_compare: Compare::Less, 68 depth_bounds_test: DepthBounds::Disabled, 69 stencil_front: Default::default(), 70 stencil_back: Default::default(), 71 } 72 } 73 } 74 75 impl Default for DepthStencil { 76 #[inline] default() -> DepthStencil77 fn default() -> DepthStencil { 78 DepthStencil::disabled() 79 } 80 } 81 82 /// Configuration of a stencil test. 83 #[derive(Debug, Copy, Clone)] 84 pub struct Stencil { 85 /// The comparison to perform between the existing stencil value in the stencil buffer, and 86 /// the reference value (given by `reference`). 87 pub compare: Compare, 88 89 /// The operation to perform when both the depth test and the stencil test passed. 90 pub pass_op: StencilOp, 91 92 /// The operation to perform when the stencil test failed. 93 pub fail_op: StencilOp, 94 95 /// The operation to perform when the stencil test passed but the depth test failed. 96 pub depth_fail_op: StencilOp, 97 98 /// Selects the bits of the unsigned integer stencil values participating in the stencil test. 99 /// 100 /// Ignored if `compare` is `Never` or `Always`. 101 /// 102 /// If `None`, then this value is dynamic and will need to be set when drawing. Doesn't apply 103 /// if `compare` is `Never` or `Always`. 104 /// 105 /// Note that if this value is `Some` in `stencil_front`, it must also be `Some` in 106 /// `stencil_back` (but the content can be different). If this value is `None` in 107 /// `stencil_front`, then it must also be `None` in `stencil_back`. This rule doesn't apply 108 /// if `compare` is `Never` or `Always`. 109 pub compare_mask: Option<u32>, 110 111 /// Selects the bits of the unsigned integer stencil values updated by the stencil test in the 112 /// stencil framebuffer attachment. 113 /// 114 /// If `None`, then this value is dynamic and will need to be set when drawing. 115 /// 116 /// Note that if this value is `Some` in `stencil_front`, it must also be `Some` in 117 /// `stencil_back` (but the content can be different). If this value is `None` in 118 /// `stencil_front`, then it must also be `None` in `stencil_back`. 119 pub write_mask: Option<u32>, 120 121 /// Reference value that is used in the unsigned stencil comparison. 122 /// 123 /// If `None`, then this value is dynamic and will need to be set when drawing. 124 /// 125 /// Note that if this value is `Some` in `stencil_front`, it must also be `Some` in 126 /// `stencil_back` (but the content can be different). If this value is `None` in 127 /// `stencil_front`, then it must also be `None` in `stencil_back`. 128 pub reference: Option<u32>, 129 } 130 131 impl Stencil { 132 /// Returns true if the stencil operation will always result in `Keep`. 133 #[inline] always_keep(&self) -> bool134 pub fn always_keep(&self) -> bool { 135 match self.compare { 136 Compare::Always => { 137 self.pass_op == StencilOp::Keep && self.depth_fail_op == StencilOp::Keep 138 } 139 Compare::Never => self.fail_op == StencilOp::Keep, 140 _ => { 141 self.pass_op == StencilOp::Keep 142 && self.fail_op == StencilOp::Keep 143 && self.depth_fail_op == StencilOp::Keep 144 } 145 } 146 } 147 } 148 149 impl Default for Stencil { 150 #[inline] default() -> Stencil151 fn default() -> Stencil { 152 Stencil { 153 compare: Compare::Never, 154 pass_op: StencilOp::Keep, 155 fail_op: StencilOp::Keep, 156 depth_fail_op: StencilOp::Keep, 157 compare_mask: Some(u32::MAX), 158 write_mask: Some(u32::MAX), 159 reference: Some(u32::MAX), 160 } 161 } 162 } 163 164 /// Operation to perform after the depth and stencil tests. 165 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 166 #[repr(i32)] 167 pub enum StencilOp { 168 Keep = ash::vk::StencilOp::KEEP.as_raw(), 169 Zero = ash::vk::StencilOp::ZERO.as_raw(), 170 Replace = ash::vk::StencilOp::REPLACE.as_raw(), 171 IncrementAndClamp = ash::vk::StencilOp::INCREMENT_AND_CLAMP.as_raw(), 172 DecrementAndClamp = ash::vk::StencilOp::DECREMENT_AND_CLAMP.as_raw(), 173 Invert = ash::vk::StencilOp::INVERT.as_raw(), 174 IncrementAndWrap = ash::vk::StencilOp::INCREMENT_AND_WRAP.as_raw(), 175 DecrementAndWrap = ash::vk::StencilOp::DECREMENT_AND_WRAP.as_raw(), 176 } 177 178 impl From<StencilOp> for ash::vk::StencilOp { 179 #[inline] from(val: StencilOp) -> Self180 fn from(val: StencilOp) -> Self { 181 Self::from_raw(val as i32) 182 } 183 } 184 185 /// Specifies a face for stencil operations. 186 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 187 #[repr(u32)] 188 pub enum StencilFaces { 189 Front = ash::vk::StencilFaceFlags::FRONT.as_raw(), 190 Back = ash::vk::StencilFaceFlags::BACK.as_raw(), 191 FrontAndBack = ash::vk::StencilFaceFlags::FRONT_AND_BACK.as_raw(), 192 } 193 194 impl From<StencilFaces> for ash::vk::StencilFaceFlags { 195 #[inline] from(val: StencilFaces) -> Self196 fn from(val: StencilFaces) -> Self { 197 Self::from_raw(val as u32) 198 } 199 } 200 201 /// Specifies a dynamic state value for the front and back faces. 202 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 203 pub struct DynamicStencilValue { 204 pub front: u32, 205 pub back: u32, 206 } 207 208 /// Allows you to ask the GPU to exclude fragments that are outside of a certain range. 209 #[derive(Debug, Clone, PartialEq)] 210 pub enum DepthBounds { 211 /// The test is disabled. All fragments pass the depth bounds test. 212 Disabled, 213 214 /// Fragments that are within the given range do pass the test. Values are depth values 215 /// between 0.0 and 1.0. 216 Fixed(Range<f32>), 217 218 /// The depth bounds test is enabled, but the range will need to specified when you submit 219 /// a draw command. 220 Dynamic, 221 } 222 223 impl DepthBounds { 224 /// Returns true if equal to `DepthBounds::Dynamic`. 225 #[inline] is_dynamic(&self) -> bool226 pub fn is_dynamic(&self) -> bool { 227 match self { 228 &DepthBounds::Dynamic => true, 229 _ => false, 230 } 231 } 232 } 233 234 /// Specifies how two values should be compared to decide whether a test passes or fails. 235 /// 236 /// Used for both depth testing and stencil testing. 237 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 238 #[repr(i32)] 239 pub enum Compare { 240 /// The test never passes. 241 Never = ash::vk::CompareOp::NEVER.as_raw(), 242 /// The test passes if `value < reference_value`. 243 Less = ash::vk::CompareOp::LESS.as_raw(), 244 /// The test passes if `value == reference_value`. 245 Equal = ash::vk::CompareOp::EQUAL.as_raw(), 246 /// The test passes if `value <= reference_value`. 247 LessOrEqual = ash::vk::CompareOp::LESS_OR_EQUAL.as_raw(), 248 /// The test passes if `value > reference_value`. 249 Greater = ash::vk::CompareOp::GREATER.as_raw(), 250 /// The test passes if `value != reference_value`. 251 NotEqual = ash::vk::CompareOp::NOT_EQUAL.as_raw(), 252 /// The test passes if `value >= reference_value`. 253 GreaterOrEqual = ash::vk::CompareOp::GREATER_OR_EQUAL.as_raw(), 254 /// The test always passes. 255 Always = ash::vk::CompareOp::ALWAYS.as_raw(), 256 } 257 258 impl From<Compare> for ash::vk::CompareOp { 259 #[inline] from(val: Compare) -> Self260 fn from(val: Compare) -> Self { 261 Self::from_raw(val as i32) 262 } 263 } 264