Skip to main content

mev/vulkan/
instance.rs

1use std::{
2    alloc::Layout,
3    convert::identity,
4    ffi::{c_void, CStr},
5    fmt,
6    sync::Arc,
7};
8
9use ash::*;
10use hashbrown::HashMap;
11
12use crate::{
13    generic::{
14        Capabilities, DeviceCapabilities, DeviceDesc, FamilyCapabilities, Features, OutOfMemory,
15    },
16    DeviceError,
17};
18
19use super::{device::Device, from::*, handle_host_oom, unexpected_error, Queue, Version};
20
21macro_rules! extension_name {
22    ($name:literal) => {
23        str::as_ptr(concat!($name, "\0")) as *const i8
24    };
25}
26
27pub(super) struct InstanceGuard {
28    entry: ash::Entry,
29    instance: ash::Instance,
30}
31
32impl Drop for InstanceGuard {
33    fn drop(&mut self) {
34        unsafe {
35            self.instance.destroy_instance(None);
36        }
37    }
38}
39
40pub struct Instance {
41    guard: Arc<InstanceGuard>,
42    version: Version,
43    instance: ash::Instance,
44    devices: Vec<vk::PhysicalDevice>,
45    capabilities: Capabilities,
46
47    // # Extensions
48    get_physical_device_properties2: Option<ash::khr::get_physical_device_properties2::Instance>,
49
50    #[cfg(any(debug_assertions, feature = "debug"))]
51    debug_utils: Option<ash::ext::debug_utils::Instance>,
52
53    surface: Option<ash::khr::surface::Instance>,
54
55    #[cfg(target_os = "windows")]
56    win32_surface: Option<ash::khr::win32_surface::Instance>,
57}
58
59impl fmt::Debug for Instance {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        f.debug_struct("Instance")
62            .field("version", &self.version)
63            .field("instance", &self.instance.handle())
64            .field("devices", &self.devices)
65            .field("capabilities", &self.capabilities)
66            .finish()
67    }
68}
69
70unsafe fn find_layer<'a>(
71    layers: &'a [vk::LayerProperties],
72    name: &str,
73) -> Option<&'a vk::LayerProperties> {
74    layers.iter().find(|layer| unsafe {
75        CStr::from_ptr(layer.layer_name.as_ptr()).to_bytes() == name.as_bytes()
76    })
77}
78
79unsafe fn find_extension<'a>(
80    extensions: &'a [vk::ExtensionProperties],
81    name: &str,
82) -> Option<&'a vk::ExtensionProperties> {
83    extensions.iter().find(|extension| unsafe {
84        CStr::from_ptr(extension.extension_name.as_ptr()).to_bytes() == name.as_bytes()
85    })
86}
87
88fn engine_version() -> u32 {
89    let major = env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap();
90    let minor = env!("CARGO_PKG_VERSION_MINOR").parse().unwrap();
91    let patch = env!("CARGO_PKG_VERSION_PATCH").parse().unwrap();
92    vk::make_api_version(0, major, minor, patch)
93}
94
95impl Instance {
96    pub fn load() -> Result<Self, DeviceError> {
97        // Load the Vulkan entry points.
98
99        // SAFETY:
100        // This call is unsafe and cannot be made completely safe.
101        // It loads dynamic library and some function pointers.
102        // The library must behave correctly in order for the rest of the code to be safe.
103        let entry = unsafe { Entry::load() }.map_err(|err| {
104            tracing::error!("Vulkan entry load error: {err}");
105            DeviceError::DeviceLost
106        })?;
107
108        // Collect instance layers and extensions.
109
110        let layers =
111            unsafe { entry.enumerate_instance_layer_properties() }.map_err(|err| match err {
112                vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
113                vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => DeviceError::OutOfMemory,
114                err => unexpected_error(err),
115            })?;
116
117        let mut enabled_layer_names = Vec::new();
118
119        let extensions = unsafe { entry.enumerate_instance_extension_properties(None) }.map_err(
120            |err| match err {
121                vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
122                vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => DeviceError::OutOfMemory,
123                vk::Result::ERROR_LAYER_NOT_PRESENT => unreachable!("No layer specified"),
124                err => unexpected_error(err),
125            },
126        )?;
127
128        // Enable layers and instance extensions.
129
130        let mut enabled_extension_names = Vec::new();
131
132        #[cfg(any(debug_assertions, feature = "debug"))]
133        if let Some(layer) = unsafe { find_layer(&layers, "VK_LAYER_KHRONOS_validation") } {
134            enabled_layer_names.push(layer.layer_name.as_ptr());
135        }
136
137        #[cfg(any(debug_assertions, feature = "debug"))]
138        let mut has_debug_utils = false;
139
140        #[cfg(any(debug_assertions, feature = "debug"))]
141        if let Some(extension) = unsafe { find_extension(&extensions, "VK_EXT_debug_utils") } {
142            enabled_extension_names.push(extension.extension_name.as_ptr());
143            has_debug_utils = true;
144        }
145
146        let mut has_surface = false;
147        if let Some(surface_extension) = unsafe { find_extension(&extensions, "VK_KHR_surface") } {
148            #[cfg(target_os = "windows")]
149            let name = "VK_KHR_win32_surface";
150
151            if let Some(platform_extension) = unsafe { find_extension(&extensions, name) } {
152                has_surface = true;
153                enabled_extension_names.push(surface_extension.extension_name.as_ptr());
154                enabled_extension_names.push(platform_extension.extension_name.as_ptr());
155
156                if let Some(surface_maintenance1) =
157                    unsafe { find_extension(&extensions, "VK_EXT_surface_maintenance1") }
158                {
159                    enabled_extension_names.push(surface_maintenance1.extension_name.as_ptr());
160                }
161            }
162        }
163
164        // Choose latest Vulkan version.
165
166        let api_version = unsafe { entry.try_enumerate_instance_version() }
167            .map_err(|err| match err {
168                vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
169                _ => unreachable!(),
170            })
171            .unwrap_or_else(identity)
172            .unwrap_or(vk::make_api_version(0, 1, 0, 0));
173
174        let version = Version {
175            major: vk::api_version_major(api_version),
176            minor: vk::api_version_minor(api_version),
177            patch: vk::api_version_patch(api_version),
178        };
179
180        let mut has_physical_device_properties2 = false;
181        if version < Version::V1_1 {
182            if let Some(extension) =
183                unsafe { find_extension(&extensions, "VK_KHR_get_physical_device_properties2") }
184            {
185                has_physical_device_properties2 = true;
186                enabled_extension_names.push(extension.extension_name.as_ptr());
187            }
188        }
189
190        // Create the Vulkan instance.
191
192        let result = unsafe {
193            entry.create_instance(
194                &vk::InstanceCreateInfo::default()
195                    .application_info(
196                        &vk::ApplicationInfo::default()
197                            .api_version(api_version)
198                            .application_version(0)
199                            .engine_name(CStr::from_bytes_with_nul(b"nothing-engine\0").unwrap())
200                            .engine_version(engine_version()),
201                    )
202                    .enabled_layer_names(&enabled_layer_names)
203                    .enabled_extension_names(&enabled_extension_names)
204                    .push_next(
205                        &mut vk::DebugUtilsMessengerCreateInfoEXT::default()
206                            .message_severity(vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE)
207                            .message_type(
208                                vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
209                                    | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
210                                    | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
211                            )
212                            .pfn_user_callback(Some(vulkan_debug_callback))
213                            .user_data(std::ptr::null_mut()),
214                    ),
215                None,
216            )
217        };
218
219        let instance = result.map_err(|err| match err {
220            vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
221            vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => DeviceError::OutOfMemory,
222            vk::Result::ERROR_INITIALIZATION_FAILED => DeviceError::DeviceLost,
223            vk::Result::ERROR_LAYER_NOT_PRESENT => unreachable!("Layers were checked"),
224            vk::Result::ERROR_EXTENSION_NOT_PRESENT => unreachable!("Extensions were checked"),
225            vk::Result::ERROR_INCOMPATIBLE_DRIVER => unreachable!("Version was checked"),
226            err => unexpected_error(err),
227        })?;
228
229        let get_physical_device_properties2 = has_physical_device_properties2
230            .then(|| ash::khr::get_physical_device_properties2::Instance::new(&entry, &instance));
231
232        // Init debug utils extension functions
233
234        #[cfg(any(debug_assertions, feature = "debug"))]
235        let debug_utils =
236            has_debug_utils.then(|| ash::ext::debug_utils::Instance::new(&entry, &instance));
237
238        // Init surface extension functions
239        let mut surface = None;
240
241        #[cfg(target_os = "windows")]
242        let mut win32_surface = None;
243        if has_surface {
244            surface = Some(ash::khr::surface::Instance::new(&entry, &instance));
245
246            #[cfg(target_os = "windows")]
247            {
248                win32_surface = Some(ash::khr::win32_surface::Instance::new(&entry, &instance));
249            }
250        }
251
252        // Collect physical devices
253
254        let devices =
255            unsafe { instance.enumerate_physical_devices() }.map_err(|err| match err {
256                vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
257                vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => DeviceError::OutOfMemory,
258                vk::Result::ERROR_INITIALIZATION_FAILED => DeviceError::DeviceLost,
259                err => unexpected_error(err),
260            })?;
261
262        let mut device_caps = Vec::with_capacity(devices.len());
263
264        for &device in &devices {
265            let result = unsafe { instance.enumerate_device_extension_properties(device) };
266            let extensions = result.map_err(|err| match err {
267                vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
268                vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => DeviceError::OutOfMemory,
269                vk::Result::ERROR_LAYER_NOT_PRESENT => unreachable!("No layer specified"),
270                err => unexpected_error(err),
271            })?;
272
273            let mut features = vk::PhysicalDeviceFeatures2::default();
274            let mut features11 = vk::PhysicalDeviceVulkan11Features::default();
275            let mut features12 = vk::PhysicalDeviceVulkan12Features::default();
276            let mut features13 = vk::PhysicalDeviceVulkan13Features::default();
277
278            if version < Version::V1_1 {
279                if get_physical_device_properties2.is_some() {
280                    unsafe {
281                        instance.get_physical_device_features2(device, &mut features);
282                    }
283                } else {
284                    features.features = unsafe { instance.get_physical_device_features(device) };
285                }
286            } else {
287                if version >= Version::V1_1 {
288                    features = features.push_next(&mut features11);
289                }
290                if version >= Version::V1_2 {
291                    features = features.push_next(&mut features12);
292                }
293                if version >= Version::V1_3 {
294                    features = features.push_next(&mut features13);
295                }
296                unsafe {
297                    instance.get_physical_device_features2(device, &mut features);
298                }
299            }
300
301            if version < Version::V1_1 {
302                if unsafe { find_extension(&extensions, "VK_KHR_descriptor_update_template") }
303                    .is_none()
304                {
305                    // Skip devices that don't support descriptor update templates.
306                    continue;
307                }
308            }
309
310            if features13.dynamic_rendering == 0 {
311                if unsafe { find_extension(&extensions, "VK_KHR_dynamic_rendering") }.is_none() {
312                    // Skip devices that don't support dynamic rendering.
313                    continue;
314                }
315            }
316
317            if features13.inline_uniform_block == 0 {
318                if unsafe { find_extension(&extensions, "VK_EXT_inline_uniform_block") }.is_none() {
319                    // Skip devices that don't support inline uniform blocks.
320                    continue;
321                }
322            }
323
324            // if features13.synchronization2 == 0 {
325            //     if unsafe { find_extension(&extensions, "VK_KHR_synchronization2") }.is_none() {
326            //         // Skip devices that don't support synchronization2.
327            //         continue;
328            //     }
329            // }
330
331            if unsafe { find_extension(&extensions, "VK_KHR_push_descriptor") }.is_none() {
332                // Skip devices that don't support push descriptors.
333                continue;
334            }
335
336            let mut features = Features::empty();
337
338            if has_surface {
339                if unsafe { find_extension(&extensions, "VK_KHR_swapchain") }.is_some() {
340                    features |= Features::SURFACE;
341                }
342            }
343
344            let mut properties = vk::PhysicalDeviceProperties2::default();
345            let mut properties11 = vk::PhysicalDeviceVulkan11Properties::default();
346            let mut properties12 = vk::PhysicalDeviceVulkan12Properties::default();
347            let mut properties13 = vk::PhysicalDeviceVulkan13Properties::default();
348            let mut properties_pd = vk::PhysicalDevicePushDescriptorPropertiesKHR::default();
349
350            if version >= Version::V1_1 || has_physical_device_properties2 {
351                if version >= Version::V1_1 {
352                    properties = properties.push_next(&mut properties11);
353                }
354                if version >= Version::V1_2 {
355                    properties = properties.push_next(&mut properties12);
356                }
357                if version >= Version::V1_3 {
358                    properties = properties.push_next(&mut properties13);
359                }
360
361                properties = properties.push_next(&mut properties_pd);
362
363                unsafe {
364                    instance.get_physical_device_properties2(device, &mut properties);
365                }
366            } else {
367                properties.properties = unsafe { instance.get_physical_device_properties(device) };
368            }
369
370            // let memory = unsafe { instance.get_physical_device_memory_properties(device) };
371
372            let families = if version >= Version::V1_1 {
373                let count =
374                    unsafe { instance.get_physical_device_queue_family_properties2_len(device) };
375                let mut families = vec![vk::QueueFamilyProperties2::default(); count];
376                unsafe {
377                    instance.get_physical_device_queue_family_properties2(device, &mut families);
378                }
379
380                families
381                    .into_iter()
382                    .map(FamilyCapabilities::from_ash)
383                    .collect()
384            } else {
385                let families =
386                    unsafe { instance.get_physical_device_queue_family_properties(device) };
387
388                families
389                    .into_iter()
390                    .map(FamilyCapabilities::from_ash)
391                    .collect()
392            };
393
394            device_caps.push(DeviceCapabilities {
395                features: Features::empty(),
396                families,
397            })
398        }
399
400        // Build instance instance.
401
402        Ok(Instance {
403            version,
404            instance: instance.clone(),
405            guard: Arc::new(InstanceGuard { entry, instance }),
406            devices,
407            capabilities: Capabilities {
408                devices: device_caps,
409            },
410
411            get_physical_device_properties2,
412            #[cfg(any(debug_assertions, feature = "debug"))]
413            debug_utils,
414            surface,
415
416            #[cfg(target_os = "windows")]
417            win32_surface,
418        })
419    }
420}
421
422impl crate::traits::Resource for Instance {}
423
424#[hidden_trait::expose]
425impl crate::traits::Instance for Instance {
426    fn capabilities(&self) -> &Capabilities {
427        &self.capabilities
428    }
429
430    fn new_device(&self, desc: DeviceDesc) -> Result<(Device, Vec<Queue>), DeviceError> {
431        let physical_device = self.devices[desc.idx];
432        let device_caps = &self.capabilities.devices[desc.idx];
433
434        let result = unsafe {
435            self.instance
436                .enumerate_device_extension_properties(physical_device)
437        };
438
439        let extensions = result.map_err(|err| match err {
440            vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
441            vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => DeviceError::OutOfMemory,
442            vk::Result::ERROR_LAYER_NOT_PRESENT => unreachable!("No layer specified"),
443            err => unexpected_error(err),
444        })?;
445
446        // Collect queue create infos
447        // Pre-allocate queue priorities array of enough size
448        let mut priorities = vec![1.0; desc.queues.len()];
449        let mut queue_create_infos = Vec::<vk::DeviceQueueCreateInfo>::new();
450
451        for &family in desc.queues {
452            match queue_create_infos
453                .iter_mut()
454                .find(|info| info.queue_family_index == family)
455            {
456                Some(info) => {
457                    info.queue_count += 1;
458                }
459                None => {
460                    let mut info = vk::DeviceQueueCreateInfo::default();
461                    info.queue_family_index = family;
462                    info.p_queue_priorities = priorities.as_mut_ptr();
463                    info.queue_count = 1;
464                    queue_create_infos.push(info);
465                }
466            }
467        }
468
469        for info in &queue_create_infos {
470            u32::try_from(info.queue_count).expect("Too many queues requested");
471            let family_caps = &device_caps.families[info.queue_family_index as usize];
472            let max_queue_count = family_caps.queue_count;
473            assert!(
474                max_queue_count as u32 >= info.queue_count,
475                "Family {} has {} queues, but {} were requested",
476                info.queue_family_index,
477                max_queue_count,
478                info.queue_count
479            );
480        }
481
482        // Init memory allocator
483        let properties = unsafe {
484            self.instance
485                .get_physical_device_properties(physical_device)
486        };
487
488        let memory_properties = unsafe {
489            self.instance
490                .get_physical_device_memory_properties(physical_device)
491        };
492
493        let allocator = gpu_alloc::GpuAllocator::<_>::new(
494            gpu_alloc::Config::i_am_prototyping(),
495            gpu_alloc::DeviceProperties {
496                max_memory_allocation_count: properties.limits.max_memory_allocation_count,
497                max_memory_allocation_size: u64::max_value(), // FIXME: Can query this information if instance is v1.1
498                non_coherent_atom_size: properties.limits.non_coherent_atom_size,
499                memory_types: memory_properties.memory_types
500                    [..memory_properties.memory_type_count as usize]
501                    .iter()
502                    .map(|memory_type| gpu_alloc::MemoryType {
503                        props: memory_properties_from_ash(memory_type.property_flags),
504                        heap: memory_type.heap_index,
505                    })
506                    .collect(),
507                memory_heaps: memory_properties.memory_heaps
508                    [..memory_properties.memory_heap_count as usize]
509                    .iter()
510                    .map(|&memory_heap| gpu_alloc::MemoryHeap {
511                        size: memory_heap.size,
512                    })
513                    .collect(),
514                buffer_device_address: false,
515            },
516        );
517
518        let mut enabled_extension_names = Vec::new();
519
520        let mut features = vk::PhysicalDeviceFeatures2::default();
521        let mut features11 = vk::PhysicalDeviceVulkan11Features::default();
522        let mut features12 = vk::PhysicalDeviceVulkan12Features::default();
523        let mut features13 = vk::PhysicalDeviceVulkan13Features::default();
524
525        if self.version < Version::V1_1 {
526            enabled_extension_names.push(extension_name!("VK_KHR_descriptor_update_template"));
527        }
528
529        if self.version < Version::V1_3 {
530            // Dynamic rendering is required
531            enabled_extension_names.push(extension_name!("VK_KHR_dynamic_rendering"));
532            enabled_extension_names.push(extension_name!("VK_EXT_inline_uniform_block"));
533            // enabled_extension_names.push(extension_name!("VK_KHR_synchronization2"));
534        } else {
535            features13.dynamic_rendering = 1;
536            features13.inline_uniform_block = 1;
537            // features13.synchronization2 = 1;
538        }
539
540        enabled_extension_names.push(extension_name!("VK_KHR_push_descriptor"));
541
542        let mut has_swapchain_maintenance1 = false;
543        if desc.features.contains(Features::SURFACE) {
544            enabled_extension_names.push(extension_name!("VK_KHR_swapchain"));
545
546            if let Some(extension) =
547                unsafe { find_extension(&extensions, "VK_EXT_swapchain_maintenance1") }
548            {
549                has_swapchain_maintenance1 = true;
550                enabled_extension_names.push(extension.extension_name.as_ptr());
551            }
552        }
553
554        let mut info = vk::DeviceCreateInfo::default()
555            .enabled_extension_names(&enabled_extension_names)
556            .queue_create_infos(&queue_create_infos);
557
558        if self.version < Version::V1_1 {
559            info.p_enabled_features = &features.features;
560        } else {
561            info = info.push_next(&mut features);
562            info = info.push_next(&mut features11);
563
564            if self.version >= Version::V1_2 {
565                info = info.push_next(&mut features12);
566            }
567            if self.version >= Version::V1_3 {
568                info = info.push_next(&mut features13);
569            }
570        }
571
572        let result = unsafe { self.instance.create_device(physical_device, &info, None) };
573
574        let device = result.map_err(|err| match err {
575            vk::Result::ERROR_OUT_OF_HOST_MEMORY => handle_host_oom(),
576            vk::Result::ERROR_OUT_OF_DEVICE_MEMORY => DeviceError::OutOfMemory,
577            vk::Result::ERROR_INITIALIZATION_FAILED => DeviceError::DeviceLost,
578            vk::Result::ERROR_EXTENSION_NOT_PRESENT => unreachable!("Extensions were checked"),
579            vk::Result::ERROR_FEATURE_NOT_PRESENT => unreachable!("Features were checked"),
580            vk::Result::ERROR_TOO_MANY_OBJECTS => DeviceError::DeviceLost,
581            vk::Result::ERROR_DEVICE_LOST => DeviceError::DeviceLost,
582            err => unexpected_error(err),
583        })?;
584
585        let swapchain_maintenance1 = has_swapchain_maintenance1
586            .then(|| ash::ext::swapchain_maintenance1::Device::new(&self.instance, &device));
587
588        let swapchain = desc
589            .features
590            .contains(Features::SURFACE)
591            .then(|| ash::khr::swapchain::Device::new(&self.instance, &device));
592
593        let push_descriptor = ash::khr::push_descriptor::Device::new(&self.instance, &device);
594
595        #[cfg(any(debug_assertions, feature = "debug"))]
596        let debug_utils = self
597            .debug_utils
598            .is_some()
599            .then(|| ash::ext::debug_utils::Device::new(&self.instance, &device));
600
601        let device = Device::new(
602            self.guard.clone(),
603            self.version,
604            self.instance.clone(),
605            physical_device,
606            device,
607            queue_create_infos
608                .iter()
609                .map(|info| info.queue_family_index)
610                .collect(),
611            desc.features,
612            properties,
613            allocator,
614            push_descriptor,
615            self.surface.clone(),
616            #[cfg(target_os = "windows")]
617            self.win32_surface.clone(),
618            swapchain,
619            swapchain_maintenance1,
620            #[cfg(any(debug_assertions, feature = "debug"))]
621            debug_utils,
622        );
623
624        // Collect queues from the device.
625        let mut queues = Vec::new();
626        let mut family_counters = HashMap::new();
627
628        for &family in desc.queues {
629            let counter = family_counters.entry(family).or_insert(0);
630
631            let family_caps = &device_caps.families[family as usize];
632            let queue = unsafe { device.ash().get_device_queue(family, *counter) };
633            *counter += 1;
634
635            queues.push(Queue::new(
636                device.clone(),
637                queue,
638                family_caps.queue_flags,
639                family,
640            ));
641        }
642
643        Ok((device, queues))
644    }
645}
646
647unsafe extern "system" fn vulkan_debug_callback(
648    message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
649    message_types: vk::DebugUtilsMessageTypeFlagsEXT,
650    p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
651    _p_user_data: *mut c_void,
652) -> vk::Bool32 {
653    unsafe { vulkan_debug_callback_impl(message_severity, message_types, p_callback_data) }
654    vk::FALSE
655}
656
657unsafe fn vulkan_debug_callback_impl(
658    message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
659    _message_types: vk::DebugUtilsMessageTypeFlagsEXT,
660    p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
661) {
662    let enabled = match message_severity {
663        vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE => {
664            tracing::event_enabled!(tracing::Level::TRACE)
665        }
666        vk::DebugUtilsMessageSeverityFlagsEXT::INFO => {
667            tracing::event_enabled!(tracing::Level::INFO)
668        }
669        vk::DebugUtilsMessageSeverityFlagsEXT::WARNING => {
670            tracing::event_enabled!(tracing::Level::WARN)
671        }
672        vk::DebugUtilsMessageSeverityFlagsEXT::ERROR => {
673            tracing::event_enabled!(tracing::Level::ERROR)
674        }
675        _ => unreachable!("Unexpected message severity"),
676    };
677    if !enabled {
678        return;
679    }
680
681    let callback_data = unsafe { &*p_callback_data };
682
683    let message_id_name = unsafe { CStr::from_ptr(callback_data.p_message_id_name) }
684        .to_str()
685        .unwrap_or("<Non-UTF8>");
686    let message_id_number = callback_data.message_id_number;
687    let message = unsafe { CStr::from_ptr(callback_data.p_message) }
688        .to_str()
689        .unwrap_or("<Non-UTF8>");
690
691    let objects = (0..callback_data.object_count)
692        .map(|idx| unsafe { &*callback_data.p_objects.add(idx as usize) })
693        .map(|object| {
694            (
695                object.object_type,
696                object.object_handle,
697                unsafe { CStr::from_ptr(object.p_object_name) }
698                    .to_str()
699                    .unwrap_or("<Non-UTF8>"),
700            )
701        })
702        .collect::<Vec<_>>();
703
704    tracing::event!(
705        target: "vulkan",
706        tracing::Level::TRACE,
707        message_id_name,
708        message_id_number,
709        message,
710        objects = ?objects,
711    );
712}
713
714pub fn memory_properties_from_ash(
715    props: vk::MemoryPropertyFlags,
716) -> gpu_alloc::MemoryPropertyFlags {
717    let mut result = gpu_alloc::MemoryPropertyFlags::empty();
718    if props.contains(vk::MemoryPropertyFlags::DEVICE_LOCAL) {
719        result |= gpu_alloc::MemoryPropertyFlags::DEVICE_LOCAL;
720    }
721    if props.contains(vk::MemoryPropertyFlags::HOST_VISIBLE) {
722        result |= gpu_alloc::MemoryPropertyFlags::HOST_VISIBLE;
723    }
724    if props.contains(vk::MemoryPropertyFlags::HOST_COHERENT) {
725        result |= gpu_alloc::MemoryPropertyFlags::HOST_COHERENT;
726    }
727    if props.contains(vk::MemoryPropertyFlags::HOST_CACHED) {
728        result |= gpu_alloc::MemoryPropertyFlags::HOST_CACHED;
729    }
730    if props.contains(vk::MemoryPropertyFlags::LAZILY_ALLOCATED) {
731        result |= gpu_alloc::MemoryPropertyFlags::LAZILY_ALLOCATED;
732    }
733    result
734}