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