Skip to main content

libamdgpu_top/
lib.rs

1use std::time::Duration;
2use std::path::PathBuf;
3
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5
6pub use libdrm_amdgpu_sys::*;
7use libdrm_amdgpu_sys::AMDGPU::{
8    CHIP_CLASS,
9    DeviceHandle,
10    drm_amdgpu_memory_info,
11    HW_IP::{HW_IP_TYPE, HwIpInfo},
12};
13
14mod app_device_info;
15pub use app_device_info::*;
16
17pub mod stat;
18pub mod app;
19pub mod xdna;
20
21mod device_path;
22pub use device_path::{DeviceType, DevicePath};
23
24mod drm_mode;
25pub use drm_mode::*;
26
27mod ppfeaturemask;
28pub use ppfeaturemask::*;
29
30#[derive(Debug, Copy, Clone, Eq, PartialEq, IntoPrimitive, TryFromPrimitive)]
31#[repr(u8)]
32pub enum GuiMode {
33    Auto,
34    Single,
35    Tab,
36}
37
38impl GuiMode {
39    pub fn is_tab_mode(&self) -> bool {
40        *self == Self::Tab
41    }
42}
43
44#[derive(Debug, Copy, Clone, Eq, PartialEq)]
45pub enum GuiWgpuBackend {
46    Gl,
47    Vulkan,
48}
49
50#[derive(Debug, Clone)]
51pub struct UiArgs {
52    pub selected_device_path: DevicePath,
53    pub device_path_list: Vec<DevicePath>,
54    pub update_process_index: u64,
55    pub no_pc: bool,
56    pub is_dark_mode: Option<bool>, // TUI, GUI
57    pub hide_fdinfo: bool, // TUI
58    pub gui_wgpu_backend: GuiWgpuBackend, // GUI
59    pub gui_mode: GuiMode, // GUI
60}
61
62pub struct Sampling {
63    pub count: usize,
64    pub delay: Duration,
65}
66
67impl Default for Sampling {
68    fn default() -> Self {
69        Self::low()
70    }
71}
72
73impl Sampling {
74    pub const fn low() -> Self {
75        Self {
76            count: 100,
77            delay: Duration::from_millis(10),
78        }
79    }
80
81    pub const fn high() -> Self {
82        Self {
83            count: 100,
84            delay: Duration::from_millis(1),
85        }
86    }
87
88    pub fn to_duration(&self) -> Duration {
89        self.delay * self.count as u32
90    }
91}
92
93#[derive(Debug, Clone)]
94pub struct VramUsage(pub drm_amdgpu_memory_info);
95
96impl VramUsage {
97    pub fn new(memory_info: &drm_amdgpu_memory_info) -> Self {
98        Self(*memory_info)
99    }
100
101    pub fn update_usage(&mut self, amdgpu_dev: &DeviceHandle) {
102        if let [Ok(vram), Ok(vis_vram), Ok(gtt)] = [
103            amdgpu_dev.vram_usage_info(),
104            amdgpu_dev.vis_vram_usage_info(),
105            amdgpu_dev.gtt_usage_info(),
106        ] {
107            self.0.vram.heap_usage = vram;
108            self.0.cpu_accessible_vram.heap_usage = vis_vram;
109            self.0.gtt.heap_usage = gtt;
110        }
111    }
112
113    pub fn update_usable_heap_size(&mut self, amdgpu_dev: &DeviceHandle) {
114        let Ok(info) = amdgpu_dev.vram_gtt_info() else { return };
115
116        self.0.vram.usable_heap_size = info.vram_size;
117        self.0.cpu_accessible_vram.usable_heap_size = info.vram_cpu_accessible_size;
118        self.0.gtt.usable_heap_size = info.gtt_size;
119    }
120}
121
122pub fn get_hw_ip_info_list(
123    amdgpu_dev: &DeviceHandle,
124    chip_class: CHIP_CLASS,
125) -> Vec<HwIpInfo> {
126    const HW_IP_LIST: &[HW_IP_TYPE] = &[
127        // HW_IP_TYPE::GFX,
128        // HW_IP_TYPE::COMPUTE,
129        HW_IP_TYPE::DMA,
130        HW_IP_TYPE::UVD,
131        HW_IP_TYPE::VCE,
132        HW_IP_TYPE::UVD_ENC,
133        HW_IP_TYPE::VCN_DEC,
134        HW_IP_TYPE::VCN_ENC,
135        HW_IP_TYPE::VCN_JPEG,
136        HW_IP_TYPE::VPE,
137    ];
138
139    let mut hw_ip_list: Vec<HwIpInfo> = Vec::with_capacity(10);
140
141    {
142        for ip_type in [HW_IP_TYPE::GFX, HW_IP_TYPE::COMPUTE] {
143            let Ok(mut ip_info) = amdgpu_dev.get_hw_ip_info(ip_type) else { continue };
144
145            // Fix incorrect IP versions reported by the kernel.
146            // ref: https://gitlab.freedesktop.org/mesa/mesa/blob/main/src/amd/common/ac_gpu_info.c
147            match chip_class {
148                CHIP_CLASS::GFX10 => ip_info.info.hw_ip_version_minor = 1,
149                CHIP_CLASS::GFX10_3 => ip_info.info.hw_ip_version_minor = 3,
150                _ => {},
151            }
152
153            if ip_info.count != 0 {
154                hw_ip_list.push(ip_info);
155            }
156        }
157    }
158
159    for ip_type in HW_IP_LIST {
160        let Ok(ip_info) = amdgpu_dev.get_hw_ip_info(*ip_type) else { continue };
161
162        if ip_info.count != 0 {
163            hw_ip_list.push(ip_info);
164        }
165    }
166
167    hw_ip_list
168}
169
170pub fn get_rocm_version() -> Option<String> {
171    let rocm_path = std::env::var("ROCM_PATH").unwrap_or("/opt/rocm".to_string());
172    let rocm_path = PathBuf::from(rocm_path);
173
174    let s = std::fs::read_to_string(rocm_path.join(".info/version")).ok()?;
175    let s = s.trim_end();
176
177    if let Some((ver, _)) = s.split_once('-') {
178        Some(ver.to_string())
179    } else {
180        Some(s.to_string())
181    }
182}