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

View File

@ -13,7 +13,7 @@ license = "MIT OR Apache-2.0"
[features]
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"]
[dependencies]
@ -31,8 +31,6 @@ log = "0.4"
# backend: Metal
block = { version = "0.1", 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
ash = { version = "0.32", 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 }
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]
git = "https://github.com/gfx-rs/naga"
tag = "gfx-25"

View File

@ -1,5 +1,9 @@
use std::{mem, os::raw::c_void, ptr::NonNull, thread};
use core_graphics_types::{
base::CGFloat,
geometry::{CGRect, CGSize},
};
use objc::{
class, msg_send,
rc::autoreleasepool,
@ -14,22 +18,6 @@ extern "C" {
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 {
fn new(view: Option<NonNull<Object>>, layer: mtl::MetalLayer) -> Self {
Self {
@ -117,7 +105,7 @@ impl super::Surface {
let window: *mut Object = msg_send![view, window];
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, setDelegate: self.gfx_managed_metal_layer_delegate.0];
@ -138,7 +126,7 @@ impl super::Surface {
}
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 {
let bounds: CGRect = msg_send![view.as_ptr(), bounds];
let window: Option<NonNull<Object>> = msg_send![view.as_ptr(), window];
@ -149,7 +137,7 @@ impl super::Surface {
Some(screen) => {
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 scale_factor: mtl::CGFloat = msg_send![screen.as_ptr(), nativeScale];
let scale_factor: CGFloat = msg_send![screen.as_ptr(), nativeScale];
(rect.size, scale_factor)
}
None => (bounds.size, 1.0),
@ -159,7 +147,7 @@ impl super::Surface {
let render_layer_borrow = self.render_layer.lock();
let render_layer = render_layer_borrow.as_ref();
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)
},
};
@ -186,8 +174,7 @@ impl crate::Surface<super::Api> for super::Surface {
let render_layer = self.render_layer.lock();
let framebuffer_only = config.usage == crate::TextureUse::COLOR_TARGET;
let display_sync = config.present_mode != wgt::PresentMode::Immediate;
let drawable_size =
mtl::CGSize::new(config.extent.width as f64, config.extent.height as f64);
let drawable_size = CGSize::new(config.extent.width as f64, config.extent.height as f64);
match config.composite_alpha_mode {
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)
}
#[cfg(feature = "disabled")]
#[cfg(any(target_os = "macos", target_os = "ios"))]
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 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?
unsafe {
if !self.extensions.contains(&ext::MetalSurface::name()) {
panic!(
"Vulkan Portability driver does not support {:?}",
ext::MetalSurface::name()
);
}
let layer = unsafe {
let view = view as *mut Object;
let existing: *mut Object = msg_send![view, layer];
let class = class!(CAMetalLayer);
@ -249,7 +258,9 @@ impl super::Instance {
result == YES
};
if !use_current {
if use_current {
existing
} else {
let layer: *mut Object = msg_send![class, new];
let () = msg_send![view, setLayer: layer];
let bounds: CGRect = msg_send![view, bounds];
@ -260,26 +271,18 @@ impl super::Instance {
let scale_factor: CGFloat = msg_send![window, backingScaleFactor];
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 mac_os_loader = mvk::MacOSSurface::new(&self.entry, &self.shared.raw);
let mut info = vk::MacOSSurfaceCreateInfoMVK::builder()
.flags(vk::MacOSSurfaceCreateFlagsMVK::empty());
if let Some(view) = unsafe { view.as_ref() } {
info = info.view(view);
}
let metal_loader = ext::MetalSurface::new(&self.entry, &self.shared.raw);
let vk_info = vk::MetalSurfaceCreateInfoEXT::builder()
.flags(vk::MetalSurfaceCreateFlagsEXT::empty())
.layer(layer as *mut _)
.build();
unsafe {
mac_os_loader
.create_mac_os_surface_mvk(&info, None)
.expect("Unable to create macOS surface")
}
unsafe { metal_loader.create_metal_surface(&vk_info, None).unwrap() }
};
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());
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)),
_ => Err(crate::InstanceError),
}