use { super::{KeyedCopy, TransferType}, ahash::AHashSet, linearize::static_copy_map, }; #[derive(Debug)] pub(super) struct QueueToAllocate { pub(super) family: u32, pub(super) num: usize, } #[derive(Copy, Clone, Default, Debug)] pub(super) struct QueueIndex { pub(super) allocate_idx: usize, pub(super) family: u32, pub(super) idx_within_family: u32, pub(super) transfer_granularity_mask: (u32, u32), } type QueueInfo = (u32, (u32, u32), u32); pub(super) fn allocate_queues( gfx: QueueInfo, compute_only: Option, transfer_only: Option, ) -> (Vec, KeyedCopy) { let intra = compute_only.unwrap_or(gfx); let cross = transfer_only.unwrap_or(intra); let mut distinct_families = AHashSet::default(); distinct_families.insert(cross); distinct_families.insert(intra); distinct_families.insert(gfx); let mut queues_to_allocate = vec![]; macro_rules! index { ($qi:expr, $within:expr) => { QueueIndex { allocate_idx: queues_to_allocate.len(), family: $qi.0, idx_within_family: $within as u32, transfer_granularity_mask: $qi.1, } }; } macro_rules! alloc { ($qi:expr, $num:expr) => { QueueToAllocate { family: $qi.0, num: $num as usize, } }; } let (blit, intra_idx, download, upload); if distinct_families.len() == 3 { let num_cross = cross.2.min(2) as usize; blit = index!(gfx, 0); queues_to_allocate.push(alloc!(gfx, 1)); intra_idx = index!(intra, 0); queues_to_allocate.push(alloc!(intra, 1)); download = index!(cross, 0); upload = index!(cross, num_cross - 1); queues_to_allocate.push(alloc!(cross, num_cross)); } else if distinct_families.len() == 1 { let qi = cross; let num = qi.2.min(4); match num { 1 => { blit = index!(qi, 0); intra_idx = index!(qi, 0); download = index!(qi, 0); upload = index!(qi, 0); } 2 => { blit = index!(qi, 0); intra_idx = index!(qi, 0); download = index!(qi, 0); upload = index!(qi, 1); } 3 => { blit = index!(qi, 0); intra_idx = index!(qi, 0); download = index!(qi, 1); upload = index!(qi, 2); } 4 => { blit = index!(qi, 0); intra_idx = index!(qi, 1); download = index!(qi, 2); upload = index!(qi, 3); } _ => unreachable!(), } queues_to_allocate.push(alloc!(qi, num)); } else { if gfx == intra { let num_gfx = gfx.2.min(2); blit = index!(gfx, 0); intra_idx = index!(gfx, num_gfx - 1); queues_to_allocate.push(alloc!(gfx, num_gfx)); let num_cross = cross.2.min(2); download = index!(cross, 0); upload = index!(cross, num_cross - 1); queues_to_allocate.push(alloc!(cross, num_cross)); } else { // if cross == gfx then intra == gfx assert_eq!(intra, cross); blit = index!(gfx, 0); queues_to_allocate.push(alloc!(gfx, 1)); let num_intra = intra.2.min(3); match num_intra { 1 => { intra_idx = index!(intra, 0); download = index!(intra, 0); upload = index!(intra, 0); } 2 => { intra_idx = index!(intra, 0); download = index!(intra, 0); upload = index!(intra, 1); } 3 => { intra_idx = index!(intra, 0); download = index!(intra, 1); upload = index!(intra, 2); } _ => unreachable!(), } queues_to_allocate.push(alloc!(intra, num_intra)); } } let queue_indices = static_copy_map! { TransferType::Blit => blit, TransferType::Intra => intra_idx, TransferType::Download => download, TransferType::Upload => upload, }; (queues_to_allocate, queue_indices) }