Skip to main content

codec/gpu/
types.rs

1//! Core GPU type definitions: `GpuDevice`, `GpuVendor`, `GpuUtilization`.
2
3#[derive(Debug, Clone)]
4pub struct GpuDevice {
5    pub vendor: GpuVendor,
6    pub name: String,
7    /// Global device index across ALL vendors (0-based, in `detect_gpus()`
8    /// order) — what the user addresses via `--decode-gpu N` / the GPU policy.
9    pub index: u32,
10    /// Index of this device WITHIN its own vendor's set (0-based). On a
11    /// single-vendor host this equals `index`; on a mixed host (e.g. NVIDIA +
12    /// AMD iGPU) they differ. The per-vendor hardware decoder/encoder uses THIS
13    /// to pick the physical adapter (CUDA ordinal, QSV/AMF adapter), since those
14    /// SDKs enumerate only their own vendor's devices.
15    pub vendor_index: u32,
16    /// Architecture / generation label, e.g. "Blackwell" (RTX 5060),
17    /// "Ada Lovelace" (RTX 4000-series), "Ampere" (RTX 3000), "Alchemist DG2"
18    /// (Arc A-series), "Battlemage BMG" (Arc B-series), "RDNA3" (RX 7000).
19    /// Phase 2 (2026-05-07) inventory page surface — derived from the PCI
20    /// device id at detect time so the inventory aggregations don't have
21    /// to re-derive it. "Unknown" when the device id falls outside the
22    /// per-vendor known-id table; preserved verbatim to the admin UI so
23    /// operators can spot fleet rows that need a label update.
24    pub generation: String,
25    /// Lowercase `vendor:device` PCI tuple, e.g. `"0x10de:0x2d05"`. Stable
26    /// identifier across driver / kernel versions. Empty string when the
27    /// platform path doesn't expose a device id (NVIDIA via CUDA on
28    /// Windows: cuda doesn't surface PCI; the field stays empty rather
29    /// than synthesise something misleading).
30    pub pci_id: String,
31    /// Total VRAM in MiB. NVIDIA via NVML `memory_info().total`; Intel via
32    /// `/sys/class/drm/cardN/device/mem_info_vram_total` when present;
33    /// AMD same. 0 when the platform path can't read it — admin UI shows
34    /// "—" for that case rather than "0 MiB".
35    pub vram_mib: u64,
36    /// Vendor-reported serial number of the physical card. NVIDIA via
37    /// NVML `Device::serial()` (returns the manufacturer's serial sticker
38    /// for cards that have one — datacenter Tesla / A10G / consumer Pro
39    /// cards expose it; consumer GeForce typically doesn't). Intel /
40    /// AMD: try `/sys/class/drm/cardN/device/serial[_number]` paths;
41    /// usually `None`. Stable identifier for warranty tracking + the
42    /// `transcoder_gpus` asset table — when present, the same card
43    /// across host moves dedups to a single row.
44    pub serial: Option<String>,
45    /// PCI host slot address, e.g. `"04:00.0"`. Used as the dedupe
46    /// fallback when `serial` is absent — assumes the card stays in
47    /// the same slot of the same host (the dev-box reality).
48    /// Empty when the platform path doesn't expose it.
49    pub host_pci_address: String,
50    /// Vendor portion of the PCI tuple as a standalone hex string,
51    /// e.g. `"0x10de"`. Already implicit in `pci_id` but exposed
52    /// separately so the SQL inventory query can index on it
53    /// without parsing.
54    pub vendor_id_hex: String,
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum GpuVendor {
59    Nvidia,
60    Amd,
61    Intel,
62}
63
64/// Per-GPU live utilisation snapshot. Read on every load tick (5 s
65/// cadence) by the Phase 2 (2026-05-07) `worker_load` reporter and
66/// folded into the `WsGpuLeaseEntry` for the wire. NVIDIA values come
67/// from NVML; Intel values come from sysfs `gt_cur_freq_mhz` /
68/// `gt_max_freq_mhz` for a coarse "busy" proxy + `mem_info_vram_*`
69/// for memory; AMD is currently a no-op (returns all zeros) — radeontop
70/// / `amdsmi` integration is the proper fix and is deferred per the
71/// brief's "Phase 1 stand-in for Intel; AMD skipped" guidance.
72#[derive(Debug, Clone, Default)]
73pub struct GpuUtilization {
74    /// 0..=100 compute / overall GPU busy.
75    pub util_percent: u8,
76    /// 0..=100 NVENC ASIC busy (encoder pipeline).
77    pub encoder_percent: u8,
78    /// 0..=100 NVDEC ASIC busy (decoder pipeline).
79    pub decoder_percent: u8,
80    /// VRAM in use (MiB).
81    pub mem_used_mib: u32,
82    /// VRAM total (MiB) — duplicated from the static device record so
83    /// the wire entry is self-contained for the FE bar render.
84    pub mem_total_mib: u32,
85    /// Core temperature in °C; `None` when the platform path doesn't
86    /// expose it.
87    pub temperature_c: Option<u8>,
88}