metrale_gpu_runtime/
gpu_args.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-25: Packing typed kernel arguments into the driver's u64 parameter
4//! slots.
5//!
6//! Owner: gpu-runtime.
7//! Invariants:
8//! - `starts` has one entry per argument, in order, pointing at its first slot.
9//! - Every byte of every argument is copied; none is truncated.
10
11use crate::gpu::KernelArg;
12
13/// 2026-09-25: Pack typed args into u64 slots; returns the slots and each
14/// argument's starting slot index.
15///
16/// A buffer takes one slot. A byte argument takes `ceil(len / 8)` consecutive
17/// slots (one when empty), little-endian, the last zero-padded; a 128-byte
18/// `CUtensorMap` takes 16. Each argument contributes one entry to `starts`.
19pub fn pack_kernel_args(args: &[KernelArg<'_>]) -> (Vec<u64>, Vec<usize>) {
20    let total_slots: usize = args
21        .iter()
22        .map(|a| match a {
23            KernelArg::Buffer(_) => 1,
24            KernelArg::Bytes(b) => b.len().div_ceil(8).max(1),
25        })
26        .sum();
27    let mut storage: Vec<u64> = Vec::with_capacity(total_slots);
28    let mut starts: Vec<usize> = Vec::with_capacity(args.len());
29    for arg in args {
30        starts.push(storage.len());
31        match arg {
32            KernelArg::Buffer(p) => storage.push(p.0),
33            KernelArg::Bytes(b) => {
34                for c in b.chunks(8) {
35                    let mut slot = [0u8; 8];
36                    slot[..c.len()].copy_from_slice(c);
37                    storage.push(u64::from_le_bytes(slot));
38                }
39                if b.is_empty() {
40                    storage.push(0);
41                }
42            }
43        }
44    }
45    (storage, starts)
46}