• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2022 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 use crate::{
11     command_buffer::{
12         allocator::CommandBufferAllocator,
13         synced::{Command, SyncCommandBufferBuilder},
14         sys::UnsafeCommandBufferBuilder,
15         AutoCommandBufferBuilder,
16     },
17     device::{DeviceOwned, QueueFlags},
18     instance::debug::DebugUtilsLabel,
19     RequiresOneOf,
20 };
21 use std::{
22     error::Error,
23     ffi::CString,
24     fmt::{Display, Error as FmtError, Formatter},
25 };
26 
27 /// # Commands for debugging.
28 ///
29 /// These commands all require the [`ext_debug_utils`] extension to be enabled on the instance.
30 ///
31 /// [`ext_debug_utils`]: crate::instance::InstanceExtensions::ext_debug_utils
32 impl<L, A> AutoCommandBufferBuilder<L, A>
33 where
34     A: CommandBufferAllocator,
35 {
36     /// Opens a command buffer debug label region.
begin_debug_utils_label( &mut self, mut label_info: DebugUtilsLabel, ) -> Result<&mut Self, DebugUtilsError>37     pub fn begin_debug_utils_label(
38         &mut self,
39         mut label_info: DebugUtilsLabel,
40     ) -> Result<&mut Self, DebugUtilsError> {
41         self.validate_begin_debug_utils_label(&mut label_info)?;
42 
43         unsafe {
44             self.inner.begin_debug_utils_label(label_info);
45         }
46 
47         Ok(self)
48     }
49 
validate_begin_debug_utils_label( &self, _label_info: &mut DebugUtilsLabel, ) -> Result<(), DebugUtilsError>50     fn validate_begin_debug_utils_label(
51         &self,
52         _label_info: &mut DebugUtilsLabel,
53     ) -> Result<(), DebugUtilsError> {
54         if !self
55             .device()
56             .instance()
57             .enabled_extensions()
58             .ext_debug_utils
59         {
60             return Err(DebugUtilsError::RequirementNotMet {
61                 required_for: "`AutoCommandBufferBuilder::begin_debug_utils_label`",
62                 requires_one_of: RequiresOneOf {
63                     instance_extensions: &["ext_debug_utils"],
64                     ..Default::default()
65                 },
66             });
67         }
68 
69         let queue_family_properties = self.queue_family_properties();
70 
71         // VUID-vkCmdBeginDebugUtilsLabelEXT-commandBuffer-cmdpool
72         if !queue_family_properties
73             .queue_flags
74             .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
75         {
76             return Err(DebugUtilsError::NotSupportedByQueueFamily);
77         }
78 
79         Ok(())
80     }
81 
82     /// Closes a command buffer debug label region.
83     ///
84     /// # Safety
85     ///
86     /// - When submitting the command buffer, there must be an outstanding command buffer label
87     ///   region begun with `begin_debug_utils_label` in the queue, either within this command
88     ///   buffer or a previously submitted one.
end_debug_utils_label(&mut self) -> Result<&mut Self, DebugUtilsError>89     pub unsafe fn end_debug_utils_label(&mut self) -> Result<&mut Self, DebugUtilsError> {
90         self.validate_end_debug_utils_label()?;
91 
92         self.inner.end_debug_utils_label();
93 
94         Ok(self)
95     }
96 
validate_end_debug_utils_label(&self) -> Result<(), DebugUtilsError>97     fn validate_end_debug_utils_label(&self) -> Result<(), DebugUtilsError> {
98         if !self
99             .device()
100             .instance()
101             .enabled_extensions()
102             .ext_debug_utils
103         {
104             return Err(DebugUtilsError::RequirementNotMet {
105                 required_for: "`AutoCommandBufferBuilder::end_debug_utils_label`",
106                 requires_one_of: RequiresOneOf {
107                     instance_extensions: &["ext_debug_utils"],
108                     ..Default::default()
109                 },
110             });
111         }
112 
113         let queue_family_properties = self.queue_family_properties();
114 
115         // VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-cmdpool
116         if !queue_family_properties
117             .queue_flags
118             .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
119         {
120             return Err(DebugUtilsError::NotSupportedByQueueFamily);
121         }
122 
123         // VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-01912
124         // TODO: not checked, so unsafe for now
125 
126         // VUID-vkCmdEndDebugUtilsLabelEXT-commandBuffer-01913
127         // TODO: not checked, so unsafe for now
128 
129         Ok(())
130     }
131 
132     /// Inserts a command buffer debug label.
insert_debug_utils_label( &mut self, mut label_info: DebugUtilsLabel, ) -> Result<&mut Self, DebugUtilsError>133     pub fn insert_debug_utils_label(
134         &mut self,
135         mut label_info: DebugUtilsLabel,
136     ) -> Result<&mut Self, DebugUtilsError> {
137         self.validate_insert_debug_utils_label(&mut label_info)?;
138 
139         unsafe {
140             self.inner.insert_debug_utils_label(label_info);
141         }
142 
143         Ok(self)
144     }
145 
validate_insert_debug_utils_label( &self, _label_info: &mut DebugUtilsLabel, ) -> Result<(), DebugUtilsError>146     fn validate_insert_debug_utils_label(
147         &self,
148         _label_info: &mut DebugUtilsLabel,
149     ) -> Result<(), DebugUtilsError> {
150         if !self
151             .device()
152             .instance()
153             .enabled_extensions()
154             .ext_debug_utils
155         {
156             return Err(DebugUtilsError::RequirementNotMet {
157                 required_for: "`AutoCommandBufferBuilder::insert_debug_utils_label`",
158                 requires_one_of: RequiresOneOf {
159                     instance_extensions: &["ext_debug_utils"],
160                     ..Default::default()
161                 },
162             });
163         }
164 
165         let queue_family_properties = self.queue_family_properties();
166 
167         // VUID-vkCmdInsertDebugUtilsLabelEXT-commandBuffer-cmdpool
168         if !queue_family_properties
169             .queue_flags
170             .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE)
171         {
172             return Err(DebugUtilsError::NotSupportedByQueueFamily);
173         }
174 
175         Ok(())
176     }
177 }
178 
179 impl SyncCommandBufferBuilder {
180     /// Calls `vkCmdBeginDebugUtilsLabelEXT` on the builder.
181     ///
182     /// # Safety
183     /// The command pool that this command buffer was allocated from must support graphics or
184     /// compute operations
185     #[inline]
begin_debug_utils_label(&mut self, label_info: DebugUtilsLabel)186     pub unsafe fn begin_debug_utils_label(&mut self, label_info: DebugUtilsLabel) {
187         struct Cmd {
188             label_info: DebugUtilsLabel,
189         }
190 
191         impl Command for Cmd {
192             fn name(&self) -> &'static str {
193                 "begin_debug_utils_label"
194             }
195 
196             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
197                 out.begin_debug_utils_label(&self.label_info);
198             }
199         }
200 
201         self.commands.push(Box::new(Cmd { label_info }));
202     }
203 
204     /// Calls `vkCmdEndDebugUtilsLabelEXT` on the builder.
205     ///
206     /// # Safety
207     ///
208     /// - The command pool that this command buffer was allocated from must support graphics or
209     /// compute operations
210     /// - There must be an outstanding `debug_marker_begin` command prior to the
211     /// `debug_marker_end` on the queue.
212     #[inline]
end_debug_utils_label(&mut self)213     pub unsafe fn end_debug_utils_label(&mut self) {
214         struct Cmd {}
215 
216         impl Command for Cmd {
217             fn name(&self) -> &'static str {
218                 "end_debug_utils_label"
219             }
220 
221             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
222                 out.end_debug_utils_label();
223             }
224         }
225 
226         self.commands.push(Box::new(Cmd {}));
227     }
228 
229     /// Calls `vkCmdInsertDebugUtilsLabelEXT` on the builder.
230     ///
231     /// # Safety
232     /// The command pool that this command buffer was allocated from must support graphics or
233     /// compute operations
234     #[inline]
insert_debug_utils_label(&mut self, label_info: DebugUtilsLabel)235     pub unsafe fn insert_debug_utils_label(&mut self, label_info: DebugUtilsLabel) {
236         struct Cmd {
237             label_info: DebugUtilsLabel,
238         }
239 
240         impl Command for Cmd {
241             fn name(&self) -> &'static str {
242                 "insert_debug_utils_label"
243             }
244 
245             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
246                 out.insert_debug_utils_label(&self.label_info);
247             }
248         }
249 
250         self.commands.push(Box::new(Cmd { label_info }));
251     }
252 }
253 
254 impl UnsafeCommandBufferBuilder {
255     /// Calls `vkCmdBeginDebugUtilsLabelEXT` on the builder.
256     ///
257     /// # Safety
258     /// The command pool that this command buffer was allocated from must support graphics or
259     /// compute operations
260     #[inline]
begin_debug_utils_label(&mut self, label_info: &DebugUtilsLabel)261     pub unsafe fn begin_debug_utils_label(&mut self, label_info: &DebugUtilsLabel) {
262         let &DebugUtilsLabel {
263             ref label_name,
264             color,
265             _ne: _,
266         } = label_info;
267 
268         let label_name_vk = CString::new(label_name.as_str()).unwrap();
269         let label_info = ash::vk::DebugUtilsLabelEXT {
270             p_label_name: label_name_vk.as_ptr(),
271             color,
272             ..Default::default()
273         };
274 
275         let fns = self.device.instance().fns();
276         (fns.ext_debug_utils.cmd_begin_debug_utils_label_ext)(self.handle, &label_info);
277     }
278 
279     /// Calls `vkCmdEndDebugUtilsLabelEXT` on the builder.
280     ///
281     /// # Safety
282     /// There must be an outstanding `vkCmdBeginDebugUtilsLabelEXT` command prior to the
283     /// `vkQueueEndDebugUtilsLabelEXT` on the queue tha `CommandBuffer` is submitted to.
284     #[inline]
end_debug_utils_label(&mut self)285     pub unsafe fn end_debug_utils_label(&mut self) {
286         let fns = self.device.instance().fns();
287         (fns.ext_debug_utils.cmd_end_debug_utils_label_ext)(self.handle);
288     }
289 
290     /// Calls `vkCmdInsertDebugUtilsLabelEXT` on the builder.
291     ///
292     /// # Safety
293     /// The command pool that this command buffer was allocated from must support graphics or
294     /// compute operations
295     #[inline]
insert_debug_utils_label(&mut self, label_info: &DebugUtilsLabel)296     pub unsafe fn insert_debug_utils_label(&mut self, label_info: &DebugUtilsLabel) {
297         let &DebugUtilsLabel {
298             ref label_name,
299             color,
300             _ne: _,
301         } = label_info;
302 
303         let label_name_vk = CString::new(label_name.as_str()).unwrap();
304         let label_info = ash::vk::DebugUtilsLabelEXT {
305             p_label_name: label_name_vk.as_ptr(),
306             color,
307             ..Default::default()
308         };
309 
310         let fns = self.device.instance().fns();
311         (fns.ext_debug_utils.cmd_insert_debug_utils_label_ext)(self.handle, &label_info);
312     }
313 }
314 
315 /// Error that can happen when recording a debug utils command.
316 #[derive(Clone, Debug)]
317 pub enum DebugUtilsError {
318     RequirementNotMet {
319         required_for: &'static str,
320         requires_one_of: RequiresOneOf,
321     },
322 
323     /// The queue family doesn't allow this operation.
324     NotSupportedByQueueFamily,
325 }
326 
327 impl Error for DebugUtilsError {}
328 
329 impl Display for DebugUtilsError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>330     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
331         match self {
332             Self::RequirementNotMet {
333                 required_for,
334                 requires_one_of,
335             } => write!(
336                 f,
337                 "a requirement was not met for: {}; requires one of: {}",
338                 required_for, requires_one_of,
339             ),
340             Self::NotSupportedByQueueFamily => {
341                 write!(f, "the queue family doesn't allow this operation")
342             }
343         }
344     }
345 }
346