Skip to main content

blade_graphics/vulkan/
resource.rs

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                    // All sources that are exporting don't need a specific struct
84                    _ => &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    //TODO: move these into `ResourceDevice` trait when ready
166    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        // Enable mutable format for multi-aspect textures (e.g. depth+stencil)
377        // so that views can select individual aspects with compatible formats.
378        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        /*
408            TODO(ErikWDev): Support lazily allocated texture with transient allocation for efficient msaa?
409                            Measure bandwidth usage!
410        */
411        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        // wgt::AddressMode::MirrorClamp => vk::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE,
664    }
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                //Means its a import, which already knows what its source is
753                _ => e,
754            })
755        }
756        _ => None,
757    }
758}