metal-rust 1.0.0

Safe Rust interfaces for Apple Metal
docs.rs failed to build metal-rust-1.0.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Metal-Rust

Safe Rust interfaces for Apple Metal. The API follows the same framework and protocol surface as Apple's metal-cpp, while making Objective-C ownership and message-send invariants private implementation details.

Safety boundary

  • The public metal-rust crate uses #![forbid(unsafe_code)].
  • Raw Objective-C interop is confined to the separately audited metal-rust-ffi workspace crate. That implementation crate is published only so package registries can resolve metal-rust; applications should depend on metal-rust, and both crates expose safe Rust APIs only.
  • Public APIs return owned Rust values and typed RAII objects. They never expose Objective-C pointers, selectors, NSError **, retain/release, or unchecked ranges.
  • APIs whose safety depends on GPU synchronization remain unavailable until resource use and command completion can be tied together by the type system.

The safe facade covers the core Metal submission/resource path, Metal 4 timestamp CounterHeap ownership, device-wide capture, MetalFX spatial and temporal scaler descriptors, and CAMetalLayer drawable ownership. The full metal-cpp reference inventory is tracked in api/metal-cpp-inventory.json, with one explicit implemented or unimplemented status per declaration in api/coverage.json. Only audited facade mappings count as coverage; a transitive generated binding does not.

The audited generated layer currently supplies owned opaque wrappers, safe scalar and struct representations, non-callback aliases, runtime-gated default constructors, and checked property accessors. Generated try_* getters return None when a selector is unavailable; enum setters reject undeclared values, floating-point setters reject non-finite values, and object/string setters keep all Objective-C ownership inside metal-rust-ffi. Methods involving callbacks, raw buffers, synchronization, or API-specific numeric constraints remain explicitly unimplemented until their contracts are represented safely.

Source layout

Framework directories and API filenames intentionally track metal-cpp:

src/
  Foundation/
    Foundation.rs
    NSError.rs
  Metal/
    Metal.rs
    MTLBuffer.rs
    MTLBlitCommandEncoder.rs
    MTLCommandBuffer.rs
    MTLCommandEncoder.rs
    MTLCommandQueue.rs
    MTLRenderPass.rs
    MTLShader.rs
    MTLTexture.rs
    MTLTypes.rs
    MTLDevice.rs
    MTLCaptureManager.rs
    MTL4Counters.rs
  MetalFX/
    MetalFX.rs
    MTLFXSpatialScaler.rs
    MTLFXTemporalScaler.rs
  QuartzCore/
    CAMetalLayer.rs
    QuartzCore.rs

The implementation-only metal-rust-ffi/src/ tree uses the same Foundation/Metal mapping, so an API has a predictable public facade and Objective-C implementation file. Rust module names remain snake_case, while source filenames retain Apple's framework spelling for direct comparison with metal-cpp and SDK declarations.

Safe workflow

The normal workflow is entirely safe Rust: create a Device and CommandQueue, allocate shared Buffer/Texture resources, compile a Library and Function, build a pipeline, encode render/compute/blit work, then commit and wait on the CommandBuffer. GPU-written resource readback is intentionally not exposed yet: completion of an unrelated command buffer is not proof that a particular resource is idle. Layer::next_drawable and CommandBuffer::present_drawable cover presentation when Core Animation can provide a drawable. CaptureSession, MetalFX descriptors, and the Metal 4 counter heap return owned Error values when the installed runtime does not support the requested capability. No resource readback API exposes mapped GPU memory before a resource-specific synchronization model is implemented.

Reference

The API organization and naming are informed by Apple's metal-cpp distribution. metal-cpp and this project are licensed under Apache License 2.0. Objective-C binding generation is provided internally by the Apache/MIT/Zlib-licensed objc2 project; its raw bindings are not re-exported.

Development

Use Conventional Commit subjects in the form type(scope): summary. The reviewed types and scopes live in scripts/conventional-commit-keywords.sh, and the repository hook validates local commit subjects. Install it with:

scripts/install-git-hooks.sh

Before submitting a change, run:

cargo fmt --all -- --check
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
scripts/check-commit-message.sh --self-test
python3 scripts/check-api-coverage.py
python3 scripts/check-safety.py

See RELEASING.md for the crates.io publication order and release checks. General pull-request CI is intentionally deferred; releases use a manual workflow on the organization's macOS runner.