138 lines
4.4 KiB
Rust
138 lines
4.4 KiB
Rust
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<QueueInfo>,
|
|
transfer_only: Option<QueueInfo>,
|
|
) -> (Vec<QueueToAllocate>, KeyedCopy<QueueIndex>) {
|
|
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)
|
|
}
|