mod queue;
mod submission;
use {
crate::{
buffer::Reset,
capability::{Capability, QueueType, Supports},
core::{device_owned, Device, DeviceId},
pool::CommandPool,
},
rendy_core::hal::Backend,
};
pub use self::{queue::*, submission::*};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct FamilyId {
pub index: usize,
pub device: DeviceId,
}
impl From<FamilyId> for rendy_core::hal::queue::QueueFamilyId {
fn from(id: FamilyId) -> Self {
rendy_core::hal::queue::QueueFamilyId(id.index)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct QueueId {
pub index: usize,
pub family: FamilyId,
}
#[derive(Debug)]
pub struct Family<B: Backend, C = QueueType> {
id: FamilyId,
queues: Vec<Queue<B>>,
capability: C,
}
device_owned!(Family<B, C> @ |f: &Self| f.id.device);
impl<B> Family<B, QueueType>
where
B: Backend,
{
pub unsafe fn from_device(
queue_groups: &mut Vec<rendy_core::hal::queue::QueueGroup<B>>,
id: FamilyId,
count: usize,
family: &impl rendy_core::hal::queue::QueueFamily,
) -> Self {
Family {
id,
queues: {
let pos = queue_groups.iter().position(|qg| qg.family.0 == id.index);
let group = queue_groups.swap_remove(pos.unwrap());
assert_eq!(group.queues.len(), count);
group
.queues
.into_iter()
.enumerate()
.map(|(index, queue)| Queue::new(queue, QueueId { family: id, index }))
.collect()
},
capability: family.queue_type(),
}
}
}
impl<B, C> Family<B, C>
where
B: Backend,
{
pub fn id(&self) -> FamilyId {
self.id
}
pub fn queue(&self, index: usize) -> &Queue<B> {
&self.queues[index]
}
pub fn queue_mut(&mut self, index: usize) -> &mut Queue<B> {
&mut self.queues[index]
}
pub fn as_slice(&self) -> &[Queue<B>] {
&self.queues
}
pub fn as_slice_mut(&mut self) -> &mut [Queue<B>] {
&mut self.queues
}
pub fn create_pool<R>(
&self,
device: &Device<B>,
) -> Result<CommandPool<B, C, R>, rendy_core::hal::device::OutOfMemory>
where
R: Reset,
C: Capability,
{
self.assert_device_owner(device);
unsafe { CommandPool::create(self.id, self.capability, device) }
}
pub fn capability(&self) -> C
where
C: Capability,
{
self.capability
}
pub fn with_queue_type(self) -> Family<B, QueueType>
where
C: Capability,
{
Family {
id: self.id,
queues: self.queues,
capability: self.capability.into_queue_type(),
}
}
pub fn with_capability<U>(self) -> Result<Family<B, U>, Self>
where
C: Supports<U>,
{
if let Some(capability) = self.capability.supports() {
Ok(Family {
id: self.id,
queues: self.queues,
capability,
})
} else {
Err(self)
}
}
}
#[derive(Debug)]
pub struct Families<B: Backend> {
device: DeviceId,
families: Vec<Family<B>>,
families_indices: Vec<usize>,
}
impl<B> Families<B>
where
B: Backend,
{
pub fn family(&self, id: FamilyId) -> &Family<B> {
assert_eq!(id.device, self.device);
self.family_by_index(id.index)
}
pub fn family_by_index(&self, index: usize) -> &Family<B> {
&self.families[self.families_indices[index]]
}
pub fn family_mut(&mut self, id: FamilyId) -> &mut Family<B> {
assert_eq!(id.device, self.device);
self.family_by_index_mut(id.index)
}
pub fn family_by_index_mut(&mut self, index: usize) -> &mut Family<B> {
&mut self.families[self.families_indices[index]]
}
pub fn as_slice(&self) -> &[Family<B>] {
&self.families
}
pub fn as_slice_mut(&mut self) -> &mut [Family<B>] {
&mut self.families
}
pub fn indices(&self) -> &[usize] {
&self.families_indices
}
pub fn find<F>(&self, predicate: F) -> Option<FamilyId>
where
F: FnMut(&&Family<B>) -> bool,
{
self.families.iter().find(predicate).map(Family::id)
}
pub fn with_capability<C: Capability>(&self) -> Option<FamilyId> {
self.find(|family| Supports::<C>::supports(&family.capability()).is_some())
}
}
pub unsafe fn families_from_device<B>(
device: DeviceId,
queue_groups: &mut Vec<rendy_core::hal::queue::QueueGroup<B>>,
families: impl IntoIterator<Item = (FamilyId, usize)>,
queue_types: &[impl rendy_core::hal::queue::QueueFamily],
) -> Families<B>
where
B: Backend,
{
let families: Vec<_> = families
.into_iter()
.map(|(id, count)| Family::from_device(queue_groups, id, count, &queue_types[id.index]))
.collect();
let mut families_indices = vec![!0; families.len()];
for (index, family) in families.iter().enumerate() {
families_indices[family.id.index] = index;
}
Families {
device,
families,
families_indices,
}
}