@@ -686,6 +686,7 @@ impl super::Device {
686
686
super :: Texture {
687
687
raw : vk_image,
688
688
drop_guard,
689
+ external_memory : None ,
689
690
block : None ,
690
691
usage : desc. usage ,
691
692
format : desc. format ,
@@ -695,6 +696,167 @@ impl super::Device {
695
696
}
696
697
}
697
698
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
+
698
860
/// # Safety
699
861
///
700
862
/// - `vk_buffer`'s memory must be managed by the caller
@@ -1028,74 +1190,16 @@ impl crate::Device for super::Device {
1028
1190
& self ,
1029
1191
desc : & crate :: TextureDescriptor ,
1030
1192
) -> 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 ) ?;
1090
1194
1091
1195
let block = unsafe {
1092
1196
self . mem_allocator . lock ( ) . alloc (
1093
1197
& * self . shared ,
1094
1198
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 ,
1097
1201
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 ,
1099
1203
} ,
1100
1204
) ?
1101
1205
} ;
@@ -1105,31 +1209,35 @@ impl crate::Device for super::Device {
1105
1209
unsafe {
1106
1210
self . shared
1107
1211
. raw
1108
- . bind_image_memory ( raw, * block. memory ( ) , block. offset ( ) )
1212
+ . bind_image_memory ( image . raw , * block. memory ( ) , block. offset ( ) )
1109
1213
. map_err ( super :: map_host_device_oom_err) ?
1110
1214
} ;
1111
1215
1112
1216
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) } ;
1114
1218
}
1115
1219
1116
1220
self . counters . textures . add ( 1 ) ;
1117
1221
1118
1222
Ok ( super :: Texture {
1119
- raw,
1223
+ raw : image . raw ,
1120
1224
drop_guard : None ,
1225
+ external_memory : None ,
1121
1226
block : Some ( block) ,
1122
1227
usage : desc. usage ,
1123
1228
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 ,
1127
1232
} )
1128
1233
}
1129
1234
unsafe fn destroy_texture ( & self , texture : super :: Texture ) {
1130
1235
if texture. drop_guard . is_none ( ) {
1131
1236
unsafe { self . shared . raw . destroy_image ( texture. raw , None ) } ;
1132
1237
}
1238
+ if let Some ( memory) = texture. external_memory {
1239
+ unsafe { self . shared . raw . free_memory ( memory, None ) } ;
1240
+ }
1133
1241
if let Some ( block) = texture. block {
1134
1242
self . counters . texture_memory . sub ( block. size ( ) as isize ) ;
1135
1243
@@ -2584,3 +2692,11 @@ impl From<gpu_descriptor::AllocationError> for crate::DeviceError {
2584
2692
fn handle_unexpected ( err : vk:: Result ) -> ! {
2585
2693
panic ! ( "Unexpected Vulkan error: `{err}`" )
2586
2694
}
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