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