1use ash::vk;
2use gpu_alloc_ash::AshMemoryDevice;
3use std::{mem, ptr};
4
5struct Allocation {
6 memory: vk::DeviceMemory,
7 offset: u64,
8 data: *mut u8,
9 handle: usize,
10 memory_type: crate::Memory,
11}
12
13impl super::Context {
14 fn allocate_memory(
15 &self,
16 requirements: vk::MemoryRequirements,
17 memory: crate::Memory,
18 ) -> Allocation {
19 let mut manager = self.memory.lock().unwrap();
20 let device_address_usage = if self.device.buffer_device_address {
21 gpu_alloc::UsageFlags::DEVICE_ADDRESS
22 } else {
23 gpu_alloc::UsageFlags::empty()
24 };
25 let alloc_usage = match memory {
26 crate::Memory::Device | crate::Memory::External(_) => {
27 gpu_alloc::UsageFlags::FAST_DEVICE_ACCESS | device_address_usage
28 }
29 crate::Memory::Shared => {
30 gpu_alloc::UsageFlags::HOST_ACCESS
31 | gpu_alloc::UsageFlags::DOWNLOAD
32 | gpu_alloc::UsageFlags::UPLOAD
33 | gpu_alloc::UsageFlags::FAST_DEVICE_ACCESS
34 | device_address_usage
35 }
36 crate::Memory::Upload => {
37 gpu_alloc::UsageFlags::HOST_ACCESS | gpu_alloc::UsageFlags::UPLOAD
38 }
39 };
40 let memory_types = requirements.memory_type_bits & manager.valid_ash_memory_types;
41 let mut block = match memory {
42 crate::Memory::External(e) => {
43 let memory_properties = unsafe {
44 self.instance
45 .core
46 .get_physical_device_memory_properties(self.physical_device)
47 };
48 let memory_type_index = memory_types.ilog2();
49 let memory_type: vk::MemoryType =
50 memory_properties.memory_types[memory_type_index as usize];
51
52 let handle_type = external_source_handle_type(e);
53 let external_info: &mut dyn vk::ExtendsMemoryAllocateInfo = match e {
54 #[cfg(target_os = "windows")]
55 crate::ExternalMemorySource::Win32(Some(handle))
56 | crate::ExternalMemorySource::Win32KMT(Some(handle)) => {
57 &mut vk::ImportMemoryWin32HandleInfoKHR {
58 handle_type,
59 handle,
60 ..Default::default()
61 }
62 }
63 #[cfg(not(target_os = "windows"))]
64 crate::ExternalMemorySource::Fd(Some(fd)) => &mut vk::ImportMemoryFdInfoKHR {
65 handle_type,
66 fd,
67 ..Default::default()
68 },
69 #[cfg(target_os = "linux")]
70 crate::ExternalMemorySource::Dma(Some(fd)) => &mut vk::ImportMemoryFdInfoKHR {
71 handle_type,
72 fd,
73 ..Default::default()
74 },
75 crate::ExternalMemorySource::HostAllocation(ptr) => {
76 &mut vk::ImportMemoryHostPointerInfoEXT {
77 handle_type,
78 p_host_pointer: ptr as *mut std::ffi::c_void,
79 ..Default::default()
80 }
81 }
82 _ => &mut vk::ExportMemoryAllocateInfo {
84 handle_types: handle_type,
85 ..Default::default()
86 },
87 };
88
89 let allocation_info = vk::MemoryAllocateInfo {
90 allocation_size: requirements.size,
91 memory_type_index,
92 ..vk::MemoryAllocateInfo::default()
93 }
94 .push_next(external_info);
95
96 let memory = unsafe {
97 self.device
98 .core
99 .allocate_memory(&allocation_info, None)
100 .unwrap()
101 };
102
103 unsafe {
104 manager.allocator.import_memory(
105 memory,
106 memory_type_index,
107 gpu_alloc_ash::memory_properties_from_ash(memory_type.property_flags),
108 0,
109 requirements.size,
110 )
111 }
112 }
113 _ => unsafe {
114 manager
115 .allocator
116 .alloc(
117 AshMemoryDevice::wrap(&self.device.core),
118 gpu_alloc::Request {
119 size: requirements.size,
120 align_mask: requirements.alignment - 1,
121 usage: alloc_usage,
122 memory_types,
123 },
124 )
125 .unwrap()
126 },
127 };
128
129 let data = match memory {
130 crate::Memory::External(crate::ExternalMemorySource::HostAllocation(ptr)) => {
131 ptr as *mut u8
132 }
133 crate::Memory::Device | crate::Memory::External(_) => ptr::null_mut(),
134 crate::Memory::Shared | crate::Memory::Upload => unsafe {
135 block
136 .map(
137 AshMemoryDevice::wrap(&self.device.core),
138 0,
139 requirements.size as usize,
140 )
141 .unwrap()
142 .as_ptr()
143 },
144 };
145 Allocation {
146 memory: *block.memory(),
147 offset: block.offset(),
148 data,
149 handle: manager.slab.insert(block),
150 memory_type: memory,
151 }
152 }
153
154 fn free_memory(&self, handle: usize) {
155 let mut manager = self.memory.lock().unwrap();
156 let block = manager.slab.remove(handle);
157 unsafe {
158 manager
159 .allocator
160 .dealloc(AshMemoryDevice::wrap(&self.device.core), block);
161 }
162 }
163
164 pub fn get_bottom_level_acceleration_structure_sizes(
166 &self,
167 meshes: &[crate::AccelerationStructureMesh],
168 ) -> crate::AccelerationStructureSizes {
169 let blas_input = self.device.map_acceleration_structure_meshes(meshes);
170 let rt = self.device.ray_tracing.as_ref().unwrap();
171 let mut sizes_raw = vk::AccelerationStructureBuildSizesInfoKHR::default();
172 unsafe {
173 rt.acceleration_structure
174 .get_acceleration_structure_build_sizes(
175 vk::AccelerationStructureBuildTypeKHR::DEVICE,
176 &blas_input.build_info,
177 &blas_input.max_primitive_counts,
178 &mut sizes_raw,
179 )
180 };
181 crate::AccelerationStructureSizes {
182 data: sizes_raw.acceleration_structure_size,
183 scratch: sizes_raw.build_scratch_size,
184 }
185 }
186
187 pub fn get_top_level_acceleration_structure_sizes(
188 &self,
189 instance_count: u32,
190 ) -> crate::AccelerationStructureSizes {
191 let geometry = vk::AccelerationStructureGeometryKHR::default()
192 .geometry_type(vk::GeometryTypeKHR::INSTANCES)
193 .geometry(vk::AccelerationStructureGeometryDataKHR {
194 instances: vk::AccelerationStructureGeometryInstancesDataKHR::default(),
195 });
196 let geometries = [geometry];
197 let build_info = vk::AccelerationStructureBuildGeometryInfoKHR::default()
198 .ty(vk::AccelerationStructureTypeKHR::TOP_LEVEL)
199 .mode(vk::BuildAccelerationStructureModeKHR::BUILD)
200 .geometries(&geometries);
201
202 let rt = self.device.ray_tracing.as_ref().unwrap();
203 let mut sizes_raw = vk::AccelerationStructureBuildSizesInfoKHR::default();
204 unsafe {
205 rt.acceleration_structure
206 .get_acceleration_structure_build_sizes(
207 vk::AccelerationStructureBuildTypeKHR::DEVICE,
208 &build_info,
209 &[instance_count],
210 &mut sizes_raw,
211 )
212 };
213 crate::AccelerationStructureSizes {
214 data: sizes_raw.acceleration_structure_size,
215 scratch: sizes_raw.build_scratch_size,
216 }
217 }
218
219 pub fn create_acceleration_structure_instance_buffer(
220 &self,
221 instances: &[crate::AccelerationStructureInstance],
222 bottom_level: &[super::AccelerationStructure],
223 ) -> super::Buffer {
224 let buffer = self.create_buffer(crate::BufferDesc {
225 name: "instance buffer",
226 size: (instances.len().max(1) * mem::size_of::<vk::AccelerationStructureInstanceKHR>())
227 as u64,
228 memory: crate::Memory::Shared,
229 });
230 let rt = self.device.ray_tracing.as_ref().unwrap();
231 for (i, instance) in instances.iter().enumerate() {
232 let device_address_info = vk::AccelerationStructureDeviceAddressInfoKHR {
233 acceleration_structure: bottom_level
234 [instance.acceleration_structure_index as usize]
235 .raw,
236 ..Default::default()
237 };
238 let vk_instance = vk::AccelerationStructureInstanceKHR {
239 transform: unsafe {
240 mem::transmute::<mint::RowMatrix3x4<f32>, vk::TransformMatrixKHR>(
241 instance.transform,
242 )
243 },
244 instance_custom_index_and_mask: vk::Packed24_8::new(
245 instance.custom_index,
246 instance.mask as u8,
247 ),
248 instance_shader_binding_table_record_offset_and_flags: vk::Packed24_8::new(0, 0),
249 acceleration_structure_reference: vk::AccelerationStructureReferenceKHR {
250 device_handle: unsafe {
251 rt.acceleration_structure
252 .get_acceleration_structure_device_address(&device_address_info)
253 },
254 },
255 };
256 unsafe {
257 ptr::write(
258 (buffer.data() as *mut vk::AccelerationStructureInstanceKHR).add(i),
259 vk_instance,
260 );
261 }
262 }
263 buffer
264 }
265
266 pub fn get_external_texture_source(
267 &self,
268 texture: super::Texture,
269 ) -> Option<crate::ExternalMemorySource> {
270 texture.external
271 }
272
273 pub fn get_external_buffer_source(
274 &self,
275 buffer: super::Buffer,
276 ) -> Option<crate::ExternalMemorySource> {
277 buffer.external
278 }
279}
280
281#[hidden_trait::expose]
282impl crate::traits::ResourceDevice for super::Context {
283 type Buffer = super::Buffer;
284 type Texture = super::Texture;
285 type TextureView = super::TextureView;
286 type Sampler = super::Sampler;
287 type AccelerationStructure = super::AccelerationStructure;
288
289 fn create_buffer(&self, desc: crate::BufferDesc) -> super::Buffer {
290 use vk::BufferUsageFlags as Buf;
291 let external_source = match desc.memory {
292 crate::Memory::External(e) => Some(e),
293 _ => None,
294 };
295 let mut external_next = external_source.map(|e| vk::ExternalMemoryBufferCreateInfo {
296 handle_types: external_source_handle_type(e),
297 ..Default::default()
298 });
299 let mut vk_info = vk::BufferCreateInfo {
300 size: desc.size,
301 usage: Buf::TRANSFER_SRC
302 | Buf::TRANSFER_DST
303 | Buf::STORAGE_BUFFER
304 | Buf::INDEX_BUFFER
305 | Buf::VERTEX_BUFFER
306 | Buf::INDIRECT_BUFFER,
307 sharing_mode: vk::SharingMode::EXCLUSIVE,
308 ..Default::default()
309 };
310 if !self.device.inline_uniform_blocks {
311 vk_info.usage |= Buf::UNIFORM_BUFFER;
312 }
313 if let Some(external_next) = external_next.as_mut() {
314 vk_info = vk_info.push_next(external_next);
315 }
316 if self.device.buffer_device_address {
317 vk_info.usage |= Buf::SHADER_DEVICE_ADDRESS;
318 }
319 if self.device.ray_tracing.is_some() {
320 vk_info.usage |= Buf::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR;
321 }
322
323 let raw = unsafe { self.device.core.create_buffer(&vk_info, None).unwrap() };
324 let mut requirements = unsafe { self.device.core.get_buffer_memory_requirements(raw) };
325 requirements.alignment = requirements.alignment.max(self.min_buffer_alignment);
326 let allocation = self.allocate_memory(requirements, desc.memory);
327
328 log::info!(
329 "Creating buffer {:?} of size {}, name '{}', handle {:?}",
330 raw,
331 desc.size,
332 desc.name,
333 allocation.handle
334 );
335 unsafe {
336 self.device
337 .core
338 .bind_buffer_memory(raw, allocation.memory, allocation.offset)
339 .unwrap()
340 };
341 if !desc.name.is_empty() {
342 self.set_object_name(raw, desc.name);
343 }
344
345 super::Buffer {
346 raw,
347 memory_handle: allocation.handle,
348 mapped_data: allocation.data,
349 size: desc.size,
350 external: fetch_external_source(&self.device, allocation),
351 }
352 }
353
354 fn sync_buffer(&self, _buffer: super::Buffer) {}
355
356 fn destroy_buffer(&self, buffer: super::Buffer) {
357 log::info!(
358 "Destroying buffer {:?}, handle {:?}",
359 buffer.raw,
360 buffer.memory_handle
361 );
362 unsafe { self.device.core.destroy_buffer(buffer.raw, None) };
363 self.free_memory(buffer.memory_handle);
364 }
365
366 fn create_texture(&self, desc: crate::TextureDesc) -> super::Texture {
367 let mut create_flags = vk::ImageCreateFlags::empty();
368 if desc.dimension == crate::TextureDimension::D2
369 && desc.size.depth.is_multiple_of(6)
370 && desc.sample_count == 1
371 && desc.size.width == desc.size.height
372 {
373 create_flags |= vk::ImageCreateFlags::CUBE_COMPATIBLE;
374 }
375 if desc.format.aspects().contains(crate::TexelAspects::DEPTH)
378 && desc.format.aspects().contains(crate::TexelAspects::STENCIL)
379 {
380 create_flags |= vk::ImageCreateFlags::MUTABLE_FORMAT;
381 }
382
383 let mut external_next = desc.external.map(|e| vk::ExternalMemoryImageCreateInfo {
384 handle_types: external_source_handle_type(e),
385 ..Default::default()
386 });
387
388 let mut vk_info = vk::ImageCreateInfo {
389 flags: create_flags,
390 image_type: map_texture_dimension(desc.dimension),
391 format: super::map_texture_format(desc.format),
392 extent: super::map_extent_3d(&desc.size),
393 mip_levels: desc.mip_level_count,
394 array_layers: desc.array_layer_count,
395 samples: vk::SampleCountFlags::from_raw(desc.sample_count),
396 tiling: vk::ImageTiling::OPTIMAL,
397 usage: map_texture_usage(desc.usage, desc.format.aspects()),
398 sharing_mode: vk::SharingMode::EXCLUSIVE,
399 ..Default::default()
400 };
401
402 if let Some(external_next) = external_next.as_mut() {
403 vk_info = vk_info.push_next(external_next);
404 }
405
406 let raw = unsafe { self.device.core.create_image(&vk_info, None).unwrap() };
411 let requirements = unsafe { self.device.core.get_image_memory_requirements(raw) };
412 let allocation = self.allocate_memory(
413 requirements,
414 desc.external
415 .map_or(crate::Memory::Device, crate::Memory::External),
416 );
417
418 log::info!(
419 "Creating texture {:?} of size {} and format {:?}, name '{}', handle {:?}",
420 raw,
421 desc.size,
422 desc.format,
423 desc.name,
424 allocation.handle
425 );
426 unsafe {
427 self.device
428 .core
429 .bind_image_memory(raw, allocation.memory, allocation.offset)
430 .unwrap()
431 };
432 if !desc.name.is_empty() {
433 self.set_object_name(raw, desc.name);
434 }
435
436 super::Texture {
437 raw,
438 memory_handle: allocation.handle,
439 target_size: [desc.size.width as u16, desc.size.height as u16],
440 format: desc.format,
441 external: fetch_external_source(&self.device, allocation),
442 }
443 }
444
445 fn destroy_texture(&self, texture: super::Texture) {
446 log::info!(
447 "Destroying texture {:?}, handle {:?}",
448 texture.raw,
449 texture.memory_handle
450 );
451 unsafe { self.device.core.destroy_image(texture.raw, None) };
452 self.free_memory(texture.memory_handle);
453 }
454
455 fn create_texture_view(
456 &self,
457 texture: super::Texture,
458 desc: crate::TextureViewDesc,
459 ) -> super::TextureView {
460 let aspects = desc.format.aspects();
461 let subresource_range = super::map_subresource_range(desc.subresources, aspects);
462 let vk_info = vk::ImageViewCreateInfo {
463 image: texture.raw,
464 view_type: map_view_dimension(desc.dimension),
465 format: super::map_texture_format(desc.format),
466 subresource_range,
467 ..Default::default()
468 };
469
470 let raw = unsafe { self.device.core.create_image_view(&vk_info, None).unwrap() };
471 if !desc.name.is_empty() {
472 self.set_object_name(raw, desc.name);
473 }
474
475 super::TextureView {
476 raw,
477 target_size: [
478 (texture.target_size[0] >> desc.subresources.base_mip_level).max(1),
479 (texture.target_size[1] >> desc.subresources.base_mip_level).max(1),
480 ],
481 aspects,
482 }
483 }
484
485 fn destroy_texture_view(&self, view: super::TextureView) {
486 unsafe { self.device.core.destroy_image_view(view.raw, None) };
487 }
488
489 fn create_sampler(&self, desc: crate::SamplerDesc) -> super::Sampler {
490 let mut vk_info = vk::SamplerCreateInfo {
491 mag_filter: map_filter_mode(desc.mag_filter),
492 min_filter: map_filter_mode(desc.min_filter),
493 mipmap_mode: map_mip_filter_mode(desc.mipmap_filter),
494 address_mode_u: map_address_mode(desc.address_modes[0]),
495 address_mode_v: map_address_mode(desc.address_modes[1]),
496 address_mode_w: map_address_mode(desc.address_modes[2]),
497 min_lod: desc.lod_min_clamp,
498 max_lod: desc.lod_max_clamp.unwrap_or(vk::LOD_CLAMP_NONE),
499 ..Default::default()
500 };
501
502 if let Some(fun) = desc.compare {
503 vk_info.compare_enable = vk::TRUE;
504 vk_info.compare_op = super::map_comparison(fun);
505 }
506 if desc.anisotropy_clamp > 1 {
507 vk_info.anisotropy_enable = vk::TRUE;
508 vk_info.max_anisotropy = desc.anisotropy_clamp as f32;
509 }
510 if let Some(color) = desc.border_color {
511 vk_info.border_color = map_border_color(color);
512 }
513
514 let raw = unsafe { self.device.core.create_sampler(&vk_info, None).unwrap() };
515 if !desc.name.is_empty() {
516 self.set_object_name(raw, desc.name);
517 }
518
519 super::Sampler { raw }
520 }
521
522 fn destroy_sampler(&self, sampler: super::Sampler) {
523 unsafe { self.device.core.destroy_sampler(sampler.raw, None) };
524 }
525
526 fn create_acceleration_structure(
527 &self,
528 desc: crate::AccelerationStructureDesc,
529 ) -> super::AccelerationStructure {
530 let buffer_info = vk::BufferCreateInfo {
531 size: desc.size,
532 usage: vk::BufferUsageFlags::ACCELERATION_STRUCTURE_STORAGE_KHR
533 | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS,
534 sharing_mode: vk::SharingMode::EXCLUSIVE,
535 ..Default::default()
536 };
537
538 let buffer = unsafe { self.device.core.create_buffer(&buffer_info, None).unwrap() };
539 let requirements = unsafe { self.device.core.get_buffer_memory_requirements(buffer) };
540 let allocation = self.allocate_memory(requirements, crate::Memory::Device);
541
542 unsafe {
543 self.device
544 .core
545 .bind_buffer_memory(buffer, allocation.memory, allocation.offset)
546 .unwrap()
547 };
548
549 let raw_ty = match desc.ty {
550 crate::AccelerationStructureType::TopLevel => {
551 vk::AccelerationStructureTypeKHR::TOP_LEVEL
552 }
553 crate::AccelerationStructureType::BottomLevel => {
554 vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL
555 }
556 };
557 let vk_info = vk::AccelerationStructureCreateInfoKHR {
558 ty: raw_ty,
559 buffer,
560 size: desc.size,
561 ..Default::default()
562 };
563
564 let rt = self.device.ray_tracing.as_ref().unwrap();
565 let raw = unsafe {
566 rt.acceleration_structure
567 .create_acceleration_structure(&vk_info, None)
568 .unwrap()
569 };
570
571 if !desc.name.is_empty() {
572 self.set_object_name(buffer, desc.name);
573 self.set_object_name(raw, desc.name);
574 }
575 super::AccelerationStructure {
576 raw,
577 buffer,
578 memory_handle: allocation.handle,
579 }
580 }
581
582 fn destroy_acceleration_structure(&self, acceleration_structure: super::AccelerationStructure) {
583 let rt = self.device.ray_tracing.as_ref().unwrap();
584 unsafe {
585 rt.acceleration_structure
586 .destroy_acceleration_structure(acceleration_structure.raw, None);
587 self.device
588 .core
589 .destroy_buffer(acceleration_structure.buffer, None);
590 }
591 self.free_memory(acceleration_structure.memory_handle);
592 }
593}
594
595fn map_texture_dimension(dimension: crate::TextureDimension) -> vk::ImageType {
596 match dimension {
597 crate::TextureDimension::D1 => vk::ImageType::TYPE_1D,
598 crate::TextureDimension::D2 => vk::ImageType::TYPE_2D,
599 crate::TextureDimension::D3 => vk::ImageType::TYPE_3D,
600 }
601}
602
603fn map_view_dimension(dimension: crate::ViewDimension) -> vk::ImageViewType {
604 use crate::ViewDimension as Vd;
605 match dimension {
606 Vd::D1 => vk::ImageViewType::TYPE_1D,
607 Vd::D1Array => vk::ImageViewType::TYPE_1D_ARRAY,
608 Vd::D2 => vk::ImageViewType::TYPE_2D,
609 Vd::D2Array => vk::ImageViewType::TYPE_2D_ARRAY,
610 Vd::Cube => vk::ImageViewType::CUBE,
611 Vd::CubeArray => vk::ImageViewType::CUBE_ARRAY,
612 Vd::D3 => vk::ImageViewType::TYPE_3D,
613 }
614}
615
616pub(super) fn map_texture_usage(
617 usage: crate::TextureUsage,
618 aspects: crate::TexelAspects,
619) -> vk::ImageUsageFlags {
620 use vk::ImageUsageFlags as Iuf;
621
622 let mut flags = Iuf::empty();
623 if usage.contains(crate::TextureUsage::COPY) {
624 flags |= Iuf::TRANSFER_SRC | Iuf::TRANSFER_DST;
625 }
626 if usage.contains(crate::TextureUsage::RESOURCE) {
627 flags |= vk::ImageUsageFlags::SAMPLED;
628 }
629 if usage.contains(crate::TextureUsage::TARGET) {
630 flags |= if aspects.contains(crate::TexelAspects::COLOR) {
631 vk::ImageUsageFlags::COLOR_ATTACHMENT
632 } else {
633 vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT
634 };
635 }
636 if usage.intersects(crate::TextureUsage::STORAGE) {
637 flags |= vk::ImageUsageFlags::STORAGE;
638 }
639 flags
640}
641
642fn map_filter_mode(mode: crate::FilterMode) -> vk::Filter {
643 match mode {
644 crate::FilterMode::Nearest => vk::Filter::NEAREST,
645 crate::FilterMode::Linear => vk::Filter::LINEAR,
646 }
647}
648
649fn map_mip_filter_mode(mode: crate::FilterMode) -> vk::SamplerMipmapMode {
650 match mode {
651 crate::FilterMode::Nearest => vk::SamplerMipmapMode::NEAREST,
652 crate::FilterMode::Linear => vk::SamplerMipmapMode::LINEAR,
653 }
654}
655
656fn map_address_mode(mode: crate::AddressMode) -> vk::SamplerAddressMode {
657 match mode {
658 crate::AddressMode::ClampToEdge => vk::SamplerAddressMode::CLAMP_TO_EDGE,
659 crate::AddressMode::Repeat => vk::SamplerAddressMode::REPEAT,
660 crate::AddressMode::MirrorRepeat => vk::SamplerAddressMode::MIRRORED_REPEAT,
661 crate::AddressMode::ClampToBorder => vk::SamplerAddressMode::CLAMP_TO_BORDER,
662 }
664}
665
666fn map_border_color(border_color: crate::TextureColor) -> vk::BorderColor {
667 match border_color {
668 crate::TextureColor::TransparentBlack => vk::BorderColor::FLOAT_TRANSPARENT_BLACK,
669 crate::TextureColor::OpaqueBlack => vk::BorderColor::FLOAT_OPAQUE_BLACK,
670 crate::TextureColor::White => vk::BorderColor::FLOAT_OPAQUE_WHITE,
671 }
672}
673
674fn external_source_handle_type(
675 source: crate::ExternalMemorySource,
676) -> vk::ExternalMemoryHandleTypeFlags {
677 match source {
678 #[cfg(target_os = "windows")]
679 crate::ExternalMemorySource::Win32(_) => vk::ExternalMemoryHandleTypeFlags::OPAQUE_WIN32,
680 #[cfg(target_os = "windows")]
681 crate::ExternalMemorySource::Win32KMT(_) => {
682 vk::ExternalMemoryHandleTypeFlags::OPAQUE_WIN32_KMT
683 }
684 #[cfg(not(target_os = "windows"))]
685 crate::ExternalMemorySource::Fd(_) => vk::ExternalMemoryHandleTypeFlags::OPAQUE_FD,
686 #[cfg(target_os = "linux")]
687 crate::ExternalMemorySource::Dma(_) => vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT,
688 crate::ExternalMemorySource::HostAllocation(_) => {
689 vk::ExternalMemoryHandleTypeFlags::HOST_ALLOCATION_EXT
690 }
691 }
692}
693
694fn fetch_external_source(
695 device: &super::Device,
696 allocation: Allocation,
697) -> Option<crate::ExternalMemorySource> {
698 match allocation.memory_type {
699 crate::Memory::External(e) => {
700 let device = device
701 .external_memory
702 .as_ref()
703 .expect("External memory is not supported");
704 let memory = allocation.memory;
705 let handle_type = external_source_handle_type(e);
706
707 Some(match e {
708 #[cfg(target_os = "windows")]
709 crate::ExternalMemorySource::Win32KMT(None)
710 | crate::ExternalMemorySource::Win32(None) => {
711 let info = vk::MemoryGetWin32HandleInfoKHR {
712 memory,
713 handle_type,
714 ..vk::MemoryGetWin32HandleInfoKHR::default()
715 };
716
717 let handle = unsafe { device.get_memory_win32_handle(&info).unwrap() };
718 match e {
719 crate::ExternalMemorySource::Win32(_) => {
720 crate::ExternalMemorySource::Win32(Some(handle))
721 }
722 crate::ExternalMemorySource::Win32KMT(_) => {
723 crate::ExternalMemorySource::Win32KMT(Some(handle))
724 }
725 _ => unreachable!(),
726 }
727 }
728 #[cfg(not(target_os = "windows"))]
729 crate::ExternalMemorySource::Fd(None) => {
730 let info = vk::MemoryGetFdInfoKHR {
731 memory,
732 handle_type,
733 ..vk::MemoryGetFdInfoKHR::default()
734 };
735
736 let handle = unsafe { device.get_memory_fd(&info).unwrap() };
737 crate::ExternalMemorySource::Fd(Some(handle))
738 }
739 #[cfg(target_os = "linux")]
740 crate::ExternalMemorySource::Dma(None) => {
741 let info = vk::MemoryGetFdInfoKHR {
742 memory,
743 handle_type,
744 ..vk::MemoryGetFdInfoKHR::default()
745 };
746
747 let handle = unsafe { device.get_memory_fd(&info).unwrap() };
748 crate::ExternalMemorySource::Dma(Some(handle))
749 }
750
751 _ => e,
753 })
754 }
755 _ => None,
756 }
757}