mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-08-17 16:34:54 -05:00
feat: fmt gpu name in gpu-picker (#1157)
* feat: fmt gpu name in gpu-picker * move implementation to daemon * move to schema * add Radeon/Geforce prefix back * remove from info_elements
This commit is contained in:
@@ -265,7 +265,7 @@ There is also a cli available.
|
||||
Example output:
|
||||
|
||||
```
|
||||
10DE:2704-1462:5110-0000:09:00.0 (AD103 [GeForce RTX 4080])
|
||||
0: 10DE:2704-1462:5110-0000:09:00.0 (GeForce RTX 4080) [Dedicated]
|
||||
```
|
||||
- Getting GPU information:
|
||||
|
||||
@@ -277,7 +277,7 @@ There is also a cli available.
|
||||
$ lact cli info
|
||||
GPU 10DE:2704-1462:5110-0000:09:00.0:
|
||||
=====================================
|
||||
GPU Model: NVIDIA GeForce RTX 4080 (0x10DE:0x2704)
|
||||
GPU Model: GeForce RTX 4080 (0x10DE:0x2704)
|
||||
Card Manufacturer: Micro-Star International Co., Ltd. [MSI] (0x1462)
|
||||
Card Model: Unknown (0x5110)
|
||||
Driver Used: nvidia 570.124.04
|
||||
|
||||
+8
-2
@@ -8,6 +8,7 @@ use anyhow::{Context, Result, bail};
|
||||
use lact_client::DaemonClient;
|
||||
use lact_schema::{
|
||||
args::cli::{CliArgs, CliCommand, ProfileAutoSwitchCommand, ProfileCommand},
|
||||
clean_gpu_name,
|
||||
config::GpuConfig,
|
||||
request::ConfirmCommand,
|
||||
};
|
||||
@@ -100,7 +101,11 @@ impl CliContext<'_> {
|
||||
if entries.len() > 1 {
|
||||
eprintln!(
|
||||
"GPU id not specified, selecting {}",
|
||||
first_entry.name.as_deref().unwrap_or("<Unknown>")
|
||||
first_entry
|
||||
.name
|
||||
.as_deref()
|
||||
.map(clean_gpu_name)
|
||||
.unwrap_or("<Unknown>")
|
||||
);
|
||||
}
|
||||
Ok(first_entry.id.clone())
|
||||
@@ -141,6 +146,7 @@ impl CliContext<'_> {
|
||||
.await?
|
||||
.into_iter()
|
||||
.find(|entry| entry.id == gpu_id)
|
||||
.and_then(|entry| entry.name))
|
||||
.and_then(|entry| entry.name)
|
||||
.map(|name| clean_gpu_name(&name).to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,10 @@ const PROFILE_DEFAULT: &str = "Default";
|
||||
pub async fn list_gpus(ctx: CliContext<'_>) -> Result<()> {
|
||||
let entries = ctx.client.list_devices().await?;
|
||||
for (i, entry) in entries.into_iter().enumerate() {
|
||||
let id = entry.id;
|
||||
let device_type = entry.device_type;
|
||||
|
||||
if let Some(name) = entry.name {
|
||||
println!("{i}: {id} ({name}) [{device_type}]");
|
||||
if entry.name.is_some() {
|
||||
println!("{i}: {} ({entry}) [{}]", entry.id, entry.device_type);
|
||||
} else {
|
||||
println!("{i}: {id} [{device_type}]");
|
||||
println!("{i}: {} [{}]", entry.id, entry.device_type);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::{
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
use jiff::Zoned;
|
||||
use lact_schema::DeviceStats;
|
||||
use lact_schema::{DeviceStats, clean_gpu_name};
|
||||
use schema::{
|
||||
Attribute, Gauge, GaugeDataPoint, Metric, MetricsPayload, Resource, ResourceMetric, Scope,
|
||||
ScopeMetric, Value,
|
||||
@@ -335,7 +335,15 @@ async fn get_stats(handler: &Handler) -> anyhow::Result<IndexMap<String, (String
|
||||
for device in device_list {
|
||||
let stats = handler.get_gpu_stats(&device.id).await?;
|
||||
|
||||
devices.insert(device.id, (device.name.unwrap_or_default(), stats));
|
||||
devices.insert(
|
||||
device.id,
|
||||
(
|
||||
device
|
||||
.name
|
||||
.map_or_else(String::new, |name| clean_gpu_name(&name).to_owned()),
|
||||
stats,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(devices)
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::app::{
|
||||
use gtk::pango::AttrList;
|
||||
use gtk::prelude::{BoxExt, OrientableExt, PopoverExt as _, WidgetExt};
|
||||
use i18n_embed_fl::fl;
|
||||
use lact_schema::{DeviceInfo, DeviceStats, PowerStates, PowerStats};
|
||||
use lact_schema::{DeviceInfo, DeviceStats, PowerStates, PowerStats, clean_gpu_name};
|
||||
use relm4::{ComponentParts, ComponentSender, RelmWidgetExt as _};
|
||||
use std::collections::HashSet;
|
||||
use std::str::FromStr as _;
|
||||
@@ -360,13 +360,14 @@ impl relm4::SimpleComponent for GpuStatsSection {
|
||||
GpuStatsSectionMsg::Info(info) => {
|
||||
self.vram_clock_ratio = info.vram_clock_ratio();
|
||||
if let Some(pci_info) = &info.pci_info {
|
||||
self.gpu_model = info
|
||||
.drm_info
|
||||
.as_ref()
|
||||
.and_then(|drm| drm.device_name.as_deref())
|
||||
.or(pci_info.device_pci_info.model.as_deref())
|
||||
.unwrap_or("Unknown")
|
||||
.to_owned();
|
||||
self.gpu_model = clean_gpu_name(
|
||||
info.drm_info
|
||||
.as_ref()
|
||||
.and_then(|drm| drm.device_name.as_deref())
|
||||
.or(pci_info.device_pci_info.model.as_deref())
|
||||
.unwrap_or("Unknown"),
|
||||
)
|
||||
.to_owned();
|
||||
}
|
||||
}
|
||||
GpuStatsSectionMsg::Stats(stats) => {
|
||||
|
||||
+28
-1
@@ -67,6 +67,33 @@ pub fn bytes_to_mib(bytes: u64) -> f64 {
|
||||
bytes as f64 / 1024.0 / 1024.0
|
||||
}
|
||||
|
||||
const GPU_VENDOR_PREFIXES: &[&str] = &["AMD ", "NVIDIA ", "Intel "];
|
||||
|
||||
pub fn clean_gpu_name(name: &str) -> &str {
|
||||
let mut short = name.trim();
|
||||
|
||||
if let Some(marketing_name) = GPU_VENDOR_PREFIXES
|
||||
.iter()
|
||||
.find_map(|&prefix| short.strip_prefix(prefix))
|
||||
{
|
||||
short = marketing_name
|
||||
.split_once('[')
|
||||
.map_or(marketing_name, |(model, _)| model.trim_end());
|
||||
} else if let Some((_, bracketed)) = short.split_once('[')
|
||||
&& let Some((model, _)) = bracketed.split_once(']')
|
||||
{
|
||||
// PCI device names carry the marketing name in brackets, e.g. "DG2 [Arc A770]"
|
||||
short = model.trim();
|
||||
}
|
||||
|
||||
short = GPU_VENDOR_PREFIXES
|
||||
.iter()
|
||||
.find_map(|&prefix| short.strip_prefix(prefix))
|
||||
.unwrap_or(short);
|
||||
|
||||
short
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Pong;
|
||||
|
||||
@@ -121,7 +148,7 @@ pub struct DeviceListEntry {
|
||||
impl Display for DeviceListEntry {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.name {
|
||||
Some(name) => Display::fmt(name, f),
|
||||
Some(name) => Display::fmt(clean_gpu_name(name), f),
|
||||
None => Display::fmt(&self.id, f),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{FanControlMode, FanOptions, PmfwOptions, Pong, Request, Response};
|
||||
use crate::{FanControlMode, FanOptions, PmfwOptions, Pong, Request, Response, clean_gpu_name};
|
||||
use anyhow::anyhow;
|
||||
use serde_json::json;
|
||||
use std::collections::BTreeMap;
|
||||
@@ -86,3 +86,55 @@ fn set_fan_clocks() {
|
||||
});
|
||||
assert_eq!(expected_request, request);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_gpu_name_removes_vendor_prefixes() {
|
||||
assert_eq!(clean_gpu_name("AMD Radeon RX 9070 XT"), "Radeon RX 9070 XT");
|
||||
assert_eq!(
|
||||
clean_gpu_name("NVIDIA GeForce RTX 5090"),
|
||||
"GeForce RTX 5090"
|
||||
);
|
||||
assert_eq!(clean_gpu_name("NVIDIA GeForce MX450"), "GeForce MX450");
|
||||
assert_eq!(
|
||||
clean_gpu_name("NVIDIA GeForce RTX 5090 [Founders Edition]"),
|
||||
"GeForce RTX 5090"
|
||||
);
|
||||
assert_eq!(
|
||||
clean_gpu_name("NVIDIA GeForce RTX 4070 Super"),
|
||||
"GeForce RTX 4070 Super"
|
||||
);
|
||||
assert_eq!(clean_gpu_name("Intel Arc A380"), "Arc A380");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_gpu_name_unwraps_pci_names() {
|
||||
assert_eq!(
|
||||
clean_gpu_name("Pitcairn XT [Radeon HD 7870 GHz Edition]"),
|
||||
"Radeon HD 7870 GHz Edition"
|
||||
);
|
||||
assert_eq!(clean_gpu_name("DG2 [Arc A380]"), "Arc A380");
|
||||
assert_eq!(clean_gpu_name("GK107M [GeForce 710A]"), "GeForce 710A");
|
||||
assert_eq!(clean_gpu_name("GK107M [GeForce 820M]"), "GeForce 820M");
|
||||
assert_eq!(clean_gpu_name("TU117M [GeForce MX450]"), "GeForce MX450");
|
||||
assert_eq!(
|
||||
clean_gpu_name("TigerLake-LP GT2 [Iris Xe Graphics]"),
|
||||
"Iris Xe Graphics"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_gpu_name_keeps_consumer_brands_and_unrecognized_names() {
|
||||
assert_eq!(
|
||||
clean_gpu_name("AMD Radeon 780M Graphics"),
|
||||
"Radeon 780M Graphics"
|
||||
);
|
||||
assert_eq!(clean_gpu_name("AMD Radeon VII"), "Radeon VII");
|
||||
assert_eq!(clean_gpu_name("Phoenix1"), "Phoenix1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_gpu_name_keeps_professional_product_brands() {
|
||||
assert_eq!(clean_gpu_name("GK107GL [Quadro K600]"), "Quadro K600");
|
||||
assert_eq!(clean_gpu_name("GK110GL [Tesla K20]"), "Tesla K20");
|
||||
assert_eq!(clean_gpu_name("NVIDIA Quadro RTX 6000"), "Quadro RTX 6000");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user