diff --git a/wgpu-hal/src/vulkan/instance.rs b/wgpu-hal/src/vulkan/instance.rs index 568278e04..a035b4fa1 100644 --- a/wgpu-hal/src/vulkan/instance.rs +++ b/wgpu-hal/src/vulkan/instance.rs @@ -368,7 +368,7 @@ impl super::Instance { } #[cfg(any(target_os = "macos", target_os = "ios"))] - fn create_surface_from_ns_view(&self, view: *mut c_void) -> super::Surface { + fn create_surface_from_view(&self, view: *mut c_void) -> super::Surface { use core_graphics_types::{base::CGFloat, geometry::CGRect}; use objc::{ class, msg_send, @@ -381,27 +381,33 @@ impl super::Instance { let existing: *mut Object = msg_send![view, layer]; let class = class!(CAMetalLayer); - let use_current = if existing.is_null() { - false - } else { - let result: BOOL = msg_send![existing, isKindOfClass: class]; - result == YES - }; - - if use_current { + let use_current: BOOL = msg_send![existing, isKindOfClass: class]; + if use_current == YES { existing } else { - let layer: *mut Object = msg_send![class, new]; - let () = msg_send![view, setLayer: layer]; - let bounds: CGRect = msg_send![view, bounds]; - let () = msg_send![layer, setBounds: bounds]; + let new_layer: *mut Object = msg_send![class, new]; + let frame: CGRect = msg_send![existing, bounds]; + let () = msg_send![new_layer, setFrame: frame]; - let window: *mut Object = msg_send![view, window]; - if !window.is_null() { - let scale_factor: CGFloat = msg_send![window, backingScaleFactor]; - let () = msg_send![layer, setContentsScale: scale_factor]; - } - layer + let scale_factor: CGFloat = if cfg!(target_os = "ios") { + let () = msg_send![existing, addSublayer: new_layer]; + // On iOS, `create_surface_from_view` may be called before the application initialization is complete, + // `msg_send![view, window]` and `msg_send![window, screen]` will get null. + let screen: *mut Object = msg_send![class!(UIScreen), mainScreen]; + msg_send![screen, nativeScale] + } else { + let () = msg_send![view, setLayer: new_layer]; + let () = msg_send![view, setWantsLayer: YES]; + let window: *mut Object = msg_send![view, window]; + if !window.is_null() { + msg_send![window, backingScaleFactor] + } else { + 1.0 + } + }; + let () = msg_send![new_layer, setContentsScale: scale_factor]; + + new_layer } }; @@ -586,13 +592,13 @@ impl crate::Instance for super::Instance { RawWindowHandle::AppKit(handle) if self.extensions.contains(&ext::MetalSurface::name()) => { - Ok(self.create_surface_from_ns_view(handle.ns_view)) + Ok(self.create_surface_from_view(handle.ns_view)) } #[cfg(target_os = "ios")] RawWindowHandle::UiKit(handle) if self.extensions.contains(&ext::MetalSurface::name()) => { - Ok(self.create_surface_from_ns_view(handle.ui_view)) + Ok(self.create_surface_from_view(handle.ui_view)) } _ => Err(crate::InstanceError), }