rendy_command/
pool.rs

1//! CommandPool module docs.
2
3use {
4    crate::{buffer::*, capability::*, core::Device, family::FamilyId},
5    rendy_core::hal::{device::Device as _, pool::CommandPool as _, Backend},
6};
7
8/// Simple pool wrapper.
9/// Doesn't provide any guarantees.
10/// Wraps raw buffers into `CommandCommand buffer`.
11#[derive(Debug)]
12pub struct CommandPool<B: Backend, C = QueueType, R = NoIndividualReset> {
13    raw: B::CommandPool,
14    capability: C,
15    reset: R,
16    family: FamilyId,
17    relevant: relevant::Relevant,
18}
19
20family_owned!(CommandPool<B, C, R>);
21
22impl<B, C, R> CommandPool<B, C, R>
23where
24    B: Backend,
25    R: Reset,
26{
27    /// Create command pool associated with the family.
28    /// Command buffers created from the pool could be submitted to the queues of the family.
29    ///
30    /// # Safety
31    ///
32    /// Family must belong to specified device.
33    /// Family must have specified capability.
34    pub unsafe fn create(
35        family: FamilyId,
36        capability: C,
37        device: &Device<B>,
38    ) -> Result<Self, rendy_core::hal::device::OutOfMemory>
39    where
40        R: Reset,
41        C: Capability,
42    {
43        let reset = R::default();
44        let raw = device.create_command_pool(
45            rendy_core::hal::queue::QueueFamilyId(family.index),
46            reset.flags(),
47        )?;
48        Ok(CommandPool::from_raw(raw, capability, reset, family))
49    }
50
51    /// Wrap raw command pool.
52    ///
53    /// # Safety
54    ///
55    /// * `raw` must be valid command pool handle.
56    /// * The command pool must be created for specified `family` index.
57    /// * `capability` must be subset of capabilites of the `family` the pool was created for.
58    /// * if `reset` is `IndividualReset` the pool must be created with individual command buffer reset flag set.
59    pub unsafe fn from_raw(raw: B::CommandPool, capability: C, reset: R, family: FamilyId) -> Self {
60        CommandPool {
61            raw,
62            capability,
63            reset,
64            family,
65            relevant: relevant::Relevant,
66        }
67    }
68
69    /// Allocate new command buffers.
70    pub fn allocate_buffers<L: Level>(
71        &mut self,
72        count: usize,
73    ) -> Vec<CommandBuffer<B, C, InitialState, L, R>>
74    where
75        L: Level,
76        C: Capability,
77    {
78        let level = L::default();
79
80        let buffers = unsafe { self.raw.allocate_vec(count, level.raw_level()) };
81
82        buffers
83            .into_iter()
84            .map(|raw| unsafe {
85                CommandBuffer::from_raw(
86                    raw,
87                    self.capability,
88                    InitialState,
89                    level,
90                    self.reset,
91                    self.family,
92                )
93            })
94            .collect()
95    }
96
97    /// Free buffers.
98    /// Buffers must be in droppable state.
99    /// TODO: Validate buffers were allocated from this pool.
100    pub unsafe fn free_buffers(
101        &mut self,
102        buffers: impl IntoIterator<Item = CommandBuffer<B, C, impl Resettable, impl Level, R>>,
103    ) {
104        let buffers = buffers
105            .into_iter()
106            .map(|buffer| buffer.into_raw())
107            .collect::<Vec<_>>();
108
109        self.raw.free(buffers);
110    }
111
112    /// Reset all buffers of this pool.
113    ///
114    /// # Safety
115    ///
116    /// All buffers allocated from this pool must be marked reset.
117    /// See [`CommandBuffer::mark_reset`](struct.Command buffer.html#method.mark_reset)
118    pub unsafe fn reset(&mut self) {
119        rendy_core::hal::pool::CommandPool::reset(&mut self.raw, false);
120    }
121
122    /// Dispose of command pool.
123    ///
124    /// # Safety
125    ///
126    /// All buffers allocated from this pool must be [freed](#method.free_buffers).
127    pub unsafe fn dispose(self, device: &Device<B>) {
128        self.assert_device_owner(device);
129        device.destroy_command_pool(self.raw);
130        self.relevant.dispose();
131    }
132
133    /// Convert capability level
134    pub fn with_queue_type(self) -> CommandPool<B, QueueType, R>
135    where
136        C: Capability,
137    {
138        CommandPool {
139            raw: self.raw,
140            capability: self.capability.into_queue_type(),
141            reset: self.reset,
142            family: self.family,
143            relevant: self.relevant,
144        }
145    }
146
147    /// Convert capability level
148    pub fn with_capability<U>(self) -> Result<CommandPool<B, U, R>, Self>
149    where
150        C: Supports<U>,
151    {
152        if let Some(capability) = self.capability.supports() {
153            Ok(CommandPool {
154                raw: self.raw,
155                capability,
156                reset: self.reset,
157                family: self.family,
158                relevant: self.relevant,
159            })
160        } else {
161            Err(self)
162        }
163    }
164}