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 //! Configures the operation of the depth, stencil and depth bounds tests. 11 //! 12 //! The depth test passes of fails depending on how the depth value of each fragment compares 13 //! to the existing depth value in the depth buffer at that fragment's location. Depth values 14 //! are always between 0.0 and 1.0. 15 //! 16 //! The depth bounds test allows you to ask the GPU to exclude fragments that are outside of a 17 //! certain range. This is done in addition to the regular depth test. 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 crate::{macros::vulkan_enum, pipeline::StateMode}; 24 use std::ops::RangeInclusive; 25 26 /// The state in a graphics pipeline describing how the depth, depth bounds and stencil tests 27 /// should behave. 28 #[derive(Clone, Debug)] 29 pub struct DepthStencilState { 30 /// The state of the depth test. 31 /// 32 /// If set to `None`, the depth test is disabled, all fragments will pass and no depth writes 33 /// are performed. 34 pub depth: Option<DepthState>, 35 36 /// The state of the depth bounds test. 37 /// 38 /// If set to `None`, the depth bounds test is disabled, all fragments will pass. 39 pub depth_bounds: Option<DepthBoundsState>, 40 41 /// The state of the stencil test. 42 /// 43 /// If set to `None`, the stencil test is disabled, all fragments will pass and no stencil 44 /// writes are performed. 45 pub stencil: Option<StencilState>, 46 } 47 48 impl DepthStencilState { 49 /// Creates a `DepthStencilState` where all tests are disabled and have no effect. 50 #[inline] disabled() -> Self51 pub fn disabled() -> Self { 52 Self { 53 depth: Default::default(), 54 depth_bounds: Default::default(), 55 stencil: Default::default(), 56 } 57 } 58 59 /// Creates a `DepthStencilState` with a `Less` depth test, `depth_write` set to true, and other 60 /// tests disabled. 61 #[inline] simple_depth_test() -> Self62 pub fn simple_depth_test() -> Self { 63 Self { 64 depth: Some(DepthState { 65 enable_dynamic: false, 66 compare_op: StateMode::Fixed(CompareOp::Less), 67 write_enable: StateMode::Fixed(true), 68 }), 69 depth_bounds: Default::default(), 70 stencil: Default::default(), 71 } 72 } 73 } 74 75 impl Default for DepthStencilState { 76 /// Returns [`DepthStencilState::disabled()`]. 77 #[inline] default() -> Self78 fn default() -> Self { 79 DepthStencilState::disabled() 80 } 81 } 82 83 /// The state in a graphics pipeline describing how the depth test should behave when enabled. 84 #[derive(Clone, Copy, Debug)] 85 pub struct DepthState { 86 /// Sets whether depth testing should be enabled and disabled dynamically. If set to `false`, 87 /// depth testing is always enabled. 88 /// 89 /// If set to `true`, the device API version must be at least 1.3, or the 90 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 91 /// enabled on the device. 92 pub enable_dynamic: bool, 93 94 /// Sets whether the value in the depth buffer will be updated when the depth test succeeds. 95 /// 96 /// If set to `Dynamic`, the device API version must be at least 1.3, or the 97 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 98 /// enabled on the device. 99 pub write_enable: StateMode<bool>, 100 101 /// Comparison operation to use between the depth value of each incoming fragment and the depth 102 /// value currently in the depth buffer. 103 /// 104 /// If set to `Dynamic`, the device API version must be at least 1.3, or the 105 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 106 /// enabled on the device. 107 pub compare_op: StateMode<CompareOp>, 108 } 109 110 impl Default for DepthState { 111 /// Creates a `DepthState` with no dynamic state, depth writes disabled and `compare_op` set 112 /// to always pass. 113 #[inline] default() -> Self114 fn default() -> Self { 115 Self { 116 enable_dynamic: false, 117 write_enable: StateMode::Fixed(false), 118 compare_op: StateMode::Fixed(CompareOp::Always), 119 } 120 } 121 } 122 123 /// The state in a graphics pipeline describing how the depth bounds test should behave when 124 /// enabled. 125 #[derive(Clone, Debug)] 126 pub struct DepthBoundsState { 127 /// Sets whether depth bounds testing should be enabled and disabled dynamically. If set to 128 /// `false`, depth bounds testing is always enabled. 129 /// 130 /// If set to `true`, the device API version must be at least 1.3, or the 131 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 132 /// enabled on the device. 133 pub enable_dynamic: bool, 134 135 /// The minimum and maximum depth values to use for the test. Fragments with values outside this 136 /// range are discarded. 137 /// 138 /// If set to `Dynamic`, the device API version must be at least 1.3, or the 139 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 140 /// enabled on the device. 141 pub bounds: StateMode<RangeInclusive<f32>>, 142 } 143 144 impl Default for DepthBoundsState { 145 /// Creates a `DepthBoundsState` with no dynamic state and the bounds set to `0.0..=1.0`. 146 #[inline] default() -> Self147 fn default() -> Self { 148 Self { 149 enable_dynamic: false, 150 bounds: StateMode::Fixed(0.0..=1.0), 151 } 152 } 153 } 154 155 /// The state in a graphics pipeline describing how the stencil test should behave when enabled. 156 /// 157 /// Dynamic state can only be enabled or disabled for both faces at once. Therefore, the dynamic 158 /// state values in `StencilOpState`, must match: the values for `front` and `back` must either both 159 /// be `Fixed` or both be `Dynamic`. 160 #[derive(Clone, Debug)] 161 pub struct StencilState { 162 /// Sets whether stencil testing should be enabled and disabled dynamically. If set to 163 /// `false`, stencil testing is always enabled. 164 /// 165 /// If set to `true`, the device API version must be at least 1.3, or the 166 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 167 /// enabled on the device. 168 pub enable_dynamic: bool, 169 170 /// The stencil operation state to use for points and lines, and for triangles whose front is 171 /// facing the user. 172 pub front: StencilOpState, 173 174 /// The stencil operation state to use for triangles whose back is facing the user. 175 pub back: StencilOpState, 176 } 177 178 /// Stencil test operations for a single face. 179 #[derive(Clone, Copy, Debug)] 180 pub struct StencilOpState { 181 /// The stencil operations to perform. 182 /// 183 /// If set to `Dynamic`, the device API version must be at least 1.3, or the 184 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 185 /// enabled on the device. 186 pub ops: StateMode<StencilOps>, 187 188 /// A bitmask that selects the bits of the unsigned integer stencil values participating in the 189 /// stencil test. Ignored if `compare_op` is `Never` or `Always`. 190 pub compare_mask: StateMode<u32>, 191 192 /// A bitmask that selects the bits of the unsigned integer stencil values updated by the 193 /// stencil test in the stencil framebuffer attachment. Ignored if the relevant operation is 194 /// `Keep`. 195 pub write_mask: StateMode<u32>, 196 197 /// Reference value that is used in the unsigned stencil comparison. The stencil test is 198 /// considered to pass if the `compare_op` between the stencil buffer value and this reference 199 /// value yields true. 200 /// 201 /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag) 202 /// devices, if culling is disabled, and the `reference` values of the front and back face 203 /// are not equal, then the 204 /// [`separate_stencil_mask_ref`](crate::device::Features::separate_stencil_mask_ref) 205 /// feature must be enabled on the device. 206 pub reference: StateMode<u32>, 207 } 208 209 impl Default for StencilOpState { 210 /// Creates a `StencilOpState` with no dynamic state, `compare_op` set to `Never`, the stencil 211 /// operations set to `Keep`, and the masks and reference values set to `u32::MAX`. 212 #[inline] default() -> StencilOpState213 fn default() -> StencilOpState { 214 StencilOpState { 215 ops: StateMode::Fixed(Default::default()), 216 compare_mask: StateMode::Fixed(u32::MAX), 217 write_mask: StateMode::Fixed(u32::MAX), 218 reference: StateMode::Fixed(u32::MAX), 219 } 220 } 221 } 222 223 #[derive(Clone, Copy, Debug)] 224 pub struct StencilOps { 225 /// The operation to perform when the stencil test failed. 226 pub fail_op: StencilOp, 227 228 /// The operation to perform when both the depth test and the stencil test passed. 229 pub pass_op: StencilOp, 230 231 /// The operation to perform when the stencil test passed but the depth test failed. 232 pub depth_fail_op: StencilOp, 233 234 /// The comparison to perform between the existing stencil value in the stencil buffer, and 235 /// the reference value (given by `reference`). 236 pub compare_op: CompareOp, 237 } 238 239 impl Default for StencilOps { 240 /// Creates a `StencilOps` with no dynamic state, `compare_op` set to `Never` and the stencil 241 /// operations set to `Keep`. 242 #[inline] default() -> Self243 fn default() -> Self { 244 Self { 245 pass_op: StencilOp::Keep, 246 fail_op: StencilOp::Keep, 247 depth_fail_op: StencilOp::Keep, 248 compare_op: CompareOp::Never, 249 } 250 } 251 } 252 253 vulkan_enum! { 254 #[non_exhaustive] 255 256 /// Operation to perform after the depth and stencil tests. 257 StencilOp = StencilOp(i32); 258 259 // TODO: document 260 Keep = KEEP, 261 262 // TODO: document 263 Zero = ZERO, 264 265 // TODO: document 266 Replace = REPLACE, 267 268 // TODO: document 269 IncrementAndClamp = INCREMENT_AND_CLAMP, 270 271 // TODO: document 272 DecrementAndClamp = DECREMENT_AND_CLAMP, 273 274 // TODO: document 275 Invert = INVERT, 276 277 // TODO: document 278 IncrementAndWrap = INCREMENT_AND_WRAP, 279 280 // TODO: document 281 DecrementAndWrap = DECREMENT_AND_WRAP, 282 } 283 284 vulkan_enum! { 285 #[non_exhaustive] 286 287 /// Specifies a face for stencil operations. 288 StencilFaces = StencilFaceFlags(u32); 289 290 // TODO: document 291 Front = FRONT, 292 293 // TODO: document 294 Back = BACK, 295 296 // TODO: document 297 FrontAndBack = FRONT_AND_BACK, 298 } 299 300 /// Specifies a dynamic state value for the front and back faces. 301 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 302 pub struct DynamicStencilValue { 303 pub front: u32, 304 pub back: u32, 305 } 306 307 vulkan_enum! { 308 #[non_exhaustive] 309 310 /// Specifies how two values should be compared to decide whether a test passes or fails. 311 /// 312 /// Used for both depth testing and stencil testing. 313 CompareOp = CompareOp(i32); 314 315 /// The test never passes. 316 Never = NEVER, 317 318 /// The test passes if `value < reference_value`. 319 Less = LESS, 320 321 /// The test passes if `value == reference_value`. 322 Equal = EQUAL, 323 324 /// The test passes if `value <= reference_value`. 325 LessOrEqual = LESS_OR_EQUAL, 326 327 /// The test passes if `value > reference_value`. 328 Greater = GREATER, 329 330 /// The test passes if `value != reference_value`. 331 NotEqual = NOT_EQUAL, 332 333 /// The test passes if `value >= reference_value`. 334 GreaterOrEqual = GREATER_OR_EQUAL, 335 336 /// The test always passes. 337 Always = ALWAYS, 338 } 339