1use std::fmt::Debug;
10use std::mem::MaybeUninit;
11use std::sync::Weak;
12
13use crate::descriptor_set::DescriptorSetLayout;
14use crate::device::Device;
15use crate::enums::*;
16use crate::error::{Error, ErrorAndSelf, Result, ResultAndSelf};
17use crate::exclusive::Exclusive;
18use crate::framebuffer::Framebuffer;
19use crate::pipeline::Pipeline;
20use crate::render_pass::RenderPass;
21use crate::subobject::{Owner, Subobject};
22use crate::types::*;
23
24mod transfer;
25pub mod barrier;
26mod bind;
27mod draw;
28
29pub struct CommandPool {
42 recording: Option<Arc<RecordedCommands>>,
43 res: Owner<CommandPoolLifetime>,
44 scratch: Exclusive<bumpalo::Bump>,
45}
46
47#[must_use = "Leaks pool resources if not freed"]
55#[derive(Debug)]
56pub struct CommandBuffer(Arc<CommandBufferLifetime>);
60
61#[must_use = "Leaks pool resources if not freed"]
69#[derive(Debug)]
70pub struct SecondaryCommandBuffer {
71 buf: Arc<CommandBufferLifetime>,
72 pass: Option<Arc<RenderPass>>,
73 subpass: u32,
74}
75
76struct Bindings<'a> {
77 layout: bumpalo::collections::Vec<'a, Arc<DescriptorSetLayout>>,
78 inited: bumpalo::collections::Vec<'a, bool>,
79 pipeline: Option<Arc<Pipeline>>,
80}
81
82pub struct CommandRecording<'a> {
84 pool: &'a mut Owner<CommandPoolLifetime>,
85 recording: &'a Arc<RecordedCommands>,
86 scratch: &'a bumpalo::Bump,
87 graphics: Bindings<'a>,
88 compute: Bindings<'a>,
89 buffer: Owner<CommandBufferLifetime>,
90}
91
92#[must_use = "Record render pass commands on this object"]
94pub struct RenderPassRecording<'a> {
95 rec: CommandRecording<'a>,
96 pass: Arc<RenderPass>,
97 subpass: u32,
98}
99
100#[must_use = "Record secondary command buffers on this object"]
103pub struct ExternalRenderPassRecording<'a> {
104 rec: CommandRecording<'a>,
105 pass: Arc<RenderPass>,
106 subpass: u32,
107}
108
109pub struct SecondaryCommandRecording<'a> {
111 rec: CommandRecording<'a>,
112 pass: Arc<RenderPass>,
113 subpass: u32,
114}
115
116#[derive(Debug)]
117struct CommandBufferLifetime {
118 handle: Handle<VkCommandBuffer>,
119 pool: Subobject<CommandPoolLifetime>,
120 recording: Weak<RecordedCommands>,
123}
124
125#[derive(Debug)]
126struct CommandPoolLifetime {
127 handle: Handle<VkCommandPool>,
128 resources: Vec<Arc<dyn Send + Sync + Debug>>,
129 device: Arc<Device>,
130}
131
132#[derive(Debug)]
133struct RecordedCommands(Subobject<CommandPoolLifetime>);
134
135impl std::fmt::Debug for CommandPool {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 self.res.handle.fmt(f)
138 }
139}
140
141impl std::panic::UnwindSafe for CommandPoolLifetime {}
143impl std::panic::RefUnwindSafe for CommandPoolLifetime {}
144
145impl CommandPool {
146 #[doc = crate::man_link!(vkCreateCommandPool)]
149 pub fn new(device: &Arc<Device>, queue_family_index: u32) -> Result<Self> {
150 if !device.has_queue(queue_family_index, 1) {
151 return Err(Error::OutOfBounds);
152 }
153 let mut handle = None;
154 unsafe {
155 (device.fun.create_command_pool)(
156 device.handle(),
157 &CommandPoolCreateInfo {
158 queue_family_index,
159 ..Default::default()
160 },
161 None,
162 &mut handle,
163 )?;
164 }
165 let handle = handle.unwrap();
166
167 let res = Owner::new(CommandPoolLifetime {
168 handle,
169 resources: vec![],
170 device: device.clone(),
171 });
172 let _res = Subobject::new(&res);
173 Ok(CommandPool {
174 res,
175 recording: Some(Arc::new(RecordedCommands(_res))),
176 scratch: Exclusive::new(bumpalo::Bump::new()),
177 })
178 }
179}
180
181impl Drop for CommandPoolLifetime {
182 fn drop(&mut self) {
183 unsafe {
184 (self.device.fun.destroy_command_pool)(
185 self.device.handle(),
186 self.handle.borrow_mut(),
187 None,
188 )
189 }
190 }
191}
192
193impl CommandPool {
194 pub fn mut_handle(&mut self) -> Mut<VkCommandPool> {
196 self.res.handle.borrow_mut()
197 }
198
199 pub fn reset(&mut self, flags: CommandPoolResetFlags) -> Result<()> {
202 match Arc::try_unwrap(self.recording.take().unwrap()) {
203 Err(arc) => {
205 self.recording = Some(arc);
206 Err(Error::SynchronizationError)
207 }
208 Ok(_) => {
209 let res = &mut *self.res;
210 unsafe {
211 (res.device.fun.reset_command_pool)(
212 res.device.handle(),
213 res.handle.borrow_mut(),
214 flags,
215 )?;
216 }
217 self.recording =
218 Some(Arc::new(RecordedCommands(Subobject::new(&self.res))));
219 self.res.resources.clear();
220 Ok(())
221 }
222 }
223 }
224
225 #[doc = crate::man_link!(vkAllocateCommandBuffers)]
227 pub fn allocate(&mut self) -> Result<CommandBuffer> {
228 Ok(CommandBuffer(self.allocate_impl(CommandBufferLevel::PRIMARY)?))
229 }
230
231 #[doc = crate::man_link!(vkAllocateCommandBuffers)]
233 pub fn allocate_secondary(&mut self) -> Result<SecondaryCommandBuffer> {
234 Ok(SecondaryCommandBuffer {
235 buf: self.allocate_impl(CommandBufferLevel::SECONDARY)?,
236 pass: None,
237 subpass: 0,
238 })
239 }
240
241 fn allocate_impl(
242 &mut self, level: CommandBufferLevel,
243 ) -> Result<Arc<CommandBufferLifetime>> {
244 let mut handle = MaybeUninit::uninit();
245 let res = &mut *self.res;
246 let handle = unsafe {
247 (res.device.fun.allocate_command_buffers)(
248 res.device.handle(),
249 &CommandBufferAllocateInfo {
250 stype: Default::default(),
251 next: Default::default(),
252 pool: res.handle.borrow_mut(),
253 level,
254 count: 1,
255 },
256 std::array::from_mut(&mut handle).into(),
257 )?;
258 handle.assume_init()
259 };
260 Ok(Arc::new(CommandBufferLifetime {
261 handle,
262 pool: Subobject::new(&self.res),
263 recording: Weak::new(),
264 }))
265 }
266
267 #[doc = crate::man_link!(vkFreeCommandBuffers)]
269 pub fn free(&mut self, mut buffer: CommandBuffer) -> Result<()> {
270 if !Owner::ptr_eq(&self.res, &buffer.0.pool) {
271 return Err(Error::InvalidArgument);
272 }
273 self.free_impl(buffer.mut_handle()?);
274 Ok(())
275 }
276
277 #[doc = crate::man_link!(vkFreeCommandBuffers)]
279 pub fn free_secondary(
280 &mut self, mut buffer: SecondaryCommandBuffer,
281 ) -> Result<()> {
282 if !Owner::ptr_eq(&self.res, &buffer.buf.pool) {
283 return Err(Error::InvalidArgument);
284 }
285 self.free_impl(buffer.mut_handle()?);
286 Ok(())
287 }
288
289 fn free_impl(&mut self, buffer: Mut<VkCommandBuffer>) {
290 let res = &mut *self.res;
291 unsafe {
292 (res.device.fun.free_command_buffers)(
293 res.device.handle(),
294 res.handle.borrow_mut(),
295 1,
296 &buffer,
297 );
298 }
299 }
300
301 #[doc = crate::man_link!(vkBeginCommandBuffer)]
305 pub fn begin(
306 &mut self, buffer: CommandBuffer,
307 ) -> ResultAndSelf<CommandRecording<'_>, CommandBuffer> {
308 if !Owner::ptr_eq(&self.res, &buffer.0.pool)
309 || buffer.lock_resources().is_some()
311 {
312 return Err(ErrorAndSelf(Error::InvalidArgument, buffer));
313 }
314 let mut inner = Owner::from_arc(buffer.0).map_err(|arc| {
316 ErrorAndSelf(Error::SynchronizationError, CommandBuffer(arc))
317 })?;
318 unsafe {
319 if let Err(err) = (self.res.device.fun.begin_command_buffer)(
320 inner.handle.borrow_mut(),
321 &Default::default(),
322 ) {
323 return Err(ErrorAndSelf(
324 err.into(),
325 CommandBuffer(Owner::into_arc(inner)),
326 ));
327 };
328 }
329 let scratch = self.scratch.get_mut();
330 scratch.reset();
331 Ok(CommandRecording {
332 pool: &mut self.res,
333 recording: self.recording.as_ref().unwrap(),
334 graphics: Bindings::new(scratch),
335 compute: Bindings::new(scratch),
336 scratch,
337 buffer: inner,
338 })
339 }
340
341 #[doc = crate::man_link!(vkBeginCommandBuffer)]
345 pub fn begin_secondary<'a>(
346 &'a mut self, buffer: SecondaryCommandBuffer,
347 render_pass: &Arc<RenderPass>, subpass: u32,
348 ) -> ResultAndSelf<SecondaryCommandRecording<'a>, SecondaryCommandBuffer>
349 {
350 if subpass >= render_pass.num_subpasses() {
351 return Err(ErrorAndSelf(Error::InvalidArgument, buffer));
352 }
353 if !Owner::ptr_eq(&self.res, &buffer.buf.pool)
354 || buffer.lock_resources().is_some()
356 {
357 return Err(ErrorAndSelf(Error::InvalidArgument, buffer));
358 }
359 let mut inner = Owner::from_arc(buffer.buf).map_err(|arc| {
361 ErrorAndSelf(
362 Error::SynchronizationError,
363 SecondaryCommandBuffer { buf: arc, pass: None, subpass: 0 },
364 )
365 })?;
366 unsafe {
367 if let Err(err) = (self.res.device.fun.begin_command_buffer)(
368 inner.handle.borrow_mut(),
369 &CommandBufferBeginInfo {
370 flags: CommandBufferUsageFlags::RENDER_PASS_CONTINUE,
371 inheritance_info: Some(&CommandBufferInheritanceInfo {
372 stype: Default::default(),
373 next: Default::default(),
374 render_pass: render_pass.handle(),
375 subpass,
376 framebuffer: Default::default(),
377 occlusion_query_enable: Default::default(),
378 query_flags: Default::default(),
379 pipeline_statistics: Default::default(),
380 }),
381 ..Default::default()
382 },
383 ) {
384 return Err(ErrorAndSelf(
385 err.into(),
386 SecondaryCommandBuffer {
387 buf: Owner::into_arc(inner),
388 pass: None,
389 subpass: 0,
390 },
391 ));
392 };
393 }
394 let scratch = self.scratch.get_mut();
395 scratch.reset();
396 Ok(SecondaryCommandRecording {
397 rec: CommandRecording {
398 pool: &mut self.res,
399 recording: self.recording.as_ref().unwrap(),
400 graphics: Bindings::new(scratch),
401 compute: Bindings::new(scratch),
402 scratch,
403 buffer: inner,
404 },
405 pass: render_pass.clone(),
406 subpass,
407 })
408 }
409}
410
411impl CommandBuffer {
412 pub fn mut_handle(&mut self) -> Result<Mut<VkCommandBuffer>> {
415 match Arc::get_mut(&mut self.0) {
416 Some(inner) => Ok(inner.handle.borrow_mut()),
417 None => Err(Error::SynchronizationError),
418 }
419 }
420 pub(crate) fn lock_self(&self) -> Arc<impl Send + Sync + Debug> {
423 self.0.clone()
424 }
425 pub(crate) fn lock_resources(
428 &self,
429 ) -> Option<Arc<impl Send + Sync + Debug>> {
430 self.0.recording.upgrade()
431 }
432}
433
434impl SecondaryCommandBuffer {
435 pub fn mut_handle(&mut self) -> Result<Mut<VkCommandBuffer>> {
438 match Arc::get_mut(&mut self.buf) {
439 Some(inner) => Ok(inner.handle.borrow_mut()),
440 None => Err(Error::SynchronizationError),
441 }
442 }
443 pub(crate) fn lock_self(&self) -> Arc<impl Send + Sync + Debug> {
446 self.buf.clone()
447 }
448 pub(crate) fn lock_resources(
451 &self,
452 ) -> Option<Arc<impl Send + Sync + Debug>> {
453 self.buf.recording.upgrade()
454 }
455}
456
457impl<'a> Bindings<'a> {
458 fn new(scratch: &'a bumpalo::Bump) -> Self {
459 Self {
460 layout: bumpalo::vec![in scratch],
461 inited: bumpalo::vec![in scratch],
462 pipeline: None,
463 }
464 }
465}
466
467impl<'a> CommandRecording<'a> {
468 fn add_resource(&mut self, value: Arc<dyn Send + Sync + Debug>) {
469 self.pool.resources.push(value);
470 }
471 #[doc = crate::man_link!(vkEndCommandBuffer)]
474 pub fn end(mut self) -> Result<CommandBuffer> {
475 unsafe {
476 (self.pool.device.fun.end_command_buffer)(
477 self.buffer.handle.borrow_mut(),
478 )?;
479 }
480 self.buffer.recording = Arc::downgrade(self.recording);
481 Ok(CommandBuffer(Owner::into_arc(self.buffer)))
482 }
483}
484
485impl<'a> SecondaryCommandRecording<'a> {
486 #[doc = crate::man_link!(vkEndCommandBuffer)]
489 pub fn end(mut self) -> Result<SecondaryCommandBuffer> {
490 unsafe {
491 (self.rec.pool.device.fun.end_command_buffer)(
492 self.rec.buffer.handle.borrow_mut(),
493 )?;
494 }
495 self.rec.buffer.recording = Arc::downgrade(self.rec.recording);
496 Ok(SecondaryCommandBuffer {
497 buf: Owner::into_arc(self.rec.buffer),
498 pass: Some(self.pass),
499 subpass: self.subpass,
500 })
501 }
502}
503
504impl<'a> CommandRecording<'a> {
505 #[doc = crate::man_link!(vkCmdBeginRenderPass)]
508 pub fn begin_render_pass(
509 mut self, render_pass: &Arc<RenderPass>,
510 framebuffer: &Arc<Framebuffer>, render_area: &Rect2D,
511 clear_values: &[ClearValue],
512 ) -> Result<RenderPassRecording<'a>> {
513 self.begin_render_pass_impl(
514 render_pass,
515 framebuffer,
516 render_area,
517 clear_values,
518 SubpassContents::INLINE,
519 )?;
520 Ok(RenderPassRecording {
521 rec: self,
522 pass: render_pass.clone(),
523 subpass: 0,
524 })
525 }
526 #[doc = crate::man_link!(vkCmdBeginRenderPass)]
530 pub fn begin_render_pass_secondary(
531 mut self, render_pass: &Arc<RenderPass>,
532 framebuffer: &Arc<Framebuffer>, render_area: &Rect2D,
533 clear_values: &[ClearValue],
534 ) -> Result<ExternalRenderPassRecording<'a>> {
535 if !framebuffer.is_compatible_with(render_pass) {
536 return Err(Error::InvalidArgument);
537 }
538 self.begin_render_pass_impl(
539 render_pass,
540 framebuffer,
541 render_area,
542 clear_values,
543 SubpassContents::SECONDARY_COMMAND_BUFFERS,
544 )?;
545 Ok(ExternalRenderPassRecording {
546 rec: self,
547 pass: render_pass.clone(),
548 subpass: 0,
549 })
550 }
551 fn begin_render_pass_impl(
552 &mut self, render_pass: &Arc<RenderPass>,
553 framebuffer: &Arc<Framebuffer>, render_area: &Rect2D,
554 clear_values: &[ClearValue], subpass_contents: SubpassContents,
555 ) -> Result<()> {
556 if !framebuffer.is_compatible_with(render_pass) {
557 return Err(Error::InvalidArgument);
558 }
559 self.add_resource(render_pass.clone());
560 self.add_resource(framebuffer.clone());
561 let info = RenderPassBeginInfo {
562 stype: Default::default(),
563 next: Default::default(),
564 render_pass: render_pass.handle(),
565 framebuffer: framebuffer.handle(),
566 render_area: *render_area,
567 clear_values: clear_values.into(),
568 };
569 unsafe {
570 (self.pool.device.fun.cmd_begin_render_pass)(
571 self.buffer.handle.borrow_mut(),
572 &info,
573 subpass_contents,
574 );
575 }
576 Ok(())
577 }
578}
579
580impl<'a> RenderPassRecording<'a> {
581 #[doc = crate::man_link!(vkCmdNextSubpass)]
584 pub fn next_subpass(&mut self) -> Result<()> {
585 if self.subpass >= self.pass.num_subpasses() - 1 {
586 return Err(Error::OutOfBounds);
587 }
588 self.subpass += 1;
589 unsafe {
590 (self.rec.pool.device.fun.cmd_next_subpass)(
591 self.rec.buffer.handle.borrow_mut(),
592 SubpassContents::INLINE,
593 )
594 }
595 Ok(())
596 }
597 #[doc = crate::man_link!(vkCmdNextSubpass)]
600 pub fn next_subpass_secondary(
601 mut self,
602 ) -> Result<ExternalRenderPassRecording<'a>> {
603 if self.subpass >= self.pass.num_subpasses() - 1 {
604 return Err(Error::OutOfBounds);
605 }
606 unsafe {
607 (self.rec.pool.device.fun.cmd_next_subpass)(
608 self.rec.buffer.handle.borrow_mut(),
609 SubpassContents::SECONDARY_COMMAND_BUFFERS,
610 );
611 }
612 Ok(ExternalRenderPassRecording {
613 rec: self.rec,
614 pass: self.pass,
615 subpass: self.subpass + 1,
616 })
617 }
618 #[doc = crate::man_link!(vkCmdEndRenderPass)]
621 pub fn end(mut self) -> Result<CommandRecording<'a>> {
622 if self.subpass != self.pass.num_subpasses() - 1 {
623 return Err(Error::InvalidState);
624 }
625 unsafe {
626 (self.rec.pool.device.fun.cmd_end_render_pass)(
627 self.rec.buffer.handle.borrow_mut(),
628 );
629 }
630 Ok(self.rec)
631 }
632}
633
634impl<'a> ExternalRenderPassRecording<'a> {
635 #[doc = crate::man_link!(vkCmdNextSubpass)]
638 pub fn next_subpass_secondary(&mut self) -> Result<()> {
639 if self.subpass >= self.pass.num_subpasses() - 1 {
640 return Err(Error::OutOfBounds);
641 }
642 self.subpass += 1;
643 unsafe {
644 (self.rec.pool.device.fun.cmd_next_subpass)(
645 self.rec.buffer.handle.borrow_mut(),
646 SubpassContents::SECONDARY_COMMAND_BUFFERS,
647 )
648 }
649 Ok(())
650 }
651 #[doc = crate::man_link!(vkCmdNextSubpass)]
654 pub fn next_subpass(mut self) -> Result<RenderPassRecording<'a>> {
655 if self.subpass >= self.pass.num_subpasses() - 1 {
656 return Err(Error::OutOfBounds);
657 }
658 unsafe {
659 (self.rec.pool.device.fun.cmd_next_subpass)(
660 self.rec.buffer.handle.borrow_mut(),
661 SubpassContents::INLINE,
662 );
663 }
664 Ok(RenderPassRecording {
665 rec: self.rec,
666 pass: self.pass,
667 subpass: self.subpass + 1,
668 })
669 }
670 #[doc = crate::man_link!(vkCmdEndRenderPass)]
673 pub fn end(mut self) -> Result<CommandRecording<'a>> {
674 if self.subpass != self.pass.num_subpasses() - 1 {
675 return Err(Error::InvalidState);
676 }
677 unsafe {
678 (self.rec.pool.device.fun.cmd_end_render_pass)(
679 self.rec.buffer.handle.borrow_mut(),
680 );
681 }
682 Ok(self.rec)
683 }
684}
685
686#[cfg(test)]
687mod test {
688 use crate::vk;
689
690 #[test]
691 fn secondary_reset() -> vk::Result<()> {
692 let (dev, _) = crate::test_device()?;
693 let pass = vk::RenderPass::new(
694 &dev,
695 &vk::RenderPassCreateInfo {
696 subpasses: vk::slice(&[Default::default()]),
697 ..Default::default()
698 },
699 )?;
700 let fb = vk::Framebuffer::new(
701 &pass,
702 Default::default(),
703 vec![],
704 Default::default(),
705 )?;
706 let mut pool1 = vk::CommandPool::new(&dev, 0)?;
707 let mut pool2 = vk::CommandPool::new(&dev, 0)?;
708
709 let sec = pool2.allocate_secondary()?;
710 let mut sec = pool2.begin_secondary(sec, &pass, 0)?.end()?;
711 let prim = pool1.allocate()?;
712 let rec = pool1.begin(prim)?;
713 let mut rec = rec.begin_render_pass_secondary(
714 &pass,
715 &fb,
716 &Default::default(),
717 Default::default(),
718 )?;
719 rec.execute_commands(&mut [&mut sec])?;
720 let prim = rec.end()?.end()?;
721
722 assert!(pool2.reset(Default::default()).is_err());
723 assert!(pool1.reset(Default::default()).is_ok());
724 assert!(pool2.reset(Default::default()).is_ok());
725
726 assert!(pool1.free_secondary(sec).is_err());
727 assert!(pool2.free(prim).is_err());
728
729 let sec = pool1.allocate_secondary()?;
730 let mut sec = pool1.begin_secondary(sec, &pass, 0)?.end()?;
731 let prim = pool1.allocate()?;
732 let rec = pool1.begin(prim)?;
733 let mut rec = rec.begin_render_pass_secondary(
734 &pass,
735 &fb,
736 &Default::default(),
737 Default::default(),
738 )?;
739 rec.execute_commands(&mut [&mut sec])?;
740 let _ = rec.end()?.end()?;
741
742 assert!(pool1.reset(Default::default()).is_ok());
743
744 Ok(())
745 }
746
747 #[test]
748 fn subpass() -> vk::Result<()> {
749 let (dev, _) = crate::test_device()?;
750 let pass = vk::RenderPass::new(
751 &dev,
752 &vk::RenderPassCreateInfo {
753 subpasses: vk::slice(&[Default::default(), Default::default()]),
754 ..Default::default()
755 },
756 )?;
757 let fb = vk::Framebuffer::new(
758 &pass,
759 Default::default(),
760 vec![],
761 Default::default(),
762 )?;
763
764 let mut pool = vk::CommandPool::new(&dev, 0)?;
765
766 let buf = pool.allocate()?;
767 let rec = pool.begin(buf)?;
768 let rec = rec.begin_render_pass(
769 &pass,
770 &fb,
771 &Default::default(),
772 Default::default(),
773 )?;
774 assert!(rec.end().is_err());
775
776 let buf = pool.allocate()?;
777 let rec = pool.begin(buf)?;
778 let mut rec = rec.begin_render_pass(
779 &pass,
780 &fb,
781 &Default::default(),
782 Default::default(),
783 )?;
784 assert!(rec.next_subpass().is_ok());
785 assert!(rec.next_subpass().is_err());
786 assert!(rec.next_subpass_secondary().is_err());
787
788 pool.reset(Default::default())?;
789
790 let buf = pool.allocate()?;
791 let rec = pool.begin(buf)?;
792 let mut rec = rec.begin_render_pass_secondary(
793 &pass,
794 &fb,
795 &Default::default(),
796 Default::default(),
797 )?;
798 assert!(rec.next_subpass_secondary().is_ok());
799 assert!(rec.next_subpass_secondary().is_err());
800 assert!(rec.next_subpass().is_err());
801
802 Ok(())
803 }
804}