diff --git a/src/backend/metal/Cargo.toml b/src/backend/metal/Cargo.toml index 535f81deaa3..78e148944a9 100644 --- a/src/backend/metal/Cargo.toml +++ b/src/backend/metal/Cargo.toml @@ -30,10 +30,11 @@ bitflags = "1.0" copyless = "0.1.4" log = { version = "0.4" } dispatch = { version = "0.2", optional = true } -metal = { version = "0.20", features = ["private"] } +metal = { git = "https://github.com/gfx-rs/metal-rs", rev="ba08f5f98c70ab941020b8997936c9c75363b9aa", features = ["private"] } foreign-types = "0.3" objc = "0.2.5" block = "0.1" +#TODO: remove this, only used for `Id` cocoa-foundation = "0.1" spirv_cross = { version = "0.22", features = ["msl"] } parking_lot = "0.11" diff --git a/src/backend/metal/src/command.rs b/src/backend/metal/src/command.rs index d8a0349308b..1bec682695f 100644 --- a/src/backend/metal/src/command.rs +++ b/src/backend/metal/src/command.rs @@ -21,12 +21,12 @@ use hal::{ use arrayvec::ArrayVec; use auxil::{FastHashMap, ShaderStage}; use block::ConcreteBlock; -use cocoa_foundation::foundation::{NSRange, NSUInteger}; +use cocoa_foundation::foundation::NSUInteger; use copyless::VecHelper; #[cfg(feature = "dispatch")] use dispatch; use foreign_types::ForeignType; -use metal::{self, MTLIndexType, MTLPrimitiveType, MTLScissorRect, MTLSize, MTLViewport}; +use metal::{self, MTLIndexType, MTLPrimitiveType, MTLScissorRect, MTLSize, MTLViewport, NSRange}; use objc::rc::autoreleasepool; use parking_lot::Mutex; diff --git a/src/backend/metal/src/device.rs b/src/backend/metal/src/device.rs index d1aaf39fb8e..93572cea063 100644 --- a/src/backend/metal/src/device.rs +++ b/src/backend/metal/src/device.rs @@ -7,7 +7,7 @@ use crate::{ use arrayvec::ArrayVec; use auxil::{spirv_cross_specialize_ast, FastHashMap, ShaderStage}; -use cocoa_foundation::foundation::{NSRange, NSUInteger}; +use cocoa_foundation::foundation::NSUInteger; use copyless::VecHelper; use foreign_types::{ForeignType, ForeignTypeRef}; use hal::{ @@ -23,7 +23,7 @@ use hal::{ use metal::{ CaptureManager, MTLCPUCacheMode, MTLLanguageVersion, MTLPrimitiveTopologyClass, MTLPrimitiveType, MTLResourceOptions, MTLSamplerMipFilter, MTLStorageMode, MTLTextureType, - MTLVertexStepFunction, + MTLVertexStepFunction, NSRange, }; use objc::{ rc::autoreleasepool, @@ -1301,6 +1301,7 @@ impl hal::device::Device for Device { MTLLanguageVersion::V2_0 => (2, 0), MTLLanguageVersion::V2_1 => (2, 1), MTLLanguageVersion::V2_2 => (2, 2), + MTLLanguageVersion::V2_3 => (2, 3), }, spirv_cross_compatibility: true, binding_map: res_overrides @@ -1336,6 +1337,7 @@ impl hal::device::Device for Device { MTLLanguageVersion::V2_0 => msl::Version::V2_0, MTLLanguageVersion::V2_1 => msl::Version::V2_1, MTLLanguageVersion::V2_2 => msl::Version::V2_2, + MTLLanguageVersion::V2_3 => msl::Version::V2_2, //TODO: update this! }; shader_compiler_options.enable_point_size_builtin = false; shader_compiler_options.vertex.invert_y = !self.features.contains(hal::Features::NDC_Y_UP); diff --git a/src/backend/metal/src/lib.rs b/src/backend/metal/src/lib.rs index 5c51cb91a75..987ca896651 100644 --- a/src/backend/metal/src/lib.rs +++ b/src/backend/metal/src/lib.rs @@ -71,7 +71,7 @@ use foreign_types::ForeignTypeRef; use lazy_static::lazy_static; use metal::MTLFeatureSet; use metal::MTLLanguageVersion; -use metal::{CGFloat, CGSize, CoreAnimationLayer, CoreAnimationLayerRef}; +use metal::{CGFloat, CGSize, MetalLayer, MetalLayerRef}; use objc::{ declare::ClassDecl, runtime::{Class, Object, Sel, BOOL, YES}, @@ -361,11 +361,11 @@ impl Instance { let class = class!(CAMetalLayer); let is_valid_layer: BOOL = msg_send![main_layer, isKindOfClass: class]; let render_layer = if is_valid_layer == YES { - mem::transmute::<_, &CoreAnimationLayerRef>(main_layer).to_owned() + mem::transmute::<_, &MetalLayerRef>(main_layer).to_owned() } else { // If the main layer is not a CAMetalLayer, we create a CAMetalLayer sublayer and use it instead. // Unlike on macOS, we cannot replace the main view as UIView does not allow it (when NSView does). - let new_layer: CoreAnimationLayer = msg_send![class, new]; + let new_layer: MetalLayer = msg_send![class, new]; let bounds: CGRect = msg_send![main_layer, bounds]; let () = msg_send![new_layer.as_ref(), setFrame: bounds]; let () = msg_send![main_layer, addSublayer: new_layer.as_ref()]; @@ -407,10 +407,10 @@ impl Instance { result == YES }; - let render_layer: CoreAnimationLayer = if use_current { - mem::transmute::<_, &CoreAnimationLayerRef>(existing).to_owned() + let render_layer: MetalLayer = if use_current { + mem::transmute::<_, &MetalLayerRef>(existing).to_owned() } else { - let layer: CoreAnimationLayer = msg_send![class, new]; + let layer: MetalLayer = msg_send![class, new]; let () = msg_send![view, setLayer: layer.as_ref()]; let () = msg_send![view, setWantsLayer: YES]; let bounds: CGRect = msg_send![view, bounds]; @@ -429,14 +429,14 @@ impl Instance { Surface::new(NonNull::new(view), render_layer) } - unsafe fn create_from_layer(&self, layer: &CoreAnimationLayerRef) -> Surface { + unsafe fn create_from_layer(&self, layer: &MetalLayerRef) -> Surface { let class = class!(CAMetalLayer); let proper_kind: BOOL = msg_send![layer, isKindOfClass: class]; assert_eq!(proper_kind, YES); Surface::new(None, layer.to_owned()) } - pub fn create_surface_from_layer(&self, layer: &CoreAnimationLayerRef) -> Surface { + pub fn create_surface_from_layer(&self, layer: &MetalLayerRef) -> Surface { unsafe { self.create_from_layer(layer) } } @@ -785,10 +785,10 @@ impl PrivateCapabilities { let os_is_mac = device.supports_feature_set(MTLFeatureSet::macOS_GPUFamily1_v1); let mut sample_count_mask: u8 = 1 | 4; // 1 and 4 samples are supported on all devices - if device.supports_sample_count(2) { + if device.supports_texture_sample_count(2) { sample_count_mask |= 2; } - if device.supports_sample_count(8) { + if device.supports_texture_sample_count(8) { sample_count_mask |= 8; } diff --git a/src/backend/metal/src/native.rs b/src/backend/metal/src/native.rs index 0f7e7d18334..eb483b9cb2c 100644 --- a/src/backend/metal/src/native.rs +++ b/src/backend/metal/src/native.rs @@ -15,7 +15,6 @@ use hal::{ use range_alloc::RangeAllocator; use arrayvec::ArrayVec; -use cocoa_foundation::foundation::NSRange; use metal; use parking_lot::RwLock; use spirv_cross::{msl, spirv}; @@ -352,11 +351,11 @@ impl Image { Some(raw.new_texture_view_from_slice( self.mtl_format, metal::MTLTextureType::D2Array, - NSRange { + metal::NSRange { location: 0, length: raw.mipmap_level_count(), }, - NSRange { + metal::NSRange { location: 0, length: self.kind.num_layers() as _, }, diff --git a/src/backend/metal/src/window.rs b/src/backend/metal/src/window.rs index fe3276a6e48..07af7c2a21c 100644 --- a/src/backend/metal/src/window.rs +++ b/src/backend/metal/src/window.rs @@ -7,7 +7,6 @@ use crate::{ use hal::{format, image, window as w}; use crate::CGRect; -use metal::{CGFloat, CGSize, CoreAnimationDrawable}; use objc::rc::autoreleasepool; use objc::runtime::Object; use parking_lot::Mutex; @@ -19,7 +18,7 @@ use std::thread; #[derive(Debug)] pub struct Surface { view: Option>, - render_layer: Mutex, + render_layer: Mutex, swapchain_format: metal::MTLPixelFormat, swapchain_format_desc: format::FormatDesc, main_thread_id: thread::ThreadId, @@ -29,7 +28,7 @@ unsafe impl Send for Surface {} unsafe impl Sync for Surface {} impl Surface { - pub fn new(view: Option>, layer: metal::CoreAnimationLayer) -> Self { + pub fn new(view: Option>, layer: metal::MetalLayer) -> Self { Surface { view, render_layer: Mutex::new(layer), @@ -68,7 +67,14 @@ impl Surface { caps.has_version_at_least(11, 0) }; let can_set_display_sync = is_mac && caps.has_version_at_least(10, 13); - let drawable_size = CGSize::new(config.extent.width as f64, config.extent.height as f64); + let drawable_size = + metal::CGSize::new(config.extent.width as f64, config.extent.height as f64); + + match config.composite_alpha_mode { + w::CompositeAlphaMode::OPAQUE => render_layer.set_opaque(true), + w::CompositeAlphaMode::POSTMULTIPLIED => render_layer.set_opaque(false), + _ => (), + } let device_raw = shared.device.lock(); unsafe { @@ -104,7 +110,7 @@ impl Surface { } fn dimensions(&self) -> w::Extent2D { - let (size, scale): (CGSize, CGFloat) = match self.view { + let (size, scale): (metal::CGSize, metal::CGFloat) = match self.view { Some(view) if !cfg!(target_os = "macos") => unsafe { let bounds: CGRect = msg_send![view.as_ptr(), bounds]; let window: Option> = msg_send![view.as_ptr(), window]; @@ -115,7 +121,7 @@ impl 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: CGFloat = msg_send![screen.as_ptr(), nativeScale]; + let scale_factor: metal::CGFloat = msg_send![screen.as_ptr(), nativeScale]; (rect.size, scale_factor) } None => (bounds.size, 1.0), @@ -125,7 +131,7 @@ impl 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: CGFloat = msg_send![render_layer, contentsScale]; + let contents_scale: metal::CGFloat = msg_send![render_layer, contentsScale]; (bounds.size, contents_scale) }, }; @@ -152,14 +158,14 @@ impl Default for AcquireMode { pub struct SwapchainImage { image: native::Image, view: native::ImageView, - drawable: metal::CoreAnimationDrawable, + drawable: metal::MetalDrawable, } unsafe impl Send for SwapchainImage {} unsafe impl Sync for SwapchainImage {} impl SwapchainImage { - pub(crate) fn into_drawable(self) -> CoreAnimationDrawable { + pub(crate) fn into_drawable(self) -> metal::MetalDrawable { self.drawable } } @@ -203,7 +209,9 @@ impl w::Surface for Surface { } else { w::PresentMode::FIFO }, - composite_alpha_modes: w::CompositeAlphaMode::OPAQUE, //TODO + composite_alpha_modes: w::CompositeAlphaMode::OPAQUE + | w::CompositeAlphaMode::POSTMULTIPLIED + | w::CompositeAlphaMode::INHERIT, //Note: this is hardcoded in `CAMetalLayer` documentation image_count: if can_set_maximum_drawables_count { 2..=3