Skip to content

Commit

Permalink
metal: Migrate to objc2 architecture with objc2-metal bindings
Browse files Browse the repository at this point in the history
The current `objc` crate stack is completely unmaintained and has
severely fallen out of date with no updates for over 4 years.  The
`metal-rs` crate, built on top of this architecture, is completely
written by hand which is tedious to keep up-to-date, not to mention
has inconsistencies in its implementation.

All of this is superseded by the new `objc2` crate stack built by
@madsmtm.  Beyond providing what seems like a better, safer abstraction
over Objective-C, _all_ bindings are completely autogenerated meaning
we'll no longer lag behind upstream bindings (requiring painstaking
manual patching) or have inconsistencies in the implementations, as long
as the generator is properly able to represent the bindings.
  • Loading branch information
MarijnS95 committed May 4, 2024
1 parent cbf5299 commit 2ed732e
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 105 deletions.
25 changes: 19 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,18 @@ egui = { version = ">=0.24, <=0.27", optional = true, default-features = false }
egui_extras = { version = ">=0.24, <=0.27", optional = true, default-features = false }

[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
metal = { version = "0.27.0", default-features = false, features = ["link", "dispatch"], optional = true }
objc2 = { version = "0.5", default-features = false, optional = true }
objc2-foundation = { version = "0.2", default-features = false, optional = true }
objc2-metal = { version = "0.2.0", default-features = false, features = [
"MTLAccelerationStructure",
"MTLBuffer",
"MTLDevice",
"MTLHeap",
# "MTLPixelFormat",
"MTLResource",
"MTLTexture",
"std",
], optional = true }

[target.'cfg(windows)'.dependencies]
# Only needed for public-winapi interop helpers
Expand Down Expand Up @@ -71,6 +82,11 @@ features = [
"Win32_Graphics_Dxgi_Common",
]

[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dev-dependencies]
objc2-metal = { version = "0.2.0", default-features = false, features = [
"MTLPixelFormat",
] }

[[example]]
name = "vulkan-buffer"
required-features = ["vulkan", "ash/loaded"]
Expand All @@ -91,11 +107,8 @@ required-features = ["metal"]
visualizer = ["dep:egui", "dep:egui_extras"]
vulkan = ["dep:ash"]
d3d12 = ["dep:windows"]
metal = ["dep:metal"]
metal = ["dep:objc2", "dep:objc2-metal", "dep:objc2-foundation"]
# Expose helper functionality for winapi types to interface with gpu-allocator, which is primarily windows-rs driven
public-winapi = ["dep:winapi"]

default = ["d3d12", "vulkan"]

[patch.crates-io]
metal = { git = "https://github.com/Traverse-Research/metal-rs", rev = "a354c33" }
default = ["d3d12", "vulkan", "metal"]
28 changes: 17 additions & 11 deletions examples/metal-buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ use std::sync::Arc;

use gpu_allocator::metal::{AllocationCreateDesc, Allocator, AllocatorCreateDesc};
use log::info;
use metal::MTLDevice as _;
use objc2::rc::Id;
use objc2_foundation::NSArray;
use objc2_metal as metal;

fn main() {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();

let device = Arc::new(metal::Device::system_default().unwrap());
let device = unsafe { metal::MTLCreateSystemDefaultDevice() };
// TODO: Not SendSync
let device = Arc::new(unsafe { Id::from_raw(device) }.expect("No MTLDevice found"));

// Setting up the allocator
let mut allocator = Allocator::new(&AllocatorCreateDesc {
Expand Down Expand Up @@ -60,11 +66,11 @@ fn main() {

// Test allocating texture
{
let texture_desc = metal::TextureDescriptor::new();
texture_desc.set_pixel_format(metal::MTLPixelFormat::RGBA8Unorm);
texture_desc.set_width(64);
texture_desc.set_height(64);
texture_desc.set_storage_mode(metal::MTLStorageMode::Private);
let texture_desc = unsafe { metal::MTLTextureDescriptor::new() };
texture_desc.setPixelFormat(metal::MTLPixelFormat::RGBA8Unorm);
unsafe { texture_desc.setWidth(64) };
unsafe { texture_desc.setHeight(64) };
texture_desc.setStorageMode(metal::MTLStorageMode::Private);
let allocation_desc =
AllocationCreateDesc::texture(&device, "Test allocation (Texture)", &texture_desc);
let allocation = allocator.allocate(&allocation_desc).unwrap();
Expand All @@ -75,14 +81,14 @@ fn main() {

// Test allocating acceleration structure
{
let empty_array = metal::Array::from_slice(&[]);
let acc_desc = metal::PrimitiveAccelerationStructureDescriptor::descriptor();
acc_desc.set_geometry_descriptors(empty_array);
let sizes = device.acceleration_structure_sizes_with_descriptor(&acc_desc);
let empty_array = NSArray::from_slice(&[]);
let acc_desc = metal::MTLPrimitiveAccelerationStructureDescriptor::descriptor();
acc_desc.setGeometryDescriptors(Some(&empty_array));
let sizes = device.accelerationStructureSizesWithDescriptor(&acc_desc);
let allocation_desc = AllocationCreateDesc::acceleration_structure_with_size(
&device,
"Test allocation (Acceleration structure)",
sizes.acceleration_structure_size,
sizes.accelerationStructureSize as u64,
gpu_allocator::MemoryLocation::GpuOnly,
);
let allocation = allocator.allocate(&allocation_desc).unwrap();
Expand Down
2 changes: 0 additions & 2 deletions src/d3d12/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![deny(clippy::unimplemented, clippy::unwrap_used, clippy::ok_expect)]

use std::{backtrace::Backtrace, fmt, sync::Arc};

use log::{debug, warn, Level};
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
//! # #[cfg(not(feature = "metal"))]
//! # fn main() {}
//! ```
#![deny(clippy::unimplemented, clippy::unwrap_used, clippy::ok_expect)]

mod result;
pub use result::*;
Expand Down
Loading

0 comments on commit 2ed732e

Please sign in to comment.