• 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         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