monitoring kit
Diffstat (limited to 'gpu/src/intel.rs')
-rw-r--r--gpu/src/intel.rs201
1 files changed, 201 insertions, 0 deletions
diff --git a/gpu/src/intel.rs b/gpu/src/intel.rs
new file mode 100644
index 0000000..b9c7dc8
--- /dev/null
+++ b/gpu/src/intel.rs
@@ -0,0 +1,201 @@
+#![feature(
+ generic_arg_infer,
+ import_trait_associated_functions,
+ string_deref_patterns,
+ deref_patterns,
+ let_chains,
+ iter_array_chunks,
+ array_chunks,
+ generic_const_exprs,
+ portable_simd,
+ iter_chain
+)]
+use anyhow::*;
+use collar::CollectArray as _;
+use comat::cwrite;
+use grapher::Grapher;
+use parking_lot::Mutex;
+use std::array;
+use std::ffi::{c_char, CStr};
+use std::fmt::Display;
+use std::fs::{read_dir, read_to_string as read};
+use std::io::{stdout, Read};
+use std::io::{BufRead, BufReader, Write};
+use std::process::{Command, Stdio};
+use std::thread::sleep;
+use std::time::Duration;
+use termion::color::*;
+use termion::cursor::Hide;
+use termion::raw::IntoRawMode;
+use termion::screen::IntoAlternateScreen;
+use termion::{async_stdin, clear, cursor, style};
+
+#[repr(C)]
+#[derive(Default)]
+struct igt_devices_print_format {
+ ty: u32,
+ option: u32,
+ numeric: bool,
+ codename: bool,
+}
+#[repr(C)]
+struct strong<const N: usize>([c_char; N]);
+impl<const N: usize> Default for strong<N> {
+ fn default() -> Self {
+ Self([0; N])
+ }
+}
+impl<const N: usize> Display for strong<N> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", unsafe {
+ CStr::from_ptr(self.0.as_ptr()).to_str().unwrap()
+ })
+ }
+}
+
+#[repr(C)]
+#[derive(Default)]
+struct igt_device_card {
+ subsystem: strong<256>,
+ card: strong<256>,
+ render: strong<256>,
+ pci_slot_name: strong<13>,
+ pci_vendor: u16,
+ pci_device: u16,
+}
+
+unsafe extern "C" {
+ fn igt_devices_scan();
+ fn igt_devices_print(opts: *const igt_devices_print_format);
+ fn igt_device_find_integrated_card(card: *mut igt_device_card) -> bool;
+ fn igt_device_get_pretty_name(card: *const igt_device_card, numeric: bool) -> *const c_char;
+
+}
+
+fn uh() -> Result<()> {
+ dbg!("???");
+ let x = std::fs::read_dir("/sys/devices")?
+ .filter_map(Result::ok)
+ .filter(|x| {
+ x.file_name()
+ .into_string()
+ .is_ok_and(|x| x.starts_with("pci"))
+ })
+ .filter_map(|x| read_dir(x.path()).ok())
+ .flatten()
+ .filter_map(Result::ok)
+ .find(|x| read(x.path().join("uevent")).is_ok_and(|x| x.contains("i915")))
+ .ok_or(anyhow!("intelless"))?
+ .path();
+
+ // println!("{:?}", x.location().unwrap());
+ let pciid = read(x.join("uevent"))
+ .unwrap()
+ .lines()
+ .find(|x| x.starts_with("PCI_ID"))
+ .ok_or(anyhow!("eh"))?
+ .split_once("=")
+ .unwrap()
+ .1
+ .split_once(":")
+ .unwrap()
+ .1
+ .to_lowercase();
+
+ let name = read("/usr/share/hwdata/pci.ids")?
+ .lines()
+ .filter(|x| x.starts_with('\t'))
+ .find(|x| x[1..].starts_with(&pciid))
+ .map(|x| x[1 + pciid.len()..].trim().to_string())
+ .unwrap();
+ dbg!(name);
+ Ok(())
+}
+fn main() -> Result<()> {
+ use atools::Join;
+
+ let mut c = Command::new("intel_gpu_top")
+ .args(["-s", "100", "-c"])
+ .stdout(Stdio::piped())
+ .stdin(Stdio::inherit())
+ .spawn()?;
+ let r = c.stdout.take().unwrap();
+ static last: Mutex<[f64; 7]> = Mutex::new([f64::NAN; _]);
+ std::thread::spawn(move || {
+ // Freq MHz req,Freq MHz act,IRQ /s,RC6 %,Power W gpu,Power W pkg,RCS %,RCS se,RCS wa,BCS %,BCS se,BCS wa,VCS %,VCS se,VCS wa,VECS %,VECS se,VECS wa
+ for line in BufReader::new(r).lines().skip(1) {
+ let line = line.unwrap();
+ let mut splat = line.split(",").map(|x| x.parse::<f64>().unwrap());
+ let x = splat.collect_array::<6>();
+ let busy = splat.array_chunks::<3>().map(|x| x[0]).sum::<f64>();
+ *last.lock() = x.join(busy / 100.);
+ }
+ });
+
+ // [f_req, f_act, irq, rc6, power_gpu, power_package, busy]
+ unsafe { igt_devices_scan() };
+ let mut card = igt_device_card::default();
+ let ret = unsafe { igt_device_find_integrated_card(&mut card) };
+ if !ret {
+ bail!("igpuless!! (i dont have an arc gpu it should be simple to add that tho)")
+ }
+ let name = unsafe {
+ CStr::from_ptr(igt_device_get_pretty_name(&card, false))
+ .to_str()
+ .unwrap()
+ };
+
+ fn inter([a, b, c]: [f32; 3], [d, e, f]: [f32; 3], fc: f32) -> [f32; 3] {
+ [a + (d - a) * fc, b + (e - b) * fc, c + (f - c) * fc]
+ }
+
+ let mut g = Grapher::new()?;
+ sleep(Duration::from_secs_f32(0.5));
+ if let std::result::Result::Ok(Some(_)) = c.try_wait() {
+ return Ok(());
+ }
+ let d = 0.1;
+ let mut stdout = stdout().into_raw_mode()?.into_alternate_screen()?;
+ let mut stdin = async_stdin();
+ write!(stdout, "{}{}{}", Hide, clear::All, style::Reset).unwrap();
+ 'out: loop {
+ if let std::result::Result::Ok(Some(_)) = c.try_wait() {
+ return Ok(());
+ }
+ let (_, h) = termion::terminal_size()?;
+
+ let mut key = 0;
+ while stdin.read(array::from_mut(&mut key)).unwrap() != 0 {
+ match key {
+ b'q' => break 'out,
+
+ _ => (),
+ }
+ }
+
+ g.draw(|y| {
+ Some(
+ inter(
+ [243, 64, 64].map(|x| x as f32 / 255.0), // red
+ [228, 197, 63].map(|x| x as f32 / 255.0), // yellow
+ y as f32 / (h - 1) as f32,
+ )
+ .map(|x| (x * 255.0) as u8),
+ )
+ })?;
+
+ write!(g.buffer, "{}{}", White.fg_str(), cursor::Goto(1, 1))?;
+ let [f_req, f_act, irq, _rc6, power_gpu, power_package, busy] = *last.lock();
+ cwrite!(
+ g.buffer,
+ " {name} @ {f_req:.0}/ {f_act:.0} MHz ─── {power_gpu:.1}/ {power_package:.1} W ─── {irq:.0} irqs/s"
+ )?;
+ stdout.write_all(&g.buffer)?;
+ stdout.flush()?;
+
+ sleep(Duration::from_secs_f32(d));
+ g.push_point(busy);
+ }
+ println!("\x1B[?7l");
+ Ok(())
+}