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