Skip to content

Commit

Permalink
[metal] Use raw-window-metal to do 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 ffabb52
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 ffabb52

Please sign in to comment.