mod queue;
mod submission;
use {
crate::{
buffer::Reset,
capability::{Capability, QueueType, Supports},
pool::CommandPool,
util::{device_owned, Device, DeviceId},
},
gfx_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 gfx_hal::queue::QueueFamilyId {
fn from(id: FamilyId) -> Self {
gfx_hal::queue::QueueFamilyId(id.index)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct QueueId {
pub index: usize,
pub family: FamilyId,
}
#[derive(derivative::Derivative)]
#[derivative(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(
queues: &mut gfx_hal::queue::Queues<B>,
id: FamilyId,
count: usize,
family: &impl gfx_hal::queue::QueueFamily,
) -> Self {
Family {
id,
queues: {
let queues = queues
.take_raw(gfx_hal::queue::QueueFamilyId(id.index))
.expect("");
assert_eq!(queues.len(), count);
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>, gfx_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 unsafe fn families_from_device<B>(
device: DeviceId,
queues: &mut gfx_hal::queue::Queues<B>,
families: impl IntoIterator<Item = (FamilyId, usize)>,
queue_types: &[impl gfx_hal::queue::QueueFamily],
) -> Families<B>
where
B: Backend,
{
let families: Vec<_> = families
.into_iter()
.map(|(id, count)| Family::from_device(queues, 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,
}
}