Skip to content

Commit

Permalink
Merge #3561
Browse files Browse the repository at this point in the history
3561: [metal] use metal-rs github, implement transparency r=kvark a=kvark

Adds an ability to make surfaces transparent on Metal.
Related to gfx-rs/wgpu#687 (comment)

Co-authored-by: Dzmitry Malyshau <[email protected]>
  • Loading branch information
bors[bot] and kvark authored Jan 3, 2021
2 parents aa9c552 + f457631 commit 83cebfd
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 28 deletions.
3 changes: 2 additions & 1 deletion src/backend/metal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions src/backend/metal/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
6 changes: 4 additions & 2 deletions src/backend/metal/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -23,7 +23,7 @@ use hal::{
use metal::{
CaptureManager, MTLCPUCacheMode, MTLLanguageVersion, MTLPrimitiveTopologyClass,
MTLPrimitiveType, MTLResourceOptions, MTLSamplerMipFilter, MTLStorageMode, MTLTextureType,
MTLVertexStepFunction,
MTLVertexStepFunction, NSRange,
};
use objc::{
rc::autoreleasepool,
Expand Down Expand Up @@ -1301,6 +1301,7 @@ impl hal::device::Device<Backend> 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
Expand Down Expand Up @@ -1336,6 +1337,7 @@ impl hal::device::Device<Backend> 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);
Expand Down
20 changes: 10 additions & 10 deletions src/backend/metal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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()];
Expand Down Expand Up @@ -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];
Expand All @@ -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) }
}

Expand Down Expand Up @@ -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;
}

Expand Down
5 changes: 2 additions & 3 deletions src/backend/metal/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 _,
},
Expand Down
28 changes: 18 additions & 10 deletions src/backend/metal/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -19,7 +18,7 @@ use std::thread;
#[derive(Debug)]
pub struct Surface {
view: Option<NonNull<Object>>,
render_layer: Mutex<metal::CoreAnimationLayer>,
render_layer: Mutex<metal::MetalLayer>,
swapchain_format: metal::MTLPixelFormat,
swapchain_format_desc: format::FormatDesc,
main_thread_id: thread::ThreadId,
Expand All @@ -29,7 +28,7 @@ unsafe impl Send for Surface {}
unsafe impl Sync for Surface {}

impl Surface {
pub fn new(view: Option<NonNull<Object>>, layer: metal::CoreAnimationLayer) -> Self {
pub fn new(view: Option<NonNull<Object>>, layer: metal::MetalLayer) -> Self {
Surface {
view,
render_layer: Mutex::new(layer),
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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<NonNull<Object>> = msg_send![view.as_ptr(), window];
Expand All @@ -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),
Expand All @@ -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)
},
};
Expand All @@ -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
}
}
Expand Down Expand Up @@ -203,7 +209,9 @@ impl w::Surface<Backend> 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
Expand Down

0 comments on commit 83cebfd

Please sign in to comment.