Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 0 additions & 35 deletions .cargo/audit.toml
Original file line number Diff line number Diff line change
Expand Up @@ -137,39 +137,4 @@ ignore = [
# cargo tree --workspace | grep -cE "h2 v0.3" -> 0
# REMOVE WHEN aws-smithy-http-client drops hyper 0.14.
"RUSTSEC-2026-0258", # h2 0.3.27 via optional s3 feature only

# manzana 0.2.0 stubbed cryptography. CONTAINMENT ONLY - remove per the
# condition at the bottom of this block, which is NOT "when a new manzana
# ships".
#
# The advisory is about `manzana::secure_enclave::SecureEnclaveSigner`, whose
# sign() derives a "signature" from public values only and whose verify()
# merely recomputes sign() and compares. aprender does not touch any of it.
# Reachability measured on a clean origin/main worktree, x86_64 Linux, using
# the absolute cargo binary (a `cargo` shell function on the dev box shadows
# it and silently redirects CARGO_TARGET_DIR):
# cargo tree -p aprender-gpu | grep -c manzana -> 0
# cargo tree -p aprender-gpu --features metal | grep -c manzana -> 0
# cargo tree --workspace | grep -c manzana -> 0
# git grep -l 'secure_enclave|SecureEnclave' -- '*.rs' -> 0 files
# The middle line is the load-bearing one: manzana is BOTH optional and
# declared under [target.'cfg(target_os = "macos")'.dependencies], so
# enabling `metal` on Linux still pulls in nothing. aprender's only three
# call sites are `manzana::metal::*` in aprender-gpu/src/backend/mod.rs,
# every one behind cfg(all(target_os = "macos", feature = "metal")).
# As with the h2 entry above, cargo-deny already passes without an exemption
# because it walks the ACTIVATED graph; cargo-audit scans Cargo.lock, which
# lists target- and feature-gated deps unconditionally.
#
# WHY AN IGNORE RATHER THAN AN UPGRADE. Both published versions (0.1.0 and
# 0.2.0) are YANKED, so there is nothing to bump to - `max_version` on
# crates.io reads 0.0.0. More importantly the advisory carries
# `[versions] patched = []`, which means NO version is considered fixed:
# publishing a corrected manzana does NOT clear this gate on its own. Only
# amending the upstream advisory to name a patched range does.
#
# REMOVE WHEN either the advisory gains a patched range and this workspace is
# on a version inside it, or the manzana dependency is dropped from
# aprender-gpu entirely. Publishing a new manzana alone is NOT the condition.
"RUSTSEC-2026-0273", # manzana 0.2.0 stubbed crypto; unreachable here, see above
]
15 changes: 0 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions crates/aprender-gpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ crossterm = { version = "0.28", optional = true }
# WGPU for cross-platform WebGPU compute (Vulkan/Metal/DX12/WebGPU)
wgpu = { version = "24", optional = true }

# Apple Metal backend via manzana (macOS only)
[target.'cfg(target_os = "macos")'.dependencies]
manzana = { version = "0.2.0", optional = true }

[dev-dependencies]
proptest = "1.9"
criterion = { workspace = true }
Expand Down Expand Up @@ -81,8 +77,6 @@ tui-monitor = ["stress-test", "dep:crossterm"]
gpu-pixels = ["dep:crossterm"]
# WGPU backend for cross-platform GPU compute (WebGPU via wgpu crate)
wgpu = ["dep:wgpu"]
# Apple Metal backend via manzana (macOS only)
metal = ["dep:manzana"]

[package.metadata.wasm-pack.profile.release]
wasm-opt = false
Expand Down
10 changes: 7 additions & 3 deletions crates/aprender-gpu/src/backend/metal_shaders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
//!
//! # Usage
//!
//! These are source strings only. This crate contains no Metal dispatcher, so
//! nothing here compiles or runs them -- pass a constant to a Metal API of your
//! own (`MTLDevice::newLibraryWithSource`), or use the `wgpu` feature, which
//! reaches Apple GPUs through wgpu's Metal backend and does execute.
//!
//! ```ignore
//! use trueno_gpu::backend::metal_shaders;
//! use aprender_gpu::backend::metal_shaders;
//!
//! let compute = MetalCompute::default_device()?;
//! let shader = compute.compile_shader(metal_shaders::ELEMENTWISE_ADD, "elementwise_add")?;
//! let msl: &str = metal_shaders::ELEMENTWISE_ADD; // kernel name: "elementwise_add"
//! ```

