hal/vk: enable vulkan portability support on macos

This commit is contained in:
Dzmitry Malyshau 2021-06-16 11:42:37 -04:00
parent 67dfdb9193
commit 1952ecb99c
4 changed files with 48 additions and 51 deletions

7
Cargo.lock generated
View File

@ -968,12 +968,11 @@ dependencies = [
[[package]] [[package]]
name = "metal" name = "metal"
version = "0.22.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/kvark/metal-rs?branch=core-graphics-types#457518722ac2ca51cf1e668a2d2be57b751c8071"
checksum = "1c12e48c737ee9a55e8bb2352bcde588f79ae308d3529ee888f7cc0f469b5777"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"block", "block",
"cocoa-foundation", "core-graphics-types",
"foreign-types", "foreign-types",
"log", "log",
"objc", "objc",
@ -1997,6 +1996,7 @@ dependencies = [
"ash", "ash",
"bitflags", "bitflags",
"block", "block",
"core-graphics-types",
"foreign-types", "foreign-types",
"fxhash", "fxhash",
"gpu-alloc", "gpu-alloc",
@ -2012,6 +2012,7 @@ dependencies = [
"renderdoc-sys", "renderdoc-sys",
"thiserror", "thiserror",
"wgpu-types", "wgpu-types",
"winapi 0.3.9",
"winit", "winit",
] ]

View File

@ -13,7 +13,7 @@ license = "MIT OR Apache-2.0"
[features] [features]
default = [] default = []
metal = ["naga/msl-out", "block", "foreign-types", "mtl", "objc"] metal = ["naga/msl-out", "block", "foreign-types"]
vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "inplace_it", "renderdoc-sys"] vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "inplace_it", "renderdoc-sys"]
[dependencies] [dependencies]
@ -31,8 +31,6 @@ log = "0.4"
# backend: Metal # backend: Metal
block = { version = "0.1", optional = true } block = { version = "0.1", optional = true }
foreign-types = { version = "0.3", optional = true } foreign-types = { version = "0.3", optional = true }
mtl = { package = "metal", version = "0.22", optional = true }
objc = { version = "0.2.5", optional = true }
# backend: Vulkan # backend: Vulkan
ash = { version = "0.32", optional = true } ash = { version = "0.32", optional = true }
gpu-alloc = { version = "0.4", optional = true } gpu-alloc = { version = "0.4", optional = true }
@ -40,6 +38,14 @@ gpu-descriptor = { version = "0.1", optional = true }
inplace_it = { version ="0.3.3", optional = true } inplace_it = { version ="0.3.3", optional = true }
renderdoc-sys = { version = "0.7.1", optional = true } renderdoc-sys = { version = "0.7.1", optional = true }
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["libloaderapi", "windef", "winuser"] }
[target.'cfg(any(target_os="macos", target_os="ios"))'.dependencies]
mtl = { package = "metal", version = "0.22", git="https://github.com/kvark/metal-rs", branch="core-graphics-types" }
objc = "0.2.5"
core-graphics-types = "0.1"
[dependencies.naga] [dependencies.naga]
git = "https://github.com/gfx-rs/naga" git = "https://github.com/gfx-rs/naga"
tag = "gfx-25" tag = "gfx-25"

View File

