1use std::{
2 ffi::{c_void, CStr, CString},
3 slice,
4 str::FromStr,
5 sync::Arc,
6 thread,
7};
8
9use arrayvec::ArrayVec;
10use ash::{ext, khr, vk};
11use parking_lot::RwLock;
12
13unsafe extern "system" fn debug_utils_messenger_callback(
14 message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
15 message_type: vk::DebugUtilsMessageTypeFlagsEXT,
16 callback_data_ptr: *const vk::DebugUtilsMessengerCallbackDataEXT,
17 user_data: *mut c_void,
18) -> vk::Bool32 {
19 use std::borrow::Cow;
20
21 if thread::panicking() {
22 return vk::FALSE;
23 }
24
25 let cd = unsafe { &*callback_data_ptr };
26 let user_data = unsafe { &*user_data.cast::<super::DebugUtilsMessengerUserData>() };
27
28 const VUID_VKCMDENDDEBUGUTILSLABELEXT_COMMANDBUFFER_01912: i32 = 0x56146426;
29 if cd.message_id_number == VUID_VKCMDENDDEBUGUTILSLABELEXT_COMMANDBUFFER_01912 {
30 const KHRONOS_VALIDATION_LAYER: &CStr =
34 unsafe { CStr::from_bytes_with_nul_unchecked(b"Khronos Validation Layer\0") };
35 if let Some(layer_properties) = user_data.validation_layer_properties.as_ref() {
36 if layer_properties.layer_description.as_ref() == KHRONOS_VALIDATION_LAYER
37 && layer_properties.layer_spec_version >= vk::make_api_version(0, 1, 3, 240)
38 && layer_properties.layer_spec_version <= vk::make_api_version(0, 1, 3, 250)
39 {
40 return vk::FALSE;
41 }
42 }
43 }
44
45 const VUID_VKSWAPCHAINCREATEINFOKHR_PNEXT_07781: i32 = 0x4c8929c1;
49 if cd.message_id_number == VUID_VKSWAPCHAINCREATEINFOKHR_PNEXT_07781 {
50 return vk::FALSE;
51 }
52
53 const VUID_VKRENDERPASSBEGININFO_FRAMEBUFFER_04627: i32 = 0x45125641;
60 if cd.message_id_number == VUID_VKRENDERPASSBEGININFO_FRAMEBUFFER_04627
61 && user_data.has_obs_layer
62 {
63 return vk::FALSE;
64 }
65
66 let level = match message_severity {
67 vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE => log::Level::Debug,
68 vk::DebugUtilsMessageSeverityFlagsEXT::INFO => log::Level::Info,
69 vk::DebugUtilsMessageSeverityFlagsEXT::WARNING => log::Level::Warn,
70 vk::DebugUtilsMessageSeverityFlagsEXT::ERROR => log::Level::Error,
71 _ => log::Level::Warn,
72 };
73
74 let message_id_name =
75 unsafe { cd.message_id_name_as_c_str() }.map_or(Cow::Borrowed(""), CStr::to_string_lossy);
76 let message = unsafe { cd.message_as_c_str() }.map_or(Cow::Borrowed(""), CStr::to_string_lossy);
77
78 let _ = std::panic::catch_unwind(|| {
79 log::log!(
80 level,
81 "{:?} [{} (0x{:x})]\n\t{}",
82 message_type,
83 message_id_name,
84 cd.message_id_number,
85 message,
86 );
87 });
88
89 if cd.queue_label_count != 0 {
90 let labels =
91 unsafe { slice::from_raw_parts(cd.p_queue_labels, cd.queue_label_count as usize) };
92 let names = labels
93 .iter()
94 .flat_map(|dul_obj| unsafe { dul_obj.label_name_as_c_str() }.map(CStr::to_string_lossy))
95 .collect::<Vec<_>>();
96
97 let _ = std::panic::catch_unwind(|| {
98 log::log!(level, "\tqueues: {}", names.join(", "));
99 });
100 }
101
102 if cd.cmd_buf_label_count != 0 {
103 let labels =
104 unsafe { slice::from_raw_parts(cd.p_cmd_buf_labels, cd.cmd_buf_label_count as usize) };
105 let names = labels
106 .iter()
107 .flat_map(|dul_obj| unsafe { dul_obj.label_name_as_c_str() }.map(CStr::to_string_lossy))
108 .collect::<Vec<_>>();
109
110 let _ = std::panic::catch_unwind(|| {
111 log::log!(level, "\tcommand buffers: {}", names.join(", "));
112 });
113 }
114
115 if cd.object_count != 0 {
116 let labels = unsafe { slice::from_raw_parts(cd.p_objects, cd.object_count as usize) };
117 let names = labels
119 .iter()
120 .map(|obj_info| {
121 let name = unsafe { obj_info.object_name_as_c_str() }
122 .map_or(Cow::Borrowed("?"), CStr::to_string_lossy);
123
124 format!(
125 "(type: {:?}, hndl: 0x{:x}, name: {})",
126 obj_info.object_type, obj_info.object_handle, name
127 )
128 })
129 .collect::<Vec<_>>();
130 let _ = std::panic::catch_unwind(|| {
131 log::log!(level, "\tobjects: {}", names.join(", "));
132 });
133 }
134
135 if cfg!(debug_assertions) && level == log::Level::Error {
136 crate::VALIDATION_CANARY.add(message.to_string());
138 }
139
140 vk::FALSE
141}
142
143impl super::DebugUtilsCreateInfo {
144 fn to_vk_create_info(&self) -> vk::DebugUtilsMessengerCreateInfoEXT<'_> {
145 let user_data_ptr: *const super::DebugUtilsMessengerUserData = &*self.callback_data;
146 vk::DebugUtilsMessengerCreateInfoEXT::default()
147 .message_severity(self.severity)
148 .message_type(self.message_type)
149 .user_data(user_data_ptr as *mut _)
150 .pfn_user_callback(Some(debug_utils_messenger_callback))
151 }
152}
153
154impl super::Swapchain {
155 unsafe fn release_resources(mut self, device: &ash::Device) -> Self {
159 profiling::scope!("Swapchain::release_resources");
160 {
161 profiling::scope!("vkDeviceWaitIdle");
162 let _ = unsafe {
165 device
166 .device_wait_idle()
167 .map_err(super::map_host_device_oom_and_lost_err)
168 };
169 };
170
171 for semaphore in self.surface_semaphores.drain(..) {
173 let arc_removed = Arc::into_inner(semaphore).expect(
174 "Trying to destroy a SurfaceSemaphores that is still in use by a SurfaceTexture",
175 );
176 let mutex_removed = arc_removed.into_inner();
177
178 unsafe { mutex_removed.destroy(device) };
179 }
180
181 self
182 }
183}
184
185impl super::InstanceShared {
186 pub fn entry(&self) -> &ash::Entry {
187 &self.entry
188 }
189
190 pub fn raw_instance(&self) -> &ash::Instance {
191 &self.raw
192 }
193
194 pub fn instance_api_version(&self) -> u32 {
195 self.instance_api_version
196 }
197
198 pub fn extensions(&self) -> &[&'static CStr] {
199 &self.extensions[..]
200 }
201}
202
203impl super::Instance {
204 pub fn shared_instance(&self) -> &super::InstanceShared {
205 &self.shared
206 }
207
208 fn enumerate_instance_extension_properties(
209 entry: &ash::Entry,
210 layer_name: Option<&CStr>,
211 ) -> Result<Vec<vk::ExtensionProperties>, crate::InstanceError> {
212 let instance_extensions = {
213 profiling::scope!("vkEnumerateInstanceExtensionProperties");
214 unsafe { entry.enumerate_instance_extension_properties(layer_name) }
215 };
216 instance_extensions.map_err(|e| {
217 crate::InstanceError::with_source(
218 String::from("enumerate_instance_extension_properties() failed"),
219 e,
220 )
221 })
222 }
223
224 pub fn desired_extensions(
238 entry: &ash::Entry,
239 _instance_api_version: u32,
240 flags: wgt::InstanceFlags,
241 ) -> Result<Vec<&'static CStr>, crate::InstanceError> {
242 let instance_extensions = Self::enumerate_instance_extension_properties(entry, None)?;
243
244 let mut extensions: Vec<&'static CStr> = Vec::new();
246
247 extensions.push(khr::surface::NAME);
249
250 if cfg!(all(
252 unix,
253 not(target_os = "android"),
254 not(target_os = "macos")
255 )) {
256 extensions.push(khr::xlib_surface::NAME);
258 extensions.push(khr::xcb_surface::NAME);
260 extensions.push(khr::wayland_surface::NAME);
262 }
263 if cfg!(target_os = "android") {
264 extensions.push(khr::android_surface::NAME);
266 }
267 if cfg!(target_os = "windows") {
268 extensions.push(khr::win32_surface::NAME);
270 }
271 if cfg!(target_os = "macos") {
272 extensions.push(ext::metal_surface::NAME);
274 extensions.push(khr::portability_enumeration::NAME);
275 }
276
277 if flags.contains(wgt::InstanceFlags::DEBUG) {
278 extensions.push(ext::debug_utils::NAME);
280 }
281
282 extensions.push(ext::swapchain_colorspace::NAME);
285
286 extensions.push(khr::get_physical_device_properties2::NAME);
290
291 extensions.retain(|&ext| {
293 if instance_extensions
294 .iter()
295 .any(|inst_ext| inst_ext.extension_name_as_c_str() == Ok(ext))
296 {
297 true
298 } else {
299 log::warn!("Unable to find extension: {}", ext.to_string_lossy());
300 false
301 }
302 });
303 Ok(extensions)
304 }
305
306 #[allow(clippy::too_many_arguments)]
319 pub unsafe fn from_raw(
320 entry: ash::Entry,
321 raw_instance: ash::Instance,
322 instance_api_version: u32,
323 android_sdk_version: u32,
324 debug_utils_create_info: Option<super::DebugUtilsCreateInfo>,
325 extensions: Vec<&'static CStr>,
326 flags: wgt::InstanceFlags,
327 has_nv_optimus: bool,
328 drop_callback: Option<crate::DropCallback>,
329 ) -> Result<Self, crate::InstanceError> {
330 log::debug!("Instance version: 0x{:x}", instance_api_version);
331
332 let debug_utils = if let Some(debug_utils_create_info) = debug_utils_create_info {
333 if extensions.contains(&ext::debug_utils::NAME) {
334 log::info!("Enabling debug utils");
335
336 let extension = ext::debug_utils::Instance::new(&entry, &raw_instance);
337 let vk_info = debug_utils_create_info.to_vk_create_info();
338 let messenger =
339 unsafe { extension.create_debug_utils_messenger(&vk_info, None) }.unwrap();
340
341 Some(super::DebugUtils {
342 extension,
343 messenger,
344 callback_data: debug_utils_create_info.callback_data,
345 })
346 } else {
347 log::debug!("Debug utils not enabled: extension not listed");
348 None
349 }
350 } else {
351 log::debug!(
352 "Debug utils not enabled: \
353 debug_utils_user_data not passed to Instance::from_raw"
354 );
355 None
356 };
357
358 let get_physical_device_properties =
359 if extensions.contains(&khr::get_physical_device_properties2::NAME) {
360 log::debug!("Enabling device properties2");
361 Some(khr::get_physical_device_properties2::Instance::new(
362 &entry,
363 &raw_instance,
364 ))
365 } else {
366 None
367 };
368
369 let drop_guard = crate::DropGuard::from_option(drop_callback);
370
371 Ok(Self {
372 shared: Arc::new(super::InstanceShared {
373 raw: raw_instance,
374 extensions,
375 drop_guard,
376 flags,
377 debug_utils,
378 get_physical_device_properties,
379 entry,
380 has_nv_optimus,
381 instance_api_version,
382 android_sdk_version,
383 }),
384 })
385 }
386
387 fn create_surface_from_xlib(
388 &self,
389 dpy: *mut vk::Display,
390 window: vk::Window,
391 ) -> Result<super::Surface, crate::InstanceError> {
392 if !self.shared.extensions.contains(&khr::xlib_surface::NAME) {
393 return Err(crate::InstanceError::new(String::from(
394 "Vulkan driver does not support VK_KHR_xlib_surface",
395 )));
396 }
397
398 let surface = {
399 let xlib_loader =
400 khr::xlib_surface::Instance::new(&self.shared.entry, &self.shared.raw);
401 let info = vk::XlibSurfaceCreateInfoKHR::default()
402 .flags(vk::XlibSurfaceCreateFlagsKHR::empty())
403 .window(window)
404 .dpy(dpy);
405
406 unsafe { xlib_loader.create_xlib_surface(&info, None) }
407 .expect("XlibSurface::create_xlib_surface() failed")
408 };
409
410 Ok(self.create_surface_from_vk_surface_khr(surface))
411 }
412
413 fn create_surface_from_xcb(
414 &self,
415 connection: *mut vk::xcb_connection_t,
416 window: vk::xcb_window_t,
417 ) -> Result<super::Surface, crate::InstanceError> {
418 if !self.shared.extensions.contains(&khr::xcb_surface::NAME) {
419 return Err(crate::InstanceError::new(String::from(
420 "Vulkan driver does not support VK_KHR_xcb_surface",
421 )));
422 }
423
424 let surface = {
425 let xcb_loader = khr::xcb_surface::Instance::new(&self.shared.entry, &self.shared.raw);
426 let info = vk::XcbSurfaceCreateInfoKHR::default()
427 .flags(vk::XcbSurfaceCreateFlagsKHR::empty())
428 .window(window)
429 .connection(connection);
430
431 unsafe { xcb_loader.create_xcb_surface(&info, None) }
432 .expect("XcbSurface::create_xcb_surface() failed")
433 };
434
435 Ok(self.create_surface_from_vk_surface_khr(surface))
436 }
437
438 fn create_surface_from_wayland(
439 &self,
440 display: *mut vk::wl_display,
441 surface: *mut vk::wl_surface,
442 ) -> Result<super::Surface, crate::InstanceError> {
443 if !self.shared.extensions.contains(&khr::wayland_surface::NAME) {
444 return Err(crate::InstanceError::new(String::from(
445 "Vulkan driver does not support VK_KHR_wayland_surface",
446 )));
447 }
448
449 let surface = {
450 let w_loader =
451 khr::wayland_surface::Instance::new(&self.shared.entry, &self.shared.raw);
452 let info = vk::WaylandSurfaceCreateInfoKHR::default()
453 .flags(vk::WaylandSurfaceCreateFlagsKHR::empty())
454 .display(display)
455 .surface(surface);
456
457 unsafe { w_loader.create_wayland_surface(&info, None) }.expect("WaylandSurface failed")
458 };
459
460 Ok(self.create_surface_from_vk_surface_khr(surface))
461 }
462
463 fn create_surface_android(
464 &self,
465 window: *mut vk::ANativeWindow,
466 ) -> Result<super::Surface, crate::InstanceError> {
467 if !self.shared.extensions.contains(&khr::android_surface::NAME) {
468 return Err(crate::InstanceError::new(String::from(
469 "Vulkan driver does not support VK_KHR_android_surface",
470 )));
471 }
472
473 let surface = {
474 let a_loader =
475 khr::android_surface::Instance::new(&self.shared.entry, &self.shared.raw);
476 let info = vk::AndroidSurfaceCreateInfoKHR::default()
477 .flags(vk::AndroidSurfaceCreateFlagsKHR::empty())
478 .window(window);
479
480 unsafe { a_loader.create_android_surface(&info, None) }.expect("AndroidSurface failed")
481 };
482
483 Ok(self.create_surface_from_vk_surface_khr(surface))
484 }
485
486 fn create_surface_from_hwnd(
487 &self,
488 hinstance: vk::HINSTANCE,
489 hwnd: vk::HWND,
490 ) -> Result<super::Surface, crate::InstanceError> {
491 if !self.shared.extensions.contains(&khr::win32_surface::NAME) {
492 return Err(crate::InstanceError::new(String::from(
493 "Vulkan driver does not support VK_KHR_win32_surface",
494 )));
495 }
496
497 let surface = {
498 let info = vk::Win32SurfaceCreateInfoKHR::default()
499 .flags(vk::Win32SurfaceCreateFlagsKHR::empty())
500 .hinstance(hinstance)
501 .hwnd(hwnd);
502 let win32_loader =
503 khr::win32_surface::Instance::new(&self.shared.entry, &self.shared.raw);
504 unsafe {
505 win32_loader
506 .create_win32_surface(&info, None)
507 .expect("Unable to create Win32 surface")
508 }
509 };
510
511 Ok(self.create_surface_from_vk_surface_khr(surface))
512 }
513
514 #[cfg(metal)]
515 fn create_surface_from_view(
516 &self,
517 view: std::ptr::NonNull<c_void>,
518 ) -> Result<super::Surface, crate::InstanceError> {
519 if !self.shared.extensions.contains(&ext::metal_surface::NAME) {
520 return Err(crate::InstanceError::new(String::from(
521 "Vulkan driver does not support VK_EXT_metal_surface",
522 )));
523 }
524
525 let layer = unsafe { crate::metal::Surface::get_metal_layer(view.cast()) };
526 let layer_ptr = (*layer).cast();
529
530 let surface = {
531 let metal_loader =
532 ext::metal_surface::Instance::new(&self.shared.entry, &self.shared.raw);
533 let vk_info = vk::MetalSurfaceCreateInfoEXT::default()
534 .flags(vk::MetalSurfaceCreateFlagsEXT::empty())
535 .layer(layer_ptr);
536
537 unsafe { metal_loader.create_metal_surface(&vk_info, None).unwrap() }
538 };
539
540 Ok(self.create_surface_from_vk_surface_khr(surface))
541 }
542
543 fn create_surface_from_vk_surface_khr(&self, surface: vk::SurfaceKHR) -> super::Surface {
544 let functor = khr::surface::Instance::new(&self.shared.entry, &self.shared.raw);
545 super::Surface {
546 raw: surface,
547 functor,
548 instance: Arc::clone(&self.shared),
549 swapchain: RwLock::new(None),
550 }
551 }
552}
553
554impl Drop for super::InstanceShared {
555 fn drop(&mut self) {
556 unsafe {
557 let _du = self.debug_utils.take().inspect(|du| {
559 du.extension
560 .destroy_debug_utils_messenger(du.messenger, None);
561 });
562 if self.drop_guard.is_none() {
563 self.raw.destroy_instance(None);
564 }
565 }
566 }
567}
568
569impl crate::Instance for super::Instance {
570 type A = super::Api;
571
572 unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
573 profiling::scope!("Init Vulkan Backend");
574
575 let entry = unsafe {
576 profiling::scope!("Load vk library");
577 ash::Entry::load()
578 }
579 .map_err(|err| {
580 crate::InstanceError::with_source(String::from("missing Vulkan entry points"), err)
581 })?;
582 let version = {
583 profiling::scope!("vkEnumerateInstanceVersion");
584 unsafe { entry.try_enumerate_instance_version() }
585 };
586 let instance_api_version = match version {
587 Ok(Some(version)) => version,
589 Ok(None) => vk::API_VERSION_1_0,
590 Err(err) => {
591 return Err(crate::InstanceError::with_source(
592 String::from("try_enumerate_instance_version() failed"),
593 err,
594 ));
595 }
596 };
597
598 let app_name = CString::new(desc.name).unwrap();
599 let app_info = vk::ApplicationInfo::default()
600 .application_name(app_name.as_c_str())
601 .application_version(1)
602 .engine_name(CStr::from_bytes_with_nul(b"wgpu-hal\0").unwrap())
603 .engine_version(2)
604 .api_version(
605 if instance_api_version < vk::API_VERSION_1_1 {
607 vk::API_VERSION_1_0
608 } else {
609 vk::API_VERSION_1_3
618 },
619 );
620
621 let extensions = Self::desired_extensions(&entry, instance_api_version, desc.flags)?;
622
623 let instance_layers = {
624 profiling::scope!("vkEnumerateInstanceLayerProperties");
625 unsafe { entry.enumerate_instance_layer_properties() }
626 };
627 let instance_layers = instance_layers.map_err(|e| {
628 log::debug!("enumerate_instance_layer_properties: {:?}", e);
629 crate::InstanceError::with_source(
630 String::from("enumerate_instance_layer_properties() failed"),
631 e,
632 )
633 })?;
634
635 fn find_layer<'layers>(
636 instance_layers: &'layers [vk::LayerProperties],
637 name: &CStr,
638 ) -> Option<&'layers vk::LayerProperties> {
639 instance_layers
640 .iter()
641 .find(|inst_layer| inst_layer.layer_name_as_c_str() == Ok(name))
642 }
643
644 let validation_layer_name =
645 CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0").unwrap();
646 let validation_layer_properties = find_layer(&instance_layers, validation_layer_name);
647
648 let validation_features_are_enabled = if validation_layer_properties.is_some() {
651 let exts =
653 Self::enumerate_instance_extension_properties(&entry, Some(validation_layer_name))?;
654 let mut ext_names = exts
656 .iter()
657 .filter_map(|ext| ext.extension_name_as_c_str().ok());
658 ext_names.any(|ext_name| ext_name == ext::validation_features::NAME)
660 } else {
661 false
662 };
663
664 let should_enable_gpu_based_validation = desc
665 .flags
666 .intersects(wgt::InstanceFlags::GPU_BASED_VALIDATION)
667 && validation_features_are_enabled;
668
669 let nv_optimus_layer = CStr::from_bytes_with_nul(b"VK_LAYER_NV_optimus\0").unwrap();
670 let has_nv_optimus = find_layer(&instance_layers, nv_optimus_layer).is_some();
671
672 let obs_layer = CStr::from_bytes_with_nul(b"VK_LAYER_OBS_HOOK\0").unwrap();
673 let has_obs_layer = find_layer(&instance_layers, obs_layer).is_some();
674
675 let mut layers: Vec<&'static CStr> = Vec::new();
676
677 let has_debug_extension = extensions.contains(&ext::debug_utils::NAME);
678 let mut debug_user_data = has_debug_extension.then(|| {
679 Box::new(super::DebugUtilsMessengerUserData {
682 validation_layer_properties: None,
683 has_obs_layer,
684 })
685 });
686
687 if desc.flags.intersects(wgt::InstanceFlags::VALIDATION)
689 || should_enable_gpu_based_validation
690 {
691 if let Some(layer_properties) = validation_layer_properties {
692 layers.push(validation_layer_name);
693
694 if let Some(debug_user_data) = debug_user_data.as_mut() {
695 debug_user_data.validation_layer_properties =
696 Some(super::ValidationLayerProperties {
697 layer_description: layer_properties
698 .description_as_c_str()
699 .unwrap()
700 .to_owned(),
701 layer_spec_version: layer_properties.spec_version,
702 });
703 }
704 } else {
705 log::warn!(
706 "InstanceFlags::VALIDATION requested, but unable to find layer: {}",
707 validation_layer_name.to_string_lossy()
708 );
709 }
710 }
711 let mut debug_utils = if let Some(callback_data) = debug_user_data {
712 let mut severity = vk::DebugUtilsMessageSeverityFlagsEXT::ERROR;
714 if log::max_level() >= log::LevelFilter::Debug {
715 severity |= vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE;
716 }
717 if log::max_level() >= log::LevelFilter::Info {
718 severity |= vk::DebugUtilsMessageSeverityFlagsEXT::INFO;
719 }
720 if log::max_level() >= log::LevelFilter::Warn {
721 severity |= vk::DebugUtilsMessageSeverityFlagsEXT::WARNING;
722 }
723
724 let message_type = vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
725 | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
726 | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE;
727
728 let create_info = super::DebugUtilsCreateInfo {
729 severity,
730 message_type,
731 callback_data,
732 };
733
734 Some(create_info)
735 } else {
736 None
737 };
738
739 #[cfg(target_os = "android")]
740 let android_sdk_version = {
741 let properties = android_system_properties::AndroidSystemProperties::new();
742 if let Some(val) = properties.get("ro.build.version.sdk") {
744 match val.parse::<u32>() {
745 Ok(sdk_ver) => sdk_ver,
746 Err(err) => {
747 log::error!(
748 concat!(
749 "Couldn't parse Android's ",
750 "ro.build.version.sdk system property ({}): {}",
751 ),
752 val,
753 err,
754 );
755 0
756 }
757 }
758 } else {
759 log::error!("Couldn't read Android's ro.build.version.sdk system property");
760 0
761 }
762 };
763 #[cfg(not(target_os = "android"))]
764 let android_sdk_version = 0;
765
766 let mut flags = vk::InstanceCreateFlags::empty();
767
768 if extensions.contains(&khr::portability_enumeration::NAME) {
772 flags |= vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR;
773 }
774 let vk_instance = {
775 let str_pointers = layers
776 .iter()
777 .chain(extensions.iter())
778 .map(|&s: &&'static _| {
779 s.as_ptr()
781 })
782 .collect::<Vec<_>>();
783
784 let mut create_info = vk::InstanceCreateInfo::default()
785 .flags(flags)
786 .application_info(&app_info)
787 .enabled_layer_names(&str_pointers[..layers.len()])
788 .enabled_extension_names(&str_pointers[layers.len()..]);
789
790 let mut debug_utils_create_info = debug_utils
791 .as_mut()
792 .map(|create_info| create_info.to_vk_create_info());
793 if let Some(debug_utils_create_info) = debug_utils_create_info.as_mut() {
794 create_info = create_info.push_next(debug_utils_create_info);
795 }
796
797 let mut validation_features;
799 let mut validation_feature_list: ArrayVec<_, 3>;
800 if validation_features_are_enabled {
801 validation_feature_list = ArrayVec::new();
802
803 validation_feature_list
805 .push(vk::ValidationFeatureEnableEXT::SYNCHRONIZATION_VALIDATION);
806
807 if should_enable_gpu_based_validation {
809 validation_feature_list.push(vk::ValidationFeatureEnableEXT::GPU_ASSISTED);
810 validation_feature_list
811 .push(vk::ValidationFeatureEnableEXT::GPU_ASSISTED_RESERVE_BINDING_SLOT);
812 }
813
814 validation_features = vk::ValidationFeaturesEXT::default()
815 .enabled_validation_features(&validation_feature_list);
816 create_info = create_info.push_next(&mut validation_features);
817 }
818
819 unsafe {
820 profiling::scope!("vkCreateInstance");
821 entry.create_instance(&create_info, None)
822 }
823 .map_err(|e| {
824 crate::InstanceError::with_source(
825 String::from("Entry::create_instance() failed"),
826 e,
827 )
828 })?
829 };
830
831 unsafe {
832 Self::from_raw(
833 entry,
834 vk_instance,
835 instance_api_version,
836 android_sdk_version,
837 debug_utils,
838 extensions,
839 desc.flags,
840 has_nv_optimus,
841 None,
842 )
843 }
844 }
845
846 unsafe fn create_surface(
847 &self,
848 display_handle: raw_window_handle::RawDisplayHandle,
849 window_handle: raw_window_handle::RawWindowHandle,
850 ) -> Result<super::Surface, crate::InstanceError> {
851 use raw_window_handle::{RawDisplayHandle as Rdh, RawWindowHandle as Rwh};
852
853 match (window_handle, display_handle) {
856 (Rwh::Wayland(handle), Rdh::Wayland(display)) => {
857 self.create_surface_from_wayland(display.display.as_ptr(), handle.surface.as_ptr())
858 }
859 (Rwh::Xlib(handle), Rdh::Xlib(display)) => {
860 let display = display.display.expect("Display pointer is not set.");
861 self.create_surface_from_xlib(display.as_ptr(), handle.window)
862 }
863 (Rwh::Xcb(handle), Rdh::Xcb(display)) => {
864 let connection = display.connection.expect("Pointer to X-Server is not set.");
865 self.create_surface_from_xcb(connection.as_ptr(), handle.window.get())
866 }
867 (Rwh::AndroidNdk(handle), _) => {
868 self.create_surface_android(handle.a_native_window.as_ptr())
869 }
870 (Rwh::Win32(handle), _) => {
871 let hinstance = handle.hinstance.ok_or_else(|| {
872 crate::InstanceError::new(String::from(
873 "Vulkan requires raw-window-handle's Win32::hinstance to be set",
874 ))
875 })?;
876 self.create_surface_from_hwnd(hinstance.get(), handle.hwnd.get())
877 }
878 #[cfg(all(target_os = "macos", feature = "metal"))]
879 (Rwh::AppKit(handle), _)
880 if self.shared.extensions.contains(&ext::metal_surface::NAME) =>
881 {
882 self.create_surface_from_view(handle.ns_view)
883 }
884 #[cfg(all(any(target_os = "ios", target_os = "visionos"), feature = "metal"))]
885 (Rwh::UiKit(handle), _)
886 if self.shared.extensions.contains(&ext::metal_surface::NAME) =>
887 {
888 self.create_surface_from_view(handle.ui_view)
889 }
890 (_, _) => Err(crate::InstanceError::new(format!(
891 "window handle {window_handle:?} is not a Vulkan-compatible handle"
892 ))),
893 }
894 }
895
896 unsafe fn enumerate_adapters(
897 &self,
898 _surface_hint: Option<&super::Surface>,
899 ) -> Vec<crate::ExposedAdapter<super::Api>> {
900 use crate::auxil::db;
901
902 let raw_devices = match unsafe { self.shared.raw.enumerate_physical_devices() } {
903 Ok(devices) => devices,
904 Err(err) => {
905 log::error!("enumerate_adapters: {}", err);
906 Vec::new()
907 }
908 };
909
910 let mut exposed_adapters = raw_devices
911 .into_iter()
912 .flat_map(|device| self.expose_adapter(device))
913 .collect::<Vec<_>>();
914
915 let has_nvidia_dgpu = exposed_adapters.iter().any(|exposed| {
917 exposed.info.device_type == wgt::DeviceType::DiscreteGpu
918 && exposed.info.vendor == db::nvidia::VENDOR
919 });
920 if cfg!(target_os = "linux") && has_nvidia_dgpu && self.shared.has_nv_optimus {
921 for exposed in exposed_adapters.iter_mut() {
922 if exposed.info.device_type == wgt::DeviceType::IntegratedGpu
923 && exposed.info.vendor == db::intel::VENDOR
924 {
925 if let Some(version) = exposed.info.driver_info.split_once("Mesa ").map(|s| {
927 let mut components = s.1.split('.');
928 let major = components.next().and_then(|s| u8::from_str(s).ok());
929 let minor = components.next().and_then(|s| u8::from_str(s).ok());
930 if let (Some(major), Some(minor)) = (major, minor) {
931 (major, minor)
932 } else {
933 (0, 0)
934 }
935 }) {
936 if version < (21, 2) {
937 log::warn!(
939 concat!(
940 "Disabling presentation on '{}' (id {:?}) ",
941 "due to NV Optimus and Intel Mesa < v21.2"
942 ),
943 exposed.info.name,
944 exposed.adapter.raw
945 );
946 exposed.adapter.private_caps.can_present = false;
947 }
948 }
949 }
950 }
951 }
952
953 exposed_adapters
954 }
955}
956
957impl Drop for super::Surface {
958 fn drop(&mut self) {
959 unsafe { self.functor.destroy_surface(self.raw, None) };
960 }
961}
962
963impl crate::Surface for super::Surface {
964 type A = super::Api;
965
966 unsafe fn configure(
967 &self,
968 device: &super::Device,
969 config: &crate::SurfaceConfiguration,
970 ) -> Result<(), crate::SurfaceError> {
971 let mut swap_chain = self.swapchain.write();
973 let old = swap_chain
974 .take()
975 .map(|sc| unsafe { sc.release_resources(&device.shared.raw) });
976
977 let swapchain = unsafe { device.create_swapchain(self, config, old)? };
978 *swap_chain = Some(swapchain);
979
980 Ok(())
981 }
982
983 unsafe fn unconfigure(&self, device: &super::Device) {
984 if let Some(sc) = self.swapchain.write().take() {
985 let swapchain = unsafe { sc.release_resources(&device.shared.raw) };
987 unsafe { swapchain.functor.destroy_swapchain(swapchain.raw, None) };
988 }
989 }
990
991 unsafe fn acquire_texture(
992 &self,
993 timeout: Option<std::time::Duration>,
994 fence: &super::Fence,
995 ) -> Result<Option<crate::AcquiredSurfaceTexture<super::Api>>, crate::SurfaceError> {
996 let mut swapchain = self.swapchain.write();
997 let swapchain = swapchain.as_mut().unwrap();
998
999 let mut timeout_ns = match timeout {
1000 Some(duration) => duration.as_nanos() as u64,
1001 None => u64::MAX,
1002 };
1003
1004 if cfg!(target_os = "android") && self.instance.android_sdk_version < 30 {
1014 timeout_ns = u64::MAX;
1015 }
1016
1017 let swapchain_semaphores_arc = swapchain.get_surface_semaphores();
1018 let locked_swapchain_semaphores = swapchain_semaphores_arc
1020 .try_lock()
1021 .expect("Failed to lock a SwapchainSemaphores.");
1022
1023 swapchain.device.wait_for_fence(
1037 fence,
1038 locked_swapchain_semaphores.previously_used_submission_index,
1039 timeout_ns,
1040 )?;
1041
1042 let (index, suboptimal) = match unsafe {
1044 profiling::scope!("vkAcquireNextImageKHR");
1045 swapchain.functor.acquire_next_image(
1046 swapchain.raw,
1047 timeout_ns,
1048 locked_swapchain_semaphores.acquire,
1049 vk::Fence::null(),
1050 )
1051 } {
1052 #[cfg(target_os = "android")]
1055 Ok((index, _)) => (index, false),
1056 #[cfg(not(target_os = "android"))]
1057 Ok(pair) => pair,
1058 Err(error) => {
1059 return match error {
1060 vk::Result::TIMEOUT => Ok(None),
1061 vk::Result::NOT_READY | vk::Result::ERROR_OUT_OF_DATE_KHR => {
1062 Err(crate::SurfaceError::Outdated)
1063 }
1064 vk::Result::ERROR_SURFACE_LOST_KHR => Err(crate::SurfaceError::Lost),
1065 other => Err(super::map_host_device_oom_and_lost_err(other).into()),
1068 };
1069 }
1070 };
1071
1072 drop(locked_swapchain_semaphores);
1073 swapchain.advance_surface_semaphores();
1076
1077 if swapchain.device.vendor_id == crate::auxil::db::intel::VENDOR && index > 0x100 {
1079 return Err(crate::SurfaceError::Outdated);
1080 }
1081
1082 let raw_flags = if swapchain
1084 .raw_flags
1085 .contains(vk::SwapchainCreateFlagsKHR::MUTABLE_FORMAT)
1086 {
1087 vk::ImageCreateFlags::MUTABLE_FORMAT | vk::ImageCreateFlags::EXTENDED_USAGE
1088 } else {
1089 vk::ImageCreateFlags::empty()
1090 };
1091
1092 let texture = super::SurfaceTexture {
1093 index,
1094 texture: super::Texture {
1095 raw: swapchain.images[index as usize],
1096 drop_guard: None,
1097 block: None,
1098 external_memory: None,
1099 usage: swapchain.config.usage,
1100 format: swapchain.config.format,
1101 raw_flags,
1102 copy_size: crate::CopyExtent {
1103 width: swapchain.config.extent.width,
1104 height: swapchain.config.extent.height,
1105 depth: 1,
1106 },
1107 view_formats: swapchain.view_formats.clone(),
1108 },
1109 surface_semaphores: swapchain_semaphores_arc,
1110 };
1111 Ok(Some(crate::AcquiredSurfaceTexture {
1112 texture,
1113 suboptimal,
1114 }))
1115 }
1116
1117 unsafe fn discard_texture(&self, _texture: super::SurfaceTexture) {}
1118}