Skip to content

Commit b45e6e3

Browse files
committed
Initial steps in external memory for vulkan
1 parent 1ad50b6 commit b45e6e3

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

src/result.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub enum AllocationError {
2020
CastableFormatsRequiresEnhancedBarriers,
2121
#[error("Castable formats require at least `Device12`")]
2222
CastableFormatsRequiresAtLeastDevice12,
23+
24+
#[error("Allocating exportable memory requires the allocator be created with external memory support")]
25+
ExternalMemoryUnsupported,
2326
}
2427

2528
pub type Result<V, E = AllocationError> = ::std::result::Result<V, E>;

src/vulkan/mod.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub struct AllocationCreateDesc<'a> {
4040
pub linear: bool,
4141
/// Determines how this allocation should be managed.
4242
pub allocation_scheme: AllocationScheme,
43+
/// Determines whether the memory should be usable with `VK_KHR_external_memory_fd` or `VK_KHR_external_memory_win32`
44+
pub external_use: bool,
4345
}
4446

4547
/// Wrapper type to only mark a raw pointer [`Send`] + [`Sync`] without having to
@@ -62,6 +64,8 @@ pub struct AllocatorCreateDesc {
6264
pub debug_settings: AllocatorDebugSettings,
6365
pub buffer_device_address: bool,
6466
pub allocation_sizes: AllocationSizes,
67+
/// Whether the device supports the proper external memory extension like `VK_KHR_external_memory_fd`
68+
pub external_memory: bool,
6569
}
6670

6771
/// A piece of allocated memory.
@@ -343,9 +347,11 @@ pub(crate) struct MemoryBlock {
343347
pub(crate) sub_allocator: Box<dyn SubAllocator>,
344348
#[cfg(feature = "visualizer")]
345349
pub(crate) dedicated_allocation: bool,
350+
pub(crate) exportable: bool,
346351
}
347352

348353
impl MemoryBlock {
354+
#[allow(clippy::too_many_arguments, clippy::fn_params_excessive_bools)]
349355
fn new(
350356
device: &ash::Device,
351357
size: u64,
@@ -354,6 +360,7 @@ impl MemoryBlock {
354360
buffer_device_address: bool,
355361
allocation_scheme: AllocationScheme,
356362
requires_personal_block: bool,
363+
exportable: bool,
357364
) -> Result<Self> {
358365
let device_memory = {
359366
let alloc_info = vk::MemoryAllocateInfo::default()
@@ -368,6 +375,20 @@ impl MemoryBlock {
368375
} else {
369376
alloc_info
370377
};
378+
#[cfg(windows)]
379+
let mut export_info = vk::ExportMemoryAllocateInfoKHR::default()
380+
.handle_types(vk::ExternalMemoryHandleTypeFlags::OPAQUE_WIN32_KHR);
381+
#[cfg(all(unix, not(target_vendor = "apple")))]
382+
let mut export_info = vk::ExportMemoryAllocateInfoKHR::default()
383+
.handle_types(vk::ExternalMemoryHandleTypeFlags::OPAQUE_FD_KHR);
384+
385+
// On other platforms you can't create an external capable allocator, so this would be unreachable
386+
#[cfg(any(windows, all(unix, not(target_vendor = "apple"))))]
387+
let alloc_info = if exportable {
388+
alloc_info.push_next(&mut export_info)
389+
} else {
390+
alloc_info
391+
};
371392

372393
// Flag the memory as dedicated if required.
373394
let mut dedicated_memory_info = vk::MemoryDedicatedAllocateInfo::default();
@@ -430,6 +451,7 @@ impl MemoryBlock {
430451
sub_allocator,
431452
#[cfg(feature = "visualizer")]
432453
dedicated_allocation: allocation_scheme != AllocationScheme::GpuAllocatorManaged,
454+
exportable,
433455
})
434456
}
435457

@@ -490,6 +512,7 @@ impl MemoryType {
490512
self.buffer_device_address,
491513
desc.allocation_scheme,
492514
requires_personal_block,
515+
desc.external_use,
493516
)?;
494517

495518
let mut block_index = None;
@@ -541,6 +564,9 @@ impl MemoryType {
541564
let mut empty_block_index = None;
542565
for (mem_block_i, mem_block) in self.memory_blocks.iter_mut().enumerate().rev() {
543566
if let Some(mem_block) = mem_block {
567+
if mem_block.exportable != desc.external_use {
568+
continue;
569+
}
544570
let allocation = mem_block.sub_allocator.allocate(
545571
size,
546572
alignment,
@@ -590,6 +616,7 @@ impl MemoryType {
590616
self.buffer_device_address,
591617
desc.allocation_scheme,
592618
false,
619+
desc.external_use,
593620
)?;
594621

595622
let new_block_index = if let Some(block_index) = empty_block_index {
@@ -684,6 +711,7 @@ pub struct Allocator {
684711
pub(crate) memory_heaps: Vec<vk::MemoryHeap>,
685712
device: ash::Device,
686713
pub(crate) buffer_image_granularity: u64,
714+
pub(crate) external_memory_support: bool,
687715
pub(crate) debug_settings: AllocatorDebugSettings,
688716
allocation_sizes: AllocationSizes,
689717
}
@@ -701,6 +729,12 @@ impl Allocator {
701729
"AllocatorCreateDesc field `physical_device` is null.".into(),
702730
));
703731
}
732+
#[cfg(not(any(windows, all(unix, not(target_vendor = "apple")))))]
733+
if desc.external_memory {
734+
return Err(AllocationError::InvalidAllocatorCreateDesc(
735+
"External memory is enabled but currently only supported on windows and non-apple unix platforms".into(),
736+
));
737+
}
704738

705739
let mem_props = unsafe {
706740
desc.instance
@@ -763,6 +797,7 @@ impl Allocator {
763797
buffer_image_granularity: granularity,
764798
debug_settings: desc.debug_settings,
765799
allocation_sizes: desc.allocation_sizes,
800+
external_memory_support: desc.external_memory,
766801
})
767802
}
768803

@@ -790,6 +825,9 @@ impl Allocator {
790825
if size == 0 || !alignment.is_power_of_two() {
791826
return Err(AllocationError::InvalidAllocationCreateDesc);
792827
}
828+
if desc.external_use && !self.external_memory_support {
829+
return Err(AllocationError::ExternalMemoryUnsupported);
830+
}
793831

794832
let mem_loc_preferred_bits = match desc.location {
795833
MemoryLocation::GpuOnly => vk::MemoryPropertyFlags::DEVICE_LOCAL,

0 commit comments

Comments
 (0)