@ -1,5 +1,9 @@
use std::{mem, os::raw::c_void, ptr::NonNull, thread}; use std::{mem, os::raw::c_void, ptr::NonNull, thread};
use core_graphics_types::{
base::CGFloat,
geometry::{CGRect, CGSize},
};
use objc::{ use objc::{
class, msg_send, class, msg_send,
rc::autoreleasepool, rc::autoreleasepool,
@ -14,22 +18,6 @@ extern "C" {
static kCAGravityTopLeft: *mut Object; static kCAGravityTopLeft: *mut Object;
} }
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
#[allow(clippy::upper_case_acronyms)]
pub struct CGPoint {
pub x: mtl::CGFloat,
pub y: mtl::CGFloat,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
#[allow(clippy::upper_case_acronyms)]
pub struct CGRect {
pub origin: CGPoint,
pub size: mtl::CGSize,
}
impl super::Surface { impl super::Surface {
fn new(view: Option<NonNull<Object>>, layer: mtl::MetalLayer) -> Self { fn new(view: Option<NonNull<Object>>, layer: mtl::MetalLayer) -> Self {
Self { Self {
@ -117,7 +105,7 @@ impl super::Surface {
let window: *mut Object = msg_send![view, window]; let window: *mut Object = msg_send![view, window];
if !window.is_null() { if !window.is_null() {
let scale_factor: mtl::CGFloat = msg_send![window, backingScaleFactor]; let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
let () = msg_send![layer, setContentsScale: scale_factor]; let () = msg_send![layer, setContentsScale: scale_factor];
} }
//let () = msg_send![layer, setDelegate: self.gfx_managed_metal_layer_delegate.0]; //let () = msg_send![layer, setDelegate: self.gfx_managed_metal_layer_delegate.0];
@ -138,7 +126,7 @@ impl super::Surface {
} }
pub(super) fn dimensions(&self) -> wgt::Extent3d { pub(super) fn dimensions(&self) -> wgt::Extent3d {
let (size, scale): (mtl::CGSize, mtl::CGFloat) = match self.view { let (size, scale): (CGSize, CGFloat) = match self.view {
Some(view) if !cfg!(target_os = "macos") => unsafe { Some(view) if !cfg!(target_os = "macos") => unsafe {
let bounds: CGRect = msg_send![view.as_ptr(), bounds]; let bounds: CGRect = msg_send![view.as_ptr(), bounds];
let window: Option<NonNull<Object>> = msg_send![view.as_ptr(), window]; let window: Option<NonNull<Object>> = msg_send![view.as_ptr(), window];
@ -149,7 +137,7 @@ impl super::Surface {
Some(screen) => { Some(screen) => {
let screen_space: *mut Object = msg_send![screen.as_ptr(), coordinateSpace]; let screen_space: *mut Object = msg_send![screen.as_ptr(), coordinateSpace];
let rect: CGRect = msg_send![view.as_ptr(), convertRect:bounds toCoordinateSpace:screen_space]; let rect: CGRect = msg_send![view.as_ptr(), convertRect:bounds toCoordinateSpace:screen_space];
let scale_factor: mtl::CGFloat = msg_send![screen.as_ptr(), nativeScale]; let scale_factor: CGFloat = msg_send![screen.as_ptr(), nativeScale];
(rect.size, scale_factor) (rect.size, scale_factor)
} }
None => (bounds.size, 1.0), None => (bounds.size, 1.0),
@ -159,7 +147,7 @@ impl super::Surface {
let render_layer_borrow = self.render_layer.lock(); let render_layer_borrow = self.render_layer.lock();
let render_layer = render_layer_borrow.as_ref(); let render_layer = render_layer_borrow.as_ref();
let bounds: CGRect = msg_send![render_layer, bounds]; let bounds: CGRect = msg_send![render_layer, bounds];
let contents_scale: mtl::CGFloat = msg_send![render_layer, contentsScale]; let contents_scale: CGFloat = msg_send![render_layer, contentsScale];
(bounds.size, contents_scale) (bounds.size, contents_scale)
}, },
}; };
@ -186,8 +174,7 @@ impl crate::Surface<super::Api> for super::Surface {
let render_layer = self.render_layer.lock(); let render_layer = self.render_layer.lock();
let framebuffer_only = config.usage == crate::TextureUse::COLOR_TARGET; let framebuffer_only = config.usage == crate::TextureUse::COLOR_TARGET;
let display_sync = config.present_mode != wgt::PresentMode::Immediate; let display_sync = config.present_mode != wgt::PresentMode::Immediate;
let drawable_size = let drawable_size = CGSize::new(config.extent.width as f64, config.extent.height as f64);
mtl::CGSize::new(config.extent.width as f64, config.extent.height as f64);
match config.composite_alpha_mode { match config.composite_alpha_mode {
crate::CompositeAlphaMode::Opaque => render_layer.set_opaque(true), crate::CompositeAlphaMode::Opaque => render_layer.set_opaque(true),

View File

@ -230,14 +230,23 @@ impl super::Instance {
self.create_surface_from_vk_surface_khr(surface) self.create_surface_from_vk_surface_khr(surface)
} }
#[cfg(feature = "disabled")] #[cfg(any(target_os = "macos", target_os = "ios"))]
fn create_surface_from_ns_view(&self, view: *mut c_void) -> super::Surface { fn create_surface_from_ns_view(&self, view: *mut c_void) -> super::Surface {
use ash::extensions::mvk;
use core_graphics_types::{base::CGFloat, geometry::CGRect}; use core_graphics_types::{base::CGFloat, geometry::CGRect};
use objc::runtime::{Object, BOOL, YES}; use objc::{
class, msg_send,
runtime::{Object, BOOL, YES},
sel, sel_impl,
};
// TODO: this logic is duplicated from gfx-backend-metal, refactor? if !self.extensions.contains(&ext::MetalSurface::name()) {
unsafe { panic!(
"Vulkan Portability driver does not support {:?}",
ext::MetalSurface::name()
);
}
let layer = unsafe {
let view = view as *mut Object; let view = view as *mut Object;
let existing: *mut Object = msg_send![view, layer]; let existing: *mut Object = msg_send![view, layer];
let class = class!(CAMetalLayer); let class = class!(CAMetalLayer);
@ -249,7 +258,9 @@ impl super::Instance {
result == YES result == YES
}; };
if !use_current { if use_current {
existing
} else {
let layer: *mut Object = msg_send![class, new]; let layer: *mut Object = msg_send![class, new];
let () = msg_send![view, setLayer: layer]; let () = msg_send![view, setLayer: layer];
let bounds: CGRect = msg_send![view, bounds]; let bounds: CGRect = msg_send![view, bounds];
@ -260,26 +271,18 @@ impl super::Instance {
let scale_factor: CGFloat = msg_send![window, backingScaleFactor]; let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
let () = msg_send![layer, setContentsScale: scale_factor]; let () = msg_send![layer, setContentsScale: scale_factor];
} }
layer
} }
} };
if !self.extensions.contains(&mvk::MacOSSurface::name()) {
panic!("Vulkan driver does not support VK_MVK_MACOS_SURFACE");
}
let surface = { let surface = {
let mac_os_loader = mvk::MacOSSurface::new(&self.entry, &self.shared.raw); let metal_loader = ext::MetalSurface::new(&self.entry, &self.shared.raw);
let mut info = vk::MacOSSurfaceCreateInfoMVK::builder() let vk_info = vk::MetalSurfaceCreateInfoEXT::builder()
.flags(vk::MacOSSurfaceCreateFlagsMVK::empty()); .flags(vk::MetalSurfaceCreateFlagsEXT::empty())
if let Some(view) = unsafe { view.as_ref() } { .layer(layer as *mut _)
info = info.view(view); .build();
}
unsafe { unsafe { metal_loader.create_metal_surface(&vk_info, None).unwrap() }
mac_os_loader
.create_mac_os_surface_mvk(&info, None)
.expect("Unable to create macOS surface")
}
}; };
self.create_surface_from_vk_surface_khr(surface) self.create_surface_from_vk_surface_khr(surface)
@ -542,7 +545,7 @@ impl crate::Instance<super::Api> for super::Instance {
let hinstance = GetModuleHandleW(std::ptr::null()); let hinstance = GetModuleHandleW(std::ptr::null());
Ok(self.create_surface_from_hwnd(hinstance as *mut _, handle.hwnd)) Ok(self.create_surface_from_hwnd(hinstance as *mut _, handle.hwnd))
} }
#[cfg(target_os = "macos_disabled")] #[cfg(target_os = "macos")]
RawWindowHandle::MacOS(handle) => Ok(self.create_surface_from_ns_view(handle.ns_view)), RawWindowHandle::MacOS(handle) => Ok(self.create_surface_from_ns_view(handle.ns_view)),
_ => Err(crate::InstanceError), _ => Err(crate::InstanceError),
} }