• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use crate::buffer::BufferAccess;
11 use crate::buffer::TypedBufferAccess;
12 use crate::command_buffer::pool::standard::StandardCommandPoolAlloc;
13 use crate::command_buffer::pool::standard::StandardCommandPoolBuilder;
14 use crate::command_buffer::pool::CommandPool;
15 use crate::command_buffer::pool::CommandPoolBuilderAlloc;
16 use crate::command_buffer::synced::SyncCommandBuffer;
17 use crate::command_buffer::synced::SyncCommandBufferBuilder;
18 use crate::command_buffer::synced::SyncCommandBufferBuilderError;
19 use crate::command_buffer::sys::UnsafeCommandBuffer;
20 use crate::command_buffer::sys::UnsafeCommandBufferBuilderBufferImageCopy;
21 use crate::command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
22 use crate::command_buffer::sys::UnsafeCommandBufferBuilderImageBlit;
23 use crate::command_buffer::sys::UnsafeCommandBufferBuilderImageCopy;
24 use crate::command_buffer::validity::*;
25 use crate::command_buffer::CommandBufferExecError;
26 use crate::command_buffer::CommandBufferInheritance;
27 use crate::command_buffer::CommandBufferInheritanceRenderPass;
28 use crate::command_buffer::CommandBufferLevel;
29 use crate::command_buffer::CommandBufferUsage;
30 use crate::command_buffer::DispatchIndirectCommand;
31 use crate::command_buffer::DrawIndexedIndirectCommand;
32 use crate::command_buffer::DrawIndirectCommand;
33 use crate::command_buffer::DynamicState;
34 use crate::command_buffer::ImageUninitializedSafe;
35 use crate::command_buffer::PrimaryCommandBuffer;
36 use crate::command_buffer::SecondaryCommandBuffer;
37 use crate::command_buffer::StateCacher;
38 use crate::command_buffer::StateCacherOutcome;
39 use crate::command_buffer::SubpassContents;
40 use crate::descriptor_set::DescriptorSetWithOffsets;
41 use crate::descriptor_set::DescriptorSetsCollection;
42 use crate::device::physical::QueueFamily;
43 use crate::device::Device;
44 use crate::device::DeviceOwned;
45 use crate::device::Queue;
46 use crate::format::ClearValue;
47 use crate::format::FormatTy;
48 use crate::format::Pixel;
49 use crate::image::ImageAccess;
50 use crate::image::ImageAspect;
51 use crate::image::ImageAspects;
52 use crate::image::ImageLayout;
53 use crate::pipeline::depth_stencil::StencilFaces;
54 use crate::pipeline::input_assembly::Index;
55 use crate::pipeline::layout::PipelineLayout;
56 use crate::pipeline::vertex::VertexSource;
57 use crate::pipeline::ComputePipelineAbstract;
58 use crate::pipeline::GraphicsPipelineAbstract;
59 use crate::pipeline::PipelineBindPoint;
60 use crate::query::QueryControlFlags;
61 use crate::query::QueryPipelineStatisticFlags;
62 use crate::query::QueryPool;
63 use crate::query::QueryResultElement;
64 use crate::query::QueryResultFlags;
65 use crate::query::QueryType;
66 use crate::render_pass::Framebuffer;
67 use crate::render_pass::FramebufferAbstract;
68 use crate::render_pass::LoadOp;
69 use crate::render_pass::RenderPass;
70 use crate::render_pass::Subpass;
71 use crate::sampler::Filter;
72 use crate::sync::AccessCheckError;
73 use crate::sync::AccessFlags;
74 use crate::sync::GpuFuture;
75 use crate::sync::PipelineMemoryAccess;
76 use crate::sync::PipelineStage;
77 use crate::sync::PipelineStages;
78 use crate::DeviceSize;
79 use crate::VulkanObject;
80 use crate::{OomError, SafeDeref};
81 use fnv::FnvHashMap;
82 use std::error;
83 use std::ffi::CStr;
84 use std::fmt;
85 use std::iter;
86 use std::marker::PhantomData;
87 use std::mem;
88 use std::ops::Range;
89 use std::slice;
90 use std::sync::atomic::AtomicBool;
91 use std::sync::atomic::Ordering;
92 use std::sync::Arc;
93 
94 /// Note that command buffers allocated from the default command pool (`Arc<StandardCommandPool>`)
95 /// don't implement the `Send` and `Sync` traits. If you use this pool, then the
96 /// `AutoCommandBufferBuilder` will not implement `Send` and `Sync` either. Once a command buffer
97 /// is built, however, it *does* implement `Send` and `Sync`.
98 pub struct AutoCommandBufferBuilder<L, P = StandardCommandPoolBuilder> {
99     inner: SyncCommandBufferBuilder,
100     pool_builder_alloc: P, // Safety: must be dropped after `inner`
101     state_cacher: StateCacher,
102 
103     // The queue family that this command buffer is being created for.
104     queue_family_id: u32,
105 
106     // The inheritance for secondary command buffers.
107     inheritance: Option<CommandBufferInheritance<Box<dyn FramebufferAbstract + Send + Sync>>>,
108 
109     // Usage flags passed when creating the command buffer.
110     usage: CommandBufferUsage,
111 
112     // If we're inside a render pass, contains the render pass state.
113     render_pass_state: Option<RenderPassState>,
114 
115     // If any queries are active, this hashmap contains their state.
116     query_state: FnvHashMap<ash::vk::QueryType, QueryState>,
117 
118     _data: PhantomData<L>,
119 }
120 
121 // The state of the current render pass, specifying the pass, subpass index and its intended contents.
122 struct RenderPassState {
123     subpass: (Arc<RenderPass>, u32),
124     contents: SubpassContents,
125     framebuffer: ash::vk::Framebuffer, // Always null for secondary command buffers
126 }
127 
128 // The state of an active query.
129 struct QueryState {
130     query_pool: ash::vk::QueryPool,
131     query: u32,
132     ty: QueryType,
133     flags: QueryControlFlags,
134     in_subpass: bool,
135 }
136 
137 impl AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder> {
138     /// Starts building a primary command buffer.
139     #[inline]
primary( device: Arc<Device>, queue_family: QueueFamily, usage: CommandBufferUsage, ) -> Result< AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder>, OomError, >140     pub fn primary(
141         device: Arc<Device>,
142         queue_family: QueueFamily,
143         usage: CommandBufferUsage,
144     ) -> Result<
145         AutoCommandBufferBuilder<PrimaryAutoCommandBuffer, StandardCommandPoolBuilder>,
146         OomError,
147     > {
148         AutoCommandBufferBuilder::with_level(
149             device,
150             queue_family,
151             usage,
152             CommandBufferLevel::primary(),
153         )
154     }
155 }
156 
157 impl AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder> {
158     /// Starts building a secondary compute command buffer.
159     #[inline]
secondary_compute( device: Arc<Device>, queue_family: QueueFamily, usage: CommandBufferUsage, ) -> Result< AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>, OomError, >160     pub fn secondary_compute(
161         device: Arc<Device>,
162         queue_family: QueueFamily,
163         usage: CommandBufferUsage,
164     ) -> Result<
165         AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
166         OomError,
167     > {
168         let level = CommandBufferLevel::secondary(None, QueryPipelineStatisticFlags::none());
169         AutoCommandBufferBuilder::with_level(device, queue_family, usage, level)
170     }
171 
172     /// Same as `secondary_compute`, but allows specifying how queries are being inherited.
173     #[inline]
secondary_compute_inherit_queries( device: Arc<Device>, queue_family: QueueFamily, usage: CommandBufferUsage, occlusion_query: Option<QueryControlFlags>, query_statistics_flags: QueryPipelineStatisticFlags, ) -> Result< AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>, BeginError, >174     pub fn secondary_compute_inherit_queries(
175         device: Arc<Device>,
176         queue_family: QueueFamily,
177         usage: CommandBufferUsage,
178         occlusion_query: Option<QueryControlFlags>,
179         query_statistics_flags: QueryPipelineStatisticFlags,
180     ) -> Result<
181         AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
182         BeginError,
183     > {
184         if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
185             return Err(BeginError::InheritedQueriesFeatureNotEnabled);
186         }
187 
188         if query_statistics_flags.count() > 0
189             && !device.enabled_features().pipeline_statistics_query
190         {
191             return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
192         }
193 
194         let level = CommandBufferLevel::secondary(occlusion_query, query_statistics_flags);
195         Ok(AutoCommandBufferBuilder::with_level(
196             device,
197             queue_family,
198             usage,
199             level,
200         )?)
201     }
202 
203     /// Starts building a secondary graphics command buffer.
204     #[inline]
secondary_graphics( device: Arc<Device>, queue_family: QueueFamily, usage: CommandBufferUsage, subpass: Subpass, ) -> Result< AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>, OomError, >205     pub fn secondary_graphics(
206         device: Arc<Device>,
207         queue_family: QueueFamily,
208         usage: CommandBufferUsage,
209         subpass: Subpass,
210     ) -> Result<
211         AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
212         OomError,
213     > {
214         let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
215             render_pass: Some(CommandBufferInheritanceRenderPass {
216                 subpass,
217                 framebuffer: None::<Arc<Framebuffer<()>>>,
218             }),
219             occlusion_query: None,
220             query_statistics_flags: QueryPipelineStatisticFlags::none(),
221         });
222 
223         AutoCommandBufferBuilder::with_level(device, queue_family, usage, level)
224     }
225 
226     /// Same as `secondary_graphics`, but allows specifying how queries are being inherited.
227     #[inline]
secondary_graphics_inherit_queries( device: Arc<Device>, queue_family: QueueFamily, usage: CommandBufferUsage, subpass: Subpass, occlusion_query: Option<QueryControlFlags>, query_statistics_flags: QueryPipelineStatisticFlags, ) -> Result< AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>, BeginError, >228     pub fn secondary_graphics_inherit_queries(
229         device: Arc<Device>,
230         queue_family: QueueFamily,
231         usage: CommandBufferUsage,
232         subpass: Subpass,
233         occlusion_query: Option<QueryControlFlags>,
234         query_statistics_flags: QueryPipelineStatisticFlags,
235     ) -> Result<
236         AutoCommandBufferBuilder<SecondaryAutoCommandBuffer, StandardCommandPoolBuilder>,
237         BeginError,
238     > {
239         if occlusion_query.is_some() && !device.enabled_features().inherited_queries {
240             return Err(BeginError::InheritedQueriesFeatureNotEnabled);
241         }
242 
243         if query_statistics_flags.count() > 0
244             && !device.enabled_features().pipeline_statistics_query
245         {
246             return Err(BeginError::PipelineStatisticsQueryFeatureNotEnabled);
247         }
248 
249         let level = CommandBufferLevel::Secondary(CommandBufferInheritance {
250             render_pass: Some(CommandBufferInheritanceRenderPass {
251                 subpass,
252                 framebuffer: None::<Arc<Framebuffer<()>>>,
253             }),
254             occlusion_query,
255             query_statistics_flags,
256         });
257 
258         Ok(AutoCommandBufferBuilder::with_level(
259             device,
260             queue_family,
261             usage,
262             level,
263         )?)
264     }
265 }
266 
267 impl<L> AutoCommandBufferBuilder<L, StandardCommandPoolBuilder> {
268     // Actual constructor. Private.
with_level<F>( device: Arc<Device>, queue_family: QueueFamily, usage: CommandBufferUsage, level: CommandBufferLevel<F>, ) -> Result<AutoCommandBufferBuilder<L, StandardCommandPoolBuilder>, OomError> where F: FramebufferAbstract + Clone + Send + Sync + 'static,269     fn with_level<F>(
270         device: Arc<Device>,
271         queue_family: QueueFamily,
272         usage: CommandBufferUsage,
273         level: CommandBufferLevel<F>,
274     ) -> Result<AutoCommandBufferBuilder<L, StandardCommandPoolBuilder>, OomError>
275     where
276         F: FramebufferAbstract + Clone + Send + Sync + 'static,
277     {
278         let (inheritance, render_pass_state) = match &level {
279             CommandBufferLevel::Primary => (None, None),
280             CommandBufferLevel::Secondary(inheritance) => {
281                 let (render_pass, render_pass_state) = match inheritance.render_pass.as_ref() {
282                     Some(CommandBufferInheritanceRenderPass {
283                         subpass,
284                         framebuffer,
285                     }) => {
286                         let render_pass = CommandBufferInheritanceRenderPass {
287                             subpass: Subpass::from(subpass.render_pass().clone(), subpass.index())
288                                 .unwrap(),
289                             framebuffer: framebuffer
290                                 .as_ref()
291                                 .map(|f| Box::new(f.clone()) as Box<_>),
292                         };
293                         let render_pass_state = RenderPassState {
294                             subpass: (subpass.render_pass().clone(), subpass.index()),
295                             contents: SubpassContents::Inline,
296                             framebuffer: ash::vk::Framebuffer::null(), // Only needed for primary command buffers
297                         };
298                         (Some(render_pass), Some(render_pass_state))
299                     }
300                     None => (None, None),
301                 };
302 
303                 (
304                     Some(CommandBufferInheritance {
305                         render_pass,
306                         occlusion_query: inheritance.occlusion_query,
307                         query_statistics_flags: inheritance.query_statistics_flags,
308                     }),
309                     render_pass_state,
310                 )
311             }
312         };
313 
314         unsafe {
315             let pool = Device::standard_command_pool(&device, queue_family);
316             let pool_builder_alloc = pool
317                 .alloc(!matches!(level, CommandBufferLevel::Primary), 1)?
318                 .next()
319                 .expect("Requested one command buffer from the command pool, but got zero.");
320             let inner = SyncCommandBufferBuilder::new(pool_builder_alloc.inner(), level, usage)?;
321 
322             Ok(AutoCommandBufferBuilder {
323                 inner,
324                 pool_builder_alloc,
325                 state_cacher: StateCacher::new(),
326                 queue_family_id: queue_family.id(),
327                 render_pass_state,
328                 query_state: FnvHashMap::default(),
329                 inheritance,
330                 usage,
331                 _data: PhantomData,
332             })
333         }
334     }
335 }
336 
337 #[derive(Clone, Copy, Debug)]
338 pub enum BeginError {
339     /// Occlusion query inheritance was requested, but the `inherited_queries` feature was not enabled.
340     InheritedQueriesFeatureNotEnabled,
341     /// Not enough memory.
342     OomError(OomError),
343     /// Pipeline statistics query inheritance was requested, but the `pipeline_statistics_query` feature was not enabled.
344     PipelineStatisticsQueryFeatureNotEnabled,
345 }
346 
347 impl error::Error for BeginError {
348     #[inline]
source(&self) -> Option<&(dyn error::Error + 'static)>349     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
350         match *self {
351             Self::OomError(ref err) => Some(err),
352             _ => None,
353         }
354     }
355 }
356 
357 impl fmt::Display for BeginError {
358     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>359     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
360         write!(
361             fmt,
362             "{}",
363             match *self {
364                 Self::InheritedQueriesFeatureNotEnabled => {
365                     "occlusion query inheritance was requested but the corresponding feature \
366                  wasn't enabled"
367                 }
368                 Self::OomError(_) => "not enough memory available",
369                 Self::PipelineStatisticsQueryFeatureNotEnabled => {
370                     "pipeline statistics query inheritance was requested but the corresponding \
371                  feature wasn't enabled"
372                 }
373             }
374         )
375     }
376 }
377 
378 impl From<OomError> for BeginError {
379     #[inline]
from(err: OomError) -> Self380     fn from(err: OomError) -> Self {
381         Self::OomError(err)
382     }
383 }
384 
385 impl<P> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer<P::Alloc>, P>
386 where
387     P: CommandPoolBuilderAlloc,
388 {
389     /// Builds the command buffer.
390     #[inline]
build(self) -> Result<PrimaryAutoCommandBuffer<P::Alloc>, BuildError>391     pub fn build(self) -> Result<PrimaryAutoCommandBuffer<P::Alloc>, BuildError> {
392         if self.render_pass_state.is_some() {
393             return Err(AutoCommandBufferBuilderContextError::ForbiddenInsideRenderPass.into());
394         }
395 
396         if !self.query_state.is_empty() {
397             return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
398         }
399 
400         let submit_state = match self.usage {
401             CommandBufferUsage::MultipleSubmit => SubmitState::ExclusiveUse {
402                 in_use: AtomicBool::new(false),
403             },
404             CommandBufferUsage::SimultaneousUse => SubmitState::Concurrent,
405             CommandBufferUsage::OneTimeSubmit => SubmitState::OneTime {
406                 already_submitted: AtomicBool::new(false),
407             },
408         };
409 
410         Ok(PrimaryAutoCommandBuffer {
411             inner: self.inner.build()?,
412             pool_alloc: self.pool_builder_alloc.into_alloc(),
413             submit_state,
414         })
415     }
416 }
417 
418 impl<P> AutoCommandBufferBuilder<SecondaryAutoCommandBuffer<P::Alloc>, P>
419 where
420     P: CommandPoolBuilderAlloc,
421 {
422     /// Builds the command buffer.
423     #[inline]
build(self) -> Result<SecondaryAutoCommandBuffer<P::Alloc>, BuildError>424     pub fn build(self) -> Result<SecondaryAutoCommandBuffer<P::Alloc>, BuildError> {
425         if !self.query_state.is_empty() {
426             return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
427         }
428 
429         let submit_state = match self.usage {
430             CommandBufferUsage::MultipleSubmit => SubmitState::ExclusiveUse {
431                 in_use: AtomicBool::new(false),
432             },
433             CommandBufferUsage::SimultaneousUse => SubmitState::Concurrent,
434             CommandBufferUsage::OneTimeSubmit => SubmitState::OneTime {
435                 already_submitted: AtomicBool::new(false),
436             },
437         };
438 
439         Ok(SecondaryAutoCommandBuffer {
440             inner: self.inner.build()?,
441             pool_alloc: self.pool_builder_alloc.into_alloc(),
442             inheritance: self.inheritance.unwrap(),
443             submit_state,
444         })
445     }
446 }
447 
448 impl<L, P> AutoCommandBufferBuilder<L, P> {
449     #[inline]
ensure_outside_render_pass(&self) -> Result<(), AutoCommandBufferBuilderContextError>450     fn ensure_outside_render_pass(&self) -> Result<(), AutoCommandBufferBuilderContextError> {
451         if self.render_pass_state.is_some() {
452             return Err(AutoCommandBufferBuilderContextError::ForbiddenInsideRenderPass);
453         }
454 
455         Ok(())
456     }
457 
458     #[inline]
ensure_inside_render_pass_inline<Gp>( &self, pipeline: &Gp, ) -> Result<(), AutoCommandBufferBuilderContextError> where Gp: ?Sized + GraphicsPipelineAbstract,459     fn ensure_inside_render_pass_inline<Gp>(
460         &self,
461         pipeline: &Gp,
462     ) -> Result<(), AutoCommandBufferBuilderContextError>
463     where
464         Gp: ?Sized + GraphicsPipelineAbstract,
465     {
466         let render_pass_state = self
467             .render_pass_state
468             .as_ref()
469             .ok_or(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass)?;
470 
471         // Subpass must be for inline commands
472         if render_pass_state.contents != SubpassContents::Inline {
473             return Err(AutoCommandBufferBuilderContextError::WrongSubpassType);
474         }
475 
476         // Subpasses must be the same.
477         if pipeline.subpass().index() != render_pass_state.subpass.1 {
478             return Err(AutoCommandBufferBuilderContextError::WrongSubpassIndex);
479         }
480 
481         // Render passes must be compatible.
482         if !pipeline
483             .subpass()
484             .render_pass()
485             .desc()
486             .is_compatible_with_desc(&render_pass_state.subpass.0.desc())
487         {
488             return Err(AutoCommandBufferBuilderContextError::IncompatibleRenderPass);
489         }
490 
491         Ok(())
492     }
493 
494     #[inline]
queue_family(&self) -> QueueFamily495     fn queue_family(&self) -> QueueFamily {
496         self.device()
497             .physical_device()
498             .queue_family_by_id(self.queue_family_id)
499             .unwrap()
500     }
501 
502     /// Adds a command that copies an image to another.
503     ///
504     /// Copy operations have several restrictions:
505     ///
506     /// - Copy operations are only allowed on queue families that support transfer, graphics, or
507     ///   compute operations.
508     /// - The number of samples in the source and destination images must be equal.
509     /// - The size of the uncompressed element format of the source image must be equal to the
510     ///   compressed element format of the destination.
511     /// - If you copy between depth, stencil or depth-stencil images, the format of both images
512     ///   must match exactly.
513     /// - For two-dimensional images, the Z coordinate must be 0 for the image offsets and 1 for
514     ///   the extent. Same for the Y coordinate for one-dimensional images.
515     /// - For non-array images, the base array layer must be 0 and the number of layers must be 1.
516     ///
517     /// If `layer_count` is greater than 1, the copy will happen between each individual layer as
518     /// if they were separate images.
519     ///
520     /// # Panic
521     ///
522     /// - Panics if the source or the destination was not created with `device`.
523     ///
copy_image<S, D>( &mut self, source: S, source_offset: [i32; 3], source_base_array_layer: u32, source_mip_level: u32, destination: D, destination_offset: [i32; 3], destination_base_array_layer: u32, destination_mip_level: u32, extent: [u32; 3], layer_count: u32, ) -> Result<&mut Self, CopyImageError> where S: ImageAccess + Send + Sync + 'static, D: ImageAccess + Send + Sync + 'static,524     pub fn copy_image<S, D>(
525         &mut self,
526         source: S,
527         source_offset: [i32; 3],
528         source_base_array_layer: u32,
529         source_mip_level: u32,
530         destination: D,
531         destination_offset: [i32; 3],
532         destination_base_array_layer: u32,
533         destination_mip_level: u32,
534         extent: [u32; 3],
535         layer_count: u32,
536     ) -> Result<&mut Self, CopyImageError>
537     where
538         S: ImageAccess + Send + Sync + 'static,
539         D: ImageAccess + Send + Sync + 'static,
540     {
541         unsafe {
542             self.ensure_outside_render_pass()?;
543 
544             check_copy_image(
545                 self.device(),
546                 &source,
547                 source_offset,
548                 source_base_array_layer,
549                 source_mip_level,
550                 &destination,
551                 destination_offset,
552                 destination_base_array_layer,
553                 destination_mip_level,
554                 extent,
555                 layer_count,
556             )?;
557 
558             let copy = UnsafeCommandBufferBuilderImageCopy {
559                 // TODO: Allowing choosing a subset of the image aspects, but note that if color
560                 // is included, neither depth nor stencil may.
561                 aspects: ImageAspects {
562                     color: source.has_color(),
563                     depth: !source.has_color() && source.has_depth() && destination.has_depth(),
564                     stencil: !source.has_color()
565                         && source.has_stencil()
566                         && destination.has_stencil(),
567                     ..ImageAspects::none()
568                 },
569                 source_mip_level,
570                 destination_mip_level,
571                 source_base_array_layer,
572                 destination_base_array_layer,
573                 layer_count,
574                 source_offset,
575                 destination_offset,
576                 extent,
577             };
578 
579             // TODO: Allow choosing layouts, but note that only Transfer*Optimal and General are
580             // valid.
581             self.inner.copy_image(
582                 source,
583                 ImageLayout::TransferSrcOptimal,
584                 destination,
585                 ImageLayout::TransferDstOptimal,
586                 iter::once(copy),
587             )?;
588             Ok(self)
589         }
590     }
591 
592     /// Adds a command that blits an image to another.
593     ///
594     /// A *blit* is similar to an image copy operation, except that the portion of the image that
595     /// is transferred can be resized. You choose an area of the source and an area of the
596     /// destination, and the implementation will resize the area of the source so that it matches
597     /// the size of the area of the destination before writing it.
598     ///
599     /// Blit operations have several restrictions:
600     ///
601     /// - Blit operations are only allowed on queue families that support graphics operations.
602     /// - The format of the source and destination images must support blit operations, which
603     ///   depends on the Vulkan implementation. Vulkan guarantees that some specific formats must
604     ///   always be supported. See tables 52 to 61 of the specifications.
605     /// - Only single-sampled images are allowed.
606     /// - You can only blit between two images whose formats belong to the same type. The types
607     ///   are: floating-point, signed integers, unsigned integers, depth-stencil.
608     /// - If you blit between depth, stencil or depth-stencil images, the format of both images
609     ///   must match exactly.
610     /// - If you blit between depth, stencil or depth-stencil images, only the `Nearest` filter is
611     ///   allowed.
612     /// - For two-dimensional images, the Z coordinate must be 0 for the top-left offset and 1 for
613     ///   the bottom-right offset. Same for the Y coordinate for one-dimensional images.
614     /// - For non-array images, the base array layer must be 0 and the number of layers must be 1.
615     ///
616     /// If `layer_count` is greater than 1, the blit will happen between each individual layer as
617     /// if they were separate images.
618     ///
619     /// # Panic
620     ///
621     /// - Panics if the source or the destination was not created with `device`.
622     ///
blit_image<S, D>( &mut self, source: S, source_top_left: [i32; 3], source_bottom_right: [i32; 3], source_base_array_layer: u32, source_mip_level: u32, destination: D, destination_top_left: [i32; 3], destination_bottom_right: [i32; 3], destination_base_array_layer: u32, destination_mip_level: u32, layer_count: u32, filter: Filter, ) -> Result<&mut Self, BlitImageError> where S: ImageAccess + Send + Sync + 'static, D: ImageAccess + Send + Sync + 'static,623     pub fn blit_image<S, D>(
624         &mut self,
625         source: S,
626         source_top_left: [i32; 3],
627         source_bottom_right: [i32; 3],
628         source_base_array_layer: u32,
629         source_mip_level: u32,
630         destination: D,
631         destination_top_left: [i32; 3],
632         destination_bottom_right: [i32; 3],
633         destination_base_array_layer: u32,
634         destination_mip_level: u32,
635         layer_count: u32,
636         filter: Filter,
637     ) -> Result<&mut Self, BlitImageError>
638     where
639         S: ImageAccess + Send + Sync + 'static,
640         D: ImageAccess + Send + Sync + 'static,
641     {
642         unsafe {
643             if !self.queue_family().supports_graphics() {
644                 return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
645             }
646 
647             self.ensure_outside_render_pass()?;
648 
649             check_blit_image(
650                 self.device(),
651                 &source,
652                 source_top_left,
653                 source_bottom_right,
654                 source_base_array_layer,
655                 source_mip_level,
656                 &destination,
657                 destination_top_left,
658                 destination_bottom_right,
659                 destination_base_array_layer,
660                 destination_mip_level,
661                 layer_count,
662                 filter,
663             )?;
664 
665             let blit = UnsafeCommandBufferBuilderImageBlit {
666                 // TODO:
667                 aspects: if source.has_color() {
668                     ImageAspects {
669                         color: true,
670                         ..ImageAspects::none()
671                     }
672                 } else {
673                     unimplemented!()
674                 },
675                 source_mip_level,
676                 destination_mip_level,
677                 source_base_array_layer,
678                 destination_base_array_layer,
679                 layer_count,
680                 source_top_left,
681                 source_bottom_right,
682                 destination_top_left,
683                 destination_bottom_right,
684             };
685 
686             self.inner.blit_image(
687                 source,
688                 ImageLayout::TransferSrcOptimal,
689                 destination, // TODO: let choose layout
690                 ImageLayout::TransferDstOptimal,
691                 iter::once(blit),
692                 filter,
693             )?;
694             Ok(self)
695         }
696     }
697 
698     /// Adds a command that clears all the layers and mipmap levels of a color image with a
699     /// specific value.
700     ///
701     /// # Panic
702     ///
703     /// Panics if `color` is not a color value.
704     ///
clear_color_image<I>( &mut self, image: I, color: ClearValue, ) -> Result<&mut Self, ClearColorImageError> where I: ImageAccess + Send + Sync + 'static,705     pub fn clear_color_image<I>(
706         &mut self,
707         image: I,
708         color: ClearValue,
709     ) -> Result<&mut Self, ClearColorImageError>
710     where
711         I: ImageAccess + Send + Sync + 'static,
712     {
713         let layers = image.dimensions().array_layers();
714         let levels = image.mipmap_levels();
715 
716         self.clear_color_image_dimensions(image, 0, layers, 0, levels, color)
717     }
718 
719     /// Adds a command that clears a color image with a specific value.
720     ///
721     /// # Panic
722     ///
723     /// - Panics if `color` is not a color value.
724     ///
clear_color_image_dimensions<I>( &mut self, image: I, first_layer: u32, num_layers: u32, first_mipmap: u32, num_mipmaps: u32, color: ClearValue, ) -> Result<&mut Self, ClearColorImageError> where I: ImageAccess + Send + Sync + 'static,725     pub fn clear_color_image_dimensions<I>(
726         &mut self,
727         image: I,
728         first_layer: u32,
729         num_layers: u32,
730         first_mipmap: u32,
731         num_mipmaps: u32,
732         color: ClearValue,
733     ) -> Result<&mut Self, ClearColorImageError>
734     where
735         I: ImageAccess + Send + Sync + 'static,
736     {
737         unsafe {
738             if !self.queue_family().supports_graphics() && !self.queue_family().supports_compute() {
739                 return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
740             }
741 
742             self.ensure_outside_render_pass()?;
743             check_clear_color_image(
744                 self.device(),
745                 &image,
746                 first_layer,
747                 num_layers,
748                 first_mipmap,
749                 num_mipmaps,
750             )?;
751 
752             match color {
753                 ClearValue::Float(_) | ClearValue::Int(_) | ClearValue::Uint(_) => {}
754                 _ => panic!("The clear color is not a color value"),
755             };
756 
757             let region = UnsafeCommandBufferBuilderColorImageClear {
758                 base_mip_level: first_mipmap,
759                 level_count: num_mipmaps,
760                 base_array_layer: first_layer,
761                 layer_count: num_layers,
762             };
763 
764             // TODO: let choose layout
765             self.inner.clear_color_image(
766                 image,
767                 ImageLayout::TransferDstOptimal,
768                 color,
769                 iter::once(region),
770             )?;
771             Ok(self)
772         }
773     }
774 
775     /// Adds a command that copies from a buffer to another.
776     ///
777     /// This command will copy from the source to the destination. If their size is not equal, then
778     /// the amount of data copied is equal to the smallest of the two.
779     #[inline]
copy_buffer<S, D, T>( &mut self, source: S, destination: D, ) -> Result<&mut Self, CopyBufferError> where S: TypedBufferAccess<Content = T> + Send + Sync + 'static, D: TypedBufferAccess<Content = T> + Send + Sync + 'static, T: ?Sized,780     pub fn copy_buffer<S, D, T>(
781         &mut self,
782         source: S,
783         destination: D,
784     ) -> Result<&mut Self, CopyBufferError>
785     where
786         S: TypedBufferAccess<Content = T> + Send + Sync + 'static,
787         D: TypedBufferAccess<Content = T> + Send + Sync + 'static,
788         T: ?Sized,
789     {
790         unsafe {
791             self.ensure_outside_render_pass()?;
792             let infos = check_copy_buffer(self.device(), &source, &destination)?;
793             self.inner
794                 .copy_buffer(source, destination, iter::once((0, 0, infos.copy_size)))?;
795             Ok(self)
796         }
797     }
798 
799     /// Adds a command that copies a range from the source to the destination buffer.
800     /// Panics if out of bounds.
801     #[inline]
copy_buffer_dimensions<S, D, T>( &mut self, source: S, source_offset: DeviceSize, destination: D, destination_offset: DeviceSize, count: DeviceSize, ) -> Result<&mut Self, CopyBufferError> where S: TypedBufferAccess<Content = [T]> + Send + Sync + 'static, D: TypedBufferAccess<Content = [T]> + Send + Sync + 'static,802     pub fn copy_buffer_dimensions<S, D, T>(
803         &mut self,
804         source: S,
805         source_offset: DeviceSize,
806         destination: D,
807         destination_offset: DeviceSize,
808         count: DeviceSize,
809     ) -> Result<&mut Self, CopyBufferError>
810     where
811         S: TypedBufferAccess<Content = [T]> + Send + Sync + 'static,
812         D: TypedBufferAccess<Content = [T]> + Send + Sync + 'static,
813     {
814         self.ensure_outside_render_pass()?;
815 
816         let _infos = check_copy_buffer(self.device(), &source, &destination)?;
817         debug_assert!(source_offset + count <= source.len());
818         debug_assert!(destination_offset + count <= destination.len());
819 
820         let size = std::mem::size_of::<T>() as DeviceSize;
821         unsafe {
822             self.inner.copy_buffer(
823                 source,
824                 destination,
825                 iter::once((
826                     source_offset * size,
827                     destination_offset * size,
828                     count * size,
829                 )),
830             )?;
831         }
832         Ok(self)
833     }
834 
835     /// Adds a command that copies from a buffer to an image.
copy_buffer_to_image<S, D, Px>( &mut self, source: S, destination: D, ) -> Result<&mut Self, CopyBufferImageError> where S: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static, D: ImageAccess + Send + Sync + 'static, Px: Pixel,836     pub fn copy_buffer_to_image<S, D, Px>(
837         &mut self,
838         source: S,
839         destination: D,
840     ) -> Result<&mut Self, CopyBufferImageError>
841     where
842         S: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
843         D: ImageAccess + Send + Sync + 'static,
844         Px: Pixel,
845     {
846         self.ensure_outside_render_pass()?;
847 
848         let dims = destination.dimensions().width_height_depth();
849         self.copy_buffer_to_image_dimensions(source, destination, [0, 0, 0], dims, 0, 1, 0)
850     }
851 
852     /// Adds a command that copies from a buffer to an image.
copy_buffer_to_image_dimensions<S, D, Px>( &mut self, source: S, destination: D, offset: [u32; 3], size: [u32; 3], first_layer: u32, num_layers: u32, mipmap: u32, ) -> Result<&mut Self, CopyBufferImageError> where S: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static, D: ImageAccess + Send + Sync + 'static, Px: Pixel,853     pub fn copy_buffer_to_image_dimensions<S, D, Px>(
854         &mut self,
855         source: S,
856         destination: D,
857         offset: [u32; 3],
858         size: [u32; 3],
859         first_layer: u32,
860         num_layers: u32,
861         mipmap: u32,
862     ) -> Result<&mut Self, CopyBufferImageError>
863     where
864         S: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
865         D: ImageAccess + Send + Sync + 'static,
866         Px: Pixel,
867     {
868         unsafe {
869             self.ensure_outside_render_pass()?;
870 
871             check_copy_buffer_image(
872                 self.device(),
873                 &source,
874                 &destination,
875                 CheckCopyBufferImageTy::BufferToImage,
876                 offset,
877                 size,
878                 first_layer,
879                 num_layers,
880                 mipmap,
881             )?;
882 
883             let copy = UnsafeCommandBufferBuilderBufferImageCopy {
884                 buffer_offset: 0,
885                 buffer_row_length: 0,
886                 buffer_image_height: 0,
887                 image_aspect: if destination.has_color() {
888                     ImageAspect::Color
889                 } else {
890                     unimplemented!()
891                 },
892                 image_mip_level: mipmap,
893                 image_base_array_layer: first_layer,
894                 image_layer_count: num_layers,
895                 image_offset: [offset[0] as i32, offset[1] as i32, offset[2] as i32],
896                 image_extent: size,
897             };
898 
899             self.inner.copy_buffer_to_image(
900                 source,
901                 destination,
902                 ImageLayout::TransferDstOptimal, // TODO: let choose layout
903                 iter::once(copy),
904             )?;
905             Ok(self)
906         }
907     }
908 
909     /// Adds a command that copies from an image to a buffer.
910     // The data layout of the image on the gpu is opaque, as in, it is non of our business how the gpu stores the image.
911     // This does not matter since the act of copying the image into a buffer converts it to linear form.
copy_image_to_buffer<S, D, Px>( &mut self, source: S, destination: D, ) -> Result<&mut Self, CopyBufferImageError> where S: ImageAccess + Send + Sync + 'static, D: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static, Px: Pixel,912     pub fn copy_image_to_buffer<S, D, Px>(
913         &mut self,
914         source: S,
915         destination: D,
916     ) -> Result<&mut Self, CopyBufferImageError>
917     where
918         S: ImageAccess + Send + Sync + 'static,
919         D: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
920         Px: Pixel,
921     {
922         self.ensure_outside_render_pass()?;
923 
924         let dims = source.dimensions().width_height_depth();
925         self.copy_image_to_buffer_dimensions(source, destination, [0, 0, 0], dims, 0, 1, 0)
926     }
927 
928     /// Adds a command that copies from an image to a buffer.
copy_image_to_buffer_dimensions<S, D, Px>( &mut self, source: S, destination: D, offset: [u32; 3], size: [u32; 3], first_layer: u32, num_layers: u32, mipmap: u32, ) -> Result<&mut Self, CopyBufferImageError> where S: ImageAccess + Send + Sync + 'static, D: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static, Px: Pixel,929     pub fn copy_image_to_buffer_dimensions<S, D, Px>(
930         &mut self,
931         source: S,
932         destination: D,
933         offset: [u32; 3],
934         size: [u32; 3],
935         first_layer: u32,
936         num_layers: u32,
937         mipmap: u32,
938     ) -> Result<&mut Self, CopyBufferImageError>
939     where
940         S: ImageAccess + Send + Sync + 'static,
941         D: TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
942         Px: Pixel,
943     {
944         unsafe {
945             self.ensure_outside_render_pass()?;
946 
947             check_copy_buffer_image(
948                 self.device(),
949                 &destination,
950                 &source,
951                 CheckCopyBufferImageTy::ImageToBuffer,
952                 offset,
953                 size,
954                 first_layer,
955                 num_layers,
956                 mipmap,
957             )?;
958 
959             let copy = UnsafeCommandBufferBuilderBufferImageCopy {
960                 buffer_offset: 0,
961                 buffer_row_length: 0,
962                 buffer_image_height: 0,
963                 // TODO: Allow the user to choose aspect
964                 image_aspect: if source.has_color() {
965                     ImageAspect::Color
966                 } else if source.has_depth() {
967                     ImageAspect::Depth
968                 } else if source.has_stencil() {
969                     ImageAspect::Stencil
970                 } else {
971                     unimplemented!()
972                 },
973                 image_mip_level: mipmap,
974                 image_base_array_layer: first_layer,
975                 image_layer_count: num_layers,
976                 image_offset: [offset[0] as i32, offset[1] as i32, offset[2] as i32],
977                 image_extent: size,
978             };
979 
980             self.inner.copy_image_to_buffer(
981                 source,
982                 ImageLayout::TransferSrcOptimal,
983                 destination, // TODO: let choose layout
984                 iter::once(copy),
985             )?;
986             Ok(self)
987         }
988     }
989 
990     /// Open a command buffer debug label region.
991     ///
992     /// Note: you need to enable `VK_EXT_debug_utils` extension when creating an instance.
993     #[inline]
debug_marker_begin( &mut self, name: &'static CStr, color: [f32; 4], ) -> Result<&mut Self, DebugMarkerError>994     pub fn debug_marker_begin(
995         &mut self,
996         name: &'static CStr,
997         color: [f32; 4],
998     ) -> Result<&mut Self, DebugMarkerError> {
999         if !self.queue_family().supports_graphics() && self.queue_family().supports_compute() {
1000             return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
1001         }
1002 
1003         check_debug_marker_color(color)?;
1004 
1005         unsafe {
1006             self.inner.debug_marker_begin(name.into(), color);
1007         }
1008 
1009         Ok(self)
1010     }
1011 
1012     /// Close a command buffer label region.
1013     ///
1014     /// Note: you need to open a command buffer label region first with `debug_marker_begin`.
1015     /// Note: you need to enable `VK_EXT_debug_utils` extension when creating an instance.
1016     #[inline]
debug_marker_end(&mut self) -> Result<&mut Self, DebugMarkerError>1017     pub fn debug_marker_end(&mut self) -> Result<&mut Self, DebugMarkerError> {
1018         if !self.queue_family().supports_graphics() && self.queue_family().supports_compute() {
1019             return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
1020         }
1021 
1022         // TODO: validate that debug_marker_begin with same name was sent earlier
1023 
1024         unsafe {
1025             self.inner.debug_marker_end();
1026         }
1027 
1028         Ok(self)
1029     }
1030 
1031     /// Insert a label into a command buffer.
1032     ///
1033     /// Note: you need to enable `VK_EXT_debug_utils` extension when creating an instance.
1034     #[inline]
debug_marker_insert( &mut self, name: &'static CStr, color: [f32; 4], ) -> Result<&mut Self, DebugMarkerError>1035     pub fn debug_marker_insert(
1036         &mut self,
1037         name: &'static CStr,
1038         color: [f32; 4],
1039     ) -> Result<&mut Self, DebugMarkerError> {
1040         if !self.queue_family().supports_graphics() && self.queue_family().supports_compute() {
1041             return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
1042         }
1043 
1044         check_debug_marker_color(color)?;
1045 
1046         unsafe {
1047             self.inner.debug_marker_insert(name.into(), color);
1048         }
1049 
1050         Ok(self)
1051     }
1052 
1053     /// Perform a single compute operation using a compute pipeline.
1054     #[inline]
dispatch<Cp, S, Pc>( &mut self, group_counts: [u32; 3], pipeline: Cp, descriptor_sets: S, push_constants: Pc, ) -> Result<&mut Self, DispatchError> where Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, S: DescriptorSetsCollection,1055     pub fn dispatch<Cp, S, Pc>(
1056         &mut self,
1057         group_counts: [u32; 3],
1058         pipeline: Cp,
1059         descriptor_sets: S,
1060         push_constants: Pc,
1061     ) -> Result<&mut Self, DispatchError>
1062     where
1063         Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
1064         S: DescriptorSetsCollection,
1065     {
1066         let descriptor_sets = descriptor_sets.into_vec();
1067 
1068         unsafe {
1069             if !self.queue_family().supports_compute() {
1070                 return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
1071             }
1072 
1073             self.ensure_outside_render_pass()?;
1074             check_push_constants_validity(pipeline.layout(), &push_constants)?;
1075             check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
1076             check_dispatch(pipeline.device(), group_counts)?;
1077 
1078             if let StateCacherOutcome::NeedChange =
1079                 self.state_cacher.bind_compute_pipeline(&pipeline)
1080             {
1081                 self.inner.bind_pipeline_compute(pipeline.clone());
1082             }
1083 
1084             set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
1085             bind_descriptor_sets(
1086                 &mut self.inner,
1087                 &mut self.state_cacher,
1088                 PipelineBindPoint::Compute,
1089                 pipeline.layout(),
1090                 descriptor_sets,
1091             )?;
1092 
1093             self.inner.dispatch(group_counts);
1094             Ok(self)
1095         }
1096     }
1097 
1098     /// Perform multiple compute operations using a compute pipeline. One dispatch is performed for
1099     /// each `vulkano::command_buffer::DispatchIndirectCommand` struct in `indirect_buffer`.
1100     #[inline]
dispatch_indirect<Inb, Cp, S, Pc>( &mut self, indirect_buffer: Inb, pipeline: Cp, descriptor_sets: S, push_constants: Pc, ) -> Result<&mut Self, DispatchIndirectError> where Inb: BufferAccess + TypedBufferAccess<Content = [DispatchIndirectCommand]> + Send + Sync + 'static, Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, S: DescriptorSetsCollection,1101     pub fn dispatch_indirect<Inb, Cp, S, Pc>(
1102         &mut self,
1103         indirect_buffer: Inb,
1104         pipeline: Cp,
1105         descriptor_sets: S,
1106         push_constants: Pc,
1107     ) -> Result<&mut Self, DispatchIndirectError>
1108     where
1109         Inb: BufferAccess
1110             + TypedBufferAccess<Content = [DispatchIndirectCommand]>
1111             + Send
1112             + Sync
1113             + 'static,
1114         Cp: ComputePipelineAbstract + Send + Sync + 'static + Clone, // TODO: meh for Clone
1115         S: DescriptorSetsCollection,
1116     {
1117         let descriptor_sets = descriptor_sets.into_vec();
1118 
1119         unsafe {
1120             if !self.queue_family().supports_compute() {
1121                 return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
1122             }
1123 
1124             self.ensure_outside_render_pass()?;
1125             check_indirect_buffer(self.device(), &indirect_buffer)?;
1126             check_push_constants_validity(pipeline.layout(), &push_constants)?;
1127             check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
1128 
1129             if let StateCacherOutcome::NeedChange =
1130                 self.state_cacher.bind_compute_pipeline(&pipeline)
1131             {
1132                 self.inner.bind_pipeline_compute(pipeline.clone());
1133             }
1134 
1135             set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
1136             bind_descriptor_sets(
1137                 &mut self.inner,
1138                 &mut self.state_cacher,
1139                 PipelineBindPoint::Compute,
1140                 pipeline.layout(),
1141                 descriptor_sets,
1142             )?;
1143 
1144             self.inner.dispatch_indirect(indirect_buffer)?;
1145             Ok(self)
1146         }
1147     }
1148 
1149     /// Perform a single draw operation using a graphics pipeline.
1150     ///
1151     /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input.
1152     ///
1153     /// All data in `vertex_buffer` is used for the draw operation. To use only some data in the
1154     /// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
1155     #[inline]
draw<V, Gp, S, Pc>( &mut self, pipeline: Gp, dynamic: &DynamicState, vertex_buffers: V, descriptor_sets: S, push_constants: Pc, ) -> Result<&mut Self, DrawError> where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, S: DescriptorSetsCollection,1156     pub fn draw<V, Gp, S, Pc>(
1157         &mut self,
1158         pipeline: Gp,
1159         dynamic: &DynamicState,
1160         vertex_buffers: V,
1161         descriptor_sets: S,
1162         push_constants: Pc,
1163     ) -> Result<&mut Self, DrawError>
1164     where
1165         Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
1166         S: DescriptorSetsCollection,
1167     {
1168         let descriptor_sets = descriptor_sets.into_vec();
1169 
1170         unsafe {
1171             // TODO: must check that pipeline is compatible with render pass
1172 
1173             self.ensure_inside_render_pass_inline(&pipeline)?;
1174             check_dynamic_state_validity(&pipeline, dynamic)?;
1175             check_push_constants_validity(pipeline.layout(), &push_constants)?;
1176             check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
1177             let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
1178 
1179             if let StateCacherOutcome::NeedChange =
1180                 self.state_cacher.bind_graphics_pipeline(&pipeline)
1181             {
1182                 self.inner.bind_pipeline_graphics(pipeline.clone());
1183             }
1184 
1185             let dynamic = self.state_cacher.dynamic_state(dynamic);
1186 
1187             set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
1188             set_state(&mut self.inner, &dynamic);
1189             bind_descriptor_sets(
1190                 &mut self.inner,
1191                 &mut self.state_cacher,
1192                 PipelineBindPoint::Graphics,
1193                 pipeline.layout(),
1194                 descriptor_sets,
1195             )?;
1196             bind_vertex_buffers(
1197                 &mut self.inner,
1198                 &mut self.state_cacher,
1199                 vb_infos.vertex_buffers,
1200             )?;
1201 
1202             debug_assert!(self.queue_family().supports_graphics());
1203 
1204             self.inner.draw(
1205                 vb_infos.vertex_count as u32,
1206                 vb_infos.instance_count as u32,
1207                 0,
1208                 0,
1209             );
1210             Ok(self)
1211         }
1212     }
1213 
1214     /// Perform multiple draw operations using a graphics pipeline.
1215     ///
1216     /// One draw is performed for each [`DrawIndirectCommand`] struct in `indirect_buffer`.
1217     /// The maximum number of draw commands in the buffer is limited by the
1218     /// [`max_draw_indirect_count`](crate::device::Properties::max_draw_indirect_count) limit.
1219     /// This limit is 1 unless the
1220     /// [`multi_draw_indirect`](crate::device::Features::multi_draw_indirect) feature has been
1221     /// enabled.
1222     ///
1223     /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input. It is
1224     /// used for every draw operation.
1225     ///
1226     /// All data in `vertex_buffer` is used for every draw operation. To use only some data in the
1227     /// buffer, wrap it in a `vulkano::buffer::BufferSlice`.
1228     #[inline]
draw_indirect<V, Gp, S, Pc, Inb>( &mut self, pipeline: Gp, dynamic: &DynamicState, vertex_buffers: V, indirect_buffer: Inb, descriptor_sets: S, push_constants: Pc, ) -> Result<&mut Self, DrawIndirectError> where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, S: DescriptorSetsCollection, Inb: BufferAccess + TypedBufferAccess<Content = [DrawIndirectCommand]> + Send + Sync + 'static,1229     pub fn draw_indirect<V, Gp, S, Pc, Inb>(
1230         &mut self,
1231         pipeline: Gp,
1232         dynamic: &DynamicState,
1233         vertex_buffers: V,
1234         indirect_buffer: Inb,
1235         descriptor_sets: S,
1236         push_constants: Pc,
1237     ) -> Result<&mut Self, DrawIndirectError>
1238     where
1239         Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
1240         S: DescriptorSetsCollection,
1241         Inb: BufferAccess
1242             + TypedBufferAccess<Content = [DrawIndirectCommand]>
1243             + Send
1244             + Sync
1245             + 'static,
1246     {
1247         let descriptor_sets = descriptor_sets.into_vec();
1248 
1249         unsafe {
1250             // TODO: must check that pipeline is compatible with render pass
1251 
1252             self.ensure_inside_render_pass_inline(&pipeline)?;
1253             check_indirect_buffer(self.device(), &indirect_buffer)?;
1254             check_dynamic_state_validity(&pipeline, dynamic)?;
1255             check_push_constants_validity(pipeline.layout(), &push_constants)?;
1256             check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
1257             let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
1258 
1259             let requested = indirect_buffer.len() as u32;
1260             let limit = self
1261                 .device()
1262                 .physical_device()
1263                 .properties()
1264                 .max_draw_indirect_count;
1265 
1266             if requested > limit {
1267                 return Err(
1268                     CheckIndirectBufferError::MaxDrawIndirectCountLimitExceeded {
1269                         limit,
1270                         requested,
1271                     }
1272                     .into(),
1273                 );
1274             }
1275 
1276             if let StateCacherOutcome::NeedChange =
1277                 self.state_cacher.bind_graphics_pipeline(&pipeline)
1278             {
1279                 self.inner.bind_pipeline_graphics(pipeline.clone());
1280             }
1281 
1282             let dynamic = self.state_cacher.dynamic_state(dynamic);
1283 
1284             set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
1285             set_state(&mut self.inner, &dynamic);
1286             bind_descriptor_sets(
1287                 &mut self.inner,
1288                 &mut self.state_cacher,
1289                 PipelineBindPoint::Graphics,
1290                 pipeline.layout(),
1291                 descriptor_sets,
1292             )?;
1293             bind_vertex_buffers(
1294                 &mut self.inner,
1295                 &mut self.state_cacher,
1296                 vb_infos.vertex_buffers,
1297             )?;
1298 
1299             debug_assert!(self.queue_family().supports_graphics());
1300 
1301             self.inner.draw_indirect(
1302                 indirect_buffer,
1303                 requested,
1304                 mem::size_of::<DrawIndirectCommand>() as u32,
1305             )?;
1306             Ok(self)
1307         }
1308     }
1309 
1310     /// Perform a single draw operation using a graphics pipeline, using an index buffer.
1311     ///
1312     /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input.
1313     /// `index_buffer` is a buffer containing indices into the vertex buffer that should be
1314     /// processed in order.
1315     ///
1316     /// All data in `vertex_buffer` and `index_buffer` is used for the draw operation. To use
1317     /// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
1318     #[inline]
draw_indexed<V, Gp, S, Pc, Ib, I>( &mut self, pipeline: Gp, dynamic: &DynamicState, vertex_buffers: V, index_buffer: Ib, descriptor_sets: S, push_constants: Pc, ) -> Result<&mut Self, DrawIndexedError> where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, S: DescriptorSetsCollection, Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static, I: Index + 'static,1319     pub fn draw_indexed<V, Gp, S, Pc, Ib, I>(
1320         &mut self,
1321         pipeline: Gp,
1322         dynamic: &DynamicState,
1323         vertex_buffers: V,
1324         index_buffer: Ib,
1325         descriptor_sets: S,
1326         push_constants: Pc,
1327     ) -> Result<&mut Self, DrawIndexedError>
1328     where
1329         Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
1330         S: DescriptorSetsCollection,
1331         Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
1332         I: Index + 'static,
1333     {
1334         let descriptor_sets = descriptor_sets.into_vec();
1335 
1336         unsafe {
1337             // TODO: must check that pipeline is compatible with render pass
1338 
1339             self.ensure_inside_render_pass_inline(&pipeline)?;
1340             let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
1341             check_dynamic_state_validity(&pipeline, dynamic)?;
1342             check_push_constants_validity(pipeline.layout(), &push_constants)?;
1343             check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
1344             let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
1345 
1346             if let StateCacherOutcome::NeedChange =
1347                 self.state_cacher.bind_graphics_pipeline(&pipeline)
1348             {
1349                 self.inner.bind_pipeline_graphics(pipeline.clone());
1350             }
1351 
1352             if let StateCacherOutcome::NeedChange =
1353                 self.state_cacher.bind_index_buffer(&index_buffer, I::ty())
1354             {
1355                 self.inner.bind_index_buffer(index_buffer, I::ty())?;
1356             }
1357 
1358             let dynamic = self.state_cacher.dynamic_state(dynamic);
1359 
1360             set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
1361             set_state(&mut self.inner, &dynamic);
1362             bind_descriptor_sets(
1363                 &mut self.inner,
1364                 &mut self.state_cacher,
1365                 PipelineBindPoint::Graphics,
1366                 pipeline.layout(),
1367                 descriptor_sets,
1368             )?;
1369             bind_vertex_buffers(
1370                 &mut self.inner,
1371                 &mut self.state_cacher,
1372                 vb_infos.vertex_buffers,
1373             )?;
1374             // TODO: how to handle an index out of range of the vertex buffers?
1375 
1376             debug_assert!(self.queue_family().supports_graphics());
1377 
1378             self.inner.draw_indexed(
1379                 ib_infos.num_indices as u32,
1380                 vb_infos.instance_count as u32,
1381                 0,
1382                 0,
1383                 0,
1384             );
1385             Ok(self)
1386         }
1387     }
1388 
1389     /// Perform multiple draw operations using a graphics pipeline, using an index buffer.
1390     ///
1391     /// One draw is performed for each [`DrawIndirectCommand`] struct in `indirect_buffer`.
1392     /// The maximum number of draw commands in the buffer is limited by the
1393     /// [`max_draw_indirect_count`](crate::device::Properties::max_draw_indirect_count) limit.
1394     /// This limit is 1 unless the
1395     /// [`multi_draw_indirect`](crate::device::Features::multi_draw_indirect) feature has been
1396     /// enabled.
1397     ///
1398     /// `vertex_buffer` is a set of vertex and/or instance buffers used to provide input.
1399     /// `index_buffer` is a buffer containing indices into the vertex buffer that should be
1400     /// processed in order.
1401     ///
1402     /// All data in `vertex_buffer` and `index_buffer` is used for every draw operation. To use
1403     /// only some data in the buffer, wrap it in a `vulkano::buffer::BufferSlice`.
1404     #[inline]
draw_indexed_indirect<V, Gp, S, Pc, Ib, Inb, I>( &mut self, pipeline: Gp, dynamic: &DynamicState, vertex_buffers: V, index_buffer: Ib, indirect_buffer: Inb, descriptor_sets: S, push_constants: Pc, ) -> Result<&mut Self, DrawIndexedIndirectError> where Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, S: DescriptorSetsCollection, Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static, Inb: BufferAccess + TypedBufferAccess<Content = [DrawIndexedIndirectCommand]> + Send + Sync + 'static, I: Index + 'static,1405     pub fn draw_indexed_indirect<V, Gp, S, Pc, Ib, Inb, I>(
1406         &mut self,
1407         pipeline: Gp,
1408         dynamic: &DynamicState,
1409         vertex_buffers: V,
1410         index_buffer: Ib,
1411         indirect_buffer: Inb,
1412         descriptor_sets: S,
1413         push_constants: Pc,
1414     ) -> Result<&mut Self, DrawIndexedIndirectError>
1415     where
1416         Gp: GraphicsPipelineAbstract + VertexSource<V> + Send + Sync + 'static + Clone, // TODO: meh for Clone
1417         S: DescriptorSetsCollection,
1418         Ib: BufferAccess + TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
1419         Inb: BufferAccess
1420             + TypedBufferAccess<Content = [DrawIndexedIndirectCommand]>
1421             + Send
1422             + Sync
1423             + 'static,
1424         I: Index + 'static,
1425     {
1426         let descriptor_sets = descriptor_sets.into_vec();
1427 
1428         unsafe {
1429             // TODO: must check that pipeline is compatible with render pass
1430 
1431             self.ensure_inside_render_pass_inline(&pipeline)?;
1432             let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
1433             check_indirect_buffer(self.device(), &indirect_buffer)?;
1434             check_dynamic_state_validity(&pipeline, dynamic)?;
1435             check_push_constants_validity(pipeline.layout(), &push_constants)?;
1436             check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
1437             let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
1438 
1439             let requested = indirect_buffer.len() as u32;
1440             let limit = self
1441                 .device()
1442                 .physical_device()
1443                 .properties()
1444                 .max_draw_indirect_count;
1445 
1446             if requested > limit {
1447                 return Err(
1448                     CheckIndirectBufferError::MaxDrawIndirectCountLimitExceeded {
1449                         limit,
1450                         requested,
1451                     }
1452                     .into(),
1453                 );
1454             }
1455 
1456             if let StateCacherOutcome::NeedChange =
1457                 self.state_cacher.bind_graphics_pipeline(&pipeline)
1458             {
1459                 self.inner.bind_pipeline_graphics(pipeline.clone());
1460             }
1461 
1462             if let StateCacherOutcome::NeedChange =
1463                 self.state_cacher.bind_index_buffer(&index_buffer, I::ty())
1464             {
1465                 self.inner.bind_index_buffer(index_buffer, I::ty())?;
1466             }
1467 
1468             let dynamic = self.state_cacher.dynamic_state(dynamic);
1469 
1470             set_push_constants(&mut self.inner, pipeline.layout(), push_constants);
1471             set_state(&mut self.inner, &dynamic);
1472             bind_descriptor_sets(
1473                 &mut self.inner,
1474                 &mut self.state_cacher,
1475                 PipelineBindPoint::Graphics,
1476                 pipeline.layout(),
1477                 descriptor_sets,
1478             )?;
1479             bind_vertex_buffers(
1480                 &mut self.inner,
1481                 &mut self.state_cacher,
1482                 vb_infos.vertex_buffers,
1483             )?;
1484 
1485             debug_assert!(self.queue_family().supports_graphics());
1486 
1487             self.inner.draw_indexed_indirect(
1488                 indirect_buffer,
1489                 requested,
1490                 mem::size_of::<DrawIndexedIndirectCommand>() as u32,
1491             )?;
1492             Ok(self)
1493         }
1494     }
1495 
1496     /// Adds a command that writes the content of a buffer.
1497     ///
1498     /// This function is similar to the `memset` function in C. The `data` parameter is a number
1499     /// that will be repeatedly written through the entire buffer.
1500     ///
1501     /// > **Note**: This function is technically safe because buffers can only contain integers or
1502     /// > floating point numbers, which are always valid whatever their memory representation is.
1503     /// > But unless your buffer actually contains only 32-bits integers, you are encouraged to use
1504     /// > this function only for zeroing the content of a buffer by passing `0` for the data.
1505     // TODO: not safe because of signalling NaNs
1506     #[inline]
fill_buffer<B>(&mut self, buffer: B, data: u32) -> Result<&mut Self, FillBufferError> where B: BufferAccess + Send + Sync + 'static,1507     pub fn fill_buffer<B>(&mut self, buffer: B, data: u32) -> Result<&mut Self, FillBufferError>
1508     where
1509         B: BufferAccess + Send + Sync + 'static,
1510     {
1511         unsafe {
1512             self.ensure_outside_render_pass()?;
1513             check_fill_buffer(self.device(), &buffer)?;
1514             self.inner.fill_buffer(buffer, data);
1515             Ok(self)
1516         }
1517     }
1518 
1519     /// Adds a command that writes data to a buffer.
1520     ///
1521     /// If `data` is larger than the buffer, only the part of `data` that fits is written. If the
1522     /// buffer is larger than `data`, only the start of the buffer is written.
1523     #[inline]
update_buffer<B, D, Dd>( &mut self, buffer: B, data: Dd, ) -> Result<&mut Self, UpdateBufferError> where B: TypedBufferAccess<Content = D> + Send + Sync + 'static, D: ?Sized, Dd: SafeDeref<Target = D> + Send + Sync + 'static,1524     pub fn update_buffer<B, D, Dd>(
1525         &mut self,
1526         buffer: B,
1527         data: Dd,
1528     ) -> Result<&mut Self, UpdateBufferError>
1529     where
1530         B: TypedBufferAccess<Content = D> + Send + Sync + 'static,
1531         D: ?Sized,
1532         Dd: SafeDeref<Target = D> + Send + Sync + 'static,
1533     {
1534         unsafe {
1535             self.ensure_outside_render_pass()?;
1536             check_update_buffer(self.device(), &buffer, data.deref())?;
1537 
1538             let size_of_data = mem::size_of_val(data.deref()) as DeviceSize;
1539             if buffer.size() >= size_of_data {
1540                 self.inner.update_buffer(buffer, data);
1541             } else {
1542                 unimplemented!() // TODO:
1543                                  //self.inner.update_buffer(buffer.slice(0 .. size_of_data), data);
1544             }
1545 
1546             Ok(self)
1547         }
1548     }
1549 
1550     /// Adds a command that begins a query.
1551     ///
1552     /// The query will be active until [`end_query`](Self::end_query) is called for the same query.
1553     ///
1554     /// # Safety
1555     /// The query must be unavailable, ensured by calling [`reset_query_pool`](Self::reset_query_pool).
begin_query( &mut self, query_pool: Arc<QueryPool>, query: u32, flags: QueryControlFlags, ) -> Result<&mut Self, BeginQueryError>1556     pub unsafe fn begin_query(
1557         &mut self,
1558         query_pool: Arc<QueryPool>,
1559         query: u32,
1560         flags: QueryControlFlags,
1561     ) -> Result<&mut Self, BeginQueryError> {
1562         check_begin_query(self.device(), &query_pool, query, flags)?;
1563 
1564         match query_pool.ty() {
1565             QueryType::Occlusion => {
1566                 if !self.queue_family().supports_graphics() {
1567                     return Err(
1568                         AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into(),
1569                     );
1570                 }
1571             }
1572             QueryType::PipelineStatistics(flags) => {
1573                 if flags.is_compute() && !self.queue_family().supports_compute()
1574                     || flags.is_graphics() && !self.queue_family().supports_graphics()
1575                 {
1576                     return Err(
1577                         AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into(),
1578                     );
1579                 }
1580             }
1581             QueryType::Timestamp => unreachable!(),
1582         }
1583 
1584         let ty = query_pool.ty();
1585         let raw_ty = ty.into();
1586         let raw_query_pool = query_pool.internal_object();
1587         if self.query_state.contains_key(&raw_ty) {
1588             return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
1589         }
1590 
1591         // TODO: validity checks
1592         self.inner.begin_query(query_pool, query, flags);
1593         self.query_state.insert(
1594             raw_ty,
1595             QueryState {
1596                 query_pool: raw_query_pool,
1597                 query,
1598                 ty,
1599                 flags,
1600                 in_subpass: self.render_pass_state.is_some(),
1601             },
1602         );
1603 
1604         Ok(self)
1605     }
1606 
1607     /// Adds a command that ends an active query.
end_query( &mut self, query_pool: Arc<QueryPool>, query: u32, ) -> Result<&mut Self, EndQueryError>1608     pub fn end_query(
1609         &mut self,
1610         query_pool: Arc<QueryPool>,
1611         query: u32,
1612     ) -> Result<&mut Self, EndQueryError> {
1613         unsafe {
1614             check_end_query(self.device(), &query_pool, query)?;
1615 
1616             let raw_ty = query_pool.ty().into();
1617             let raw_query_pool = query_pool.internal_object();
1618             if !self.query_state.get(&raw_ty).map_or(false, |state| {
1619                 state.query_pool == raw_query_pool && state.query == query
1620             }) {
1621                 return Err(AutoCommandBufferBuilderContextError::QueryNotActive.into());
1622             }
1623 
1624             self.inner.end_query(query_pool, query);
1625             self.query_state.remove(&raw_ty);
1626         }
1627 
1628         Ok(self)
1629     }
1630 
1631     /// Adds a command that writes a timestamp to a timestamp query.
1632     ///
1633     /// # Safety
1634     /// The query must be unavailable, ensured by calling [`reset_query_pool`](Self::reset_query_pool).
write_timestamp( &mut self, query_pool: Arc<QueryPool>, query: u32, stage: PipelineStage, ) -> Result<&mut Self, WriteTimestampError>1635     pub unsafe fn write_timestamp(
1636         &mut self,
1637         query_pool: Arc<QueryPool>,
1638         query: u32,
1639         stage: PipelineStage,
1640     ) -> Result<&mut Self, WriteTimestampError> {
1641         check_write_timestamp(
1642             self.device(),
1643             self.queue_family(),
1644             &query_pool,
1645             query,
1646             stage,
1647         )?;
1648 
1649         if !(self.queue_family().supports_graphics()
1650             || self.queue_family().supports_compute()
1651             || self.queue_family().explicitly_supports_transfers())
1652         {
1653             return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
1654         }
1655 
1656         // TODO: validity checks
1657         self.inner.write_timestamp(query_pool, query, stage);
1658 
1659         Ok(self)
1660     }
1661 
1662     /// Adds a command that copies the results of a range of queries to a buffer on the GPU.
1663     ///
1664     /// [`query_pool.ty().result_size()`](crate::query::QueryType::result_size) elements
1665     /// will be written for each query in the range, plus 1 extra element per query if
1666     /// [`QueryResultFlags::with_availability`] is enabled.
1667     /// The provided buffer must be large enough to hold the data.
1668     ///
1669     /// See also [`get_results`](crate::query::QueriesRange::get_results).
copy_query_pool_results<D, T>( &mut self, query_pool: Arc<QueryPool>, queries: Range<u32>, destination: D, flags: QueryResultFlags, ) -> Result<&mut Self, CopyQueryPoolResultsError> where D: BufferAccess + TypedBufferAccess<Content = [T]> + Send + Sync + 'static, T: QueryResultElement,1670     pub fn copy_query_pool_results<D, T>(
1671         &mut self,
1672         query_pool: Arc<QueryPool>,
1673         queries: Range<u32>,
1674         destination: D,
1675         flags: QueryResultFlags,
1676     ) -> Result<&mut Self, CopyQueryPoolResultsError>
1677     where
1678         D: BufferAccess + TypedBufferAccess<Content = [T]> + Send + Sync + 'static,
1679         T: QueryResultElement,
1680     {
1681         unsafe {
1682             self.ensure_outside_render_pass()?;
1683             let stride = check_copy_query_pool_results(
1684                 self.device(),
1685                 &query_pool,
1686                 queries.clone(),
1687                 &destination,
1688                 flags,
1689             )?;
1690             self.inner
1691                 .copy_query_pool_results(query_pool, queries, destination, stride, flags)?;
1692         }
1693 
1694         Ok(self)
1695     }
1696 
1697     /// Adds a command to reset a range of queries on a query pool.
1698     ///
1699     /// The affected queries will be marked as "unavailable" after this command runs, and will no
1700     /// longer return any results. They will be ready to have new results recorded for them.
1701     ///
1702     /// # Safety
1703     /// The queries in the specified range must not be active in another command buffer.
reset_query_pool( &mut self, query_pool: Arc<QueryPool>, queries: Range<u32>, ) -> Result<&mut Self, ResetQueryPoolError>1704     pub unsafe fn reset_query_pool(
1705         &mut self,
1706         query_pool: Arc<QueryPool>,
1707         queries: Range<u32>,
1708     ) -> Result<&mut Self, ResetQueryPoolError> {
1709         self.ensure_outside_render_pass()?;
1710         check_reset_query_pool(self.device(), &query_pool, queries.clone())?;
1711 
1712         let raw_query_pool = query_pool.internal_object();
1713         if self
1714             .query_state
1715             .values()
1716             .any(|state| state.query_pool == raw_query_pool && queries.contains(&state.query))
1717         {
1718             return Err(AutoCommandBufferBuilderContextError::QueryIsActive.into());
1719         }
1720 
1721         // TODO: validity checks
1722         // Do other command buffers actually matter here? Not sure on the Vulkan spec.
1723         self.inner.reset_query_pool(query_pool, queries);
1724 
1725         Ok(self)
1726     }
1727 }
1728 
1729 /// Commands that can only be executed on primary command buffers
1730 impl<P> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer<P::Alloc>, P>
1731 where
1732     P: CommandPoolBuilderAlloc,
1733 {
1734     /// Adds a command that enters a render pass.
1735     ///
1736     /// If `contents` is `SubpassContents::SecondaryCommandBuffers`, then you will only be able to
1737     /// add secondary command buffers while you're inside the first subpass of the render pass.
1738     /// If it is `SubpassContents::Inline`, you will only be able to add inline draw commands and
1739     /// not secondary command buffers.
1740     ///
1741     /// C must contain exactly one clear value for each attachment in the framebuffer.
1742     ///
1743     /// You must call this before you can add draw commands.
1744     #[inline]
begin_render_pass<F, I>( &mut self, framebuffer: F, contents: SubpassContents, clear_values: I, ) -> Result<&mut Self, BeginRenderPassError> where F: FramebufferAbstract + Clone + Send + Sync + 'static, I: IntoIterator<Item = ClearValue>,1745     pub fn begin_render_pass<F, I>(
1746         &mut self,
1747         framebuffer: F,
1748         contents: SubpassContents,
1749         clear_values: I,
1750     ) -> Result<&mut Self, BeginRenderPassError>
1751     where
1752         F: FramebufferAbstract + Clone + Send + Sync + 'static,
1753         I: IntoIterator<Item = ClearValue>,
1754     {
1755         unsafe {
1756             if !self.queue_family().supports_graphics() {
1757                 return Err(AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily.into());
1758             }
1759 
1760             self.ensure_outside_render_pass()?;
1761 
1762             let clear_values = framebuffer
1763                 .render_pass()
1764                 .desc()
1765                 .convert_clear_values(clear_values);
1766             let clear_values = clear_values.collect::<Vec<_>>().into_iter(); // TODO: necessary for Send + Sync ; needs an API rework of convert_clear_values
1767             let mut clear_values_copy = clear_values.clone().enumerate(); // TODO: Proper errors for clear value errors instead of panics
1768 
1769             for (atch_i, atch_desc) in framebuffer
1770                 .render_pass()
1771                 .desc()
1772                 .attachments()
1773                 .into_iter()
1774                 .enumerate()
1775             {
1776                 match clear_values_copy.next() {
1777                     Some((clear_i, clear_value)) => {
1778                         if atch_desc.load == LoadOp::Clear {
1779                             match clear_value {
1780                                 ClearValue::None => panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: None",
1781                                     clear_i, atch_i, atch_desc.format.ty()),
1782                                 ClearValue::Float(_) => if atch_desc.format.ty() != FormatTy::Float {
1783                                    panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Float",
1784                                        clear_i, atch_i, atch_desc.format.ty());
1785                                 }
1786                                 ClearValue::Int(_) => if atch_desc.format.ty() != FormatTy::Sint {
1787                                     panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Int",
1788                                        clear_i, atch_i, atch_desc.format.ty());
1789                                 }
1790                                 ClearValue::Uint(_) => if atch_desc.format.ty() != FormatTy::Uint {
1791                                     panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Uint",
1792                                        clear_i, atch_i, atch_desc.format.ty());
1793                                 }
1794                                 ClearValue::Depth(_) => if atch_desc.format.ty() != FormatTy::Depth {
1795                                     panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Depth",
1796                                        clear_i, atch_i, atch_desc.format.ty());
1797                                 }
1798                                 ClearValue::Stencil(_) => if atch_desc.format.ty() != FormatTy::Stencil {
1799                                     panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Stencil",
1800                                        clear_i, atch_i, atch_desc.format.ty());
1801                                 }
1802                                 ClearValue::DepthStencil(_) => if atch_desc.format.ty() != FormatTy::DepthStencil {
1803                                     panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: DepthStencil",
1804                                        clear_i, atch_i, atch_desc.format.ty());
1805                                 }
1806                             }
1807                         } else {
1808                             if clear_value != ClearValue::None {
1809                                 panic!("Bad ClearValue! index: {}, attachment index: {}, expected: None, got: {:?}",
1810                                    clear_i, atch_i, clear_value);
1811                             }
1812                         }
1813                     }
1814                     None => panic!("Not enough clear values"),
1815                 }
1816             }
1817 
1818             if clear_values_copy.count() != 0 {
1819                 panic!("Too many clear values")
1820             }
1821 
1822             if let Some(multiview_desc) = framebuffer.render_pass().desc().multiview() {
1823                 // When multiview is enabled, at the beginning of each subpass all non-render pass state is undefined
1824                 self.state_cacher.invalidate();
1825 
1826                 // ensure that the framebuffer is compatible with the render pass multiview configuration
1827                 if multiview_desc
1828                     .view_masks
1829                     .iter()
1830                     .chain(multiview_desc.correlation_masks.iter())
1831                     .map(|&mask| 32 - mask.leading_zeros()) // calculates the highest used layer index of the mask
1832                     .any(|highest_used_layer| highest_used_layer > framebuffer.layers())
1833                 {
1834                     panic!("A multiview mask references more layers than exist in the framebuffer");
1835                 }
1836             }
1837 
1838             let framebuffer_object = FramebufferAbstract::inner(&framebuffer).internal_object();
1839             self.inner
1840                 .begin_render_pass(framebuffer.clone(), contents, clear_values)?;
1841             self.render_pass_state = Some(RenderPassState {
1842                 subpass: (framebuffer.render_pass().clone(), 0),
1843                 contents,
1844                 framebuffer: framebuffer_object,
1845             });
1846             Ok(self)
1847         }
1848     }
1849 
1850     /// Adds a command that ends the current render pass.
1851     ///
1852     /// This must be called after you went through all the subpasses and before you can build
1853     /// the command buffer or add further commands.
1854     #[inline]
end_render_pass(&mut self) -> Result<&mut Self, AutoCommandBufferBuilderContextError>1855     pub fn end_render_pass(&mut self) -> Result<&mut Self, AutoCommandBufferBuilderContextError> {
1856         unsafe {
1857             if let Some(render_pass_state) = self.render_pass_state.as_ref() {
1858                 let (ref rp, index) = render_pass_state.subpass;
1859 
1860                 if rp.desc().subpasses().len() as u32 != index + 1 {
1861                     return Err(AutoCommandBufferBuilderContextError::NumSubpassesMismatch {
1862                         actual: rp.desc().subpasses().len() as u32,
1863                         current: index,
1864                     });
1865                 }
1866             } else {
1867                 return Err(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass);
1868             }
1869 
1870             if self.query_state.values().any(|state| state.in_subpass) {
1871                 return Err(AutoCommandBufferBuilderContextError::QueryIsActive);
1872             }
1873 
1874             debug_assert!(self.queue_family().supports_graphics());
1875 
1876             self.inner.end_render_pass();
1877             self.render_pass_state = None;
1878             Ok(self)
1879         }
1880     }
1881 
1882     /// Adds a command that executes a secondary command buffer.
1883     ///
1884     /// If the `flags` that `command_buffer` was created with are more restrictive than those of
1885     /// `self`, then `self` will be restricted to match. E.g. executing a secondary command buffer
1886     /// 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: SecondaryCommandBuffer + Send + Sync + 'static,1887     pub fn execute_commands<C>(
1888         &mut self,
1889         command_buffer: C,
1890     ) -> Result<&mut Self, ExecuteCommandsError>
1891     where
1892         C: SecondaryCommandBuffer + Send + Sync + 'static,
1893     {
1894         self.check_command_buffer(&command_buffer)?;
1895         let secondary_usage = command_buffer.inner().usage();
1896 
1897         unsafe {
1898             let mut builder = self.inner.execute_commands();
1899             builder.add(command_buffer);
1900             builder.submit()?;
1901         }
1902 
1903         // Secondary command buffer could leave the primary in any state.
1904         self.state_cacher.invalidate();
1905 
1906         // If the secondary is non-concurrent or one-time use, that restricts the primary as well.
1907         self.usage = std::cmp::min(self.usage, secondary_usage);
1908 
1909         Ok(self)
1910     }
1911 
1912     /// Adds a command that multiple secondary command buffers in a vector.
1913     ///
1914     /// This requires that the secondary command buffers do not have resource conflicts; an error
1915     /// will be returned if there are any. Use `execute_commands` if you want to ensure that
1916     /// resource conflicts are automatically resolved.
1917     // 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: SecondaryCommandBuffer + Send + Sync + 'static,1918     pub fn execute_commands_from_vec<C>(
1919         &mut self,
1920         command_buffers: Vec<C>,
1921     ) -> Result<&mut Self, ExecuteCommandsError>
1922     where
1923         C: SecondaryCommandBuffer + Send + Sync + 'static,
1924     {
1925         for command_buffer in &command_buffers {
1926             self.check_command_buffer(command_buffer)?;
1927         }
1928 
1929         let mut secondary_usage = CommandBufferUsage::SimultaneousUse; // Most permissive usage
1930         unsafe {
1931             let mut builder = self.inner.execute_commands();
1932             for command_buffer in command_buffers {
1933                 secondary_usage = std::cmp::min(secondary_usage, command_buffer.inner().usage());
1934                 builder.add(command_buffer);
1935             }
1936             builder.submit()?;
1937         }
1938 
1939         // Secondary command buffer could leave the primary in any state.
1940         self.state_cacher.invalidate();
1941 
1942         // If the secondary is non-concurrent or one-time use, that restricts the primary as well.
1943         self.usage = std::cmp::min(self.usage, secondary_usage);
1944 
1945         Ok(self)
1946     }
1947 
1948     // Helper function for execute_commands
check_command_buffer<C>( &self, command_buffer: &C, ) -> Result<(), AutoCommandBufferBuilderContextError> where C: SecondaryCommandBuffer + Send + Sync + 'static,1949     fn check_command_buffer<C>(
1950         &self,
1951         command_buffer: &C,
1952     ) -> Result<(), AutoCommandBufferBuilderContextError>
1953     where
1954         C: SecondaryCommandBuffer + Send + Sync + 'static,
1955     {
1956         if let Some(render_pass) = command_buffer.inheritance().render_pass {
1957             self.ensure_inside_render_pass_secondary(&render_pass)?;
1958         } else {
1959             self.ensure_outside_render_pass()?;
1960         }
1961 
1962         for state in self.query_state.values() {
1963             match state.ty {
1964                 QueryType::Occlusion => match command_buffer.inheritance().occlusion_query {
1965                     Some(inherited_flags) => {
1966                         let inherited_flags = ash::vk::QueryControlFlags::from(inherited_flags);
1967                         let state_flags = ash::vk::QueryControlFlags::from(state.flags);
1968 
1969                         if inherited_flags & state_flags != state_flags {
1970                             return Err(AutoCommandBufferBuilderContextError::QueryNotInherited);
1971                         }
1972                     }
1973                     None => return Err(AutoCommandBufferBuilderContextError::QueryNotInherited),
1974                 },
1975                 QueryType::PipelineStatistics(state_flags) => {
1976                     let inherited_flags = command_buffer.inheritance().query_statistics_flags;
1977                     let inherited_flags =
1978                         ash::vk::QueryPipelineStatisticFlags::from(inherited_flags);
1979                     let state_flags = ash::vk::QueryPipelineStatisticFlags::from(state_flags);
1980 
1981                     if inherited_flags & state_flags != state_flags {
1982                         return Err(AutoCommandBufferBuilderContextError::QueryNotInherited);
1983                     }
1984                 }
1985                 _ => (),
1986             }
1987         }
1988 
1989         Ok(())
1990     }
1991 
1992     #[inline]
ensure_inside_render_pass_secondary( &self, render_pass: &CommandBufferInheritanceRenderPass<&dyn FramebufferAbstract>, ) -> Result<(), AutoCommandBufferBuilderContextError>1993     fn ensure_inside_render_pass_secondary(
1994         &self,
1995         render_pass: &CommandBufferInheritanceRenderPass<&dyn FramebufferAbstract>,
1996     ) -> Result<(), AutoCommandBufferBuilderContextError> {
1997         let render_pass_state = self
1998             .render_pass_state
1999             .as_ref()
2000             .ok_or(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass)?;
2001 
2002         if render_pass_state.contents != SubpassContents::SecondaryCommandBuffers {
2003             return Err(AutoCommandBufferBuilderContextError::WrongSubpassType);
2004         }
2005 
2006         // Subpasses must be the same.
2007         if render_pass.subpass.index() != render_pass_state.subpass.1 {
2008             return Err(AutoCommandBufferBuilderContextError::WrongSubpassIndex);
2009         }
2010 
2011         // Render passes must be compatible.
2012         if !render_pass
2013             .subpass
2014             .render_pass()
2015             .desc()
2016             .is_compatible_with_desc(render_pass_state.subpass.0.desc())
2017         {
2018             return Err(AutoCommandBufferBuilderContextError::IncompatibleRenderPass);
2019         }
2020 
2021         // Framebuffer, if present on the secondary command buffer, must be the
2022         // same as the one in the current render pass.
2023         if let Some(framebuffer) = render_pass.framebuffer {
2024             if FramebufferAbstract::inner(framebuffer).internal_object()
2025                 != render_pass_state.framebuffer
2026             {
2027                 return Err(AutoCommandBufferBuilderContextError::IncompatibleFramebuffer);
2028             }
2029         }
2030 
2031         Ok(())
2032     }
2033 
2034     /// Adds a command that jumps to the next subpass of the current render pass.
2035     #[inline]
next_subpass( &mut self, contents: SubpassContents, ) -> Result<&mut Self, AutoCommandBufferBuilderContextError>2036     pub fn next_subpass(
2037         &mut self,
2038         contents: SubpassContents,
2039     ) -> Result<&mut Self, AutoCommandBufferBuilderContextError> {
2040         unsafe {
2041             if let Some(render_pass_state) = self.render_pass_state.as_mut() {
2042                 let (ref rp, ref mut index) = render_pass_state.subpass;
2043 
2044                 if *index + 1 >= rp.desc().subpasses().len() as u32 {
2045                     return Err(AutoCommandBufferBuilderContextError::NumSubpassesMismatch {
2046                         actual: rp.desc().subpasses().len() as u32,
2047                         current: *index,
2048                     });
2049                 } else {
2050                     *index += 1;
2051                     render_pass_state.contents = contents;
2052                 }
2053 
2054                 if let Some(multiview) = rp.desc().multiview() {
2055                     // When multiview is enabled, at the beginning of each subpass all non-render pass state is undefined
2056                     self.state_cacher.invalidate();
2057                 }
2058             } else {
2059                 return Err(AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass);
2060             }
2061 
2062             if self.query_state.values().any(|state| state.in_subpass) {
2063                 return Err(AutoCommandBufferBuilderContextError::QueryIsActive);
2064             }
2065 
2066             debug_assert!(self.queue_family().supports_graphics());
2067 
2068             self.inner.next_subpass(contents);
2069             Ok(self)
2070         }
2071     }
2072 }
2073 
2074 impl<P> AutoCommandBufferBuilder<SecondaryAutoCommandBuffer<P::Alloc>, P> where
2075     P: CommandPoolBuilderAlloc
2076 {
2077 }
2078 
2079 unsafe impl<L, P> DeviceOwned for AutoCommandBufferBuilder<L, P> {
2080     #[inline]
device(&self) -> &Arc<Device>2081     fn device(&self) -> &Arc<Device> {
2082         self.inner.device()
2083     }
2084 }
2085 
2086 // Shortcut function to set the push constants.
set_push_constants<Pc>( destination: &mut SyncCommandBufferBuilder, pipeline_layout: &Arc<PipelineLayout>, push_constants: Pc, )2087 unsafe fn set_push_constants<Pc>(
2088     destination: &mut SyncCommandBufferBuilder,
2089     pipeline_layout: &Arc<PipelineLayout>,
2090     push_constants: Pc,
2091 ) {
2092     for range in pipeline_layout.push_constant_ranges() {
2093         debug_assert_eq!(range.offset % 4, 0);
2094         debug_assert_eq!(range.size % 4, 0);
2095 
2096         let data = slice::from_raw_parts(
2097             (&push_constants as *const Pc as *const u8).offset(range.offset as isize),
2098             range.size as usize,
2099         );
2100 
2101         destination.push_constants::<[u8]>(
2102             pipeline_layout.clone(),
2103             range.stages,
2104             range.offset as u32,
2105             range.size as u32,
2106             data,
2107         );
2108     }
2109 }
2110 
2111 // Shortcut function to change the state of the pipeline.
set_state(destination: &mut SyncCommandBufferBuilder, dynamic: &DynamicState)2112 unsafe fn set_state(destination: &mut SyncCommandBufferBuilder, dynamic: &DynamicState) {
2113     if let Some(line_width) = dynamic.line_width {
2114         destination.set_line_width(line_width);
2115     }
2116 
2117     if let Some(ref viewports) = dynamic.viewports {
2118         destination.set_viewport(0, viewports.iter().cloned().collect::<Vec<_>>().into_iter());
2119         // TODO: don't collect
2120     }
2121 
2122     if let Some(ref scissors) = dynamic.scissors {
2123         destination.set_scissor(0, scissors.iter().cloned().collect::<Vec<_>>().into_iter());
2124         // TODO: don't collect
2125     }
2126 
2127     if let Some(compare_mask) = dynamic.compare_mask {
2128         destination.set_stencil_compare_mask(StencilFaces::Front, compare_mask.front);
2129         destination.set_stencil_compare_mask(StencilFaces::Back, compare_mask.back);
2130     }
2131 
2132     if let Some(write_mask) = dynamic.write_mask {
2133         destination.set_stencil_write_mask(StencilFaces::Front, write_mask.front);
2134         destination.set_stencil_write_mask(StencilFaces::Back, write_mask.back);
2135     }
2136 
2137     if let Some(reference) = dynamic.reference {
2138         destination.set_stencil_reference(StencilFaces::Front, reference.front);
2139         destination.set_stencil_reference(StencilFaces::Back, reference.back);
2140     }
2141 }
2142 
2143 // Shortcut function to bind vertex buffers.
bind_vertex_buffers( destination: &mut SyncCommandBufferBuilder, state_cacher: &mut StateCacher, vertex_buffers: Vec<Box<dyn BufferAccess + Send + Sync>>, ) -> Result<(), SyncCommandBufferBuilderError>2144 unsafe fn bind_vertex_buffers(
2145     destination: &mut SyncCommandBufferBuilder,
2146     state_cacher: &mut StateCacher,
2147     vertex_buffers: Vec<Box<dyn BufferAccess + Send + Sync>>,
2148 ) -> Result<(), SyncCommandBufferBuilderError> {
2149     let binding_range = {
2150         let mut compare = state_cacher.bind_vertex_buffers();
2151         for vb in vertex_buffers.iter() {
2152             compare.add(vb);
2153         }
2154         match compare.compare() {
2155             Some(r) => r,
2156             None => return Ok(()),
2157         }
2158     };
2159 
2160     let first_binding = binding_range.start;
2161     let num_bindings = binding_range.end - binding_range.start;
2162 
2163     let mut binder = destination.bind_vertex_buffers();
2164     for vb in vertex_buffers
2165         .into_iter()
2166         .skip(first_binding as usize)
2167         .take(num_bindings as usize)
2168     {
2169         binder.add(vb);
2170     }
2171     binder.submit(first_binding)?;
2172     Ok(())
2173 }
2174 
bind_descriptor_sets( destination: &mut SyncCommandBufferBuilder, state_cacher: &mut StateCacher, pipeline_bind_point: PipelineBindPoint, pipeline_layout: &Arc<PipelineLayout>, descriptor_sets: Vec<DescriptorSetWithOffsets>, ) -> Result<(), SyncCommandBufferBuilderError>2175 unsafe fn bind_descriptor_sets(
2176     destination: &mut SyncCommandBufferBuilder,
2177     state_cacher: &mut StateCacher,
2178     pipeline_bind_point: PipelineBindPoint,
2179     pipeline_layout: &Arc<PipelineLayout>,
2180     descriptor_sets: Vec<DescriptorSetWithOffsets>,
2181 ) -> Result<(), SyncCommandBufferBuilderError> {
2182     let first_binding = {
2183         let mut compare = state_cacher.bind_descriptor_sets(pipeline_bind_point);
2184         for descriptor_set in descriptor_sets.iter() {
2185             compare.add(descriptor_set);
2186         }
2187         compare.compare()
2188     };
2189 
2190     let first_binding = match first_binding {
2191         None => return Ok(()),
2192         Some(fb) => fb,
2193     };
2194 
2195     let mut sets_binder = destination.bind_descriptor_sets();
2196     for set in descriptor_sets.into_iter().skip(first_binding as usize) {
2197         sets_binder.add(set);
2198     }
2199     sets_binder.submit(pipeline_bind_point, pipeline_layout.clone(), first_binding)?;
2200     Ok(())
2201 }
2202 
2203 pub struct PrimaryAutoCommandBuffer<P = StandardCommandPoolAlloc> {
2204     inner: SyncCommandBuffer,
2205     pool_alloc: P, // Safety: must be dropped after `inner`
2206 
2207     // Tracks usage of the command buffer on the GPU.
2208     submit_state: SubmitState,
2209 }
2210 
2211 unsafe impl<P> DeviceOwned for PrimaryAutoCommandBuffer<P> {
2212     #[inline]
device(&self) -> &Arc<Device>2213     fn device(&self) -> &Arc<Device> {
2214         self.inner.device()
2215     }
2216 }
2217 
2218 unsafe impl<P> PrimaryCommandBuffer for PrimaryAutoCommandBuffer<P> {
2219     #[inline]
inner(&self) -> &UnsafeCommandBuffer2220     fn inner(&self) -> &UnsafeCommandBuffer {
2221         self.inner.as_ref()
2222     }
2223 
2224     #[inline]
lock_submit( &self, future: &dyn GpuFuture, queue: &Queue, ) -> Result<(), CommandBufferExecError>2225     fn lock_submit(
2226         &self,
2227         future: &dyn GpuFuture,
2228         queue: &Queue,
2229     ) -> Result<(), CommandBufferExecError> {
2230         match self.submit_state {
2231             SubmitState::OneTime {
2232                 ref already_submitted,
2233             } => {
2234                 let was_already_submitted = already_submitted.swap(true, Ordering::SeqCst);
2235                 if was_already_submitted {
2236                     return Err(CommandBufferExecError::OneTimeSubmitAlreadySubmitted);
2237                 }
2238             }
2239             SubmitState::ExclusiveUse { ref in_use } => {
2240                 let already_in_use = in_use.swap(true, Ordering::SeqCst);
2241                 if already_in_use {
2242                     return Err(CommandBufferExecError::ExclusiveAlreadyInUse);
2243                 }
2244             }
2245             SubmitState::Concurrent => (),
2246         };
2247 
2248         let err = match self.inner.lock_submit(future, queue) {
2249             Ok(()) => return Ok(()),
2250             Err(err) => err,
2251         };
2252 
2253         // If `self.inner.lock_submit()` failed, we revert action.
2254         match self.submit_state {
2255             SubmitState::OneTime {
2256                 ref already_submitted,
2257             } => {
2258                 already_submitted.store(false, Ordering::SeqCst);
2259             }
2260             SubmitState::ExclusiveUse { ref in_use } => {
2261                 in_use.store(false, Ordering::SeqCst);
2262             }
2263             SubmitState::Concurrent => (),
2264         };
2265 
2266         Err(err)
2267     }
2268 
2269     #[inline]
unlock(&self)2270     unsafe fn unlock(&self) {
2271         // Because of panic safety, we unlock the inner command buffer first.
2272         self.inner.unlock();
2273 
2274         match self.submit_state {
2275             SubmitState::OneTime {
2276                 ref already_submitted,
2277             } => {
2278                 debug_assert!(already_submitted.load(Ordering::SeqCst));
2279             }
2280             SubmitState::ExclusiveUse { ref in_use } => {
2281                 let old_val = in_use.swap(false, Ordering::SeqCst);
2282                 debug_assert!(old_val);
2283             }
2284             SubmitState::Concurrent => (),
2285         };
2286     }
2287 
2288     #[inline]
check_buffer_access( &self, buffer: &dyn BufferAccess, exclusive: bool, queue: &Queue, ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError>2289     fn check_buffer_access(
2290         &self,
2291         buffer: &dyn BufferAccess,
2292         exclusive: bool,
2293         queue: &Queue,
2294     ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
2295         self.inner.check_buffer_access(buffer, exclusive, queue)
2296     }
2297 
2298     #[inline]
check_image_access( &self, image: &dyn ImageAccess, layout: ImageLayout, exclusive: bool, queue: &Queue, ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError>2299     fn check_image_access(
2300         &self,
2301         image: &dyn ImageAccess,
2302         layout: ImageLayout,
2303         exclusive: bool,
2304         queue: &Queue,
2305     ) -> Result<Option<(PipelineStages, AccessFlags)>, AccessCheckError> {
2306         self.inner
2307             .check_image_access(image, layout, exclusive, queue)
2308     }
2309 }
2310 
2311 pub struct SecondaryAutoCommandBuffer<P = StandardCommandPoolAlloc> {
2312     inner: SyncCommandBuffer,
2313     pool_alloc: P, // Safety: must be dropped after `inner`
2314     inheritance: CommandBufferInheritance<Box<dyn FramebufferAbstract + Send + Sync>>,
2315 
2316     // Tracks usage of the command buffer on the GPU.
2317     submit_state: SubmitState,
2318 }
2319 
2320 unsafe impl<P> DeviceOwned for SecondaryAutoCommandBuffer<P> {
2321     #[inline]
device(&self) -> &Arc<Device>2322     fn device(&self) -> &Arc<Device> {
2323         self.inner.device()
2324     }
2325 }
2326 
2327 unsafe impl<P> SecondaryCommandBuffer for SecondaryAutoCommandBuffer<P> {
2328     #[inline]
inner(&self) -> &UnsafeCommandBuffer2329     fn inner(&self) -> &UnsafeCommandBuffer {
2330         self.inner.as_ref()
2331     }
2332 
2333     #[inline]
lock_record(&self) -> Result<(), CommandBufferExecError>2334     fn lock_record(&self) -> Result<(), CommandBufferExecError> {
2335         match self.submit_state {
2336             SubmitState::OneTime {
2337                 ref already_submitted,
2338             } => {
2339                 let was_already_submitted = already_submitted.swap(true, Ordering::SeqCst);
2340                 if was_already_submitted {
2341                     return Err(CommandBufferExecError::OneTimeSubmitAlreadySubmitted);
2342                 }
2343             }
2344             SubmitState::ExclusiveUse { ref in_use } => {
2345                 let already_in_use = in_use.swap(true, Ordering::SeqCst);
2346                 if already_in_use {
2347                     return Err(CommandBufferExecError::ExclusiveAlreadyInUse);
2348                 }
2349             }
2350             SubmitState::Concurrent => (),
2351         };
2352 
2353         Ok(())
2354     }
2355 
2356     #[inline]
unlock(&self)2357     unsafe fn unlock(&self) {
2358         match self.submit_state {
2359             SubmitState::OneTime {
2360                 ref already_submitted,
2361             } => {
2362                 debug_assert!(already_submitted.load(Ordering::SeqCst));
2363             }
2364             SubmitState::ExclusiveUse { ref in_use } => {
2365                 let old_val = in_use.swap(false, Ordering::SeqCst);
2366                 debug_assert!(old_val);
2367             }
2368             SubmitState::Concurrent => (),
2369         };
2370     }
2371 
inheritance(&self) -> CommandBufferInheritance<&dyn FramebufferAbstract>2372     fn inheritance(&self) -> CommandBufferInheritance<&dyn FramebufferAbstract> {
2373         CommandBufferInheritance {
2374             render_pass: self.inheritance.render_pass.as_ref().map(
2375                 |CommandBufferInheritanceRenderPass {
2376                      subpass,
2377                      framebuffer,
2378                  }| {
2379                     CommandBufferInheritanceRenderPass {
2380                         subpass: subpass.clone(),
2381                         framebuffer: framebuffer.as_ref().map(|f| f.as_ref() as &_),
2382                     }
2383                 },
2384             ),
2385             occlusion_query: self.inheritance.occlusion_query,
2386             query_statistics_flags: self.inheritance.query_statistics_flags,
2387         }
2388     }
2389 
2390     #[inline]
num_buffers(&self) -> usize2391     fn num_buffers(&self) -> usize {
2392         self.inner.num_buffers()
2393     }
2394 
2395     #[inline]
buffer(&self, index: usize) -> Option<(&dyn BufferAccess, PipelineMemoryAccess)>2396     fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, PipelineMemoryAccess)> {
2397         self.inner.buffer(index)
2398     }
2399 
2400     #[inline]
num_images(&self) -> usize2401     fn num_images(&self) -> usize {
2402         self.inner.num_images()
2403     }
2404 
2405     #[inline]
image( &self, index: usize, ) -> Option<( &dyn ImageAccess, PipelineMemoryAccess, ImageLayout, ImageLayout, ImageUninitializedSafe, )>2406     fn image(
2407         &self,
2408         index: usize,
2409     ) -> Option<(
2410         &dyn ImageAccess,
2411         PipelineMemoryAccess,
2412         ImageLayout,
2413         ImageLayout,
2414         ImageUninitializedSafe,
2415     )> {
2416         self.inner.image(index)
2417     }
2418 }
2419 
2420 // Whether the command buffer can be submitted.
2421 #[derive(Debug)]
2422 enum SubmitState {
2423     // The command buffer was created with the "SimultaneousUse" flag. Can always be submitted at
2424     // any time.
2425     Concurrent,
2426 
2427     // The command buffer can only be submitted once simultaneously.
2428     ExclusiveUse {
2429         // True if the command buffer is current in use by the GPU.
2430         in_use: AtomicBool,
2431     },
2432 
2433     // The command buffer can only ever be submitted once.
2434     OneTime {
2435         // True if the command buffer has already been submitted once and can be no longer be
2436         // submitted.
2437         already_submitted: AtomicBool,
2438     },
2439 }
2440 
2441 macro_rules! err_gen {
2442     ($name:ident { $($err:ident,)+ }) => (
2443         #[derive(Debug, Clone)]
2444         pub enum $name {
2445             $(
2446                 $err($err),
2447             )+
2448         }
2449 
2450         impl error::Error for $name {
2451             #[inline]
2452             fn source(&self) -> Option<&(dyn error::Error + 'static)> {
2453                 match *self {
2454                     $(
2455                         $name::$err(ref err) => Some(err),
2456                     )+
2457                 }
2458             }
2459         }
2460 
2461         impl fmt::Display for $name {
2462             #[inline]
2463             fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
2464                 write!(fmt, "{}", match *self {
2465                     $(
2466                         $name::$err(_) => {
2467                             concat!("a ", stringify!($err))
2468                         }
2469                     )+
2470                 })
2471             }
2472         }
2473 
2474         $(
2475             impl From<$err> for $name {
2476                 #[inline]
2477                 fn from(err: $err) -> $name {
2478                     $name::$err(err)
2479                 }
2480             }
2481         )+
2482     );
2483 }
2484 
2485 err_gen!(BuildError {
2486     AutoCommandBufferBuilderContextError,
2487     OomError,
2488 });
2489 
2490 err_gen!(BeginRenderPassError {
2491     AutoCommandBufferBuilderContextError,
2492     SyncCommandBufferBuilderError,
2493 });
2494 
2495 err_gen!(CopyImageError {
2496     AutoCommandBufferBuilderContextError,
2497     CheckCopyImageError,
2498     SyncCommandBufferBuilderError,
2499 });
2500 
2501 err_gen!(BlitImageError {
2502     AutoCommandBufferBuilderContextError,
2503     CheckBlitImageError,
2504     SyncCommandBufferBuilderError,
2505 });
2506 
2507 err_gen!(ClearColorImageError {
2508     AutoCommandBufferBuilderContextError,
2509     CheckClearColorImageError,
2510     SyncCommandBufferBuilderError,
2511 });
2512 
2513 err_gen!(CopyBufferError {
2514     AutoCommandBufferBuilderContextError,
2515     CheckCopyBufferError,
2516     SyncCommandBufferBuilderError,
2517 });
2518 
2519 err_gen!(CopyBufferImageError {
2520     AutoCommandBufferBuilderContextError,
2521     CheckCopyBufferImageError,
2522     SyncCommandBufferBuilderError,
2523 });
2524 
2525 err_gen!(CopyQueryPoolResultsError {
2526     AutoCommandBufferBuilderContextError,
2527     CheckCopyQueryPoolResultsError,
2528     SyncCommandBufferBuilderError,
2529 });
2530 
2531 err_gen!(FillBufferError {
2532     AutoCommandBufferBuilderContextError,
2533     CheckFillBufferError,
2534 });
2535 
2536 err_gen!(DebugMarkerError {
2537     AutoCommandBufferBuilderContextError,
2538     CheckColorError,
2539 });
2540 
2541 err_gen!(DispatchError {
2542     AutoCommandBufferBuilderContextError,
2543     CheckPushConstantsValidityError,
2544     CheckDescriptorSetsValidityError,
2545     CheckDispatchError,
2546     SyncCommandBufferBuilderError,
2547 });
2548 
2549 err_gen!(DispatchIndirectError {
2550     AutoCommandBufferBuilderContextError,
2551     CheckPushConstantsValidityError,
2552     CheckDescriptorSetsValidityError,
2553     CheckIndirectBufferError,
2554     SyncCommandBufferBuilderError,
2555 });
2556 
2557 err_gen!(DrawError {
2558     AutoCommandBufferBuilderContextError,
2559     CheckDynamicStateValidityError,
2560     CheckPushConstantsValidityError,
2561     CheckDescriptorSetsValidityError,
2562     CheckVertexBufferError,
2563     SyncCommandBufferBuilderError,
2564 });
2565 
2566 err_gen!(DrawIndexedError {
2567     AutoCommandBufferBuilderContextError,
2568     CheckDynamicStateValidityError,
2569     CheckPushConstantsValidityError,
2570     CheckDescriptorSetsValidityError,
2571     CheckVertexBufferError,
2572     CheckIndexBufferError,
2573     SyncCommandBufferBuilderError,
2574 });
2575 
2576 err_gen!(DrawIndirectError {
2577     AutoCommandBufferBuilderContextError,
2578     CheckDynamicStateValidityError,
2579     CheckPushConstantsValidityError,
2580     CheckDescriptorSetsValidityError,
2581     CheckVertexBufferError,
2582     CheckIndirectBufferError,
2583     SyncCommandBufferBuilderError,
2584 });
2585 
2586 err_gen!(DrawIndexedIndirectError {
2587     AutoCommandBufferBuilderContextError,
2588     CheckDynamicStateValidityError,
2589     CheckPushConstantsValidityError,
2590     CheckDescriptorSetsValidityError,
2591     CheckVertexBufferError,
2592     CheckIndexBufferError,
2593     CheckIndirectBufferError,
2594     SyncCommandBufferBuilderError,
2595 });
2596 
2597 err_gen!(ExecuteCommandsError {
2598     AutoCommandBufferBuilderContextError,
2599     SyncCommandBufferBuilderError,
2600 });
2601 
2602 err_gen!(BeginQueryError {
2603     AutoCommandBufferBuilderContextError,
2604     CheckBeginQueryError,
2605 });
2606 
2607 err_gen!(EndQueryError {
2608     AutoCommandBufferBuilderContextError,
2609     CheckEndQueryError,
2610 });
2611 
2612 err_gen!(WriteTimestampError {
2613     AutoCommandBufferBuilderContextError,
2614     CheckWriteTimestampError,
2615 });
2616 
2617 err_gen!(ResetQueryPoolError {
2618     AutoCommandBufferBuilderContextError,
2619     CheckResetQueryPoolError,
2620 });
2621 
2622 err_gen!(UpdateBufferError {
2623     AutoCommandBufferBuilderContextError,
2624     CheckUpdateBufferError,
2625 });
2626 
2627 #[derive(Debug, Copy, Clone)]
2628 pub enum AutoCommandBufferBuilderContextError {
2629     /// Operation forbidden inside of a render pass.
2630     ForbiddenInsideRenderPass,
2631     /// Operation forbidden outside of a render pass.
2632     ForbiddenOutsideRenderPass,
2633     /// Tried to use a secondary command buffer with a specified framebuffer that is
2634     /// incompatible with the current framebuffer.
2635     IncompatibleFramebuffer,
2636     /// Tried to use a graphics pipeline or secondary command buffer whose render pass
2637     /// is incompatible with the current render pass.
2638     IncompatibleRenderPass,
2639     /// The queue family doesn't allow this operation.
2640     NotSupportedByQueueFamily,
2641     /// Tried to end a render pass with subpasses remaining, or tried to go to next subpass with no
2642     /// subpass remaining.
2643     NumSubpassesMismatch {
2644         /// Actual number of subpasses in the current render pass.
2645         actual: u32,
2646         /// Current subpass index before the failing command.
2647         current: u32,
2648     },
2649     /// A query is active that conflicts with the current operation.
2650     QueryIsActive,
2651     /// This query was not active.
2652     QueryNotActive,
2653     /// A query is active that is not included in the `inheritance` of the secondary command buffer.
2654     QueryNotInherited,
2655     /// Tried to use a graphics pipeline or secondary command buffer whose subpass index
2656     /// didn't match the current subpass index.
2657     WrongSubpassIndex,
2658     /// Tried to execute a secondary command buffer inside a subpass that only allows inline
2659     /// commands, or a draw command in a subpass that only allows secondary command buffers.
2660     WrongSubpassType,
2661 }
2662 
2663 impl error::Error for AutoCommandBufferBuilderContextError {}
2664 
2665 impl fmt::Display for AutoCommandBufferBuilderContextError {
2666     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>2667     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
2668         write!(
2669             fmt,
2670             "{}",
2671             match *self {
2672                 AutoCommandBufferBuilderContextError::ForbiddenInsideRenderPass => {
2673                     "operation forbidden inside of a render pass"
2674                 }
2675                 AutoCommandBufferBuilderContextError::ForbiddenOutsideRenderPass => {
2676                     "operation forbidden outside of a render pass"
2677                 }
2678                 AutoCommandBufferBuilderContextError::IncompatibleFramebuffer => {
2679                     "tried to use a secondary command buffer with a specified framebuffer that is \
2680                  incompatible with the current framebuffer"
2681                 }
2682                 AutoCommandBufferBuilderContextError::IncompatibleRenderPass => {
2683                     "tried to use a graphics pipeline or secondary command buffer whose render pass \
2684                   is incompatible with the current render pass"
2685                 }
2686                 AutoCommandBufferBuilderContextError::NotSupportedByQueueFamily => {
2687                     "the queue family doesn't allow this operation"
2688                 }
2689                 AutoCommandBufferBuilderContextError::NumSubpassesMismatch { .. } => {
2690                     "tried to end a render pass with subpasses remaining, or tried to go to next \
2691                  subpass with no subpass remaining"
2692                 }
2693                 AutoCommandBufferBuilderContextError::QueryIsActive => {
2694                     "a query is active that conflicts with the current operation"
2695                 }
2696                 AutoCommandBufferBuilderContextError::QueryNotActive => {
2697                     "this query was not active"
2698                 }
2699                 AutoCommandBufferBuilderContextError::QueryNotInherited => {
2700                     "a query is active that is not included in the inheritance of the secondary command buffer"
2701                 }
2702                 AutoCommandBufferBuilderContextError::WrongSubpassIndex => {
2703                     "tried to use a graphics pipeline whose subpass index didn't match the current \
2704                  subpass index"
2705                 }
2706                 AutoCommandBufferBuilderContextError::WrongSubpassType => {
2707                     "tried to execute a secondary command buffer inside a subpass that only allows \
2708                  inline commands, or a draw command in a subpass that only allows secondary \
2709                  command buffers"
2710                 }
2711             }
2712         )
2713     }
2714 }
2715 
2716 #[cfg(test)]
2717 mod tests {
2718     use crate::buffer::BufferUsage;
2719     use crate::buffer::CpuAccessibleBuffer;
2720     use crate::command_buffer::synced::SyncCommandBufferBuilderError;
2721     use crate::command_buffer::AutoCommandBufferBuilder;
2722     use crate::command_buffer::CommandBufferExecError;
2723     use crate::command_buffer::CommandBufferUsage;
2724     use crate::command_buffer::ExecuteCommandsError;
2725     use crate::command_buffer::PrimaryCommandBuffer;
2726     use crate::device::physical::PhysicalDevice;
2727     use crate::device::Device;
2728     use crate::device::DeviceExtensions;
2729     use crate::device::Features;
2730     use crate::sync::GpuFuture;
2731     use std::sync::Arc;
2732 
2733     #[test]
copy_buffer_dimensions()2734     fn copy_buffer_dimensions() {
2735         let instance = instance!();
2736 
2737         let phys = match PhysicalDevice::enumerate(&instance).next() {
2738             Some(p) => p,
2739             None => return,
2740         };
2741 
2742         let queue_family = match phys.queue_families().next() {
2743             Some(q) => q,
2744             None => return,
2745         };
2746 
2747         let (device, mut queues) = Device::new(
2748             phys,
2749             &Features::none(),
2750             &DeviceExtensions::none(),
2751             std::iter::once((queue_family, 0.5)),
2752         )
2753         .unwrap();
2754 
2755         let queue = queues.next().unwrap();
2756 
2757         let source = CpuAccessibleBuffer::from_iter(
2758             device.clone(),
2759             BufferUsage::all(),
2760             true,
2761             [1_u32, 2].iter().copied(),
2762         )
2763         .unwrap();
2764 
2765         let destination = CpuAccessibleBuffer::from_iter(
2766             device.clone(),
2767             BufferUsage::all(),
2768             true,
2769             [0_u32, 10, 20, 3, 4].iter().copied(),
2770         )
2771         .unwrap();
2772 
2773         let mut cbb = AutoCommandBufferBuilder::primary(
2774             device.clone(),
2775             queue.family(),
2776             CommandBufferUsage::OneTimeSubmit,
2777         )
2778         .unwrap();
2779 
2780         cbb.copy_buffer_dimensions(source.clone(), 0, destination.clone(), 1, 2)
2781             .unwrap();
2782 
2783         let cb = cbb.build().unwrap();
2784 
2785         let future = cb
2786             .execute(queue.clone())
2787             .unwrap()
2788             .then_signal_fence_and_flush()
2789             .unwrap();
2790         future.wait(None).unwrap();
2791 
2792         let result = destination.read().unwrap();
2793 
2794         assert_eq!(*result, [0_u32, 1, 2, 3, 4]);
2795     }
2796 
2797     #[test]
secondary_nonconcurrent_conflict()2798     fn secondary_nonconcurrent_conflict() {
2799         let (device, queue) = gfx_dev_and_queue!();
2800 
2801         // Make a secondary CB that doesn't support simultaneous use.
2802         let builder = AutoCommandBufferBuilder::secondary_compute(
2803             device.clone(),
2804             queue.family(),
2805             CommandBufferUsage::MultipleSubmit,
2806         )
2807         .unwrap();
2808         let secondary = Arc::new(builder.build().unwrap());
2809 
2810         {
2811             let mut builder = AutoCommandBufferBuilder::primary(
2812                 device.clone(),
2813                 queue.family(),
2814                 CommandBufferUsage::SimultaneousUse,
2815             )
2816             .unwrap();
2817 
2818             // Add the secondary a first time
2819             builder.execute_commands(secondary.clone()).unwrap();
2820 
2821             // Recording the same non-concurrent secondary command buffer twice into the same
2822             // primary is an error.
2823             assert!(matches!(
2824                 builder.execute_commands(secondary.clone()),
2825                 Err(ExecuteCommandsError::SyncCommandBufferBuilderError(
2826                     SyncCommandBufferBuilderError::ExecError(
2827                         CommandBufferExecError::ExclusiveAlreadyInUse
2828                     )
2829                 ))
2830             ));
2831         }
2832 
2833         {
2834             let mut builder = AutoCommandBufferBuilder::primary(
2835                 device.clone(),
2836                 queue.family(),
2837                 CommandBufferUsage::SimultaneousUse,
2838             )
2839             .unwrap();
2840             builder.execute_commands(secondary.clone()).unwrap();
2841             let cb1 = builder.build().unwrap();
2842 
2843             let mut builder = AutoCommandBufferBuilder::primary(
2844                 device.clone(),
2845                 queue.family(),
2846                 CommandBufferUsage::SimultaneousUse,
2847             )
2848             .unwrap();
2849 
2850             // Recording the same non-concurrent secondary command buffer into multiple
2851             // primaries is an error.
2852             assert!(matches!(
2853                 builder.execute_commands(secondary.clone()),
2854                 Err(ExecuteCommandsError::SyncCommandBufferBuilderError(
2855                     SyncCommandBufferBuilderError::ExecError(
2856                         CommandBufferExecError::ExclusiveAlreadyInUse
2857                     )
2858                 ))
2859             ));
2860 
2861             std::mem::drop(cb1);
2862 
2863             // Now that the first cb is dropped, we should be able to record.
2864             builder.execute_commands(secondary.clone()).unwrap();
2865         }
2866     }
2867 }
2868