rendy_command/family/
queue.rs

1use {
2    super::{submission::*, QueueId},
3    crate::{buffer::Submittable, fence::*},
4    rendy_core::hal::{queue::CommandQueue, Backend},
5};
6
7/// Command queue wrapper.
8#[derive(Debug)]
9pub struct Queue<B: Backend> {
10    raw: B::CommandQueue,
11    id: QueueId,
12    next_epoch: u64,
13}
14
15family_owned!(@NOCAP Queue<B> @ |q: &Self| q.id.family);
16
17impl<B> Queue<B>
18where
19    B: Backend,
20{
21    pub(super) fn new(raw: B::CommandQueue, id: QueueId) -> Self {
22        Queue {
23            id,
24            raw,
25            next_epoch: 0,
26        }
27    }
28
29    /// Id of the queue.
30    pub fn id(&self) -> QueueId {
31        self.id
32    }
33
34    /// Get raw command queue.
35    pub fn raw(&mut self) -> &mut impl CommandQueue<B> {
36        &mut self.raw
37    }
38
39    /// Returns next queue epoch.
40    pub fn next_epoch(&self) -> u64 {
41        self.next_epoch
42    }
43
44    /// Submit commands to the queue of the family.
45    /// Fence must be submitted.
46    pub unsafe fn submit<'a>(
47        &mut self,
48        submissions: impl IntoIterator<
49            Item = Submission<
50                B,
51                impl IntoIterator<
52                    Item = (
53                        &'a (impl std::borrow::Borrow<B::Semaphore> + 'a),
54                        rendy_core::hal::pso::PipelineStage,
55                    ),
56                >,
57                impl IntoIterator<Item = impl Submittable<B>>,
58                impl IntoIterator<Item = &'a (impl std::borrow::Borrow<B::Semaphore> + 'a)>,
59            >,
60        >,
61        fence: Option<&mut Fence<B>>,
62    ) {
63        assert!(fence.as_ref().map_or(true, |f| f.is_unsignaled()));
64
65        let mut submissions = submissions.into_iter().peekable();
66        if submissions.peek().is_none() && fence.is_some() {
67            self.raw.submit(
68                rendy_core::hal::queue::Submission {
69                    command_buffers: std::iter::empty::<&'a B::CommandBuffer>(),
70                    wait_semaphores: std::iter::empty::<(&'a B::Semaphore, _)>(),
71                    signal_semaphores: std::iter::empty::<&'a B::Semaphore>(),
72                },
73                fence.as_ref().map(|f| f.raw()),
74            );
75        } else {
76            let family = self.id.family;
77            while let Some(submission) = submissions.next() {
78                self.raw.submit(
79                    rendy_core::hal::queue::Submission {
80                        command_buffers: submission.submits.into_iter().map(|submit| {
81                            assert_eq!(submit.family(), family);
82                            submit.raw()
83                        }),
84                        wait_semaphores: submission.waits.into_iter().map(|w| (w.0.borrow(), w.1)),
85                        signal_semaphores: submission.signals.into_iter().map(|s| s.borrow()),
86                    },
87                    submissions
88                        .peek()
89                        .map_or(fence.as_ref().map(|f| f.raw()), |_| None),
90                );
91            }
92        }
93
94        if let Some(fence) = fence {
95            fence.mark_submitted(FenceEpoch {
96                queue: self.id,
97                epoch: self.next_epoch,
98            });
99            self.next_epoch += 1;
100        }
101    }
102
103    /// Submit commands to the queue of the family.
104    /// Fence must be submitted.
105    /// This version uses raw fence and doesn't increment epoch.
106    pub unsafe fn submit_raw_fence<'a>(
107        &mut self,
108        submissions: impl IntoIterator<
109            Item = Submission<
110                B,
111                impl IntoIterator<
112                    Item = (
113                        &'a (impl std::borrow::Borrow<B::Semaphore> + 'a),
114                        rendy_core::hal::pso::PipelineStage,
115                    ),
116                >,
117                impl IntoIterator<Item = impl Submittable<B>>,
118                impl IntoIterator<Item = &'a (impl std::borrow::Borrow<B::Semaphore> + 'a)>,
119            >,
120        >,
121        fence: Option<&B::Fence>,
122    ) {
123        let mut submissions = submissions.into_iter().peekable();
124        if submissions.peek().is_none() && fence.is_some() {
125            self.raw.submit(
126                rendy_core::hal::queue::Submission {
127                    command_buffers: std::iter::empty::<&'a B::CommandBuffer>(),
128                    wait_semaphores: std::iter::empty::<(&'a B::Semaphore, _)>(),
129                    signal_semaphores: std::iter::empty::<&'a B::Semaphore>(),
130                },
131                fence,
132            );
133        } else {
134            let family = self.id.family;
135            while let Some(submission) = submissions.next() {
136                self.raw.submit(
137                    rendy_core::hal::queue::Submission {
138                        command_buffers: submission.submits.into_iter().map(|submit| {
139                            assert_eq!(submit.family(), family);
140                            submit.raw()
141                        }),
142                        wait_semaphores: submission.waits.into_iter().map(|w| (w.0.borrow(), w.1)),
143                        signal_semaphores: submission.signals.into_iter().map(|s| s.borrow()),
144                    },
145                    submissions.peek().map_or(fence, |_| None),
146                );
147            }
148        }
149    }
150
151    /// Wait for queue to finish all pending commands.
152    pub fn wait_idle(&self) -> Result<(), rendy_core::hal::device::OutOfMemory> {
153        self.raw.wait_idle()
154    }
155}