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 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 let entry = unsafe { Entry::load() }.map_err(|err| {
104 tracing::error!("Vulkan entry load error: {err}");
105 DeviceError::DeviceLost
106 })?;
107
108 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 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 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 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 #[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 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 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 continue;
307 }
308 }
309
310 if features13.dynamic_rendering == 0 {
311 if unsafe { find_extension(&extensions, "VK_KHR_dynamic_rendering") }.is_none() {
312 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 continue;
321 }
322 }
323
324 if unsafe { find_extension(&extensions, "VK_KHR_push_descriptor") }.is_none() {
332 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 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 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 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 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(), 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 enabled_extension_names.push(extension_name!("VK_KHR_dynamic_rendering"));
532 enabled_extension_names.push(extension_name!("VK_EXT_inline_uniform_block"));
533 } else {
535 features13.dynamic_rendering = 1;
536 features13.inline_uniform_block = 1;
537 }
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 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}