@@ -686,6 +686,7 @@ impl super::Device {
686686 super :: Texture {
687687 raw : vk_image,
688688 drop_guard,
689+ external_memory : None ,
689690 block : None ,
690691 usage : desc. usage ,
691692 format : desc. format ,
@@ -695,6 +696,167 @@ impl super::Device {
695696 }
696697 }
697698
699+ #[ cfg( windows) ]
700+ fn find_memory_type_index (
701+ & self ,
702+ type_bits_req : u32 ,
703+ flags_req : vk:: MemoryPropertyFlags ,
704+ ) -> Option < usize > {
705+ let mem_properties = unsafe {
706+ self . shared
707+ . instance
708+ . raw
709+ . get_physical_device_memory_properties ( self . shared . physical_device )
710+ } ;
711+
712+ // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceMemoryProperties.html
713+ for ( i, mem_ty) in mem_properties. memory_types_as_slice ( ) . iter ( ) . enumerate ( ) {
714+ let types_bits = 1 << i;
715+ let is_required_memory_type = type_bits_req & types_bits != 0 ;
716+ let has_required_properties = mem_ty. property_flags & flags_req == flags_req;
717+ if is_required_memory_type && has_required_properties {
718+ return Some ( i) ;
719+ }
720+ }
721+
722+ None
723+ }
724+
725+ fn create_image_without_memory (
726+ & self ,
727+ desc : & crate :: TextureDescriptor ,
728+ external_memory_image_create_info : Option < & mut vk:: ExternalMemoryImageCreateInfo > ,
729+ ) -> Result < ImageWithoutMemory , crate :: DeviceError > {
730+ let copy_size = desc. copy_extent ( ) ;
731+
732+ let mut raw_flags = vk:: ImageCreateFlags :: empty ( ) ;
733+ if desc. is_cube_compatible ( ) {
734+ raw_flags |= vk:: ImageCreateFlags :: CUBE_COMPATIBLE ;
735+ }
736+
737+ let original_format = self . shared . private_caps . map_texture_format ( desc. format ) ;
738+ let mut vk_view_formats = vec ! [ ] ;
739+ let mut wgt_view_formats = vec ! [ ] ;
740+ if !desc. view_formats . is_empty ( ) {
741+ raw_flags |= vk:: ImageCreateFlags :: MUTABLE_FORMAT ;
742+ wgt_view_formats. clone_from ( & desc. view_formats ) ;
743+ wgt_view_formats. push ( desc. format ) ;
744+
745+ if self . shared . private_caps . image_format_list {
746+ vk_view_formats = desc
747+ . view_formats
748+ . iter ( )
749+ . map ( |f| self . shared . private_caps . map_texture_format ( * f) )
750+ . collect ( ) ;
751+ vk_view_formats. push ( original_format)
752+ }
753+ }
754+ if desc. format . is_multi_planar_format ( ) {
755+ raw_flags |= vk:: ImageCreateFlags :: MUTABLE_FORMAT ;
756+ }
757+
758+ let mut vk_info = vk:: ImageCreateInfo :: default ( )
759+ . flags ( raw_flags)
760+ . image_type ( conv:: map_texture_dimension ( desc. dimension ) )
761+ . format ( original_format)
762+ . extent ( conv:: map_copy_extent ( & copy_size) )
763+ . mip_levels ( desc. mip_level_count )
764+ . array_layers ( desc. array_layer_count ( ) )
765+ . samples ( vk:: SampleCountFlags :: from_raw ( desc. sample_count ) )
766+ . tiling ( vk:: ImageTiling :: OPTIMAL )
767+ . usage ( conv:: map_texture_usage ( desc. usage ) )
768+ . sharing_mode ( vk:: SharingMode :: EXCLUSIVE )
769+ . initial_layout ( vk:: ImageLayout :: UNDEFINED ) ;
770+
771+ let mut format_list_info = vk:: ImageFormatListCreateInfo :: default ( ) ;
772+ if !vk_view_formats. is_empty ( ) {
773+ format_list_info = format_list_info. view_formats ( & vk_view_formats) ;
774+ vk_info = vk_info. push_next ( & mut format_list_info) ;
775+ }
776+
777+ if let Some ( ext_info) = external_memory_image_create_info {
778+ vk_info = vk_info. push_next ( ext_info) ;
779+ }
780+
781+ let raw = unsafe { self . shared . raw . create_image ( & vk_info, None ) } . map_err ( map_err) ?;
782+ fn map_err ( err : vk:: Result ) -> crate :: DeviceError {
783+ // We don't use VK_EXT_image_compression_control
784+ // VK_ERROR_COMPRESSION_EXHAUSTED_EXT
785+ super :: map_host_device_oom_and_ioca_err ( err)
786+ }
787+ let req = unsafe { self . shared . raw . get_image_memory_requirements ( raw) } ;
788+
789+ Ok ( ImageWithoutMemory {
790+ raw,
791+ requirements : req,
792+ copy_size,
793+ view_formats : wgt_view_formats,
794+ raw_flags,
795+ } )
796+ }
797+
798+ /// # Safety
799+ ///
800+ /// - Vulkan 1.1+ (or VK_KHR_external_memory)
801+ /// - The `d3d11_shared_handle` must be valid and respecting `desc`
802+ /// - `VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT` flag is used because we need to hold a reference to the handle
803+ #[ cfg( windows) ]
804+ pub unsafe fn texture_from_d3d11_shared_handle (
805+ & self ,
806+ d3d11_shared_handle : windows:: Win32 :: Foundation :: HANDLE ,
807+ desc : & crate :: TextureDescriptor ,
808+ ) -> Result < super :: Texture , crate :: DeviceError > {
809+ if !self . shared . private_caps . external_memory_win32 {
810+ log:: error!( "VK_KHR_external_memory extension is required" ) ;
811+ return Err ( crate :: DeviceError :: ResourceCreationFailed ) ;
812+ }
813+
814+ let mut external_memory_image_info = vk:: ExternalMemoryImageCreateInfo :: default ( )
815+ . handle_types ( vk:: ExternalMemoryHandleTypeFlags :: D3D11_TEXTURE ) ;
816+
817+ let image =
818+ self . create_image_without_memory ( desc, Some ( & mut external_memory_image_info) ) ?;
819+
820+ let mut import_memory_info = vk:: ImportMemoryWin32HandleInfoKHR :: default ( )
821+ . handle_type ( vk:: ExternalMemoryHandleTypeFlags :: D3D11_TEXTURE )
822+ . handle ( d3d11_shared_handle. 0 as _ ) ;
823+
824+ let mem_type_index = self
825+ . find_memory_type_index (
826+ image. requirements . memory_type_bits ,
827+ vk:: MemoryPropertyFlags :: DEVICE_LOCAL ,
828+ )
829+ . ok_or ( crate :: DeviceError :: ResourceCreationFailed ) ?;
830+
831+ let memory_allocate_info = vk:: MemoryAllocateInfo :: default ( )
832+ . allocation_size ( image. requirements . size )
833+ . memory_type_index ( mem_type_index as _ )
834+ . push_next ( & mut import_memory_info) ;
835+ let memory = unsafe { self . shared . raw . allocate_memory ( & memory_allocate_info, None ) }
836+ . map_err ( super :: map_host_device_oom_err) ?;
837+
838+ unsafe { self . shared . raw . bind_image_memory ( image. raw , memory, 0 ) }
839+ . map_err ( super :: map_host_device_oom_err) ?;
840+
841+ if let Some ( label) = desc. label {
842+ unsafe { self . shared . set_object_name ( image. raw , label) } ;
843+ }
844+
845+ self . counters . textures . add ( 1 ) ;
846+
847+ Ok ( super :: Texture {
848+ raw : image. raw ,
849+ drop_guard : None ,
850+ external_memory : Some ( memory) ,
851+ block : None ,
852+ usage : desc. usage ,
853+ format : desc. format ,
854+ raw_flags : image. raw_flags ,
855+ copy_size : image. copy_size ,
856+ view_formats : image. view_formats ,
857+ } )
858+ }
859+
698860 /// # Safety
699861 ///
700862 /// - `vk_buffer`'s memory must be managed by the caller
@@ -1028,74 +1190,16 @@ impl crate::Device for super::Device {
10281190 & self ,
10291191 desc : & crate :: TextureDescriptor ,
10301192 ) -> Result < super :: Texture , crate :: DeviceError > {
1031- let copy_size = desc. copy_extent ( ) ;
1032-
1033- let mut raw_flags = vk:: ImageCreateFlags :: empty ( ) ;
1034- if desc. is_cube_compatible ( ) {
1035- raw_flags |= vk:: ImageCreateFlags :: CUBE_COMPATIBLE ;
1036- }
1037-
1038- let original_format = self . shared . private_caps . map_texture_format ( desc. format ) ;
1039- let mut vk_view_formats = vec ! [ ] ;
1040- let mut wgt_view_formats = vec ! [ ] ;
1041- if !desc. view_formats . is_empty ( ) {
1042- raw_flags |= vk:: ImageCreateFlags :: MUTABLE_FORMAT ;
1043- wgt_view_formats. clone_from ( & desc. view_formats ) ;
1044- wgt_view_formats. push ( desc. format ) ;
1045-
1046- if self . shared . private_caps . image_format_list {
1047- vk_view_formats = desc
1048- . view_formats
1049- . iter ( )
1050- . map ( |f| self . shared . private_caps . map_texture_format ( * f) )
1051- . collect ( ) ;
1052- vk_view_formats. push ( original_format)
1053- }
1054- }
1055- if desc. format . is_multi_planar_format ( ) {
1056- raw_flags |= vk:: ImageCreateFlags :: MUTABLE_FORMAT ;
1057- }
1058-
1059- let mut vk_info = vk:: ImageCreateInfo :: default ( )
1060- . flags ( raw_flags)
1061- . image_type ( conv:: map_texture_dimension ( desc. dimension ) )
1062- . format ( original_format)
1063- . extent ( conv:: map_copy_extent ( & copy_size) )
1064- . mip_levels ( desc. mip_level_count )
1065- . array_layers ( desc. array_layer_count ( ) )
1066- . samples ( vk:: SampleCountFlags :: from_raw ( desc. sample_count ) )
1067- . tiling ( vk:: ImageTiling :: OPTIMAL )
1068- . usage ( conv:: map_texture_usage ( desc. usage ) )
1069- . sharing_mode ( vk:: SharingMode :: EXCLUSIVE )
1070- . initial_layout ( vk:: ImageLayout :: UNDEFINED ) ;
1071-
1072- let mut format_list_info = vk:: ImageFormatListCreateInfo :: default ( ) ;
1073- if !vk_view_formats. is_empty ( ) {
1074- format_list_info = format_list_info. view_formats ( & vk_view_formats) ;
1075- vk_info = vk_info. push_next ( & mut format_list_info) ;
1076- }
1077-
1078- let raw = unsafe {
1079- self . shared
1080- . raw
1081- . create_image ( & vk_info, None )
1082- . map_err ( map_err) ?
1083- } ;
1084- fn map_err ( err : vk:: Result ) -> crate :: DeviceError {
1085- // We don't use VK_EXT_image_compression_control
1086- // VK_ERROR_COMPRESSION_EXHAUSTED_EXT
1087- super :: map_host_device_oom_and_ioca_err ( err)
1088- }
1089- let req = unsafe { self . shared . raw . get_image_memory_requirements ( raw) } ;
1193+ let image = self . create_image_without_memory ( desc, None ) ?;
10901194
10911195 let block = unsafe {
10921196 self . mem_allocator . lock ( ) . alloc (
10931197 & * self . shared ,
10941198 gpu_alloc:: Request {
1095- size : req . size ,
1096- align_mask : req . alignment - 1 ,
1199+ size : image . requirements . size ,
1200+ align_mask : image . requirements . alignment - 1 ,
10971201 usage : gpu_alloc:: UsageFlags :: FAST_DEVICE_ACCESS ,
1098- memory_types : req . memory_type_bits & self . valid_ash_memory_types ,
1202+ memory_types : image . requirements . memory_type_bits & self . valid_ash_memory_types ,
10991203 } ,
11001204 ) ?
11011205 } ;
@@ -1105,31 +1209,35 @@ impl crate::Device for super::Device {
11051209 unsafe {
11061210 self . shared
11071211 . raw
1108- . bind_image_memory ( raw, * block. memory ( ) , block. offset ( ) )
1212+ . bind_image_memory ( image . raw , * block. memory ( ) , block. offset ( ) )
11091213 . map_err ( super :: map_host_device_oom_err) ?
11101214 } ;
11111215
11121216 if let Some ( label) = desc. label {
1113- unsafe { self . shared . set_object_name ( raw, label) } ;
1217+ unsafe { self . shared . set_object_name ( image . raw , label) } ;
11141218 }
11151219
11161220 self . counters . textures . add ( 1 ) ;
11171221
11181222 Ok ( super :: Texture {
1119- raw,
1223+ raw : image . raw ,
11201224 drop_guard : None ,
1225+ external_memory : None ,
11211226 block : Some ( block) ,
11221227 usage : desc. usage ,
11231228 format : desc. format ,
1124- raw_flags,
1125- copy_size,
1126- view_formats : wgt_view_formats ,
1229+ raw_flags : image . raw_flags ,
1230+ copy_size : image . copy_size ,
1231+ view_formats : image . view_formats ,
11271232 } )
11281233 }
11291234 unsafe fn destroy_texture ( & self , texture : super :: Texture ) {
11301235 if texture. drop_guard . is_none ( ) {
11311236 unsafe { self . shared . raw . destroy_image ( texture. raw , None ) } ;
11321237 }
1238+ if let Some ( memory) = texture. external_memory {
1239+ unsafe { self . shared . raw . free_memory ( memory, None ) } ;
1240+ }
11331241 if let Some ( block) = texture. block {
11341242 self . counters . texture_memory . sub ( block. size ( ) as isize ) ;
11351243
@@ -2584,3 +2692,11 @@ impl From<gpu_descriptor::AllocationError> for crate::DeviceError {
25842692fn handle_unexpected ( err : vk:: Result ) -> ! {
25852693 panic ! ( "Unexpected Vulkan error: `{err}`" )
25862694}
2695+
2696+ struct ImageWithoutMemory {
2697+ raw : vk:: Image ,
2698+ requirements : vk:: MemoryRequirements ,
2699+ copy_size : crate :: CopyExtent ,
2700+ view_formats : Vec < wgt:: TextureFormat > ,
2701+ raw_flags : vk:: ImageCreateFlags ,
2702+ }
0 commit comments