@@ -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
348353impl 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