metrale_gpu_runtime/gpu/handles.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: Opaque device handles and the typed kernel argument every backend
4//! accepts.
5//!
6//! Owner: gpu-runtime.
7//! Invariants: none beyond the types.
8
9use super::*;
10
11/// 2026-09-25: A device address: a `CUdeviceptr` on CUDA, an `MTLBuffer`
12/// `gpuAddress` on Metal. 0 is null.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub struct DevicePtr(pub u64);
15
16impl DevicePtr {
17 pub const NULL: Self = Self(0);
18
19 pub fn is_null(self) -> bool {
20 self.0 == 0
21 }
22
23 /// 2026-09-25: The address `bytes` past this one.
24 pub fn offset(self, bytes: usize) -> Self {
25 Self(self.0 + bytes as u64)
26 }
27}
28
29/// 2026-09-25: A kernel function: a `CUfunction` on CUDA, a pipeline slab index
30/// on Metal.
31#[derive(Debug, Clone, Copy)]
32pub struct KernelHandle(pub u64);
33
34/// 2026-09-25: An instantiated CUDA graph (`CUgraphExec`).
35#[derive(Debug, Clone, Copy)]
36pub struct GraphHandle(pub u64);
37
38/// 2026-09-25: A typed kernel argument for `launch_typed`. The Metal backend
39/// binds buffers with `setBuffer:offset:atIndex:` and bytes with
40/// `setBytes:length:atIndex:`; CUDA packs both into parameter slots.
41#[derive(Debug, Clone, Copy)]
42pub enum KernelArg<'a> {
43 /// 2026-09-25: A device address. The Metal backend resolves it to its
44 /// owning `MTLBuffer` and offset; CUDA passes the `u64` as is.
45 Buffer(DevicePtr),
46 /// 2026-09-25: Scalar or struct bytes, passed by value. CUDA packs them into
47 /// 8-byte slots, zero-padding the last (`pack_kernel_args`).
48 Bytes(&'a [u8]),
49}
50
51impl fmt::Display for DevicePtr {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "DevicePtr(0x{:x})", self.0)
54 }
55}