• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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