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 Jul 7, 2024
1 parent 10f30f7 commit a905b33
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 103 deletions.
9 changes: 0 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,6 @@ jobs:
uses: dtolnay/rust-toolchain@nightly
- name: Generate lockfile with minimal dependency versions
run: cargo +nightly generate-lockfile -Zminimal-versions
- name: Bump `libc 0.1` version to `0.2` via `malloc_buf 0.0.6`
if: ${{ runner.os == 'macOS' }}
run: |
# The 7-year-unmaintained malloc_buf (depended on via metal-rs->objc)
# only allows using libc 0.2 since the 0.0.6 release, which is necessary
# since the libc 0.1 range no longer compiles. Fortunately objc which
# is also unmaintained for 4 years depends on malloc_buf >=0.0,<0.1.0,
# allowing the 0.0.6 release to be used (but not the 1.0.0 release).
cargo update -p malloc_buf --precise 0.0.6
- name: Cargo clippy with minimal-versions
run: cargo +stable clippy --workspace --all-targets --features ${{ matrix.features }} --no-default-features -- -D warnings

Expand Down
21 changes: 18 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,17 @@ 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.28.0", git = "https://github.com/gfx-rs/metal-rs", rev = "0d6214f", 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.2", default-features = false, features = [
"MTLAccelerationStructure",
"MTLBuffer",
"MTLDevice",
"MTLHeap",
"MTLResource",
"MTLTexture",
"std",
], optional = true }

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

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

[[example]]
name = "vulkan-buffer"
required-features = ["vulkan", "ash/loaded"]
Expand All @@ -84,8 +99,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"]
default = ["d3d12", "vulkan", "metal"]
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ allocator.free(allocation).unwrap();

```rust
use gpu_allocator::metal::*;

use objc2_metal as metal;
let mut allocator = Allocator::new(&AllocatorCreateDesc {
device: device.clone(),
debug_settings: Default::default(),
Expand All @@ -146,12 +146,12 @@ let mut allocator = Allocator::new(&AllocatorCreateDesc {
```rust
use gpu_allocator::metal::*;
use gpu_allocator::MemoryLocation;

use objc2_metal as metal;
let allocation_desc = AllocationCreateDesc::buffer(
&device,
"Example allocation",
512, // size in bytes
gpu_allocator::MemoryLocation::GpuOnly,
MemoryLocation::GpuOnly,
);
let allocation = allocator.allocate(&allocation_desc).unwrap();
let resource = allocation.make_buffer().unwrap();
Expand Down
30 changes: 17 additions & 13 deletions examples/metal-buffer.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
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 = 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 +64,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 +79,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
17 changes: 10 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,11 @@
//! ```no_run
//! # #[cfg(feature = "metal")]
//! # fn main() {
//! # use std::sync::Arc;
//! use gpu_allocator::metal::*;
//!
//! # let device = Arc::new(metal::Device::system_default().unwrap());
//! # use objc2::rc::Id;
//! use objc2_metal as metal;
//! # let device = unsafe { metal::MTLCreateSystemDefaultDevice() };
//! # let device = unsafe { Id::from_raw(device) }.expect("No MTLDevice found");
//! let mut allocator = Allocator::new(&AllocatorCreateDesc {
//! device: device.clone(),
//! debug_settings: Default::default(),
Expand All @@ -179,22 +180,23 @@
//! ```no_run
//! # #[cfg(feature = "metal")]
//! # fn main() {
//! # use std::sync::Arc;
//! use gpu_allocator::metal::*;
//! use gpu_allocator::MemoryLocation;
//! # let device = Arc::new(metal::Device::system_default().unwrap());
//! # use objc2::rc::Id;
//! use objc2_metal as metal;
//! # let device = unsafe { metal::MTLCreateSystemDefaultDevice() };
//! # let device = unsafe { Id::from_raw(device) }.expect("No MTLDevice found");
//! # let mut allocator = Allocator::new(&AllocatorCreateDesc {
//! # device: device.clone(),
//! # debug_settings: Default::default(),
//! # allocation_sizes: Default::default(),
//! # })
//! # .unwrap();
//!
//! let allocation_desc = AllocationCreateDesc::buffer(
//! &device,
//! "Example allocation",
//! 512, // size in bytes
//! gpu_allocator::MemoryLocation::GpuOnly,
//! MemoryLocation::GpuOnly,
//! );
//! let allocation = allocator.allocate(&allocation_desc).unwrap();
//! let resource = allocation.make_buffer().unwrap();
Expand All @@ -206,6 +208,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 a905b33

Please sign in to comment.