Skip to content

Commit 5e8b57a

Browse files
committed
Use raw-window-metal to get a CAMetalLayer from raw-window-handle
The way `raw-window-metal` works is by creating a layer, and inserting that as a sublayer, just like we did on iOS before. The bounds are then kept in-sync with an observer, ensuring smooth resizing. This also fixes compilation errors on iOS, and adds preliminary support for tvOS. The implementation now solely uses `VK_EXT_metal_surface`, which was added in 2018, instead of `VK_MVK_ios_surface` / `VK_MVK_macos_surface`, which are deprecated, and only available a year and a half earlier anyhow. Note that apart from the above, there is a slight behavioral change on macOS: we no longer set `edgeAntialiasingMask` on the layer, as it's not really required, and allows us to avoid depending on `objc2` directly. It was introduced without motivation in 40e0b24, so I doubt anyone uses it, and if they do, they can change it on the layer themselves.
1 parent 38b9aff commit 5e8b57a

File tree

13 files changed

+167
-276
lines changed

13 files changed

+167
-276
lines changed

Cargo.lock

Lines changed: 79 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,20 @@ ahash = "0.8"
4747
ash = "0.38.0"
4848
bytemuck = "1.9"
4949
concurrent-slotmap = { git = "https://github.com/vulkano-rs/concurrent-slotmap", rev = "fa906d916d8d126d3cc3a2b4ab9a29fa27bee62d" }
50-
core-graphics-types = "0.1"
5150
crossbeam-queue = "0.3"
5251
half = "2.0"
5352
heck = "0.4"
5453
indexmap = "2.0"
5554
libloading = "0.8"
5655
nom = "7.1"
57-
objc = "0.2.5"
5856
once_cell = "1.17"
5957
parking_lot = "0.12"
6058
proc-macro2 = "1.0"
6159
proc-macro-crate = "2.0"
6260
quote = "1.0"
6361
rangemap = "1.5"
6462
raw-window-handle = "0.6"
63+
raw-window-metal = "1.0"
6564
serde = "1.0"
6665
serde_json = "1.0"
6766
shaderc = "0.8.3"

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ Vulkano uses [shaderc-rs](https://github.com/google/shaderc-rs) for shader compi
155155
Note that in general vulkano does **not** require you to install the official Vulkan SDK. This is
156156
not something specific to vulkano (you don't need the SDK to write programs that use Vulkan, even
157157
without vulkano), but many people are unaware of that and install the SDK thinking that it is
158-
required. However, macOS and iOS platforms do require a little more Vulkan setup since it is not
158+
required. However, macOS, iOS and tvOS platforms do require a little more Vulkan setup since it is not
159159
natively supported. See below for more details.
160160

161161
Unless you provide libshaderc, in order to build libshaderc with the shaderc-sys crate, the following tools must be installed and available on `PATH`:
@@ -203,17 +203,16 @@ On arch based system
203203
sudo pacman -Sy base-devel git python cmake vulkan-devel --noconfirm
204204
```
205205

206-
### macOS and iOS Specific Setup
206+
### macOS, iOS and tvOS Specific Setup
207207

208-
Vulkan is not natively supported by macOS and iOS. However, there exists [MoltenVK](https://github.com/KhronosGroup/MoltenVK)
209-
an open-source Vulkan implementation on top of Apple's Metal API. This allows vulkano to build and run on macOS
210-
and iOS platforms.
208+
Vulkan is not natively supported by macOS, iOS and tvOS. However, there exists [MoltenVK](https://github.com/KhronosGroup/MoltenVK)
209+
an open-source Vulkan implementation on top of Apple's Metal API. This allows vulkano to build and run on macOS, iOS and tvOS platforms.
211210

212211
The easiest way to get vulkano up and running with MoltenVK is to install the
213212
[Vulkan SDK for macOS](https://vulkan.lunarg.com/sdk/home). There are [installation instructions](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html) on the LunarG website.
214213

215-
On iOS, vulkano links directly to the MoltenVK framework. There is nothing else to do besides
216-
installing it. Note that the Vulkan SDK for macOS also comes with the iOS framework.
214+
On iOS and tvOS, vulkano links directly to the MoltenVK framework. There is nothing else to do besides
215+
installing it. Note that the Vulkan SDK for macOS also comes with the framework for iOS and tvOS.
217216

218217
## License
219218

vulkano-util/src/context.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl VulkanoContext {
120120
pub fn new(mut config: VulkanoConfig) -> Self {
121121
let library = match VulkanLibrary::new() {
122122
Ok(x) => x,
123-
#[cfg(target_os = "macos")]
123+
#[cfg(target_vendor = "apple")]
124124
Err(vulkano::library::LoadingError::LibraryLoadFailure(err)) => panic!(
125125
"failed to load Vulkan library: {err}; did you install VulkanSDK from \
126126
https://vulkan.lunarg.com/sdk/home?",
@@ -140,8 +140,7 @@ impl VulkanoContext {
140140
khr_wayland_surface: true,
141141
khr_android_surface: true,
142142
khr_win32_surface: true,
143-
mvk_ios_surface: true,
144-
mvk_macos_surface: true,
143+
ext_metal_surface: true,
145144
..InstanceExtensions::empty()
146145
})
147146
.union(&config.instance_create_info.enabled_extensions);

vulkano-util/src/renderer.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,6 @@ impl VulkanoWindowRenderer {
373373
self.remove_additional_image_view(i);
374374
self.add_additional_image_view(i, format, usage);
375375
}
376-
#[cfg(target_os = "ios")]
377-
unsafe {
378-
self.surface.update_ios_sublayer_on_resize();
379-
}
380376
self.recreate_swapchain = false;
381377
}
382378
}

vulkano-win/Cargo.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
name = "vulkano-win"
33
version = "0.34.0"
44
edition = "2021"
5-
authors = ["Pierre Krieger <[email protected]>", "The vulkano contributors"]
5+
authors = [
6+
"Pierre Krieger <[email protected]>",
7+
"The vulkano contributors",
8+
]
69
repository = "https://github.com/vulkano-rs/vulkano/tree/master/vulkano-win"
710
description = "Link between vulkano and winit"
811
license = "MIT OR Apache-2.0"
@@ -16,8 +19,8 @@ readme = "../README.md"
1619
default = ["winit", "raw-window-handle"]
1720
raw-window-handle = ["dep:raw-window-handle"]
1821
raw-window-handle_ = ["dep:raw-window-handle"]
19-
winit = ["dep:winit", "dep:objc", "dep:core-graphics-types"]
20-
winit_ = ["dep:winit", "dep:objc", "dep:core-graphics-types"]
22+
winit = ["dep:winit"]
23+
winit_ = ["dep:winit"]
2124

2225
# NOTE(Marc): The dependencies here are not workspace dependencies because vulkano-win is
2326
# deprecated and won't be receiving updates.
@@ -27,6 +30,5 @@ raw-window-handle = { version = "0.5", optional = true }
2730
vulkano = { workspace = true }
2831
winit = { version = "0.28", optional = true }
2932

30-
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
31-
objc = { version = "0.2.5", optional = true }
32-
core-graphics-types = { version = "0.1", optional = true }
33+
[target.'cfg(target_vendor = "apple")'.dependencies]
34+
raw-window-metal.workspace = true

vulkano-win/src/raw_window_handle.rs

Lines changed: 28 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
#[cfg(target_os = "ios")]
2-
use crate::get_metal_layer_ios;
3-
#[cfg(target_os = "macos")]
4-
use crate::get_metal_layer_macos;
51
use raw_window_handle::{
62
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
73
};
@@ -19,29 +15,21 @@ pub fn create_surface_from_handle(
1915
RawWindowHandle::AndroidNdk(h) => {
2016
Surface::from_android(instance, h.a_native_window, Some(window))
2117
}
22-
RawWindowHandle::UiKit(_h) => {
23-
#[cfg(target_os = "ios")]
24-
{
25-
// Ensure the layer is CAMetalLayer
26-
let metal_layer = get_metal_layer_ios(_h.ui_view);
27-
Surface::from_ios(instance, metal_layer.render_layer.0 as _, Some(window))
28-
}
29-
#[cfg(not(target_os = "ios"))]
30-
{
31-
panic!("UiKit handle should only be used when target_os == 'ios'");
32-
}
18+
#[cfg(target_vendor = "apple")]
19+
RawWindowHandle::AppKit(handle) => {
20+
let view = std::ptr::NonNull::new(handle.ns_view).unwrap();
21+
let layer = raw_window_metal::Layer::from_ns_view(view);
22+
23+
// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
24+
Surface::from_metal(instance, layer.as_ptr(), Some(window))
3325
}
34-
RawWindowHandle::AppKit(_h) => {
35-
#[cfg(target_os = "macos")]
36-
{
37-
// Ensure the layer is CAMetalLayer
38-
let metal_layer = get_metal_layer_macos(_h.ns_view);
39-
Surface::from_mac_os(instance, metal_layer as _, Some(window))
40-
}
41-
#[cfg(not(target_os = "macos"))]
42-
{
43-
panic!("AppKit handle should only be used when target_os == 'macos'");
44-
}
26+
#[cfg(target_vendor = "apple")]
27+
RawWindowHandle::UiKit(handle) => {
28+
let view = std::ptr::NonNull::new(handle.ui_view).unwrap();
29+
let layer = raw_window_metal::Layer::from_ui_view(view);
30+
31+
// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
32+
Surface::from_metal(instance, layer.as_ptr(), Some(window))
4533
}
4634
RawWindowHandle::Wayland(h) => {
4735
let d = match window.raw_display_handle() {
@@ -88,29 +76,21 @@ pub unsafe fn create_surface_from_handle_ref(
8876
RawWindowHandle::AndroidNdk(h) => {
8977
Surface::from_android(instance, h.a_native_window, None)
9078
}
91-
RawWindowHandle::UiKit(_h) => {
92-
#[cfg(target_os = "ios")]
93-
{
94-
// Ensure the layer is CAMetalLayer
95-
let metal_layer = get_metal_layer_ios(_h.ui_view);
96-
Surface::from_ios(instance, metal_layer.render_layer.0 as _, None)
97-
}
98-
#[cfg(not(target_os = "ios"))]
99-
{
100-
panic!("UiKit handle should only be used when target_os == 'ios'");
101-
}
79+
#[cfg(target_vendor = "apple")]
80+
(RawWindowHandle::AppKit(handle), _) => {
81+
let view = std::ptr::NonNull::new(handle.ns_view).unwrap();
82+
let layer = raw_window_metal::Layer::from_ns_view(view);
83+
84+
// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
85+
Surface::from_metal(instance, layer.as_ptr(), None)
10286
}
103-
RawWindowHandle::AppKit(_h) => {
104-
#[cfg(target_os = "macos")]
105-
{
106-
// Ensure the layer is CAMetalLayer
107-
let metal_layer = get_metal_layer_macos(_h.ns_view);
108-
Surface::from_mac_os(instance, metal_layer as _, None)
109-
}
110-
#[cfg(not(target_os = "macos"))]
111-
{
112-
panic!("AppKit handle should only be used when target_os == 'macos'");
113-
}
87+
#[cfg(target_vendor = "apple")]
88+
(RawWindowHandle::UiKit(handle), _) => {
89+
let view = std::ptr::NonNull::new(handle.ui_view).unwrap();
90+
let layer = raw_window_metal::Layer::from_ui_view(view);
91+
92+
// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
93+
Surface::from_metal(instance, layer.as_ptr(), None)
11494
}
11595
RawWindowHandle::Wayland(h) => {
11696
let d = match window.raw_display_handle() {

0 commit comments

Comments
 (0)