From 18c05b85c0d9781b49e0d7438f5175e1275c0727 Mon Sep 17 00:00:00 2001 From: hakolao Date: Mon, 8 Aug 2022 21:23:44 +0300 Subject: [PATCH 1/7] Fix iOS, use similar approach for metal layer as wgpu --- vulkano-win/Cargo.toml | 9 ++--- vulkano-win/src/winit.rs | 87 +++++++++++++++++++++++++++++----------- vulkano/src/library.rs | 9 ++--- 3 files changed, 72 insertions(+), 33 deletions(-) diff --git a/vulkano-win/Cargo.toml b/vulkano-win/Cargo.toml index 8b3c714d0d..ebe1269a30 100644 --- a/vulkano-win/Cargo.toml +++ b/vulkano-win/Cargo.toml @@ -13,7 +13,7 @@ categories = ["rendering::graphics-api"] [features] default = ["winit_", "raw-window-handle_"] -winit_ = ["winit", "metal", "cocoa", "objc"] +winit_ = ["winit", "objc", "core-graphics-types"] raw-window-handle_ = ["raw-window-handle"] [dependencies] @@ -21,7 +21,6 @@ raw-window-handle = { version = "0.4", optional = true } vulkano = { version = "0.30.0", path = "../vulkano" } winit = { version = "0.27", optional = true } -[target.'cfg(target_os = "macos")'.dependencies] -cocoa = { version = "0.24", optional = true } -metal = { version = "0.23", optional = true } -objc = { version = "0.2", optional = true } +[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] +objc = { version = "0.2.5", optional = true } +core-graphics-types = { version = "0.1", optional = true } \ No newline at end of file diff --git a/vulkano-win/src/winit.rs b/vulkano-win/src/winit.rs index 0637b7ad07..59f093704c 100644 --- a/vulkano-win/src/winit.rs +++ b/vulkano-win/src/winit.rs @@ -123,7 +123,12 @@ unsafe fn winit_to_surface>( } } -#[cfg(all(unix, not(target_os = "android"), not(target_os = "macos")))] +#[cfg(all( + unix, + not(target_os = "android"), + not(target_os = "macos"), + not(target_os = "ios") +))] unsafe fn winit_to_surface>( instance: Arc, win: W, @@ -157,47 +162,83 @@ unsafe fn winit_to_surface>( } } -#[cfg(target_os = "macos")] -use cocoa::{ - appkit::{NSView, NSWindow}, - base::id as cocoa_id, +#[cfg(any(target_os = "macos", target_os = "ios"))] +use objc::{ + class, msg_send, + runtime::{Object, BOOL, NO}, + sel, sel_impl, }; -#[cfg(target_os = "macos")] -use metal::MetalLayer; + #[cfg(target_os = "macos")] use objc::runtime::YES; + #[cfg(target_os = "macos")] -use std::mem; +use core_graphics_types::base::CGFloat; /// Ensure `CAMetalLayer` (native rendering surface on MacOs) is used by the ns_view. /// This is necessary to be able to render on Mac. #[cfg(target_os = "macos")] -unsafe fn set_ca_metal_layer_to_winit>(win: W) { +unsafe fn get_metal_layer_macos>(win: W) -> *mut Object { use winit::platform::macos::WindowExtMacOS; - let wnd: cocoa_id = mem::transmute(win.borrow().ns_window()); - let layer = MetalLayer::new(); + let view: *mut Object = std::mem::transmute(win.borrow().ns_view()); + let main_layer: *mut Object = msg_send![view, layer]; + let class = class!(CAMetalLayer); + let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class]; + if is_valid_layer == NO { + let new_layer: *mut Object = msg_send![class, new]; + 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() { + let scale_factor: CGFloat = msg_send![window, backingScaleFactor]; + let () = msg_send![new_layer, setContentsScale: scale_factor]; + } + new_layer + } else { + main_layer + } +} - layer.set_edge_antialiasing_mask(0); - layer.set_presents_with_transaction(false); - layer.remove_all_animations(); +#[cfg(target_os = "macos")] +unsafe fn winit_to_surface>( + instance: Arc, + win: W, +) -> Result>, SurfaceCreationError> { + let layer = get_metal_layer_macos(win.borrow()); + Surface::from_mac_os(instance, layer as *const (), win) +} - let view = wnd.contentView(); +#[cfg(target_os = "ios")] +unsafe fn get_metal_layer_ios>(win: W) -> *mut Object { + use core_graphics_types::{base::CGFloat, geometry::CGRect}; + use winit::platform::ios::WindowExtIOS; - layer.set_contents_scale(view.backingScaleFactor()); - view.setLayer(mem::transmute(layer.as_ref())); // Bombs here with out of memory - view.setWantsLayer(YES); + let view: *mut Object = std::mem::transmute(win.borrow().ui_view()); + let main_layer: *mut Object = msg_send![view, layer]; + let class = class!(CAMetalLayer); + let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class]; + if is_valid_layer == NO { + let new_layer: *mut Object = msg_send![class, new]; + let frame: CGRect = msg_send![main_layer, bounds]; + let () = msg_send![new_layer, setFrame: frame]; + let () = msg_send![main_layer, addSublayer: new_layer]; + let screen: *mut Object = msg_send![class!(UIScreen), mainScreen]; + let scale_factor: CGFloat = msg_send![screen, nativeScale]; + let () = msg_send![view, setContentScaleFactor: scale_factor]; + new_layer + } else { + main_layer + } } -#[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] unsafe fn winit_to_surface>( instance: Arc, win: W, ) -> Result>, SurfaceCreationError> { - use winit::platform::macos::WindowExtMacOS; - - set_ca_metal_layer_to_winit(win.borrow()); - Surface::from_mac_os(instance, win.borrow().ns_view() as *const (), win) + let layer = get_metal_layer_ios(win.borrow()); + Surface::from_ios(instance, layer as *const (), win) } #[cfg(target_os = "windows")] diff --git a/vulkano/src/library.rs b/vulkano/src/library.rs index fb5cad013a..96e5723487 100644 --- a/vulkano/src/library.rs +++ b/vulkano/src/library.rs @@ -42,8 +42,8 @@ impl VulkanLibrary { pub fn new() -> Result, LoadingError> { #[cfg(target_os = "ios")] #[allow(non_snake_case)] - fn def_loader_impl() -> Result, LoadingError> { - let loader = statically_linked_vulkan_loader!(); + fn def_loader_impl() -> Result, LoadingError> { + let loader = crate::statically_linked_vulkan_loader!(); Ok(Box::new(loader)) } @@ -84,7 +84,6 @@ impl VulkanLibrary { .get_instance_proc_addr(ash::vk::Instance::null(), name.as_ptr()) .map_or(ptr::null(), |func| func as _) }); - // Per the Vulkan spec: // If the vkGetInstanceProcAddr returns NULL for vkEnumerateInstanceVersion, it is a // Vulkan 1.0 implementation. Otherwise, the application can call vkEnumerateInstanceVersion @@ -329,8 +328,8 @@ macro_rules! statically_linked_vulkan_loader { &self, instance: ash::vk::Instance, name: *const c_char, - ) -> extern "system" fn() -> () { - unsafe { vkGetInstanceProcAddr(instance, name) } + ) -> *const c_void { + unsafe { std::mem::transmute(vkGetInstanceProcAddr(instance, name)) } } } From 6d297e37c7a572ef9746ff5ed8a1c1c5f2fc9243 Mon Sep 17 00:00:00 2001 From: hakolao Date: Mon, 8 Aug 2022 23:16:04 +0300 Subject: [PATCH 2/7] Use correct return type --- vulkano/src/library.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vulkano/src/library.rs b/vulkano/src/library.rs index 96e5723487..b511db8ee9 100644 --- a/vulkano/src/library.rs +++ b/vulkano/src/library.rs @@ -324,12 +324,12 @@ macro_rules! statically_linked_vulkan_loader { struct StaticallyLinkedVulkanLoader; unsafe impl Loader for StaticallyLinkedVulkanLoader { - fn get_instance_proc_addr( + unsafe fn get_instance_proc_addr( &self, instance: ash::vk::Instance, name: *const c_char, - ) -> *const c_void { - unsafe { std::mem::transmute(vkGetInstanceProcAddr(instance, name)) } + ) -> ash::vk::PFN_vkVoidFunction { + unsafe { vkGetInstanceProcAddr(instance, name) } } } From 3bc71c0b53fca8c6748e9a5a7a2d116a606e027a Mon Sep 17 00:00:00 2001 From: hakolao Date: Tue, 9 Aug 2022 15:28:18 +0300 Subject: [PATCH 3/7] Handle ios resizing --- vulkano-util/src/renderer.rs | 4 ++ vulkano-win/src/raw_window_handle.rs | 33 +++++++++-- vulkano-win/src/winit.rs | 60 +++++++++---------- vulkano/Cargo.toml | 4 ++ vulkano/src/library.rs | 2 +- vulkano/src/swapchain/mod.rs | 3 + vulkano/src/swapchain/surface.rs | 86 ++++++++++++++++++++++++++-- 7 files changed, 147 insertions(+), 45 deletions(-) diff --git a/vulkano-util/src/renderer.rs b/vulkano-util/src/renderer.rs index 1092446880..7c6bc5aa31 100644 --- a/vulkano-util/src/renderer.rs +++ b/vulkano-util/src/renderer.rs @@ -339,6 +339,10 @@ impl VulkanoWindowRenderer { self.remove_additional_image_view(i); self.add_additional_image_view(i, format, usage); } + #[cfg(target_os = "ios")] + unsafe { + self.surface.update_ios_sublayer_on_resize(); + } self.recreate_swapchain = false; } } diff --git a/vulkano-win/src/raw_window_handle.rs b/vulkano-win/src/raw_window_handle.rs index 5c55d8c848..d04dea207d 100644 --- a/vulkano-win/src/raw_window_handle.rs +++ b/vulkano-win/src/raw_window_handle.rs @@ -1,3 +1,7 @@ +#[cfg(target_os = "ios")] +use crate::get_metal_layer_ios; +#[cfg(target_os = "macos")] +use crate::get_metal_layer_macos; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use std::sync::Arc; use vulkano::instance::Instance; @@ -6,9 +10,6 @@ use vulkano::swapchain::SurfaceCreationError; /// Creates a vulkan surface from a generic window /// which implements HasRawWindowHandle and thus can reveal the os-dependent handle. -/// - Note that if you wish to use this function with MacOS, you will need to ensure that the -/// `CAMetalLayer` is set to the ns_view. An example of how one might do that can be found in -/// `vulkano_win::set_ca_metal_layer_to_winit` pub fn create_surface_from_handle( window: W, instance: Arc, @@ -21,8 +22,30 @@ where RawWindowHandle::AndroidNdk(h) => { Surface::from_android(instance, h.a_native_window, window) } - RawWindowHandle::UiKit(h) => Surface::from_ios(instance, h.ui_view, window), - RawWindowHandle::AppKit(h) => Surface::from_mac_os(instance, h.ns_view, window), + RawWindowHandle::UiKit(_h) => { + #[cfg(target_os = "ios")] + { + // Ensure the layer is CAMetalLayer + let layer = get_metal_layer_ios(_h.ui_view); + Surface::from_ios(instance, layer, window) + } + #[cfg(not(target_os = "ios"))] + { + panic!("UiKit handle should only be used when target_os == 'ios'"); + } + } + RawWindowHandle::AppKit(_h) => { + #[cfg(target_os = "macos")] + { + // Ensure the layer is CAMetalLayer + let layer = get_metal_layer_macos(_h.ns_view); + Surface::from_mac_os(instance, layer as *const (), window) + } + #[cfg(not(target_os = "macos"))] + { + panic!("AppKit handle should only be used when target_os == 'ios'"); + } + } RawWindowHandle::Wayland(h) => { Surface::from_wayland(instance, h.display, h.surface, window) } diff --git a/vulkano-win/src/winit.rs b/vulkano-win/src/winit.rs index 59f093704c..d79b0cca93 100644 --- a/vulkano-win/src/winit.rs +++ b/vulkano-win/src/winit.rs @@ -163,25 +163,17 @@ unsafe fn winit_to_surface>( } #[cfg(any(target_os = "macos", target_os = "ios"))] -use objc::{ - class, msg_send, - runtime::{Object, BOOL, NO}, - sel, sel_impl, -}; - -#[cfg(target_os = "macos")] -use objc::runtime::YES; - -#[cfg(target_os = "macos")] -use core_graphics_types::base::CGFloat; +use objc::{class, msg_send, runtime::Object, sel, sel_impl}; -/// Ensure `CAMetalLayer` (native rendering surface on MacOs) is used by the ns_view. +/// Get (and set) `CAMetalLayer` to ns_view. /// This is necessary to be able to render on Mac. #[cfg(target_os = "macos")] -unsafe fn get_metal_layer_macos>(win: W) -> *mut Object { - use winit::platform::macos::WindowExtMacOS; +pub(crate) unsafe fn get_metal_layer_macos(view: *mut std::ffi::c_void) -> *mut Object { + use core_graphics_types::base::CGFloat; + use objc::runtime::YES; + use objc::runtime::{BOOL, NO}; - let view: *mut Object = std::mem::transmute(win.borrow().ns_view()); + let view: *mut Object = std::mem::transmute(view); let main_layer: *mut Object = msg_send![view, layer]; let class = class!(CAMetalLayer); let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class]; @@ -205,31 +197,30 @@ unsafe fn winit_to_surface>( instance: Arc, win: W, ) -> Result>, SurfaceCreationError> { - let layer = get_metal_layer_macos(win.borrow()); + use winit::platform::macos::WindowExtMacOS; + let layer = get_metal_layer_macos(win.borrow().ns_view()); Surface::from_mac_os(instance, layer as *const (), win) } #[cfg(target_os = "ios")] -unsafe fn get_metal_layer_ios>(win: W) -> *mut Object { +use vulkano::swapchain::IOSMetalLayer; + +/// Get sublayer from iOS main view (ui_view). The sublayer is created as CAMetalLayer +#[cfg(target_os = "ios")] +pub(crate) unsafe fn get_metal_layer_ios(view: *mut std::ffi::c_void) -> IOSMetalLayer { use core_graphics_types::{base::CGFloat, geometry::CGRect}; - use winit::platform::ios::WindowExtIOS; - let view: *mut Object = std::mem::transmute(win.borrow().ui_view()); + let view: *mut Object = std::mem::transmute(view); let main_layer: *mut Object = msg_send![view, layer]; let class = class!(CAMetalLayer); - let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class]; - if is_valid_layer == NO { - let new_layer: *mut Object = msg_send![class, new]; - let frame: CGRect = msg_send![main_layer, bounds]; - let () = msg_send![new_layer, setFrame: frame]; - let () = msg_send![main_layer, addSublayer: new_layer]; - let screen: *mut Object = msg_send![class!(UIScreen), mainScreen]; - let scale_factor: CGFloat = msg_send![screen, nativeScale]; - let () = msg_send![view, setContentScaleFactor: scale_factor]; - new_layer - } else { - main_layer - } + let new_layer: *mut Object = msg_send![class, new]; + let frame: CGRect = msg_send![main_layer, bounds]; + let () = msg_send![new_layer, setFrame: frame]; + let () = msg_send![main_layer, addSublayer: new_layer]; + let screen: *mut Object = msg_send![class!(UIScreen), mainScreen]; + let scale_factor: CGFloat = msg_send![screen, nativeScale]; + let () = msg_send![view, setContentScaleFactor: scale_factor]; + IOSMetalLayer::new(view, new_layer) } #[cfg(target_os = "ios")] @@ -237,8 +228,9 @@ unsafe fn winit_to_surface>( instance: Arc, win: W, ) -> Result>, SurfaceCreationError> { - let layer = get_metal_layer_ios(win.borrow()); - Surface::from_ios(instance, layer as *const (), win) + use winit::platform::ios::WindowExtIOS; + let layer = get_metal_layer_ios(win.borrow().ui_view()); + Surface::from_ios(instance, layer, win) } #[cfg(target_os = "windows")] diff --git a/vulkano/Cargo.toml b/vulkano/Cargo.toml index dc43bbc8da..2b3879accd 100644 --- a/vulkano/Cargo.toml +++ b/vulkano/Cargo.toml @@ -26,6 +26,10 @@ once_cell = { version = "1.13", features = ["parking_lot"] } parking_lot = { version = "0.12", features = ["send_guard"] } smallvec = "1.8" +[target.'cfg(target_os = "ios")'.dependencies] +objc = "0.2.5" +core-graphics-types = "0.1" + [build-dependencies] heck = "0.4" indexmap = "1.8" diff --git a/vulkano/src/library.rs b/vulkano/src/library.rs index b511db8ee9..62de5dbb35 100644 --- a/vulkano/src/library.rs +++ b/vulkano/src/library.rs @@ -329,7 +329,7 @@ macro_rules! statically_linked_vulkan_loader { instance: ash::vk::Instance, name: *const c_char, ) -> ash::vk::PFN_vkVoidFunction { - unsafe { vkGetInstanceProcAddr(instance, name) } + vkGetInstanceProcAddr(instance, name) } } diff --git a/vulkano/src/swapchain/mod.rs b/vulkano/src/swapchain/mod.rs index dabfb55c21..5b9e124581 100644 --- a/vulkano/src/swapchain/mod.rs +++ b/vulkano/src/swapchain/mod.rs @@ -330,6 +330,9 @@ pub use self::{ SwapchainAcquireFuture, SwapchainCreateInfo, SwapchainCreationError, Win32Monitor, }, }; +#[cfg(target_os = "ios")] +pub use surface::IOSMetalLayer; + use std::sync::atomic::AtomicBool; pub mod display; diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index 31b67d8565..eb6f4982ac 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -18,6 +18,10 @@ use crate::{ }, Error, OomError, VulkanObject, }; + +#[cfg(target_os = "ios")] +use objc::{class, msg_send, runtime::Object, sel, sel_impl}; + use std::{ error, fmt, hash::{Hash, Hasher}, @@ -35,10 +39,11 @@ pub struct Surface { instance: Arc, api: SurfaceApi, window: W, - // If true, a swapchain has been associated to this surface, and that any new swapchain // creation should be forbidden. has_swapchain: AtomicBool, + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer, } impl Surface { @@ -63,6 +68,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), } } @@ -131,6 +138,8 @@ impl Surface { window: (), has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -177,6 +186,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -188,9 +199,10 @@ impl Surface { /// - The object referred to by `view` must outlive the created `Surface`. /// The `win` parameter can be used to ensure this. /// - The `UIView` must be backed by a `CALayer` instance of type `CAMetalLayer`. - pub unsafe fn from_ios( + #[cfg(target_os = "ios")] + pub unsafe fn from_ios( instance: Arc, - view: *const T, + metal_layer: IOSMetalLayer, win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().mvk_ios_surface { @@ -201,7 +213,7 @@ impl Surface { let create_info = ash::vk::IOSSurfaceCreateInfoMVK { flags: ash::vk::IOSSurfaceCreateFlagsMVK::empty(), - p_view: view as *const _, + p_view: metal_layer.render_layer.0 as *const _, ..Default::default() }; @@ -224,6 +236,7 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + metal_layer, })) } @@ -235,6 +248,7 @@ impl Surface { /// - The object referred to by `view` must outlive the created `Surface`. /// The `win` parameter can be used to ensure this. /// - The `NSView` must be backed by a `CALayer` instance of type `CAMetalLayer`. + #[cfg(target_os = "macos")] pub unsafe fn from_mac_os( instance: Arc, view: *const T, @@ -271,6 +285,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -317,6 +333,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -363,6 +381,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -413,6 +433,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -463,6 +485,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -513,6 +537,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -563,6 +589,8 @@ impl Surface { window: win, has_swapchain: AtomicBool::new(false), + #[cfg(target_os = "ios")] + metal_layer: IOSMetalLayer::new(std::ptr::null_mut(), std::ptr::null_mut()), })) } @@ -583,6 +611,22 @@ impl Surface { pub fn window(&self) -> &W { &self.window } + + /// Resizes the sublayer bounds on iOS. This is to be called after resize has occurred. + /// + /// On iOS, we've created CAMetalLayer as a sublayer. However, when the view changes size, + /// its sublayers are not automatically resized, and we must resize + /// it here. + #[cfg(target_os = "ios")] + #[inline] + pub unsafe fn update_ios_sublayer_on_resize(&self) { + use core_graphics_types::geometry::CGRect; + let class = class!(CAMetalLayer); + let main_layer: *mut Object = self.metal_layer.main_layer.0; + let bounds: CGRect = msg_send![main_layer, bounds]; + let render_layer: *mut Object = self.metal_layer.render_layer.0; + let () = msg_send![render_layer, setFrame: bounds]; + } } impl Drop for Surface { @@ -616,8 +660,8 @@ impl fmt::Debug for Surface { instance, api, window: _, - has_swapchain, + .. } = self; fmt.debug_struct("Surface") @@ -1226,6 +1270,38 @@ impl Default for SurfaceInfo { } } +#[cfg(target_os = "ios")] +struct LayerHandle(*mut Object); + +#[cfg(target_os = "ios")] +unsafe impl Send for LayerHandle {} + +#[cfg(target_os = "ios")] +unsafe impl Sync for LayerHandle {} + +/// Represents the metal layer for IOS +#[cfg(target_os = "ios")] +pub struct IOSMetalLayer { + main_layer: LayerHandle, + render_layer: LayerHandle, +} + +#[cfg(target_os = "ios")] +impl IOSMetalLayer { + pub fn new(main_layer: *mut Object, render_layer: *mut Object) -> Self { + Self { + main_layer: LayerHandle(main_layer), + render_layer: LayerHandle(render_layer), + } + } +} + +#[cfg(target_os = "ios")] +unsafe impl Send for IOSMetalLayer {} + +#[cfg(target_os = "ios")] +unsafe impl Sync for IOSMetalLayer {} + /// The capabilities of a surface when used by a physical device. /// /// You have to match these capabilities when you create a swapchain. From 9a13a5621de91da535e493f9415d005562b18e6f Mon Sep 17 00:00:00 2001 From: hakolao Date: Tue, 9 Aug 2022 17:15:18 +0300 Subject: [PATCH 4/7] Add changelog notes --- CHANGELOG.md | 6 ++++++ vulkano/src/swapchain/surface.rs | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6ac81e69c..357abcf03a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,12 @@ - **Breaking** Changes to memory pools: - Renamed `StdMemoryPool[Alloc]`, `StdHostVisibleMemoryTypePool[Alloc]`, `StdNonHostVisibleMemoryTypePool[Alloc]` to `Standard{...}`. - Removed `Device::standard_pool` in favor of `Device::standard_memory_pool`, which returns `&Arc`. +- **Potentially Breaking** Fix iOS compilation: + - Removed dependency to `cocoa` and `metal` + - Fixed iOS compilation errors + - Added `winit_to_surface` method for iOS, ensuring we can draw to a sub `CAMetalLayer` layer + - Added `Surface::update_ios_sublayer_on_resize` to ensure iOS sublayer is fullscreen if initial window size was not the same as device's + - Ensure both iOS and MacOS have `CAMetalLayer` when using `create_surface_from_handle` - Bugs fixed: - [#1896](https://github.com/vulkano-rs/vulkano/issues/1896): Vulkano-shaders generates invalid struct definitions when struct field names are stripped out by the compiler. diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index eb6f4982ac..f0bdee1102 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -612,7 +612,9 @@ impl Surface { &self.window } - /// Resizes the sublayer bounds on iOS. This is to be called after resize has occurred. + /// Resizes the sublayer bounds on iOS. + /// It may not be necessary if original window size matches device's, but often it does not. + /// Thus this should be called after a resize has occurred abd swapchain has been recreated. /// /// On iOS, we've created CAMetalLayer as a sublayer. However, when the view changes size, /// its sublayers are not automatically resized, and we must resize From 0495bce6418993fb65320f98b82662a654b56ef5 Mon Sep 17 00:00:00 2001 From: hakolao Date: Tue, 9 Aug 2022 17:33:14 +0300 Subject: [PATCH 5/7] Fix typo --- vulkano-win/src/raw_window_handle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulkano-win/src/raw_window_handle.rs b/vulkano-win/src/raw_window_handle.rs index d04dea207d..0de7f1dbc2 100644 --- a/vulkano-win/src/raw_window_handle.rs +++ b/vulkano-win/src/raw_window_handle.rs @@ -43,7 +43,7 @@ where } #[cfg(not(target_os = "macos"))] { - panic!("AppKit handle should only be used when target_os == 'ios'"); + panic!("AppKit handle should only be used when target_os == 'macos'"); } } RawWindowHandle::Wayland(h) => { From 6ca5bc65e04745298642143c2c8c0e33573051f6 Mon Sep 17 00:00:00 2001 From: hakolao Date: Tue, 9 Aug 2022 17:50:53 +0300 Subject: [PATCH 6/7] Update raw-window-handle --- CHANGELOG.md | 1 + vulkano-win/Cargo.toml | 2 +- vulkano-win/src/raw_window_handle.rs | 28 +++++++++++++++++++++++----- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 357abcf03a..9917ab16eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ --> - **Breaking** Public dependency updates: - Winit 0.27 + - raw-window-handle 0.5 - **Breaking** Changes to `Instance` and Vulkan initialization: - `FunctionPointers` is renamed to `VulkanLibrary`, and now resides in a separate `library` module. It is re-exported from the crate root. - The `Loader` trait is now in the `library` module. diff --git a/vulkano-win/Cargo.toml b/vulkano-win/Cargo.toml index ebe1269a30..776537d4d6 100644 --- a/vulkano-win/Cargo.toml +++ b/vulkano-win/Cargo.toml @@ -17,7 +17,7 @@ winit_ = ["winit", "objc", "core-graphics-types"] raw-window-handle_ = ["raw-window-handle"] [dependencies] -raw-window-handle = { version = "0.4", optional = true } +raw-window-handle = { version = "0.5", optional = true } vulkano = { version = "0.30.0", path = "../vulkano" } winit = { version = "0.27", optional = true } diff --git a/vulkano-win/src/raw_window_handle.rs b/vulkano-win/src/raw_window_handle.rs index 0de7f1dbc2..d575b309b8 100644 --- a/vulkano-win/src/raw_window_handle.rs +++ b/vulkano-win/src/raw_window_handle.rs @@ -2,7 +2,9 @@ use crate::get_metal_layer_ios; #[cfg(target_os = "macos")] use crate::get_metal_layer_macos; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; +use raw_window_handle::{ + HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, +}; use std::sync::Arc; use vulkano::instance::Instance; use vulkano::swapchain::Surface; @@ -15,7 +17,7 @@ pub fn create_surface_from_handle( instance: Arc, ) -> Result>, SurfaceCreationError> where - W: HasRawWindowHandle, + W: HasRawWindowHandle + HasRawDisplayHandle, { unsafe { match window.raw_window_handle() { @@ -47,11 +49,27 @@ where } } RawWindowHandle::Wayland(h) => { - Surface::from_wayland(instance, h.display, h.surface, window) + let d = match window.raw_display_handle() { + RawDisplayHandle::Wayland(d) => d, + _ => panic!("Invalid RawDisplayHandle"), + }; + Surface::from_wayland(instance, d.display, h.surface, window) } RawWindowHandle::Win32(h) => Surface::from_win32(instance, h.hinstance, h.hwnd, window), - RawWindowHandle::Xcb(h) => Surface::from_xcb(instance, h.connection, h.window, window), - RawWindowHandle::Xlib(h) => Surface::from_xlib(instance, h.display, h.window, window), + RawWindowHandle::Xcb(h) => { + let d = match window.raw_display_handle() { + RawDisplayHandle::Xcb(d) => d, + _ => panic!("Invalid RawDisplayHandle"), + }; + Surface::from_xcb(instance, d.connection, h.window, window) + } + RawWindowHandle::Xlib(h) => { + let d = match window.raw_display_handle() { + RawDisplayHandle::Xlib(d) => d, + _ => panic!("Invalid RawDisplayHandle"), + }; + Surface::from_xlib(instance, d.display, h.window, window) + } RawWindowHandle::Web(_) => unimplemented!(), _ => unimplemented!(), } From fa297a23b479122e0cc538958e4754e4e6e493fe Mon Sep 17 00:00:00 2001 From: hakolao Date: Wed, 10 Aug 2022 12:35:11 +0300 Subject: [PATCH 7/7] Ensure mac changes correspond master version --- vulkano-win/src/winit.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vulkano-win/src/winit.rs b/vulkano-win/src/winit.rs index d79b0cca93..a208517e75 100644 --- a/vulkano-win/src/winit.rs +++ b/vulkano-win/src/winit.rs @@ -179,6 +179,9 @@ pub(crate) unsafe fn get_metal_layer_macos(view: *mut std::ffi::c_void) -> *mut let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class]; if is_valid_layer == NO { let new_layer: *mut Object = msg_send![class, new]; + let () = msg_send![new_layer, setEdgeAntialiasingMask: 0]; + let () = msg_send![new_layer, setPresentsWithTransaction: false]; + let () = msg_send![new_layer, removeAllAnimations]; let () = msg_send![view, setLayer: new_layer]; let () = msg_send![view, setWantsLayer: YES]; let window: *mut Object = msg_send![view, window];