Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS/iOS: Use raw-window-metal to get a CAMetalLayer from raw-window-handle #2561

Merged
merged 1 commit into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 79 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,20 @@ ahash = "0.8"
ash = "0.38.0"
bytemuck = "1.9"
concurrent-slotmap = { git = "https://github.com/vulkano-rs/concurrent-slotmap", rev = "fa906d916d8d126d3cc3a2b4ab9a29fa27bee62d" }
core-graphics-types = "0.1"
crossbeam-queue = "0.3"
half = "2.0"
heck = "0.4"
indexmap = "2.0"
libloading = "0.8"
nom = "7.1"
objc = "0.2.5"
once_cell = "1.17"
parking_lot = "0.12"
proc-macro2 = "1.0"
proc-macro-crate = "2.0"
quote = "1.0"
rangemap = "1.5"
raw-window-handle = "0.6"
raw-window-metal = "1.0"
serde = "1.0"
serde_json = "1.0"
shaderc = "0.8.3"
Expand Down
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ Vulkano uses [shaderc-rs](https://github.com/google/shaderc-rs) for shader compi
Note that in general vulkano does **not** require you to install the official Vulkan SDK. This is
not something specific to vulkano (you don't need the SDK to write programs that use Vulkan, even
without vulkano), but many people are unaware of that and install the SDK thinking that it is
required. However, macOS and iOS platforms do require a little more Vulkan setup since it is not
required. However, macOS, iOS and tvOS platforms do require a little more Vulkan setup since it is not
natively supported. See below for more details.

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

### macOS and iOS Specific Setup
### macOS, iOS and tvOS Specific Setup

Vulkan is not natively supported by macOS and iOS. However, there exists [MoltenVK](https://github.com/KhronosGroup/MoltenVK)
an open-source Vulkan implementation on top of Apple's Metal API. This allows vulkano to build and run on macOS
and iOS platforms.
Vulkan is not natively supported by macOS, iOS and tvOS. However, there exists [MoltenVK](https://github.com/KhronosGroup/MoltenVK)
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.

The easiest way to get vulkano up and running with MoltenVK is to install the
[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.

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

## License

Expand Down
5 changes: 2 additions & 3 deletions vulkano-util/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl VulkanoContext {
pub fn new(mut config: VulkanoConfig) -> Self {
let library = match VulkanLibrary::new() {
Ok(x) => x,
#[cfg(target_os = "macos")]
#[cfg(target_vendor = "apple")]
Err(vulkano::library::LoadingError::LibraryLoadFailure(err)) => panic!(
"failed to load Vulkan library: {err}; did you install VulkanSDK from \
https://vulkan.lunarg.com/sdk/home?",
Expand All @@ -140,8 +140,7 @@ impl VulkanoContext {
khr_wayland_surface: true,
khr_android_surface: true,
khr_win32_surface: true,
mvk_ios_surface: true,
mvk_macos_surface: true,
ext_metal_surface: true,
..InstanceExtensions::empty()
})
.union(&config.instance_create_info.enabled_extensions);
Expand Down
4 changes: 0 additions & 4 deletions vulkano-util/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,6 @@ 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;
}
}
14 changes: 8 additions & 6 deletions vulkano-win/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
name = "vulkano-win"
version = "0.34.0"
edition = "2021"
authors = ["Pierre Krieger <[email protected]>", "The vulkano contributors"]
authors = [
"Pierre Krieger <[email protected]>",
"The vulkano contributors",
]
repository = "https://github.com/vulkano-rs/vulkano/tree/master/vulkano-win"
description = "Link between vulkano and winit"
license = "MIT OR Apache-2.0"
Expand All @@ -16,8 +19,8 @@ readme = "../README.md"
default = ["winit", "raw-window-handle"]
raw-window-handle = ["dep:raw-window-handle"]
raw-window-handle_ = ["dep:raw-window-handle"]
winit = ["dep:winit", "dep:objc", "dep:core-graphics-types"]
winit_ = ["dep:winit", "dep:objc", "dep:core-graphics-types"]
winit = ["dep:winit"]
winit_ = ["dep:winit"]

# NOTE(Marc): The dependencies here are not workspace dependencies because vulkano-win is
# deprecated and won't be receiving updates.
Expand All @@ -27,6 +30,5 @@ raw-window-handle = { version = "0.5", optional = true }
vulkano = { workspace = true }
winit = { version = "0.28", 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 }
[target.'cfg(target_vendor = "apple")'.dependencies]
raw-window-metal.workspace = true
76 changes: 28 additions & 48 deletions vulkano-win/src/raw_window_handle.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#[cfg(target_os = "ios")]
use crate::get_metal_layer_ios;
#[cfg(target_os = "macos")]
use crate::get_metal_layer_macos;
use raw_window_handle::{
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
};
Expand All @@ -19,29 +15,21 @@ pub fn create_surface_from_handle(
RawWindowHandle::AndroidNdk(h) => {
Surface::from_android(instance, h.a_native_window, Some(window))
}
RawWindowHandle::UiKit(_h) => {
#[cfg(target_os = "ios")]
{
// Ensure the layer is CAMetalLayer
let metal_layer = get_metal_layer_ios(_h.ui_view);
Surface::from_ios(instance, metal_layer.render_layer.0 as _, Some(window))
}
#[cfg(not(target_os = "ios"))]
{
panic!("UiKit handle should only be used when target_os == 'ios'");
}
#[cfg(target_vendor = "apple")]
RawWindowHandle::AppKit(handle) => {
let view = std::ptr::NonNull::new(handle.ns_view).unwrap();
let layer = raw_window_metal::Layer::from_ns_view(view);

// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
Surface::from_metal(instance, layer.as_ptr(), Some(window))
}
RawWindowHandle::AppKit(_h) => {
#[cfg(target_os = "macos")]
{
// Ensure the layer is CAMetalLayer
let metal_layer = get_metal_layer_macos(_h.ns_view);
Surface::from_mac_os(instance, metal_layer as _, Some(window))
}
#[cfg(not(target_os = "macos"))]
{
panic!("AppKit handle should only be used when target_os == 'macos'");
}
#[cfg(target_vendor = "apple")]
RawWindowHandle::UiKit(handle) => {
let view = std::ptr::NonNull::new(handle.ui_view).unwrap();
let layer = raw_window_metal::Layer::from_ui_view(view);

// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
Surface::from_metal(instance, layer.as_ptr(), Some(window))
}
RawWindowHandle::Wayland(h) => {
let d = match window.raw_display_handle() {
Expand Down Expand Up @@ -88,29 +76,21 @@ pub unsafe fn create_surface_from_handle_ref(
RawWindowHandle::AndroidNdk(h) => {
Surface::from_android(instance, h.a_native_window, None)
}
RawWindowHandle::UiKit(_h) => {
#[cfg(target_os = "ios")]
{
// Ensure the layer is CAMetalLayer
let metal_layer = get_metal_layer_ios(_h.ui_view);
Surface::from_ios(instance, metal_layer.render_layer.0 as _, None)
}
#[cfg(not(target_os = "ios"))]
{
panic!("UiKit handle should only be used when target_os == 'ios'");
}
#[cfg(target_vendor = "apple")]
(RawWindowHandle::AppKit(handle), _) => {
let view = std::ptr::NonNull::new(handle.ns_view).unwrap();
let layer = raw_window_metal::Layer::from_ns_view(view);

// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
Surface::from_metal(instance, layer.as_ptr(), None)
}
RawWindowHandle::AppKit(_h) => {
#[cfg(target_os = "macos")]
{
// Ensure the layer is CAMetalLayer
let metal_layer = get_metal_layer_macos(_h.ns_view);
Surface::from_mac_os(instance, metal_layer as _, None)
}
#[cfg(not(target_os = "macos"))]
{
panic!("AppKit handle should only be used when target_os == 'macos'");
}
#[cfg(target_vendor = "apple")]
(RawWindowHandle::UiKit(handle), _) => {
let view = std::ptr::NonNull::new(handle.ui_view).unwrap();
let layer = raw_window_metal::Layer::from_ui_view(view);

// Vulkan retains the CAMetalLayer, so no need to retain it past this invocation
Surface::from_metal(instance, layer.as_ptr(), None)
}
RawWindowHandle::Wayland(h) => {
let d = match window.raw_display_handle() {
Expand Down
Loading
Loading