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 auto::RenderPassStateType, 14 synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, 15 sys::UnsafeCommandBufferBuilder, 16 AutoCommandBufferBuilder, CommandBufferExecError, CommandBufferInheritanceRenderPassType, 17 CommandBufferUsage, ResourceInCommand, ResourceUseRef, SecondaryCommandBufferAbstract, 18 SecondaryCommandBufferBufferUsage, SecondaryCommandBufferImageUsage, 19 SecondaryCommandBufferResourcesUsage, SubpassContents, 20 }, 21 device::{DeviceOwned, QueueFlags}, 22 format::Format, 23 image::SampleCount, 24 query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType}, 25 RequiresOneOf, SafeDeref, VulkanObject, 26 }; 27 use smallvec::SmallVec; 28 use std::{ 29 error::Error, 30 fmt::{Display, Error as FmtError, Formatter}, 31 }; 32 33 /// # Commands to execute a secondary command buffer inside a primary command buffer. 34 /// 35 /// These commands can be called on any queue that can execute the commands recorded in the 36 /// secondary command buffer. 37 impl<L, A> AutoCommandBufferBuilder<L, A> 38 where 39 A: CommandBufferAllocator, 40 { 41 /// Executes a secondary command buffer. 42 /// 43 /// If the `flags` that `command_buffer` was created with are more restrictive than those of 44 /// `self`, then `self` will be restricted to match. E.g. executing a secondary command buffer 45 /// with `Flags::OneTimeSubmit` will set `self`'s flags to `Flags::OneTimeSubmit` also. execute_commands<C>( &mut self, command_buffer: C, ) -> Result<&mut Self, ExecuteCommandsError> where C: SecondaryCommandBufferAbstract + 'static,46 pub fn execute_commands<C>( 47 &mut self, 48 command_buffer: C, 49 ) -> Result<&mut Self, ExecuteCommandsError> 50 where 51 C: SecondaryCommandBufferAbstract + 'static, 52 { 53 self.validate_execute_commands(&command_buffer, 0)?; 54 55 unsafe { 56 let secondary_usage = command_buffer.usage(); 57 let mut builder = self.inner.execute_commands(); 58 builder.add(command_buffer); 59 builder.submit()?; 60 61 // Secondary command buffer could leave the primary in any state. 62 self.inner.reset_state(); 63 64 // If the secondary is non-concurrent or one-time use, that restricts the primary as 65 // well. 66 self.usage = std::cmp::min(self.usage, secondary_usage); 67 } 68 69 Ok(self) 70 } 71 72 /// Executes multiple secondary command buffers in a vector. 73 /// 74 /// This requires that the secondary command buffers do not have resource conflicts; an error 75 /// will be returned if there are any. Use `execute_commands` if you want to ensure that 76 /// resource conflicts are automatically resolved. 77 // TODO ^ would be nice if this just worked without errors execute_commands_from_vec<C>( &mut self, command_buffers: Vec<C>, ) -> Result<&mut Self, ExecuteCommandsError> where C: SecondaryCommandBufferAbstract + 'static,78 pub fn execute_commands_from_vec<C>( 79 &mut self, 80 command_buffers: Vec<C>, 81 ) -> Result<&mut Self, ExecuteCommandsError> 82 where 83 C: SecondaryCommandBufferAbstract + 'static, 84 { 85 for (command_buffer_index, command_buffer) in command_buffers.iter().enumerate() { 86 self.validate_execute_commands(command_buffer, command_buffer_index as u32)?; 87 } 88 89 unsafe { 90 let mut secondary_usage = CommandBufferUsage::SimultaneousUse; // Most permissive usage 91 92 let mut builder = self.inner.execute_commands(); 93 for command_buffer in command_buffers { 94 secondary_usage = std::cmp::min(secondary_usage, command_buffer.usage()); 95 builder.add(command_buffer); 96 } 97 builder.submit()?; 98 99 // Secondary command buffer could leave the primary in any state. 100 self.inner.reset_state(); 101 102 // If the secondary is non-concurrent or one-time use, that restricts the primary as 103 // well. 104 self.usage = std::cmp::min(self.usage, secondary_usage); 105 } 106 107 Ok(self) 108 } 109 validate_execute_commands<C>( &self, command_buffer: &C, command_buffer_index: u32, ) -> Result<(), ExecuteCommandsError> where C: SecondaryCommandBufferAbstract + 'static,110 fn validate_execute_commands<C>( 111 &self, 112 command_buffer: &C, 113 command_buffer_index: u32, 114 ) -> Result<(), ExecuteCommandsError> 115 where 116 C: SecondaryCommandBufferAbstract + 'static, 117 { 118 // VUID-vkCmdExecuteCommands-commonparent 119 assert_eq!(self.device(), command_buffer.device()); 120 121 let queue_family_properties = self.queue_family_properties(); 122 123 // VUID-vkCmdExecuteCommands-commandBuffer-cmdpool 124 if !queue_family_properties 125 .queue_flags 126 .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) 127 { 128 return Err(ExecuteCommandsError::NotSupportedByQueueFamily); 129 } 130 131 // TODO: 132 // VUID-vkCmdExecuteCommands-pCommandBuffers-00094 133 134 if let Some(render_pass_state) = &self.render_pass_state { 135 // VUID-vkCmdExecuteCommands-contents-06018 136 // VUID-vkCmdExecuteCommands-flags-06024 137 if render_pass_state.contents != SubpassContents::SecondaryCommandBuffers { 138 return Err(ExecuteCommandsError::ForbiddenWithSubpassContents { 139 contents: render_pass_state.contents, 140 }); 141 } 142 143 // VUID-vkCmdExecuteCommands-pCommandBuffers-00096 144 let inheritance_render_pass = command_buffer 145 .inheritance_info() 146 .render_pass 147 .as_ref() 148 .ok_or(ExecuteCommandsError::RenderPassInheritanceRequired { 149 command_buffer_index, 150 })?; 151 152 match (&render_pass_state.render_pass, inheritance_render_pass) { 153 ( 154 RenderPassStateType::BeginRenderPass(state), 155 CommandBufferInheritanceRenderPassType::BeginRenderPass(inheritance_info), 156 ) => { 157 // VUID-vkCmdExecuteCommands-pBeginInfo-06020 158 if !inheritance_info 159 .subpass 160 .render_pass() 161 .is_compatible_with(state.subpass.render_pass()) 162 { 163 return Err(ExecuteCommandsError::RenderPassNotCompatible { 164 command_buffer_index, 165 }); 166 } 167 168 // VUID-vkCmdExecuteCommands-pCommandBuffers-06019 169 if inheritance_info.subpass.index() != state.subpass.index() { 170 return Err(ExecuteCommandsError::RenderPassSubpassMismatch { 171 command_buffer_index, 172 required_subpass: state.subpass.index(), 173 inherited_subpass: inheritance_info.subpass.index(), 174 }); 175 } 176 177 // VUID-vkCmdExecuteCommands-pCommandBuffers-00099 178 if let Some(framebuffer) = &inheritance_info.framebuffer { 179 if framebuffer != state.framebuffer.as_ref().unwrap() { 180 return Err(ExecuteCommandsError::RenderPassFramebufferMismatch { 181 command_buffer_index, 182 }); 183 } 184 } 185 } 186 ( 187 RenderPassStateType::BeginRendering(state), 188 CommandBufferInheritanceRenderPassType::BeginRendering(inheritance_info), 189 ) => { 190 let attachments = state.attachments.as_ref().unwrap(); 191 192 // VUID-vkCmdExecuteCommands-colorAttachmentCount-06027 193 if inheritance_info.color_attachment_formats.len() 194 != attachments.color_attachments.len() 195 { 196 return Err( 197 ExecuteCommandsError::RenderPassColorAttachmentCountMismatch { 198 command_buffer_index, 199 required_count: attachments.color_attachments.len() as u32, 200 inherited_count: inheritance_info.color_attachment_formats.len() 201 as u32, 202 }, 203 ); 204 } 205 206 for (color_attachment_index, image_view, inherited_format) in attachments 207 .color_attachments 208 .iter() 209 .zip(inheritance_info.color_attachment_formats.iter().copied()) 210 .enumerate() 211 .filter_map(|(i, (a, f))| a.as_ref().map(|a| (i as u32, &a.image_view, f))) 212 { 213 let required_format = image_view.format().unwrap(); 214 215 // VUID-vkCmdExecuteCommands-imageView-06028 216 if Some(required_format) != inherited_format { 217 return Err( 218 ExecuteCommandsError::RenderPassColorAttachmentFormatMismatch { 219 command_buffer_index, 220 color_attachment_index, 221 required_format, 222 inherited_format, 223 }, 224 ); 225 } 226 227 // VUID-vkCmdExecuteCommands-pNext-06035 228 if image_view.image().samples() != inheritance_info.rasterization_samples { 229 return Err( 230 ExecuteCommandsError::RenderPassColorAttachmentSamplesMismatch { 231 command_buffer_index, 232 color_attachment_index, 233 required_samples: image_view.image().samples(), 234 inherited_samples: inheritance_info.rasterization_samples, 235 }, 236 ); 237 } 238 } 239 240 if let Some((image_view, format)) = attachments 241 .depth_attachment 242 .as_ref() 243 .map(|a| (&a.image_view, inheritance_info.depth_attachment_format)) 244 { 245 // VUID-vkCmdExecuteCommands-pDepthAttachment-06029 246 if Some(image_view.format().unwrap()) != format { 247 return Err( 248 ExecuteCommandsError::RenderPassDepthAttachmentFormatMismatch { 249 command_buffer_index, 250 required_format: image_view.format().unwrap(), 251 inherited_format: format, 252 }, 253 ); 254 } 255 256 // VUID-vkCmdExecuteCommands-pNext-06036 257 if image_view.image().samples() != inheritance_info.rasterization_samples { 258 return Err( 259 ExecuteCommandsError::RenderPassDepthAttachmentSamplesMismatch { 260 command_buffer_index, 261 required_samples: image_view.image().samples(), 262 inherited_samples: inheritance_info.rasterization_samples, 263 }, 264 ); 265 } 266 } 267 268 if let Some((image_view, format)) = attachments 269 .stencil_attachment 270 .as_ref() 271 .map(|a| (&a.image_view, inheritance_info.stencil_attachment_format)) 272 { 273 // VUID-vkCmdExecuteCommands-pStencilAttachment-06030 274 if Some(image_view.format().unwrap()) != format { 275 return Err( 276 ExecuteCommandsError::RenderPassStencilAttachmentFormatMismatch { 277 command_buffer_index, 278 required_format: image_view.format().unwrap(), 279 inherited_format: format, 280 }, 281 ); 282 } 283 284 // VUID-vkCmdExecuteCommands-pNext-06037 285 if image_view.image().samples() != inheritance_info.rasterization_samples { 286 return Err( 287 ExecuteCommandsError::RenderPassStencilAttachmentSamplesMismatch { 288 command_buffer_index, 289 required_samples: image_view.image().samples(), 290 inherited_samples: inheritance_info.rasterization_samples, 291 }, 292 ); 293 } 294 } 295 296 // VUID-vkCmdExecuteCommands-viewMask-06031 297 if inheritance_info.view_mask != render_pass_state.view_mask { 298 return Err(ExecuteCommandsError::RenderPassViewMaskMismatch { 299 command_buffer_index, 300 required_view_mask: render_pass_state.view_mask, 301 inherited_view_mask: inheritance_info.view_mask, 302 }); 303 } 304 } 305 _ => { 306 // VUID-vkCmdExecuteCommands-pBeginInfo-06025 307 return Err(ExecuteCommandsError::RenderPassTypeMismatch { 308 command_buffer_index, 309 }); 310 } 311 } 312 313 // TODO: 314 // VUID-vkCmdExecuteCommands-commandBuffer-06533 315 // VUID-vkCmdExecuteCommands-commandBuffer-06534 316 // VUID-vkCmdExecuteCommands-pCommandBuffers-06535 317 // VUID-vkCmdExecuteCommands-pCommandBuffers-06536 318 } else { 319 // VUID-vkCmdExecuteCommands-pCommandBuffers-00100 320 if command_buffer.inheritance_info().render_pass.is_some() { 321 return Err(ExecuteCommandsError::RenderPassInheritanceForbidden { 322 command_buffer_index, 323 }); 324 } 325 } 326 327 // VUID-vkCmdExecuteCommands-commandBuffer-00101 328 if !self.query_state.is_empty() && !self.device().enabled_features().inherited_queries { 329 return Err(ExecuteCommandsError::RequirementNotMet { 330 required_for: "`AutoCommandBufferBuilder::execute_commands` when a query is active", 331 requires_one_of: RequiresOneOf { 332 features: &["inherited_queries"], 333 ..Default::default() 334 }, 335 }); 336 } 337 338 for state in self.query_state.values() { 339 match state.ty { 340 QueryType::Occlusion => { 341 // VUID-vkCmdExecuteCommands-commandBuffer-00102 342 let inherited_flags = command_buffer.inheritance_info().occlusion_query.ok_or( 343 ExecuteCommandsError::OcclusionQueryInheritanceRequired { 344 command_buffer_index, 345 }, 346 )?; 347 348 let inherited_flags_vk = ash::vk::QueryControlFlags::from(inherited_flags); 349 let state_flags_vk = ash::vk::QueryControlFlags::from(state.flags); 350 351 // VUID-vkCmdExecuteCommands-commandBuffer-00103 352 if inherited_flags_vk & state_flags_vk != state_flags_vk { 353 return Err(ExecuteCommandsError::OcclusionQueryFlagsNotSuperset { 354 command_buffer_index, 355 required_flags: state.flags, 356 inherited_flags, 357 }); 358 } 359 } 360 QueryType::PipelineStatistics(state_flags) => { 361 let inherited_flags = command_buffer.inheritance_info().query_statistics_flags; 362 let inherited_flags_vk = 363 ash::vk::QueryPipelineStatisticFlags::from(inherited_flags); 364 let state_flags_vk = ash::vk::QueryPipelineStatisticFlags::from(state_flags); 365 366 // VUID-vkCmdExecuteCommands-commandBuffer-00104 367 if inherited_flags_vk & state_flags_vk != state_flags_vk { 368 return Err( 369 ExecuteCommandsError::PipelineStatisticsQueryFlagsNotSuperset { 370 command_buffer_index, 371 required_flags: state_flags, 372 inherited_flags, 373 }, 374 ); 375 } 376 } 377 QueryType::Timestamp => (), 378 } 379 } 380 381 // TODO: 382 // VUID-vkCmdExecuteCommands-pCommandBuffers-00091 383 // VUID-vkCmdExecuteCommands-pCommandBuffers-00092 384 // VUID-vkCmdExecuteCommands-pCommandBuffers-00093 385 // VUID-vkCmdExecuteCommands-pCommandBuffers-00105 386 387 // VUID-vkCmdExecuteCommands-bufferlevel 388 // Ensured by the type of the impl block. 389 390 // VUID-vkCmdExecuteCommands-pCommandBuffers-00088 391 // VUID-vkCmdExecuteCommands-pCommandBuffers-00089 392 // Ensured by the SecondaryCommandBuffer trait. 393 394 Ok(()) 395 } 396 } 397 398 impl SyncCommandBufferBuilder { 399 /// Starts the process of executing secondary command buffers. Returns an intermediate struct 400 /// which can be used to add the command buffers. 401 #[inline] execute_commands(&mut self) -> SyncCommandBufferBuilderExecuteCommands<'_>402 pub unsafe fn execute_commands(&mut self) -> SyncCommandBufferBuilderExecuteCommands<'_> { 403 SyncCommandBufferBuilderExecuteCommands { 404 builder: self, 405 inner: Vec::new(), 406 } 407 } 408 } 409 410 /// Prototype for a `vkCmdExecuteCommands`. 411 pub struct SyncCommandBufferBuilderExecuteCommands<'a> { 412 builder: &'a mut SyncCommandBufferBuilder, 413 inner: Vec<Box<dyn SecondaryCommandBufferAbstract>>, 414 } 415 416 impl<'a> SyncCommandBufferBuilderExecuteCommands<'a> { 417 /// Adds a command buffer to the list. add(&mut self, command_buffer: impl SecondaryCommandBufferAbstract + 'static)418 pub fn add(&mut self, command_buffer: impl SecondaryCommandBufferAbstract + 'static) { 419 self.inner.push(Box::new(command_buffer)); 420 } 421 422 #[inline] submit(self) -> Result<(), SyncCommandBufferBuilderError>423 pub unsafe fn submit(self) -> Result<(), SyncCommandBufferBuilderError> { 424 struct DropUnlock(Box<dyn SecondaryCommandBufferAbstract>); 425 impl std::ops::Deref for DropUnlock { 426 type Target = Box<dyn SecondaryCommandBufferAbstract>; 427 428 fn deref(&self) -> &Self::Target { 429 &self.0 430 } 431 } 432 unsafe impl SafeDeref for DropUnlock {} 433 434 impl Drop for DropUnlock { 435 fn drop(&mut self) { 436 unsafe { 437 self.unlock(); 438 } 439 } 440 } 441 442 struct Cmd(Vec<DropUnlock>); 443 444 impl Command for Cmd { 445 fn name(&self) -> &'static str { 446 "execute_commands" 447 } 448 449 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 450 let mut execute = UnsafeCommandBufferBuilderExecuteCommands::new(); 451 self.0 452 .iter() 453 .for_each(|cbuf| execute.add_raw(cbuf.handle())); 454 out.execute_commands(execute); 455 } 456 } 457 458 let command_index = self.builder.commands.len(); 459 let command_name = "execute_commands"; 460 let resources: Vec<_> = self 461 .inner 462 .iter() 463 .enumerate() 464 .flat_map(|(index, cbuf)| { 465 let index = index as u32; 466 let SecondaryCommandBufferResourcesUsage { buffers, images } = 467 cbuf.resources_usage(); 468 469 (buffers.iter().map(move |usage| { 470 let &SecondaryCommandBufferBufferUsage { 471 use_ref, 472 ref buffer, 473 ref range, 474 memory, 475 } = usage; 476 477 ( 478 ResourceUseRef { 479 command_index, 480 command_name, 481 resource_in_command: ResourceInCommand::SecondaryCommandBuffer { 482 index, 483 }, 484 secondary_use_ref: Some(use_ref.into()), 485 }, 486 Resource::Buffer { 487 buffer: buffer.clone(), 488 range: range.clone(), 489 memory, 490 }, 491 ) 492 })) 493 .chain(images.iter().map(move |usage| { 494 let &SecondaryCommandBufferImageUsage { 495 use_ref, 496 ref image, 497 ref subresource_range, 498 memory, 499 start_layout, 500 end_layout, 501 } = usage; 502 503 ( 504 ResourceUseRef { 505 command_index, 506 command_name, 507 resource_in_command: ResourceInCommand::SecondaryCommandBuffer { 508 index, 509 }, 510 secondary_use_ref: Some(use_ref.into()), 511 }, 512 Resource::Image { 513 image: image.clone(), 514 subresource_range: subresource_range.clone(), 515 memory, 516 start_layout, 517 end_layout, 518 }, 519 ) 520 })) 521 }) 522 .collect(); 523 524 for resource in &resources { 525 self.builder.check_resource_conflicts(resource)?; 526 } 527 528 self.builder.commands.push(Box::new(Cmd(self 529 .inner 530 .into_iter() 531 .map(|cbuf| { 532 cbuf.lock_record()?; 533 Ok(DropUnlock(cbuf)) 534 }) 535 .collect::<Result<Vec<_>, CommandBufferExecError>>()?))); 536 537 for resource in resources { 538 self.builder.add_resource(resource); 539 } 540 541 Ok(()) 542 } 543 } 544 545 impl UnsafeCommandBufferBuilder { 546 /// Calls `vkCmdExecuteCommands` on the builder. 547 /// 548 /// Does nothing if the list of command buffers is empty, as it would be a no-op and isn't a 549 /// valid usage of the command anyway. 550 #[inline] execute_commands(&mut self, cbs: UnsafeCommandBufferBuilderExecuteCommands)551 pub unsafe fn execute_commands(&mut self, cbs: UnsafeCommandBufferBuilderExecuteCommands) { 552 if cbs.raw_cbs.is_empty() { 553 return; 554 } 555 556 let fns = self.device.fns(); 557 (fns.v1_0.cmd_execute_commands)( 558 self.handle, 559 cbs.raw_cbs.len() as u32, 560 cbs.raw_cbs.as_ptr(), 561 ); 562 } 563 } 564 565 /// Prototype for a `vkCmdExecuteCommands`. 566 pub struct UnsafeCommandBufferBuilderExecuteCommands { 567 // Raw handles of the command buffers to execute. 568 raw_cbs: SmallVec<[ash::vk::CommandBuffer; 4]>, 569 } 570 571 impl UnsafeCommandBufferBuilderExecuteCommands { 572 /// Builds a new empty list. 573 #[inline] new() -> UnsafeCommandBufferBuilderExecuteCommands574 pub fn new() -> UnsafeCommandBufferBuilderExecuteCommands { 575 UnsafeCommandBufferBuilderExecuteCommands { 576 raw_cbs: SmallVec::new(), 577 } 578 } 579 580 /// Adds a command buffer to the list. add(&mut self, cb: &(impl SecondaryCommandBufferAbstract + ?Sized))581 pub fn add(&mut self, cb: &(impl SecondaryCommandBufferAbstract + ?Sized)) { 582 // TODO: debug assert that it is a secondary command buffer? 583 self.raw_cbs.push(cb.handle()); 584 } 585 586 /// Adds a command buffer to the list. 587 #[inline] add_raw(&mut self, cb: ash::vk::CommandBuffer)588 pub unsafe fn add_raw(&mut self, cb: ash::vk::CommandBuffer) { 589 self.raw_cbs.push(cb); 590 } 591 } 592 593 /// Error that can happen when executing a secondary command buffer. 594 #[derive(Clone, Debug)] 595 pub enum ExecuteCommandsError { 596 SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), 597 598 RequirementNotMet { 599 required_for: &'static str, 600 requires_one_of: RequiresOneOf, 601 }, 602 603 /// Operation forbidden inside a render subpass with the specified contents. 604 ForbiddenWithSubpassContents { 605 contents: SubpassContents, 606 }, 607 608 /// The queue family doesn't allow this operation. 609 NotSupportedByQueueFamily, 610 611 /// A render pass is active, but a command buffer does not contain occlusion query inheritance 612 /// info. 613 OcclusionQueryInheritanceRequired { 614 command_buffer_index: u32, 615 }, 616 617 /// The inherited occlusion query control flags of a command buffer are not a superset of the 618 /// currently active flags. 619 OcclusionQueryFlagsNotSuperset { 620 command_buffer_index: u32, 621 required_flags: QueryControlFlags, 622 inherited_flags: QueryControlFlags, 623 }, 624 625 /// The inherited pipeline statistics query flags of a command buffer are not a superset of the 626 /// currently active flags. 627 PipelineStatisticsQueryFlagsNotSuperset { 628 command_buffer_index: u32, 629 required_flags: QueryPipelineStatisticFlags, 630 inherited_flags: QueryPipelineStatisticFlags, 631 }, 632 633 /// The inherited color attachment count of a command buffer does not match the current 634 /// attachment count. 635 RenderPassColorAttachmentCountMismatch { 636 command_buffer_index: u32, 637 required_count: u32, 638 inherited_count: u32, 639 }, 640 641 /// The inherited format of a color attachment of a command buffer does not match the current 642 /// attachment format. 643 RenderPassColorAttachmentFormatMismatch { 644 command_buffer_index: u32, 645 color_attachment_index: u32, 646 required_format: Format, 647 inherited_format: Option<Format>, 648 }, 649 650 /// The inherited sample count of a color attachment of a command buffer does not match the 651 /// current attachment sample count. 652 RenderPassColorAttachmentSamplesMismatch { 653 command_buffer_index: u32, 654 color_attachment_index: u32, 655 required_samples: SampleCount, 656 inherited_samples: SampleCount, 657 }, 658 659 /// The inherited format of the depth attachment of a command buffer does not match the current 660 /// attachment format. 661 RenderPassDepthAttachmentFormatMismatch { 662 command_buffer_index: u32, 663 required_format: Format, 664 inherited_format: Option<Format>, 665 }, 666 667 /// The inherited sample count of the depth attachment of a command buffer does not match the 668 /// current attachment sample count. 669 RenderPassDepthAttachmentSamplesMismatch { 670 command_buffer_index: u32, 671 required_samples: SampleCount, 672 inherited_samples: SampleCount, 673 }, 674 675 /// The inherited framebuffer of a command buffer does not match the current framebuffer. 676 RenderPassFramebufferMismatch { 677 command_buffer_index: u32, 678 }, 679 680 /// A render pass is active, but a command buffer does not contain render pass inheritance info. 681 RenderPassInheritanceRequired { 682 command_buffer_index: u32, 683 }, 684 685 /// A render pass is not active, but a command buffer contains render pass inheritance info. 686 RenderPassInheritanceForbidden { 687 command_buffer_index: u32, 688 }, 689 690 /// The inherited render pass of a command buffer is not compatible with the current render 691 /// pass. 692 RenderPassNotCompatible { 693 command_buffer_index: u32, 694 }, 695 696 /// The inherited format of the stencil attachment of a command buffer does not match the 697 /// current attachment format. 698 RenderPassStencilAttachmentFormatMismatch { 699 command_buffer_index: u32, 700 required_format: Format, 701 inherited_format: Option<Format>, 702 }, 703 704 /// The inherited sample count of the stencil attachment of a command buffer does not match the 705 /// current attachment sample count. 706 RenderPassStencilAttachmentSamplesMismatch { 707 command_buffer_index: u32, 708 required_samples: SampleCount, 709 inherited_samples: SampleCount, 710 }, 711 712 /// The inherited subpass index of a command buffer does not match the current subpass index. 713 RenderPassSubpassMismatch { 714 command_buffer_index: u32, 715 required_subpass: u32, 716 inherited_subpass: u32, 717 }, 718 719 /// The inherited render pass of a command buffer is of the wrong type. 720 RenderPassTypeMismatch { 721 command_buffer_index: u32, 722 }, 723 724 /// The inherited view mask of a command buffer does not match the current view mask. 725 RenderPassViewMaskMismatch { 726 command_buffer_index: u32, 727 required_view_mask: u32, 728 inherited_view_mask: u32, 729 }, 730 } 731 732 impl Error for ExecuteCommandsError { source(&self) -> Option<&(dyn Error + 'static)>733 fn source(&self) -> Option<&(dyn Error + 'static)> { 734 match self { 735 Self::SyncCommandBufferBuilderError(err) => Some(err), 736 _ => None, 737 } 738 } 739 } 740 741 impl Display for ExecuteCommandsError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>742 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 743 match self { 744 Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"), 745 Self::RequirementNotMet { 746 required_for, 747 requires_one_of, 748 } => write!( 749 f, 750 "a requirement was not met for: {}; requires one of: {}", 751 required_for, requires_one_of, 752 ), 753 Self::ForbiddenWithSubpassContents { 754 contents: subpass_contents, 755 } => write!( 756 f, 757 "operation forbidden inside a render subpass with contents {:?}", 758 subpass_contents, 759 ), 760 Self::NotSupportedByQueueFamily => { 761 write!(f, "the queue family doesn't allow this operation") 762 } 763 Self::OcclusionQueryInheritanceRequired { 764 command_buffer_index, 765 } => write!( 766 f, 767 "a render pass is active, but command buffer {} does not contain occlusion query \ 768 inheritance info", 769 command_buffer_index, 770 ), 771 Self::OcclusionQueryFlagsNotSuperset { 772 command_buffer_index, 773 required_flags, 774 inherited_flags, 775 } => write!( 776 f, 777 "the inherited occlusion query control flags ({:?}) of command buffer {} are not a \ 778 superset of the currently active flags ({:?})", 779 inherited_flags, command_buffer_index, required_flags, 780 ), 781 Self::PipelineStatisticsQueryFlagsNotSuperset { 782 command_buffer_index, 783 required_flags, 784 inherited_flags, 785 } => write!( 786 f, 787 "the inherited pipeline statistics query flags ({:?}) of command buffer {} are not \ 788 a superset of the currently active flags ({:?})", 789 inherited_flags, command_buffer_index, required_flags, 790 ), 791 Self::RenderPassColorAttachmentCountMismatch { 792 command_buffer_index, 793 required_count, 794 inherited_count, 795 } => write!( 796 f, 797 "the inherited color attachment count ({}) of command buffer {} does not match the \ 798 current attachment count ({})", 799 inherited_count, command_buffer_index, required_count, 800 ), 801 Self::RenderPassColorAttachmentFormatMismatch { 802 command_buffer_index, 803 color_attachment_index, 804 required_format, 805 inherited_format, 806 } => write!( 807 f, 808 "the inherited format ({:?}) of color attachment {} of command buffer {} does not \ 809 match the current attachment format ({:?})", 810 inherited_format, color_attachment_index, command_buffer_index, required_format, 811 ), 812 Self::RenderPassColorAttachmentSamplesMismatch { 813 command_buffer_index, 814 color_attachment_index, 815 required_samples, 816 inherited_samples, 817 } => write!( 818 f, 819 "the inherited sample count ({:?}) of color attachment {} of command buffer {} \ 820 does not match the current attachment sample count ({:?})", 821 inherited_samples, color_attachment_index, command_buffer_index, required_samples, 822 ), 823 Self::RenderPassDepthAttachmentFormatMismatch { 824 command_buffer_index, 825 required_format, 826 inherited_format, 827 } => write!( 828 f, 829 "the inherited format ({:?}) of the depth attachment of command buffer {} does not \ 830 match the current attachment format ({:?})", 831 inherited_format, command_buffer_index, required_format, 832 ), 833 Self::RenderPassDepthAttachmentSamplesMismatch { 834 command_buffer_index, 835 required_samples, 836 inherited_samples, 837 } => write!( 838 f, 839 "the inherited sample count ({:?}) of the depth attachment of command buffer {} \ 840 does not match the current attachment sample count ({:?})", 841 inherited_samples, command_buffer_index, required_samples, 842 ), 843 Self::RenderPassFramebufferMismatch { 844 command_buffer_index, 845 } => write!( 846 f, 847 "the inherited framebuffer of command buffer {} does not match the current \ 848 framebuffer", 849 command_buffer_index, 850 ), 851 Self::RenderPassInheritanceRequired { 852 command_buffer_index, 853 } => write!( 854 f, 855 "a render pass is active, but command buffer {} does not contain render pass \ 856 inheritance info", 857 command_buffer_index, 858 ), 859 Self::RenderPassInheritanceForbidden { 860 command_buffer_index, 861 } => write!( 862 f, 863 "a render pass is not active, but command buffer {} contains render pass \ 864 inheritance info", 865 command_buffer_index, 866 ), 867 Self::RenderPassNotCompatible { 868 command_buffer_index, 869 } => write!( 870 f, 871 "the inherited render pass of command buffer {} is not compatible with the current \ 872 render pass", 873 command_buffer_index, 874 ), 875 Self::RenderPassStencilAttachmentFormatMismatch { 876 command_buffer_index, 877 required_format, 878 inherited_format, 879 } => write!( 880 f, 881 "the inherited format ({:?}) of the stencil attachment of command buffer {} does \ 882 not match the current attachment format ({:?})", 883 inherited_format, command_buffer_index, required_format, 884 ), 885 Self::RenderPassStencilAttachmentSamplesMismatch { 886 command_buffer_index, 887 required_samples, 888 inherited_samples, 889 } => write!( 890 f, 891 "the inherited sample count ({:?}) of the stencil attachment of command buffer {} \ 892 does not match the current attachment sample count ({:?})", 893 inherited_samples, command_buffer_index, required_samples, 894 ), 895 Self::RenderPassSubpassMismatch { 896 command_buffer_index, 897 required_subpass, 898 inherited_subpass, 899 } => write!( 900 f, 901 "the inherited subpass index ({}) of command buffer {} does not match the current \ 902 subpass index ({})", 903 inherited_subpass, command_buffer_index, required_subpass, 904 ), 905 Self::RenderPassTypeMismatch { 906 command_buffer_index, 907 } => write!( 908 f, 909 "the inherited render pass of command buffer {} is of the wrong type", 910 command_buffer_index, 911 ), 912 Self::RenderPassViewMaskMismatch { 913 command_buffer_index, 914 required_view_mask, 915 inherited_view_mask, 916 } => write!( 917 f, 918 "the inherited view mask ({}) of command buffer {} does not match the current view \ 919 mask ({})", 920 inherited_view_mask, command_buffer_index, required_view_mask, 921 ), 922 } 923 } 924 } 925 926 impl From<SyncCommandBufferBuilderError> for ExecuteCommandsError { from(err: SyncCommandBufferBuilderError) -> Self927 fn from(err: SyncCommandBufferBuilderError) -> Self { 928 Self::SyncCommandBufferBuilderError(err) 929 } 930 } 931