1
0
Fork 0
forked from wry/wry

refactor: split cargo workspace

This commit is contained in:
kossLAN 2026-06-05 11:56:21 -04:00
parent 5db14936e7
commit 1c21bd1259
695 changed files with 32023 additions and 44964 deletions

View file

@ -5,10 +5,8 @@ use {
format::{FORMATS, Format},
gfx_api::FdSync,
io_uring::IoUring,
rect::{Rect, Region},
utils::{
clonecell::CloneCell,
copyhashmap::CopyHashMap,
errorfmt::ErrorFmt,
numcell::NumCell,
oserror::{OsError, OsErrorExt2},
@ -22,12 +20,10 @@ use {
},
vulkan_core::{
self, VULKAN_API_VERSION, VulkanCoreError, VulkanCoreInstance, device::VulkanDeviceInf,
map_extension_properties, sync::VulkanDeviceSyncExt,
timeline_semaphore::VulkanDeviceTimelineSemaphoreExt,
map_extension_properties, timeline_semaphore::VulkanDeviceTimelineSemaphoreExt,
},
},
ahash::{AHashMap, AHashSet},
arrayvec::ArrayVec,
ahash::AHashMap,
ash::{
Device,
ext::{
@ -36,12 +32,9 @@ use {
},
khr::{external_fence_fd, external_memory_fd, external_semaphore_fd},
vk::{
self, AccessFlags2, BindImageMemoryInfo, BindImagePlaneMemoryInfo, BlitImageInfo2,
BufferCopy2, BufferCreateInfo, BufferImageCopy2, BufferMemoryBarrier2,
BufferUsageFlags, CommandBuffer, CommandBufferAllocateInfo, CommandBufferBeginInfo,
CommandBufferSubmitInfo, CommandBufferUsageFlags, CommandPoolCreateFlags,
CommandPoolCreateInfo, CopyBufferInfo2, CopyBufferToImageInfo2, CopyImageInfo2,
CopyImageToBufferInfo2, DependencyInfo, DeviceCreateInfo, DeviceMemory,
self, BindImageMemoryInfo, BindImagePlaneMemoryInfo, BufferCopy2, BufferCreateInfo,
BufferImageCopy2, BufferUsageFlags, CommandBuffer, CommandBufferAllocateInfo,
CommandPoolCreateFlags, CommandPoolCreateInfo, DeviceCreateInfo, DeviceMemory,
DeviceQueueCreateInfo, DrmFormatModifierPropertiesEXT,
DrmFormatModifierPropertiesListEXT, ExportMemoryAllocateInfo, Extent3D,
ExternalBufferProperties, ExternalFenceFeatureFlags, ExternalFenceHandleTypeFlags,
@ -49,28 +42,26 @@ use {
ExternalMemoryBufferCreateInfo, ExternalMemoryBufferCreateInfoKHR,
ExternalMemoryFeatureFlags, ExternalMemoryHandleTypeFlags,
ExternalMemoryImageCreateInfo, ExternalSemaphoreFeatureFlags,
ExternalSemaphoreHandleTypeFlags, ExternalSemaphoreProperties, Filter,
FormatFeatureFlags, FormatProperties2, ImageAspectFlags, ImageBlit2, ImageCopy2,
ImageCreateFlags, ImageCreateInfo, ImageDrmFormatModifierExplicitCreateInfoEXT,
ImageFormatProperties2, ImageLayout, ImageMemoryBarrier2, ImageMemoryRequirementsInfo2,
ImagePlaneMemoryRequirementsInfo, ImageSubresourceLayers, ImageSubresourceRange,
ImageTiling, ImageType, ImageUsageFlags, ImportMemoryFdInfoKHR,
ImportSemaphoreFdInfoKHR, MemoryAllocateInfo, MemoryDedicatedAllocateInfo,
MemoryFdPropertiesKHR, MemoryGetFdInfoKHR, MemoryPropertyFlags, MemoryRequirements2,
MemoryType, Offset3D, PhysicalDevice, PhysicalDeviceDrmPropertiesEXT,
ExternalSemaphoreHandleTypeFlags, ExternalSemaphoreProperties, FormatFeatureFlags,
FormatProperties2, ImageAspectFlags, ImageBlit2, ImageCopy2, ImageCreateFlags,
ImageCreateInfo, ImageDrmFormatModifierExplicitCreateInfoEXT, ImageFormatProperties2,
ImageLayout, ImageMemoryRequirementsInfo2, ImagePlaneMemoryRequirementsInfo,
ImageTiling, ImageType, ImageUsageFlags, ImportMemoryFdInfoKHR, ImportSemaphoreFdInfoKHR,
MemoryAllocateInfo, MemoryDedicatedAllocateInfo, MemoryFdPropertiesKHR,
MemoryGetFdInfoKHR, MemoryPropertyFlags, MemoryRequirements2, MemoryType,
PhysicalDevice, PhysicalDeviceDrmPropertiesEXT,
PhysicalDeviceExternalBufferInfo, PhysicalDeviceExternalFenceInfo,
PhysicalDeviceExternalImageFormatInfoKHR, PhysicalDeviceExternalSemaphoreInfo,
PhysicalDeviceFeatures2, PhysicalDeviceImageDrmFormatModifierInfoEXT,
PhysicalDeviceImageFormatInfo2, PhysicalDeviceProperties2,
PhysicalDeviceSynchronization2Features, PhysicalDeviceTimelineSemaphoreFeatures,
PipelineStageFlags2, QUEUE_FAMILY_FOREIGN_EXT, Queue, QueueFlags, SampleCountFlags,
SemaphoreCreateInfo, SemaphoreImportFlags, SemaphoreSubmitInfo, SharingMode,
SubmitInfo2, SubresourceLayout, WHOLE_SIZE,
Queue, QueueFlags, SampleCountFlags, SemaphoreCreateInfo, SemaphoreImportFlags,
SharingMode, SubresourceLayout,
},
},
bstr::ByteSlice,
isnt::std_1::collections::IsntHashMapExt,
linearize::{Linearize, LinearizeExt, StaticCopyMap, StaticMap, static_copy_map, static_map},
linearize::{Linearize, LinearizeExt, StaticCopyMap, StaticMap, static_map},
log::Level,
run_on_drop::on_drop,
std::{
@ -86,6 +77,14 @@ use {
vk::{Buffer, CommandPool, Image, Semaphore},
};
mod execute;
mod queue_allocation;
mod registry;
pub use registry::CopyDeviceRegistry;
use queue_allocation::{QueueIndex, QueueToAllocate, allocate_queues};
#[derive(Debug, Error)]
pub enum CopyDeviceError {
#[error(transparent)]
@ -197,20 +196,6 @@ pub struct PhysicalCopyDevice {
image_blit_2: RefCell<Vec<ImageBlit2<'static>>>,
}
#[derive(Debug)]
struct QueueToAllocate {
family: u32,
num: usize,
}
#[derive(Copy, Clone, Default, Debug)]
struct QueueIndex {
allocate_idx: usize,
family: u32,
idx_within_family: u32,
transfer_granularity_mask: (u32, u32),
}
pub struct CopyDevice {
_tasks: Vec<SpawnedFuture<()>>,
dev: Rc<CopyDeviceInner>,
@ -349,13 +334,6 @@ struct ClassifiedDmabuf<'a> {
format: &'a CopyDeviceSupport,
}
pub struct CopyDeviceRegistry {
ring: Rc<IoUring>,
eng: Rc<AsyncEngine>,
eventfd_cache: Rc<EventfdCache>,
devs: CopyHashMap<c::dev_t, Option<Rc<PhysicalCopyDevice>>>,
}
const DEVICE_EXTENSIONS: [&CStr; 6] = [
external_semaphore_fd::NAME,
external_fence_fd::NAME,
@ -1290,429 +1268,6 @@ impl CopyDeviceInner {
}
}
impl CopyDeviceCopy {
fn ensure_not_busy(&self) -> Result<(), CopyDeviceError> {
let slf = &*self.inner;
if let Some(sync) = slf.busy.get()
&& sync.is_unsignaled()
{
return Err(CopyDeviceError::Busy);
}
slf.busy.take();
Ok(())
}
pub fn execute(
&self,
sync: Option<&FdSync>,
region: Option<&Region>,
) -> Result<Option<FdSync>, CopyDeviceError> {
self.ensure_not_busy()?;
let slf = &*self.inner;
let tt = slf.tt;
let dev = &slf.dev.dev;
let cmd = slf.command_buffer;
let queue_family = slf.dev.phy.queues[tt].family;
let region_buf;
let width = slf.width;
let height = slf.height;
let region = match region {
Some(r) => r,
_ => {
region_buf = Region::new(Rect::new_saturating(0, 0, width as i32, height as i32));
&region_buf
}
};
let (x_mask, y_mask) = slf.dev.phy.queues[tt].transfer_granularity_mask;
let rects = &mut *slf.dev.phy.rects.borrow_mut();
rects.clear();
for rect in region.iter() {
let x1 = (rect.x1().max(0) as u32 & !x_mask).min(width);
let y1 = (rect.y1().max(0) as u32 & !y_mask).min(height);
let x2 = ((rect.x2().max(0) as u32 + x_mask) & !x_mask).min(width);
let y2 = ((rect.y2().max(0) as u32 + y_mask) & !y_mask).min(height);
let width = x2 - x1;
let height = y2 - y1;
if width == 0 || height == 0 {
continue;
}
rects.push((x1 as i32, y1 as i32, width, height));
}
if rects.is_empty() {
return Ok(None);
}
let begin_info =
CommandBufferBeginInfo::default().flags(CommandBufferUsageFlags::ONE_TIME_SUBMIT);
unsafe {
dev.begin_command_buffer(cmd, &begin_info)
.map_err(CopyDeviceError::BeginCommandBuffer)?;
}
macro_rules! initial_buffer_barriers {
($($buf:expr, $access:expr;)*) => {
[$(
BufferMemoryBarrier2::default()
.dst_stage_mask(PipelineStageFlags2::TRANSFER)
.dst_access_mask($access)
.src_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
.dst_queue_family_index(queue_family)
.buffer($buf.buf)
.size(WHOLE_SIZE),
)*]
};
}
macro_rules! final_buffer_barriers {
($($buf:expr, $access:expr;)*) => {
[$(
BufferMemoryBarrier2::default()
.src_stage_mask(PipelineStageFlags2::TRANSFER)
.src_access_mask($access)
.src_queue_family_index(queue_family)
.dst_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
.buffer($buf.buf)
.size(WHOLE_SIZE),
)*]
};
}
let image_subresource_range = ImageSubresourceRange {
aspect_mask: ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
};
let image_subresource = ImageSubresourceLayers {
aspect_mask: ImageAspectFlags::COLOR,
mip_level: 0,
base_array_layer: 0,
layer_count: 1,
};
macro_rules! initial_image_barriers {
($($img:expr, $layout:expr, $access:expr;)*) => {
[$(
ImageMemoryBarrier2::default()
.dst_stage_mask(PipelineStageFlags2::TRANSFER)
.dst_access_mask($access)
.old_layout(ImageLayout::GENERAL)
.new_layout(ImageLayout::GENERAL)
.src_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
.dst_queue_family_index(queue_family)
.image($img.img)
.subresource_range(image_subresource_range),
ImageMemoryBarrier2::default()
.src_stage_mask(PipelineStageFlags2::TRANSFER)
.src_access_mask($access)
.dst_stage_mask(PipelineStageFlags2::TRANSFER)
.dst_access_mask($access)
.old_layout(ImageLayout::GENERAL)
.new_layout($layout)
.src_queue_family_index(queue_family)
.dst_queue_family_index(queue_family)
.image($img.img)
.subresource_range(image_subresource_range),
)*]
};
}
macro_rules! final_image_barriers {
($($img:expr, $layout:expr, $access:expr;)*) => {
[$(
ImageMemoryBarrier2::default()
.src_stage_mask(PipelineStageFlags2::TRANSFER)
.src_access_mask($access)
.dst_stage_mask(PipelineStageFlags2::TRANSFER)
.dst_access_mask($access)
.old_layout($layout)
.new_layout(ImageLayout::GENERAL)
.src_queue_family_index(queue_family)
.dst_queue_family_index(queue_family)
.image($img.img)
.subresource_range(image_subresource_range),
ImageMemoryBarrier2::default()
.src_stage_mask(PipelineStageFlags2::TRANSFER)
.src_access_mask($access)
.old_layout(ImageLayout::GENERAL)
.new_layout(ImageLayout::GENERAL)
.src_queue_family_index(queue_family)
.dst_queue_family_index(QUEUE_FAMILY_FOREIGN_EXT)
.image($img.img)
.subresource_range(image_subresource_range),
)*]
};
}
match &slf.ty {
CopyDeviceCopyType::BufferToBuffer {
src,
dst,
stride,
bpp,
} => {
let regions = &mut *slf.dev.phy.buffer_copy_2.borrow_mut();
regions.clear();
let stride = *stride as u64;
let bpp = *bpp as u64;
for &mut (x, y, width, height) in rects {
let lo = y as u64 * stride + x as u64 * bpp;
let size = (height as u64 - 1) * stride + width as u64 * bpp;
let region = BufferCopy2::default()
.src_offset(lo)
.dst_offset(lo)
.size(size);
regions.push(region);
}
use AccessFlags2 as A;
let initial_barriers = initial_buffer_barriers![
src, A::TRANSFER_READ;
dst, A::TRANSFER_WRITE;
];
let final_barriers = final_buffer_barriers![
src, A::TRANSFER_READ;
dst, A::TRANSFER_WRITE;
];
let initial_dependency_info =
DependencyInfo::default().buffer_memory_barriers(&initial_barriers);
let final_dependency_info =
DependencyInfo::default().buffer_memory_barriers(&final_barriers);
let copy_buffer_info = CopyBufferInfo2::default()
.src_buffer(src.buf)
.dst_buffer(dst.buf)
.regions(regions);
unsafe {
dev.cmd_pipeline_barrier2(cmd, &initial_dependency_info);
dev.cmd_copy_buffer2(cmd, &copy_buffer_info);
dev.cmd_pipeline_barrier2(cmd, &final_dependency_info);
}
}
CopyDeviceCopyType::BufferToImage {
buf,
buf_format,
buf_stride,
img,
}
| CopyDeviceCopyType::ImageToBuffer {
img,
buf,
buf_format,
buf_stride,
} => {
let regions = &mut *slf.dev.phy.buffer_image_copy_2.borrow_mut();
regions.clear();
for &mut (x, y, width, height) in rects {
let offset = y as u64 * *buf_stride as u64 + x as u64 * buf_format.bpp as u64;
let region = BufferImageCopy2::default()
.buffer_offset(offset)
.buffer_row_length(*buf_stride / buf_format.bpp)
.buffer_image_height(slf.height)
.image_subresource(image_subresource)
.image_offset(Offset3D { x, y, z: 0 })
.image_extent(Extent3D {
width,
height,
depth: 1,
});
regions.push(region);
}
let buffer_to_image = match &slf.ty {
CopyDeviceCopyType::BufferToImage { .. } => true,
CopyDeviceCopyType::ImageToBuffer { .. } => false,
_ => unreachable!(),
};
let image_access_mask;
let image_layout;
let buffer_access_mask;
match buffer_to_image {
true => {
image_access_mask = AccessFlags2::TRANSFER_WRITE;
image_layout = ImageLayout::TRANSFER_DST_OPTIMAL;
buffer_access_mask = AccessFlags2::TRANSFER_READ;
}
false => {
image_access_mask = AccessFlags2::TRANSFER_READ;
image_layout = ImageLayout::TRANSFER_SRC_OPTIMAL;
buffer_access_mask = AccessFlags2::TRANSFER_WRITE;
}
}
let initial_image_barriers = initial_image_barriers![
img, image_layout, image_access_mask;
];
let final_image_barriers = final_image_barriers![
img, image_layout, image_access_mask;
];
let initial_buffer_barriers = initial_buffer_barriers![
buf, buffer_access_mask;
];
let final_buffer_barriers = final_buffer_barriers![
buf, buffer_access_mask;
];
let initial_dependency_info = DependencyInfo::default()
.buffer_memory_barriers(&initial_buffer_barriers)
.image_memory_barriers(&initial_image_barriers);
let final_dependency_info = DependencyInfo::default()
.buffer_memory_barriers(&final_buffer_barriers)
.image_memory_barriers(&final_image_barriers);
unsafe {
dev.cmd_pipeline_barrier2(cmd, &initial_dependency_info);
match buffer_to_image {
true => {
let copy = CopyBufferToImageInfo2::default()
.src_buffer(buf.buf)
.dst_image(img.img)
.dst_image_layout(image_layout)
.regions(&regions);
dev.cmd_copy_buffer_to_image2(cmd, &copy);
}
false => {
let copy = CopyImageToBufferInfo2::default()
.src_image(img.img)
.src_image_layout(image_layout)
.dst_buffer(buf.buf)
.regions(&regions);
dev.cmd_copy_image_to_buffer2(cmd, &copy);
}
}
dev.cmd_pipeline_barrier2(cmd, &final_dependency_info);
}
}
CopyDeviceCopyType::ImageToImage { src, dst } => {
let regions = &mut *slf.dev.phy.image_copy_2.borrow_mut();
regions.clear();
for &mut (x, y, width, height) in rects {
let region = ImageCopy2::default()
.src_subresource(image_subresource)
.src_offset(Offset3D { x, y, z: 0 })
.dst_subresource(image_subresource)
.dst_offset(Offset3D { x, y, z: 0 })
.extent(Extent3D {
width,
height,
depth: 1,
});
regions.push(region);
}
use {AccessFlags2 as A, ImageLayout as L};
let initial_barriers = initial_image_barriers![
src, L::TRANSFER_SRC_OPTIMAL, A::TRANSFER_READ;
dst, L::TRANSFER_DST_OPTIMAL, A::TRANSFER_WRITE;
];
let final_barriers = final_image_barriers![
src, L::TRANSFER_SRC_OPTIMAL, A::TRANSFER_READ;
dst, L::TRANSFER_DST_OPTIMAL, A::TRANSFER_WRITE;
];
let initial_dependency_info =
DependencyInfo::default().image_memory_barriers(&initial_barriers);
let final_dependency_info =
DependencyInfo::default().image_memory_barriers(&final_barriers);
let copy_image_info = CopyImageInfo2::default()
.src_image(src.img)
.src_image_layout(L::TRANSFER_SRC_OPTIMAL)
.dst_image(dst.img)
.dst_image_layout(L::TRANSFER_DST_OPTIMAL)
.regions(regions);
unsafe {
dev.cmd_pipeline_barrier2(cmd, &initial_dependency_info);
dev.cmd_copy_image2(cmd, &copy_image_info);
dev.cmd_pipeline_barrier2(cmd, &final_dependency_info);
}
}
CopyDeviceCopyType::Blit { src, dst } => {
let regions = &mut *slf.dev.phy.image_blit_2.borrow_mut();
regions.clear();
for &mut (x, y, width, height) in rects {
let x1 = x;
let y1 = y;
let x2 = x1 + width as i32;
let y2 = y1 + height as i32;
let offsets = [
Offset3D { x: x1, y: y1, z: 0 },
Offset3D { x: x2, y: y2, z: 1 },
];
let region = ImageBlit2::default()
.src_subresource(image_subresource)
.src_offsets(offsets)
.dst_subresource(image_subresource)
.dst_offsets(offsets);
regions.push(region);
}
use {AccessFlags2 as A, ImageLayout as L};
let initial_barriers = initial_image_barriers![
src, L::TRANSFER_SRC_OPTIMAL, A::TRANSFER_READ;
dst, L::TRANSFER_DST_OPTIMAL, A::TRANSFER_WRITE;
];
let final_barriers = final_image_barriers![
src, L::TRANSFER_SRC_OPTIMAL, A::TRANSFER_READ;
dst, L::TRANSFER_DST_OPTIMAL, A::TRANSFER_WRITE;
];
let initial_dependency_info =
DependencyInfo::default().image_memory_barriers(&initial_barriers);
let final_dependency_info =
DependencyInfo::default().image_memory_barriers(&final_barriers);
let blit_image_info = BlitImageInfo2::default()
.src_image(src.img)
.src_image_layout(L::TRANSFER_SRC_OPTIMAL)
.dst_image(dst.img)
.dst_image_layout(L::TRANSFER_DST_OPTIMAL)
.regions(regions)
.filter(Filter::NEAREST);
unsafe {
dev.cmd_pipeline_barrier2(cmd, &initial_dependency_info);
dev.cmd_blit_image2(cmd, &blit_image_info);
dev.cmd_pipeline_barrier2(cmd, &final_dependency_info);
}
}
};
unsafe {
dev.end_command_buffer(cmd)
.map_err(CopyDeviceError::EndCommandBuffer)?;
}
let mut wait_semaphore = None;
let mut wait_semaphores = ArrayVec::<_, 1>::new();
if let Some(sync) = sync
&& let Some(sync_file) = sync.get_sync_file()
{
let semaphore = match slf.dev.semaphores.pop() {
Some(s) => s,
_ => slf.dev.create_semaphore()?,
};
semaphore.import(sync_file)?;
let info = SemaphoreSubmitInfo::default()
.semaphore(semaphore.semaphore)
.stage_mask(PipelineStageFlags2::TRANSFER);
wait_semaphores.push(info);
wait_semaphore = Some(semaphore);
}
let command_buffer_info = CommandBufferSubmitInfo::default().command_buffer(cmd);
let mut semaphore_submit_info = SemaphoreSubmitInfo::default();
let mut submit_info = SubmitInfo2::default()
.command_buffer_infos(slice::from_ref(&command_buffer_info))
.wait_semaphore_infos(&wait_semaphores);
let vulkan_sync = slf.dev.create_sync(
self.dev.timeline_semaphore.as_ref(),
&mut semaphore_submit_info,
&mut submit_info,
)?;
unsafe {
slf.dev
.dev
.queue_submit2(
slf.dev.queues[tt],
slice::from_ref(&submit_info),
vulkan_sync.fence(),
)
.map_err(CopyDeviceError::SubmitCopy)?;
}
let sync = vulkan_sync.to_sync(|| slf.dev.wait_idle());
slf.busy.set(sync.clone());
let pending = Pending {
dev: slf.dev.clone(),
busy_id: slf.busy_id.add_fetch(1),
sync: sync.clone(),
copy: self.inner.clone(),
semaphore: wait_semaphore,
vulkan_sync,
};
slf.dev.submissions[tt].pending.push(pending);
Ok(sync)
}
}
impl VulkanSemaphore {
fn import(&self, sync_file: &OwnedFd) -> Result<(), CopyDeviceError> {
let fd = uapi::fcntl_dupfd_cloexec(sync_file.raw(), 0)
@ -1733,47 +1288,6 @@ impl VulkanSemaphore {
}
}
impl CopyDeviceRegistry {
pub fn new(
ring: &Rc<IoUring>,
eng: &Rc<AsyncEngine>,
eventfd_cache: &Rc<EventfdCache>,
) -> Self {
Self {
ring: ring.clone(),
eng: eng.clone(),
eventfd_cache: eventfd_cache.clone(),
devs: Default::default(),
}
}
pub fn remove(&self, dev: c::dev_t) {
self.devs.remove(&dev);
}
pub fn get(&self, dev: c::dev_t) -> Option<Rc<PhysicalCopyDevice>> {
if let Some(dev) = self.devs.get(&dev) {
return dev;
}
match PhysicalCopyDevice::new(&self.ring, &self.eng, &self.eventfd_cache, dev).map(Some) {
Ok(cd) => {
self.devs.set(dev, cd.clone());
cd
}
Err(e) => {
let maj = uapi::major(dev);
let min = uapi::minor(dev);
log::warn!(
"Could not create physical copy device for {maj}:{min}: {}",
ErrorFmt(e),
);
self.devs.set(dev, None);
None
}
}
}
}
impl Drop for VulkanSemaphore {
fn drop(&mut self) {
unsafe {
@ -1898,125 +1412,6 @@ impl Deref for CopyDevice {
}
}
type QueueInfo = (u32, (u32, u32), u32);
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)
}
impl VulkanDeviceInf for CopyDeviceInner {
fn instance(&self) -> &VulkanCoreInstance {
&self.phy.instance