Skip to main content

nuvec_gpu/
lib.rs

1//! Metal backend: device discovery, kernel library and pipelines, shared buffers, and
2//! command encoding with minimal barriers.
3//!
4//! ```no_run
5//! # #[cfg(target_os = "macos")]
6//! # fn main() -> nuvec_gpu::Result<()> {
7//! use nuvec_gpu::{Arg, Device};
8//!
9//! let Some(device) = Device::system_default() else { return Ok(()) }; // no Metal here
10//! let add = device.pipeline("nuvec_add_f32")?;
11//! let a = device.buffer_from(&1.0f32.to_le_bytes().repeat(4))?;
12//! let b = device.buffer_from(&2.0f32.to_le_bytes().repeat(4))?;
13//! let mut out = device.new_buffer(16)?;
14//! let mut cmd = device.command_buffer()?;
15//! cmd.dispatch(&add, &[Arg::read(&a), Arg::read(&b), Arg::write(&mut out), Arg::bytes(&4u32.to_le_bytes())], 4)?;
16//! cmd.commit().wait()?;
17//! assert_eq!(&out.contents()?[..4], &3.0f32.to_le_bytes());
18//! # Ok(())
19//! # }
20//! # #[cfg(not(target_os = "macos"))]
21//! # fn main() {} // Metal exists only on Apple platforms
22//! ```
23//!
24//! Buffers live in shared (unified) memory: the CPU reads GPU results in place. CPU access
25//! is refused while submitted work uses a buffer, and GPU writes need `&mut Buffer`, so
26//! CPU and GPU never race on the same memory.
27//!
28//! Arrays evaluated on the GPU (`nuvec-core`) use the process-wide [`Device::shared`]; its
29//! allocator's limits and statistics are set and read there.
30
31mod error;
32mod info;
33mod memory;
34
35pub use error::{GpuError, Result};
36pub use info::DeviceInfo;
37pub use memory::MemoryStats;
38
39#[cfg(target_os = "macos")]
40mod metal;
41#[cfg(target_os = "macos")]
42pub use metal::{
43    Arg, Buffer, CommandBuffer, Constant, Device, Pending, Pipeline, Submitted, Timeline, profile,
44};
45
46#[cfg(not(target_os = "macos"))]
47mod stub;
48#[cfg(not(target_os = "macos"))]
49pub use stub::{Device, profile};
50
51/// The version of this crate.
52pub const VERSION: &str = env!("CARGO_PKG_VERSION");
53
54#[cfg(test)]
55mod tests {
56    #[test]
57    fn version_is_set() {
58        assert!(!super::VERSION.is_empty());
59        let _ = nuvec_kernels::MODE;
60    }
61}