Skip to content

Commit

Permalink
Use raw-window-metal to do Metal layer creation
Browse files Browse the repository at this point in the history
This uses observers internally, which fixes resizing when using Wgpu
together with an auto-layout NSView.

Though it probably won't matter much, it's also more reliable to update
the scale factor this way, rather than haphazardly in `configure`.
  • Loading branch information
madsmtm committed Sep 9, 2024
1 parent 5c7389a commit dad5c3c
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 282 deletions.
86 changes: 80 additions & 6 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ block = "0.1"
core-graphics-types = "0.1"
metal = { version = "0.29.0" }
objc = "0.2.5"
raw-window-metal = "1.0"

# Vulkan dependencies
android_system_properties = "0.1.1"
Expand Down
5 changes: 5 additions & 0 deletions wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ metal = [
# Metal is only available on Apple platforms, therefore request MSL output also only if we target an Apple platform.
"naga/msl-out-if-target-apple",
"dep:block",
"dep:raw-window-metal",
]
vulkan = [
"naga/spv-out",
Expand All @@ -53,6 +54,7 @@ vulkan = [
"dep:libloading",
"dep:smallvec",
"dep:android_system_properties",
"dep:raw-window-metal",
]
gles = [
"naga/glsl-out",
Expand Down Expand Up @@ -166,6 +168,9 @@ glutin_wgl_sys = { workspace = true, optional = true }
# backend: Metal
block = { workspace = true, optional = true }

# backend: Metal + Vulkan
raw-window-metal = { workspace = true, optional = true }

metal.workspace = true
objc.workspace = true
core-graphics-types.workspace = true
Expand Down
34 changes: 20 additions & 14 deletions wgpu-hal/src/metal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use std::{

use arrayvec::ArrayVec;
use bitflags::bitflags;
use metal::foreign_types::ForeignTypeRef as _;
use metal::foreign_types::{ForeignType as _, ForeignTypeRef as _};
use parking_lot::{Mutex, RwLock};

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -100,7 +100,7 @@ pub struct Instance {}

impl Instance {
pub fn create_surface_from_layer(&self, layer: &metal::MetalLayerRef) -> Surface {
unsafe { Surface::from_layer(layer) }
Surface::from_layer(layer)
}
}

Expand All @@ -119,19 +119,25 @@ impl crate::Instance for Instance {
_display_handle: raw_window_handle::RawDisplayHandle,
window_handle: raw_window_handle::RawWindowHandle,
) -> Result<Surface, crate::InstanceError> {
match window_handle {
#[cfg(target_os = "ios")]
raw_window_handle::RawWindowHandle::UiKit(handle) => {
Ok(unsafe { Surface::from_view(handle.ui_view.cast()) })
let layer = match window_handle {
raw_window_handle::RawWindowHandle::AppKit(handle) => unsafe {
raw_window_metal::Layer::from_ns_view(handle.ns_view)
},
raw_window_handle::RawWindowHandle::UiKit(handle) => unsafe {
raw_window_metal::Layer::from_ui_view(handle.ui_view)
},
_ => {
return Err(crate::InstanceError::new(format!(
"window handle {window_handle:?} is not a Metal-compatible handle"
)))
}
#[cfg(target_os = "macos")]
raw_window_handle::RawWindowHandle::AppKit(handle) => {
Ok(unsafe { Surface::from_view(handle.ns_view.cast()) })
}
_ => Err(crate::InstanceError::new(format!(
"window handle {window_handle:?} is not a Metal-compatible handle"
))),
}
};

// SAFETY: The layer is an initialized instance of `CAMetalLayer`, and
// we transfer the retain count to `MetalLayer` using `into_raw`.
let layer = unsafe { metal::MetalLayer::from_ptr(layer.into_raw().cast().as_ptr()) };

Ok(Surface::new(layer))
}

unsafe fn enumerate_adapters(
Expand Down
Loading

0 comments on commit dad5c3c

Please sign in to comment.