/// Element-wise vector addition kernel
Expand Down
30 changes: 8 additions & 22 deletions crates/aprender-gpu/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
//! Provides a unified interface for different GPU backends:
//! - CUDA (NVIDIA) - Primary, uses PTX
//! - WGPU (WebGPU) - Cross-platform, uses WGSL (Vulkan/Metal/DX12/WebGPU)
//! - Metal (Apple) - Native Apple GPU compute via manzana crate
//! - Metal (Apple) - shader source only; no dispatcher (see `metal_shaders`)
//! - Vulkan (cross-platform, future)

#[cfg(all(target_os = "macos", feature = "metal"))]
pub mod metal_shaders;

/// Backend trait for GPU operations
Expand Down Expand Up @@ -57,10 +56,13 @@ impl Backend for CudaBackend {
}
}

/// Metal backend (Apple GPUs)
/// Metal backend (Apple GPUs) - placeholder
///
/// Uses manzana crate for safe Rust Metal bindings on macOS.
/// Enable with `--features metal` on macOS.
/// Reports unavailable on every platform. This crate contains Metal shader
/// source (`metal_shaders`) but no dispatcher: nothing here calls
/// `MTLDevice::newLibraryWithSource` or `MTLComputeCommandEncoder`. On macOS,
/// use the `wgpu` feature, which reaches Apple GPUs through wgpu's Metal
/// backend and does execute.
#[derive(Debug, Default)]
pub struct MetalBackend;

Expand All @@ -69,31 +71,15 @@ impl Backend for MetalBackend {
"Metal"
}

#[cfg(all(target_os = "macos", feature = "metal"))]
fn is_available(&self) -> bool {
manzana::metal::is_available()
false // No dispatcher; see struct docs.
}

#[cfg(not(all(target_os = "macos", feature = "metal")))]
fn is_available(&self) -> bool {
false
}

#[cfg(all(target_os = "macos", feature = "metal"))]
fn device_count(&self) -> usize {
manzana::metal::MetalCompute::devices().len()
}

#[cfg(not(all(target_os = "macos", feature = "metal")))]
fn device_count(&self) -> usize {
0
}
}

/// Metal device information (re-exported from manzana when feature enabled)
#[cfg(all(target_os = "macos", feature = "metal"))]
pub use manzana::metal::{CompiledShader as MetalShader, MetalBuffer, MetalCompute, MetalDevice};

/// Vulkan backend (cross-platform) - placeholder
#[derive(Debug, Default)]
pub struct VulkanBackend;
Expand Down
36 changes: 4 additions & 32 deletions crates/aprender-gpu/src/backend/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,11 @@ fn test_cuda_backend_name() {
}

#[test]
#[cfg(not(all(target_os = "macos", feature = "metal")))]
fn test_metal_backend_unavailable() {
let backend = MetalBackend;
assert!(!backend.is_available());
}

#[test]
#[cfg(all(target_os = "macos", feature = "metal"))]
fn test_metal_backend_available() {
let backend = MetalBackend;
// On macOS with metal feature, should detect GPUs
assert!(backend.is_available(), "Metal should be available on macOS");
assert!(
backend.device_count() > 0,
"Should have at least one Metal device"
);
}

#[test]
fn test_detect_backend() {
let backend = detect_backend();
Expand Down Expand Up @@ -60,23 +47,11 @@ fn test_cuda_backend_device_count() {
}

#[test]
#[cfg(not(all(target_os = "macos", feature = "metal")))]
fn test_metal_backend_device_count() {
let backend = MetalBackend;
assert_eq!(backend.device_count(), 0);
}

#[test]
#[cfg(all(target_os = "macos", feature = "metal"))]
fn test_metal_backend_device_count_macos() {
let backend = MetalBackend;
// On macOS with metal feature, should have at least 1 GPU
assert!(
backend.device_count() >= 1,
"Should have at least one Metal device"
);
}

#[test]
fn test_vulkan_backend_device_count() {
let backend = VulkanBackend;
Expand Down Expand Up @@ -286,13 +261,10 @@ fn test_detect_backend_wgpu_priority_over_metal_and_vulkan() {

#[test]
fn test_detect_backend_metal_not_returned_on_linux() {
// On Linux (non-macOS without metal feature), Metal should never be returned
#[cfg(not(all(target_os = "macos", feature = "metal")))]
{
let metal = MetalBackend;
assert!(!metal.is_available());
// Metal branch in detect_backend is unreachable on Linux
}
// MetalBackend has no dispatcher, so it never reports available and the
// Metal branch in detect_backend is unreachable on every platform.
let metal = MetalBackend;
assert!(!metal.is_available());
}

#[test]
Expand Down
Loading
Loading