rendy_command/family/
mod.rs

1//! Family module docs.
2
3mod queue;
4mod submission;
5
6use {
7    crate::{
8        buffer::Reset,
9        capability::{Capability, QueueType, Supports},
10        core::{device_owned, Device, DeviceId},
11        pool::CommandPool,
12    },
13    rendy_core::hal::Backend,
14};
15
16pub use self::{queue::*, submission::*};
17
18/// Family id.
19#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
20pub struct FamilyId {
21    /// Family id within device.
22    pub index: usize,
23
24    /// Device id.
25    pub device: DeviceId,
26}
27
28impl From<FamilyId> for rendy_core::hal::queue::QueueFamilyId {
29    fn from(id: FamilyId) -> Self {
30        rendy_core::hal::queue::QueueFamilyId(id.index)
31    }
32}
33
34/// Queue id.
35#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
36pub struct QueueId {
37    /// Queue index.
38    pub index: usize,
39
40    /// Family id.
41    pub family: FamilyId,
42}
43
44/// Family of the command queues.
45/// Queues from one family can share resources and execute command buffers associated with the family.
46/// All queues of the family have same capabilities.
47#[derive(Debug)]
48pub struct Family<B: Backend, C = QueueType> {
49    id: FamilyId,
50    queues: Vec<Queue<B>>,
51    // min_image_transfer_granularity: rendy_core::hal::image::Extent,
52    capability: C,
53}
54
55device_owned!(Family<B, C> @ |f: &Self| f.id.device);
56
57impl<B> Family<B, QueueType>
58where
59    B: Backend,
60{
61    /// Query queue family from device.
62    ///
63    /// # Safety
64    ///
65    /// This function shouldn't be used more then once with the same parameters.
66    /// Raw queue handle queried from device can make `Family` usage invalid.
67    /// `family` must be one of the family indices used during `device` creation.
68    /// `properties` must be the properties retuned for queue family from physical device.
69    pub unsafe fn from_device(
70        queue_groups: &mut Vec<rendy_core::hal::queue::QueueGroup<B>>,
71        id: FamilyId,
72        count: usize,
73        family: &impl rendy_core::hal::queue::QueueFamily,
74    ) -> Self {
75        Family {
76            id,
77            queues: {
78                let pos = queue_groups.iter().position(|qg| qg.family.0 == id.index);
79                let group = queue_groups.swap_remove(pos.unwrap());
80                assert_eq!(group.queues.len(), count);
81                group
82                    .queues
83                    .into_iter()
84                    .enumerate()
85                    .map(|(index, queue)| Queue::new(queue, QueueId { family: id, index }))
86                    .collect()
87            },
88            // min_image_transfer_granularity: properties.min_image_transfer_granularity,
89            capability: family.queue_type(),
90        }
91    }
92}
93
94impl<B, C> Family<B, C>
95where
96    B: Backend,
97{
98    /// Get id of the family.
99    pub fn id(&self) -> FamilyId {
100        self.id
101    }
102
103    /// Get queue by index
104    pub fn queue(&self, index: usize) -> &Queue<B> {
105        &self.queues[index]
106    }
107
108    /// Get queue by index
109    pub fn queue_mut(&mut self, index: usize) -> &mut Queue<B> {
110        &mut self.queues[index]
111    }
112
113    /// Get queues of the family.
114    pub fn as_slice(&self) -> &[Queue<B>] {
115        &self.queues
116    }
117
118    /// Get queues of the family.
119    pub fn as_slice_mut(&mut self) -> &mut [Queue<B>] {
120        &mut self.queues
121    }
122
123    /// Create command pool associated with the family.
124    /// Command buffers created from the pool could be submitted to the queues of the family.
125    pub fn create_pool<R>(
126        &self,
127        device: &Device<B>,
128    ) -> Result<CommandPool<B, C, R>, rendy_core::hal::device::OutOfMemory>
129    where
130        R: Reset,
131        C: Capability,
132    {
133        self.assert_device_owner(device);
134        unsafe { CommandPool::create(self.id, self.capability, device) }
135    }
136
137    /// Get family capability.
138    pub fn capability(&self) -> C
139    where
140        C: Capability,
141    {
142        self.capability
143    }
144
145    /// Convert capability from type-level to value-level.
146    pub fn with_queue_type(self) -> Family<B, QueueType>
147    where
148        C: Capability,
149    {
150        Family {
151            id: self.id,
152            queues: self.queues,
153            // min_image_transfer_granularity: self.min_image_transfer_granularity,
154            capability: self.capability.into_queue_type(),
155        }
156    }
157
158    /// Convert capability into type-level one.
159    ///
160    pub fn with_capability<U>(self) -> Result<Family<B, U>, Self>
161    where
162        C: Supports<U>,
163    {
164        if let Some(capability) = self.capability.supports() {
165            Ok(Family {
166                id: self.id,
167                queues: self.queues,
168                // min_image_transfer_granularity: self.min_image_transfer_granularity,
169                capability,
170            })
171        } else {
172            Err(self)
173        }
174    }
175}
176
177/// Collection of queue families of one device.
178#[derive(Debug)]
179pub struct Families<B: Backend> {
180    device: DeviceId,
181    families: Vec<Family<B>>,
182    families_indices: Vec<usize>,
183}
184
185impl<B> Families<B>
186where
187    B: Backend,
188{
189    /// Get queue family by id.
190    pub fn family(&self, id: FamilyId) -> &Family<B> {
191        assert_eq!(id.device, self.device);
192        self.family_by_index(id.index)
193    }
194
195    /// Get queue family by index.
196    pub fn family_by_index(&self, index: usize) -> &Family<B> {
197        &self.families[self.families_indices[index]]
198    }
199
200    /// Get queue family by id.
201    pub fn family_mut(&mut self, id: FamilyId) -> &mut Family<B> {
202        assert_eq!(id.device, self.device);
203        self.family_by_index_mut(id.index)
204    }
205
206    /// Get queue family by index.
207    pub fn family_by_index_mut(&mut self, index: usize) -> &mut Family<B> {
208        &mut self.families[self.families_indices[index]]
209    }
210
211    /// Get queue families as slice.
212    pub fn as_slice(&self) -> &[Family<B>] {
213        &self.families
214    }
215
216    /// Get queue families as slice.
217    pub fn as_slice_mut(&mut self) -> &mut [Family<B>] {
218        &mut self.families
219    }
220
221    /// Get id -> index mapping.
222    pub fn indices(&self) -> &[usize] {
223        &self.families_indices
224    }
225
226    /// Find family id matching predicate
227    pub fn find<F>(&self, predicate: F) -> Option<FamilyId>
228    where
229        F: FnMut(&&Family<B>) -> bool,
230    {
231        self.families.iter().find(predicate).map(Family::id)
232    }
233
234    /// Get first matching family id with specified capability
235    pub fn with_capability<C: Capability>(&self) -> Option<FamilyId> {
236        self.find(|family| Supports::<C>::supports(&family.capability()).is_some())
237    }
238}
239
240/// Query queue families from device.
241///
242/// # Safety
243///
244/// This function shouldn't be used more then once with same parameters.
245/// Raw queue handle queried from device can make returned `Family` usage invalid.
246/// `families` iterator must yeild unique family indices with queue count used during `device` creation.
247/// `properties` must contain properties retuned for queue family from physical device for each family id yielded by `families`.
248pub unsafe fn families_from_device<B>(
249    device: DeviceId,
250    queue_groups: &mut Vec<rendy_core::hal::queue::QueueGroup<B>>,
251    families: impl IntoIterator<Item = (FamilyId, usize)>,
252    queue_types: &[impl rendy_core::hal::queue::QueueFamily],
253) -> Families<B>
254where
255    B: Backend,
256{
257    let families: Vec<_> = families
258        .into_iter()
259        .map(|(id, count)| Family::from_device(queue_groups, id, count, &queue_types[id.index]))
260        .collect();
261
262    let mut families_indices = vec![!0; families.len()];
263    for (index, family) in families.iter().enumerate() {
264        families_indices[family.id.index] = index;
265    }
266
267    Families {
268        device,
269        families,
270        families_indices,
271    }
272}