mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-08-19 01:14:43 -05:00
Merge branch 'master' into service-setup-gui-2
This commit is contained in:
Generated
+2
-2
@@ -1850,9 +1850,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libdrm_amdgpu_sys"
|
||||
version = "0.8.14"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b63f219bdee8484c65e0f54f81b6c671f1ab433f460e40c3174dea688abf31b"
|
||||
checksum = "1e11704169b7b5a043ec5627aa0433019cf67d07f233002e1233edf67c2e662b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libloading",
|
||||
|
||||
@@ -2173,14 +2173,14 @@
|
||||
{
|
||||
"type": "archive",
|
||||
"archive-type": "tar-gzip",
|
||||
"url": "https://static.crates.io/crates/libdrm_amdgpu_sys/libdrm_amdgpu_sys-0.8.14.crate",
|
||||
"sha256": "3b63f219bdee8484c65e0f54f81b6c671f1ab433f460e40c3174dea688abf31b",
|
||||
"dest": "cargo/vendor/libdrm_amdgpu_sys-0.8.14"
|
||||
"url": "https://static.crates.io/crates/libdrm_amdgpu_sys/libdrm_amdgpu_sys-0.8.16.crate",
|
||||
"sha256": "1e11704169b7b5a043ec5627aa0433019cf67d07f233002e1233edf67c2e662b",
|
||||
"dest": "cargo/vendor/libdrm_amdgpu_sys-0.8.16"
|
||||
},
|
||||
{
|
||||
"type": "inline",
|
||||
"contents": "{\"package\": \"3b63f219bdee8484c65e0f54f81b6c671f1ab433f460e40c3174dea688abf31b\", \"files\": {}}",
|
||||
"dest": "cargo/vendor/libdrm_amdgpu_sys-0.8.14",
|
||||
"contents": "{\"package\": \"1e11704169b7b5a043ec5627aa0433019cf67d07f233002e1233edf67c2e662b\", \"files\": {}}",
|
||||
"dest": "cargo/vendor/libdrm_amdgpu_sys-0.8.16",
|
||||
"dest-filename": ".cargo-checksum.json"
|
||||
},
|
||||
{
|
||||
@@ -5361,4 +5361,4 @@
|
||||
"dest": "cargo",
|
||||
"dest-filename": "config"
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -30,7 +30,7 @@ pub async fn info(ctx: CliContext<'_>) -> Result<()> {
|
||||
println!("{gpu_line}");
|
||||
println!("{}", "=".repeat(gpu_line.len()));
|
||||
|
||||
let info = ctx.client.get_device_info(&id).await?;
|
||||
let info = ctx.client.get_device_info(&id, Some(false)).await?;
|
||||
let stats = ctx.client.get_device_stats(&id).await?;
|
||||
|
||||
let elements = info.info_elements(Some(&stats));
|
||||
|
||||
+14
-2
@@ -4,7 +4,7 @@ mod macros;
|
||||
|
||||
pub use lact_schema as schema;
|
||||
use lact_schema::{
|
||||
ProcessList, ProfileRule,
|
||||
DeviceApiInfo, ProcessList, ProfileRule,
|
||||
config::{GpuConfig, Profile, ProfileHooks},
|
||||
};
|
||||
|
||||
@@ -126,12 +126,24 @@ impl DaemonClient {
|
||||
self.make_request(Request::ListDevices).await
|
||||
}
|
||||
|
||||
pub async fn get_device_info(
|
||||
&self,
|
||||
id: &str,
|
||||
include_api_info: Option<bool>,
|
||||
) -> anyhow::Result<DeviceInfo> {
|
||||
self.make_request(Request::DeviceInfo {
|
||||
id,
|
||||
include_api_info,
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
request_plain!(get_system_info, SystemInfo, SystemInfo);
|
||||
request_plain!(enable_overdrive, EnableOverdrive, String);
|
||||
request_plain!(disable_overdrive, DisableOverdrive, String);
|
||||
request_plain!(generate_debug_snapshot, GenerateSnapshot, String);
|
||||
request_plain!(reset_config, RestConfig, ());
|
||||
request_with_id!(get_device_info, DeviceInfo, DeviceInfo);
|
||||
request_with_id!(get_device_api_info, DeviceApiInfo, DeviceApiInfo);
|
||||
request_with_id!(get_device_stats, DeviceStats, DeviceStats);
|
||||
request_with_id!(get_device_clocks_info, DeviceClocksInfo, ClocksInfo);
|
||||
request_with_id!(
|
||||
|
||||
@@ -37,7 +37,7 @@ nvml-wrapper = "0.12.1"
|
||||
bitflags = "2.11.1"
|
||||
pciid-parser = { version = "0.8", features = ["serde"] }
|
||||
zbus = { workspace = true }
|
||||
libdrm_amdgpu_sys = { version = "0.8.13", default-features = false, features = [
|
||||
libdrm_amdgpu_sys = { version = "0.8.16", default-features = false, features = [
|
||||
"dynamic_loading",
|
||||
] }
|
||||
tar = "0.4.45"
|
||||
|
||||
@@ -157,7 +157,11 @@ async fn handle_request<'a>(
|
||||
Request::Ping => ok_response(ping()),
|
||||
Request::SystemInfo => ok_response(system::info().await?),
|
||||
Request::ListDevices => ok_response(handler.list_devices().await),
|
||||
Request::DeviceInfo { id } => ok_response(handler.get_device_info(id).await?),
|
||||
Request::DeviceInfo {
|
||||
id,
|
||||
include_api_info,
|
||||
} => ok_response(handler.get_device_info(id, include_api_info).await?),
|
||||
Request::DeviceApiInfo { id } => ok_response(handler.get_device_api_info(id).await?),
|
||||
Request::DeviceStats { id } => ok_response(handler.get_gpu_stats(id).await?),
|
||||
Request::DeviceClocksInfo { id } => ok_response(handler.get_clocks_info(id).await?),
|
||||
Request::DevicePowerProfileModes { id } => {
|
||||
|
||||
@@ -7,15 +7,19 @@ mod nvidia;
|
||||
|
||||
use amd::AmdGpuController;
|
||||
use intel::IntelGpuController;
|
||||
use lact_schema::DeviceApiInfo;
|
||||
use lact_schema::DeviceType;
|
||||
use lact_schema::ProcessList;
|
||||
#[cfg(feature = "nvidia")]
|
||||
use nvidia::NvidiaGpuController;
|
||||
use tokio::join;
|
||||
|
||||
pub const VENDOR_AMD: &str = "1002";
|
||||
pub const VENDOR_NVIDIA: &str = "10DE";
|
||||
|
||||
use crate::server::handler::{AMD_DRM, INTEL_DRM, NVML};
|
||||
use crate::server::opencl::get_opencl_info;
|
||||
use crate::server::vulkan::get_vulkan_info;
|
||||
use amdgpu_sysfs::gpu_handle::power_profile_mode::PowerProfileModesTable;
|
||||
use anyhow::Context;
|
||||
use anyhow::anyhow;
|
||||
@@ -43,7 +47,32 @@ pub trait GpuController {
|
||||
|
||||
fn device_type(&self) -> DeviceType;
|
||||
|
||||
fn get_info(&self, unique_vendor: bool) -> LocalBoxFuture<'_, DeviceInfo>;
|
||||
fn get_info(
|
||||
&self,
|
||||
unique_vendor: bool,
|
||||
include_api_info: bool,
|
||||
) -> LocalBoxFuture<'_, DeviceInfo>;
|
||||
|
||||
fn get_api_info(&self, unique_vendor: bool) -> LocalBoxFuture<'_, DeviceApiInfo> {
|
||||
async move {
|
||||
let common = self.controller_info();
|
||||
|
||||
let (vulkan_result, opencl_instances) = join!(
|
||||
get_vulkan_info(common),
|
||||
get_opencl_info(common, unique_vendor)
|
||||
);
|
||||
let vulkan_instances = vulkan_result.unwrap_or_else(|err| {
|
||||
warn!("could not load vulkan info: {err:#}");
|
||||
vec![]
|
||||
});
|
||||
|
||||
DeviceApiInfo {
|
||||
vulkan_instances,
|
||||
opencl_instances,
|
||||
}
|
||||
}
|
||||
.boxed_local()
|
||||
}
|
||||
|
||||
fn friendly_name(&self) -> Option<String>;
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
use super::{CommonControllerInfo, FanControlHandle, GpuController, VENDOR_AMD};
|
||||
use crate::server::{
|
||||
gpu_controller::common::{
|
||||
fan_control::FanCurveExt,
|
||||
fdinfo::{self, DrmUtilMap},
|
||||
},
|
||||
opencl::get_opencl_info,
|
||||
vulkan::get_vulkan_info,
|
||||
use crate::server::gpu_controller::common::{
|
||||
fan_control::FanCurveExt,
|
||||
fdinfo::{self, DrmUtilMap},
|
||||
};
|
||||
use amdgpu_sysfs::{
|
||||
error::Error,
|
||||
@@ -19,12 +15,13 @@ use amdgpu_sysfs::{
|
||||
sysfs::SysFS,
|
||||
};
|
||||
use anyhow::{Context, anyhow, bail};
|
||||
use futures::{FutureExt, future::LocalBoxFuture, join};
|
||||
use futures::{FutureExt, future::LocalBoxFuture};
|
||||
use lact_schema::{
|
||||
ActivePowerStates, AmdCacheInstance, AmdIpInfo, CacheInfo, CacheType, ClocksInfo,
|
||||
ClockspeedStats, DeviceFlag, DeviceInfo, DeviceStats, DeviceType, DrmInfo, FanControlMode,
|
||||
FanStats, IntelDrmInfo, LinkInfo, PmfwInfo, PowerState, PowerStates, PowerStats, ProcessList,
|
||||
ProcessUtilizationType, RopInfo, TemperatureEntry, VoltageStats, VramStats,
|
||||
ClockspeedStats, DeviceApiInfo, DeviceFlag, DeviceInfo, DeviceStats, DeviceType, DrmInfo,
|
||||
FanControlMode, FanStats, IntelDrmInfo, LinkInfo, PmfwInfo, PowerState, PowerStates,
|
||||
PowerStats, ProcessList, ProcessUtilizationType, RopInfo, TemperatureEntry, VoltageStats,
|
||||
VramStats,
|
||||
config::{ClocksConfiguration, FanControlSettings, FanCurve, GpuConfig},
|
||||
};
|
||||
use libdrm_amdgpu_sys::AMDGPU::{GpuMetrics, HW_IP::HW_IP_TYPE, ThrottlerBit, ThrottlerType};
|
||||
@@ -739,16 +736,17 @@ impl GpuController for AmdGpuController {
|
||||
})
|
||||
}
|
||||
|
||||
fn get_info(&self, unique_vendor: bool) -> LocalBoxFuture<'_, DeviceInfo> {
|
||||
fn get_info(
|
||||
&self,
|
||||
unique_vendor: bool,
|
||||
include_api_info: bool,
|
||||
) -> LocalBoxFuture<'_, DeviceInfo> {
|
||||
Box::pin(async move {
|
||||
let (vulkan_result, opencl_instances) = join!(
|
||||
get_vulkan_info(&self.common),
|
||||
get_opencl_info(&self.common, unique_vendor)
|
||||
);
|
||||
let vulkan_instances = vulkan_result.unwrap_or_else(|err| {
|
||||
warn!("could not load vulkan info: {err:#}");
|
||||
vec![]
|
||||
});
|
||||
let api_info = if include_api_info {
|
||||
self.get_api_info(unique_vendor).await
|
||||
} else {
|
||||
DeviceApiInfo::default()
|
||||
};
|
||||
|
||||
let pci_info = Some(self.common.pci_info.clone());
|
||||
let driver = self.handle.get_driver().to_owned();
|
||||
@@ -787,11 +785,10 @@ impl GpuController for AmdGpuController {
|
||||
|
||||
DeviceInfo {
|
||||
pci_info,
|
||||
vulkan_instances,
|
||||
api_info,
|
||||
driver,
|
||||
vbios_version,
|
||||
link_info,
|
||||
opencl_instances,
|
||||
drm_info,
|
||||
flags,
|
||||
}
|
||||
@@ -1427,8 +1424,6 @@ fn get_drm_handle(
|
||||
common: &CommonControllerInfo,
|
||||
libdrm_amdgpu: &LibDrmAmdgpu,
|
||||
) -> anyhow::Result<DrmHandle> {
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
let path = common.get_drm_render()?;
|
||||
let drm_file = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
@@ -1436,7 +1431,7 @@ fn get_drm_handle(
|
||||
.open(&path)
|
||||
.with_context(|| format!("Could not open drm file at {}", path.display()))?;
|
||||
let (handle, _, _) = libdrm_amdgpu
|
||||
.init_device_handle(drm_file.as_raw_fd())
|
||||
.init_device_handle_with_fd(drm_file)
|
||||
.map_err(|err| anyhow!("Could not open drm handle, error code {err}"))?;
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
@@ -6,20 +6,16 @@ use crate::{
|
||||
IntelDrm, drm_i915_gem_memory_class_I915_MEMORY_CLASS_DEVICE,
|
||||
drm_xe_memory_class_DRM_XE_MEM_REGION_CLASS_VRAM,
|
||||
},
|
||||
server::{
|
||||
gpu_controller::common::fdinfo::{self, DrmUtilMap},
|
||||
opencl::get_opencl_info,
|
||||
vulkan::get_vulkan_info,
|
||||
},
|
||||
server::gpu_controller::common::fdinfo::{self, DrmUtilMap},
|
||||
};
|
||||
use amdgpu_sysfs::{gpu_handle::power_profile_mode::PowerProfileModesTable, hw_mon::Temperature};
|
||||
use anyhow::{Context, anyhow, bail};
|
||||
use futures::{future::LocalBoxFuture, join};
|
||||
use futures::future::LocalBoxFuture;
|
||||
use lact_schema::{
|
||||
ClocksInfo, ClocksTable, ClockspeedStats, DeviceInfo, DeviceStats, DeviceType, DrmInfo,
|
||||
DrmMemoryInfo, FanStats, IntelClocksTable, IntelDrmInfo, LinkInfo, PowerState, PowerStates,
|
||||
PowerStats, ProcessList, ProcessUtilizationType, TemperatureEntry, VoltageStats, VramStats,
|
||||
config::GpuConfig,
|
||||
ClocksInfo, ClocksTable, ClockspeedStats, DeviceApiInfo, DeviceInfo, DeviceStats, DeviceType,
|
||||
DrmInfo, DrmMemoryInfo, FanStats, IntelClocksTable, IntelDrmInfo, LinkInfo, PowerState,
|
||||
PowerStates, PowerStats, ProcessList, ProcessUtilizationType, TemperatureEntry, VoltageStats,
|
||||
VramStats, config::GpuConfig,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
@@ -592,16 +588,17 @@ impl GpuController for IntelGpuController {
|
||||
self.common.pci_info.device_pci_info.model.clone()
|
||||
}
|
||||
|
||||
fn get_info(&self, unique_vendor: bool) -> LocalBoxFuture<'_, DeviceInfo> {
|
||||
fn get_info(
|
||||
&self,
|
||||
unique_vendor: bool,
|
||||
include_api_info: bool,
|
||||
) -> LocalBoxFuture<'_, DeviceInfo> {
|
||||
Box::pin(async move {
|
||||
let (vulkan_result, opencl_instances) = join!(
|
||||
get_vulkan_info(&self.common),
|
||||
get_opencl_info(&self.common, unique_vendor)
|
||||
);
|
||||
let vulkan_instances = vulkan_result.unwrap_or_else(|err| {
|
||||
warn!("could not load vulkan info: {err:#}");
|
||||
vec![]
|
||||
});
|
||||
let api_info = if include_api_info {
|
||||
self.get_api_info(unique_vendor).await
|
||||
} else {
|
||||
DeviceApiInfo::default()
|
||||
};
|
||||
|
||||
let vram_info = self.get_vram_info();
|
||||
|
||||
@@ -617,12 +614,11 @@ impl GpuController for IntelGpuController {
|
||||
|
||||
DeviceInfo {
|
||||
pci_info: Some(self.common.pci_info.clone()),
|
||||
vulkan_instances,
|
||||
api_info,
|
||||
driver: self.common.driver.clone(),
|
||||
vbios_version: None,
|
||||
link_info: LinkInfo::default(),
|
||||
drm_info: Some(drm_info),
|
||||
opencl_instances,
|
||||
flags: vec![],
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,14 +4,10 @@ pub mod nvapi;
|
||||
use super::{CommonControllerInfo, FanControlHandle, GpuController};
|
||||
use crate::{
|
||||
bindings::nvidia::NvPhysicalGpuHandle,
|
||||
server::{
|
||||
gpu_controller::{
|
||||
NvApi,
|
||||
common::{fan_control::FanCurveExt, resolve_process_name},
|
||||
nvidia::nvapi::{CLOCK_CLIENT_CLK_VF_POINT_TYPE_PROG, ClockClientClkVfPointInfoV1},
|
||||
},
|
||||
opencl::get_opencl_info,
|
||||
vulkan::get_vulkan_info,
|
||||
server::gpu_controller::{
|
||||
NvApi,
|
||||
common::{fan_control::FanCurveExt, resolve_process_name},
|
||||
nvidia::nvapi::{CLOCK_CLIENT_CLK_VF_POINT_TYPE_PROG, ClockClientClkVfPointInfoV1},
|
||||
},
|
||||
};
|
||||
use amdgpu_sysfs::{
|
||||
@@ -20,14 +16,14 @@ use amdgpu_sysfs::{
|
||||
};
|
||||
use anyhow::{Context, anyhow, bail};
|
||||
use driver::DriverHandle;
|
||||
use futures::{FutureExt, future::LocalBoxFuture, join};
|
||||
use futures::{FutureExt, future::LocalBoxFuture};
|
||||
use indexmap::IndexMap;
|
||||
use lact_schema::{
|
||||
ActivePowerStates, CacheInfo, ClocksInfo, ClocksTable, ClockspeedStats, DeviceFlag, DeviceInfo,
|
||||
DeviceStats, DeviceType, DrmInfo, DrmMemoryInfo, FanControlMode, FanStats, IntelDrmInfo,
|
||||
LinkInfo, NvidiaClockOffset, NvidiaClocksTable, NvidiaVfPoint, PmfwInfo, PowerState,
|
||||
PowerStates, PowerStats, ProcessInfo, ProcessList, ProcessType, ProcessUtilizationType,
|
||||
TemperatureEntry, VoltageStats, VramStats,
|
||||
ActivePowerStates, CacheInfo, ClocksInfo, ClocksTable, ClockspeedStats, DeviceApiInfo,
|
||||
DeviceFlag, DeviceInfo, DeviceStats, DeviceType, DrmInfo, DrmMemoryInfo, FanControlMode,
|
||||
FanStats, IntelDrmInfo, LinkInfo, NvidiaClockOffset, NvidiaClocksTable, NvidiaVfPoint,
|
||||
PmfwInfo, PowerState, PowerStates, PowerStats, ProcessInfo, ProcessList, ProcessType,
|
||||
ProcessUtilizationType, TemperatureEntry, VoltageStats, VramStats,
|
||||
config::{CurvePoint, FanControlSettings, FanCurve, GpuConfig},
|
||||
};
|
||||
use nvml_wrapper::{
|
||||
@@ -535,23 +531,24 @@ impl GpuController for NvidiaGpuController {
|
||||
.or_else(|| self.common.pci_info.device_pci_info.model.clone())
|
||||
}
|
||||
|
||||
fn get_info(&self, unique_vendor: bool) -> LocalBoxFuture<'_, DeviceInfo> {
|
||||
fn get_info(
|
||||
&self,
|
||||
unique_vendor: bool,
|
||||
include_api_info: bool,
|
||||
) -> LocalBoxFuture<'_, DeviceInfo> {
|
||||
Box::pin(async move {
|
||||
let (vulkan_result, opencl_instances) = join!(
|
||||
get_vulkan_info(&self.common),
|
||||
get_opencl_info(&self.common, unique_vendor)
|
||||
);
|
||||
let vulkan_instances = vulkan_result.unwrap_or_else(|err| {
|
||||
warn!("could not load vulkan info: {err:#}");
|
||||
vec![]
|
||||
});
|
||||
let api_info = if include_api_info {
|
||||
self.get_api_info(unique_vendor).await
|
||||
} else {
|
||||
DeviceApiInfo::default()
|
||||
};
|
||||
|
||||
let device = self.device();
|
||||
let driver_handle = self.driver_handle.as_ref();
|
||||
|
||||
DeviceInfo {
|
||||
pci_info: Some(self.common.pci_info.clone()),
|
||||
vulkan_instances,
|
||||
api_info,
|
||||
driver: format!(
|
||||
"nvidia {}",
|
||||
self.nvml.sys_driver_version().unwrap_or_default()
|
||||
@@ -585,7 +582,6 @@ impl GpuController for NvidiaGpuController {
|
||||
output
|
||||
}),
|
||||
},
|
||||
opencl_instances,
|
||||
drm_info: Some(DrmInfo {
|
||||
device_name: device.name().ok(),
|
||||
pci_revision_id: None,
|
||||
|
||||
@@ -14,8 +14,9 @@ use amdgpu_sysfs::gpu_handle::{
|
||||
};
|
||||
use anyhow::{Context, anyhow, bail};
|
||||
use lact_schema::{
|
||||
ClocksInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanControlMode, FanOptions, PmfwOptions,
|
||||
PowerStates, ProcessList, ProfileRule, ProfileWatcherState, ProfilesInfo,
|
||||
ClocksInfo, DeviceApiInfo, DeviceInfo, DeviceListEntry, DeviceStats, FanControlMode,
|
||||
FanOptions, PmfwOptions, PowerStates, ProcessList, ProfileRule, ProfileWatcherState,
|
||||
ProfilesInfo,
|
||||
config::{
|
||||
FanControlSettings, FanCurve, GpuConfig, Profile, ProfileHooks, default_fan_static_speed,
|
||||
},
|
||||
@@ -423,7 +424,23 @@ impl<'a> Handler {
|
||||
entries
|
||||
}
|
||||
|
||||
pub async fn get_device_info(&'a self, id: &str) -> anyhow::Result<DeviceInfo> {
|
||||
pub async fn get_device_info(
|
||||
&'a self,
|
||||
id: &str,
|
||||
include_api_info: Option<bool>,
|
||||
) -> anyhow::Result<DeviceInfo> {
|
||||
let controllers = self.gpu_controllers.read().await;
|
||||
let controller = controllers
|
||||
.get(id)
|
||||
.ok_or_else(|| anyhow!("Controller '{id}' not found"))?;
|
||||
|
||||
let unique_vendor = controller_vendor_is_unique(controller, id, &controllers);
|
||||
let include_api_info = include_api_info.unwrap_or(true);
|
||||
|
||||
Ok(controller.get_info(unique_vendor, include_api_info).await)
|
||||
}
|
||||
|
||||
pub async fn get_device_api_info(&'a self, id: &str) -> anyhow::Result<DeviceApiInfo> {
|
||||
let controllers = self.gpu_controllers.read().await;
|
||||
let controller = controllers
|
||||
.get(id)
|
||||
@@ -431,7 +448,7 @@ impl<'a> Handler {
|
||||
|
||||
let unique_vendor = controller_vendor_is_unique(controller, id, &controllers);
|
||||
|
||||
Ok(controller.get_info(unique_vendor).await)
|
||||
Ok(controller.get_api_info(unique_vendor).await)
|
||||
}
|
||||
|
||||
pub async fn get_gpu_stats(&'a self, id: &str) -> anyhow::Result<DeviceStats> {
|
||||
@@ -773,7 +790,7 @@ impl<'a> Handler {
|
||||
|
||||
let data = json!({
|
||||
"pci_info": controller.controller_info().pci_info.clone(),
|
||||
"info": controller.get_info(unique_vendor).await,
|
||||
"info": controller.get_info(unique_vendor, true).await,
|
||||
"stats": controller.get_stats(gpu_config),
|
||||
"clocks_info": controller.get_clocks_info(gpu_config).ok(),
|
||||
"power_profile_modes": controller.get_power_profile_modes().ok(),
|
||||
|
||||
+29
-21
@@ -69,7 +69,7 @@ use relm4::{
|
||||
AsyncComponentSender, Component, ComponentController, MessageBroker, RelmObjectExt,
|
||||
RelmWidgetExt,
|
||||
actions::{AccelsPlus, ActionGroupName, RelmAction, RelmActionGroup},
|
||||
binding::BoolBinding,
|
||||
binding::{Binding as _, BoolBinding},
|
||||
css,
|
||||
loading_widgets::LoadingWidgets,
|
||||
new_action_group, new_stateless_action,
|
||||
@@ -114,6 +114,7 @@ pub struct AppModel {
|
||||
info_dialog: relm4::Controller<InfoDialog>,
|
||||
|
||||
ui_sensitive: BoolBinding,
|
||||
is_reconnecting: BoolBinding,
|
||||
|
||||
info_page: relm4::Controller<InformationPage>,
|
||||
oc_page: relm4::Controller<OcPage>,
|
||||
@@ -203,6 +204,7 @@ impl AsyncComponent for AppModel {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_vexpand: true,
|
||||
add_css_class: "main-sidebar-container",
|
||||
add_binding: (&model.ui_sensitive, "sensitive"),
|
||||
|
||||
model.gpu_selector.widget().clone() {},
|
||||
|
||||
@@ -252,16 +254,17 @@ impl AsyncComponent for AppModel {
|
||||
set_child = &adw::ToolbarView {
|
||||
#[name = "content_header"]
|
||||
add_top_bar = &adw::HeaderBar {
|
||||
|
||||
pack_end = >k::MenuButton {
|
||||
set_icon_name: "open-menu-symbolic",
|
||||
set_tooltip_text: Some(&fl!(I18N, "menu")),
|
||||
set_menu_model: Some(&app_menu),
|
||||
add_binding: (&model.ui_sensitive, "sensitive"),
|
||||
},
|
||||
|
||||
pack_end = >k::Button {
|
||||
set_label: &fl!(I18N, "show-historical-charts"),
|
||||
connect_clicked => move |_| APP_BROKER.send(AppMsg::ShowGraphsWindow),
|
||||
add_binding: (&model.ui_sensitive, "sensitive"),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -275,6 +278,11 @@ impl AsyncComponent for AppModel {
|
||||
connect_button_clicked => AppMsg::ShowOverdriveDialog,
|
||||
},
|
||||
|
||||
add_top_bar = &adw::Banner {
|
||||
set_title: &fl!(I18N, "reconnecting-to-daemon"),
|
||||
add_binding: (&model.is_reconnecting, "revealed"),
|
||||
},
|
||||
|
||||
#[wrap(Some)]
|
||||
set_content = >k::ScrolledWindow {
|
||||
set_hscrollbar_policy: gtk::PolicyType::Never,
|
||||
@@ -319,20 +327,6 @@ impl AsyncComponent for AppModel {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[name = "reconnecting_dialog"]
|
||||
adw::Dialog {
|
||||
set_title: &fl!(I18N, "daemon-connection-lost"),
|
||||
set_content_width: 300,
|
||||
set_content_height: 80,
|
||||
set_can_close: false,
|
||||
|
||||
#[wrap(Some)]
|
||||
set_child = >k::Label {
|
||||
set_margin_all: 10,
|
||||
set_label: &fl!(I18N, "reconnecting-to-daemon"),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
fn init_loading_widgets(root: Self::Root) -> Option<LoadingWidgets> {
|
||||
@@ -549,6 +543,7 @@ impl AsyncComponent for AppModel {
|
||||
gpu_selector,
|
||||
profile_selector,
|
||||
ui_sensitive: BoolBinding::new(false),
|
||||
is_reconnecting: BoolBinding::new(false),
|
||||
stats_task_handle: None,
|
||||
settings_changed,
|
||||
system_info,
|
||||
@@ -704,6 +699,12 @@ impl AppModel {
|
||||
self.update_gpu_data(gpu_id, sender).await?;
|
||||
}
|
||||
}
|
||||
AppMsg::ReloadApiInfo => {
|
||||
let gpu_id = Self::get_selected_gpu_id()?;
|
||||
let api_info = self.daemon_client.get_device_api_info(&gpu_id).await?;
|
||||
self.software_page
|
||||
.emit(SoftwarePageMsg::DeviceApiInfo(Some(api_info)));
|
||||
}
|
||||
AppMsg::ShowPreferencesDialog => {
|
||||
self.preferences_dialog.emit(PreferencesDialogMsg::Show);
|
||||
}
|
||||
@@ -926,9 +927,13 @@ impl AppModel {
|
||||
}
|
||||
AppMsg::ConnectionStatus(status) => match status {
|
||||
ConnectionStatusMsg::Disconnected => {
|
||||
// widgets.reconnecting_dialog.present(Some(root))
|
||||
self.ui_sensitive.set(false);
|
||||
self.is_reconnecting.set(true);
|
||||
}
|
||||
ConnectionStatusMsg::Reconnected => {
|
||||
self.ui_sensitive.set(true);
|
||||
self.is_reconnecting.set(false);
|
||||
}
|
||||
ConnectionStatusMsg::Reconnected => widgets.reconnecting_dialog.force_close(),
|
||||
},
|
||||
AppMsg::EvaluateProfile(rule, sender) => {
|
||||
match self.daemon_client.evaluate_profile_rule(rule).await {
|
||||
@@ -1062,10 +1067,12 @@ impl AppModel {
|
||||
sender: AsyncComponentSender<AppModel>,
|
||||
) -> anyhow::Result<()> {
|
||||
self.ui_sensitive.set_value(false);
|
||||
self.software_page
|
||||
.emit(SoftwarePageMsg::DeviceApiInfo(None));
|
||||
|
||||
let daemon_client = self.daemon_client.clone();
|
||||
let info_buf = daemon_client
|
||||
.get_device_info(&gpu_id)
|
||||
.get_device_info(&gpu_id, Some(false))
|
||||
.await
|
||||
.context("Could not fetch info")?;
|
||||
let info = Arc::new(info_buf);
|
||||
@@ -1094,8 +1101,9 @@ impl AppModel {
|
||||
update: update.clone(),
|
||||
initial: true,
|
||||
});
|
||||
self.software_page
|
||||
.emit(SoftwarePageMsg::DeviceInfo(info.clone()));
|
||||
|
||||
sender.input(AppMsg::ReloadApiInfo);
|
||||
|
||||
self.thermals_page.emit(ThermalsPageMsg::Update {
|
||||
update: update.clone(),
|
||||
initial: true,
|
||||
|
||||
@@ -14,6 +14,7 @@ pub enum AppMsg {
|
||||
ReloadData {
|
||||
full: bool,
|
||||
},
|
||||
ReloadApiInfo,
|
||||
Stats(Arc<DeviceStats>),
|
||||
ProfilesPolled(Arc<ProfilesInfo>),
|
||||
ApplyChanges,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::app::ext::FlowBoxExt;
|
||||
mod vulkan;
|
||||
|
||||
use crate::app::loader;
|
||||
use crate::{
|
||||
GUI_VERSION, I18N, REPO_URL,
|
||||
app::{
|
||||
@@ -13,14 +14,14 @@ use gtk::prelude::*;
|
||||
use i18n_embed_fl::fl;
|
||||
use indexmap::IndexMap;
|
||||
use lact_client::schema::{GIT_COMMIT, SystemInfo};
|
||||
use lact_schema::{DeviceInfo, OpenCLInfo, VulkanInfo};
|
||||
use lact_schema::{DeviceApiInfo, OpenCLInfo, VulkanInfo};
|
||||
use relm4::{Component, ComponentController, ComponentParts, ComponentSender, RelmWidgetExt};
|
||||
use relm4_components::simple_combo_box::{SimpleComboBox, SimpleComboBoxMsg};
|
||||
use std::{fmt::Write, sync::Arc};
|
||||
use std::fmt::Write as _;
|
||||
use vulkan::feature_window::{VulkanFeature, VulkanFeaturesWindow};
|
||||
|
||||
pub struct SoftwarePage {
|
||||
device_info: Option<Arc<DeviceInfo>>,
|
||||
device_api_info: Option<DeviceApiInfo>,
|
||||
|
||||
vulkan_driver_selector: relm4::Controller<SimpleComboBox<String>>,
|
||||
opencl_platform_selector: relm4::Controller<SimpleComboBox<String>>,
|
||||
@@ -30,7 +31,7 @@ pub struct SoftwarePage {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SoftwarePageMsg {
|
||||
DeviceInfo(Arc<DeviceInfo>),
|
||||
DeviceApiInfo(Option<DeviceApiInfo>),
|
||||
ShowVulkanFeatures,
|
||||
ShowVulkanExtensions,
|
||||
SelectionChanged,
|
||||
@@ -63,163 +64,179 @@ impl relm4::SimpleComponent for SoftwarePage {
|
||||
},
|
||||
},
|
||||
|
||||
#[name = "vulkan_stack"]
|
||||
match model.selected_vulkan_info() {
|
||||
Some(info) => {
|
||||
PageSection::new("Vulkan") {
|
||||
append_child = >k::FlowBox {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_column_spacing: 10,
|
||||
set_homogeneous: true,
|
||||
set_min_children_per_line: 2,
|
||||
set_max_children_per_line: 4,
|
||||
set_selection_mode: gtk::SelectionMode::None,
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "instance"),
|
||||
append_child = model.vulkan_driver_selector.widget(),
|
||||
} -> vulkan_instance_item: gtk::FlowBoxChild {
|
||||
#[watch]
|
||||
set_visible: model.vulkan_driver_selector.model().variants.len() > 1,
|
||||
},
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "device-name"),
|
||||
#[watch]
|
||||
set_value: info.device_name.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "api-version"),
|
||||
#[watch]
|
||||
set_value: info.api_version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "driver-name"),
|
||||
#[watch]
|
||||
set_value: info.driver.name.as_deref().unwrap_or_default(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "driver-version"),
|
||||
#[watch]
|
||||
set_value: info.driver.info.as_deref().unwrap_or_default(),
|
||||
set_selectable: true,
|
||||
},
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_value: fl!(I18N, "features"),
|
||||
set_icon: "go-next-symbolic".to_string(),
|
||||
connect_clicked => SoftwarePageMsg::ShowVulkanFeatures,
|
||||
},
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_value: fl!(I18N, "extensions"),
|
||||
set_icon: "go-next-symbolic".to_string(),
|
||||
connect_clicked => SoftwarePageMsg::ShowVulkanExtensions,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
None => {
|
||||
PageSection::new("Vulkan") {
|
||||
append_child = >k::Label {
|
||||
set_label: &fl!(I18N, "device-not-found", kind = "Vulkan"),
|
||||
set_halign: gtk::Align::Start,
|
||||
},
|
||||
}
|
||||
}
|
||||
#[local_ref]
|
||||
loader_picture -> gtk::Picture {
|
||||
set_halign: gtk::Align::Center,
|
||||
set_valign: gtk::Align::Start,
|
||||
#[watch]
|
||||
set_visible: model.device_api_info.is_none(),
|
||||
},
|
||||
|
||||
#[name = "opencl_stack"]
|
||||
match model.selected_opencl_info() {
|
||||
Some(info) => {
|
||||
PageSection::new("OpenCL") {
|
||||
append_child = >k::FlowBox {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_column_spacing: 10,
|
||||
set_homogeneous: true,
|
||||
set_min_children_per_line: 2,
|
||||
set_max_children_per_line: 4,
|
||||
set_selection_mode: gtk::SelectionMode::None,
|
||||
gtk::Box {
|
||||
set_spacing: 15,
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
#[watch]
|
||||
set_visible: model.device_api_info.is_some(),
|
||||
set_visible: false,
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "platform-name"),
|
||||
append_child = model.opencl_platform_selector.widget(),
|
||||
} -> opencl_platform_item: gtk::FlowBoxChild {
|
||||
#[watch]
|
||||
set_visible: model.opencl_platform_selector.model().variants.len() > 1,
|
||||
},
|
||||
#[name = "vulkan_stack"]
|
||||
match model.selected_vulkan_info() {
|
||||
Some(info) => {
|
||||
PageSection::new("Vulkan") {
|
||||
append_child = >k::FlowBox {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_column_spacing: 10,
|
||||
set_homogeneous: true,
|
||||
set_min_children_per_line: 2,
|
||||
set_max_children_per_line: 4,
|
||||
set_selection_mode: gtk::SelectionMode::None,
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "platform-name"),
|
||||
#[watch]
|
||||
set_value: info.platform_name.as_str(),
|
||||
set_selectable: true,
|
||||
} -> opencl_platform_name_item: gtk::FlowBoxChild {
|
||||
#[watch]
|
||||
set_visible: model.opencl_platform_selector.model().variants.len() == 1,
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "instance"),
|
||||
append_child = model.vulkan_driver_selector.widget(),
|
||||
} -> vulkan_instance_item: gtk::FlowBoxChild {
|
||||
#[watch]
|
||||
set_visible: model.vulkan_driver_selector.model().variants.len() > 1,
|
||||
},
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "device-name"),
|
||||
#[watch]
|
||||
set_value: info.device_name.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "api-version"),
|
||||
#[watch]
|
||||
set_value: info.api_version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "driver-name"),
|
||||
#[watch]
|
||||
set_value: info.driver.name.as_deref().unwrap_or_default(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "driver-version"),
|
||||
#[watch]
|
||||
set_value: info.driver.info.as_deref().unwrap_or_default(),
|
||||
set_selectable: true,
|
||||
},
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_value: fl!(I18N, "features"),
|
||||
set_icon: "go-next-symbolic".to_string(),
|
||||
connect_clicked => SoftwarePageMsg::ShowVulkanFeatures,
|
||||
},
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_value: fl!(I18N, "extensions"),
|
||||
set_icon: "go-next-symbolic".to_string(),
|
||||
connect_clicked => SoftwarePageMsg::ShowVulkanExtensions,
|
||||
},
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "device-name"),
|
||||
#[watch]
|
||||
set_value: info.device_name.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "version"),
|
||||
#[watch]
|
||||
set_value: info.version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "driver-version"),
|
||||
#[watch]
|
||||
set_value: info.driver_version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "cl-c-version"),
|
||||
#[watch]
|
||||
set_value: info.c_version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "compute-units"),
|
||||
#[watch]
|
||||
set_value: info.compute_units.to_string(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "workgroup-size"),
|
||||
#[watch]
|
||||
set_value: info.workgroup_size.to_string(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "global-memory"),
|
||||
#[watch]
|
||||
set_value: formatting::fmt_human_bytes(info.global_memory, None),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "local-memory"),
|
||||
#[watch]
|
||||
set_value: formatting::fmt_human_bytes(info.local_memory, None),
|
||||
set_selectable: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
PageSection::new("OpenCL") {
|
||||
append_child = >k::Label {
|
||||
set_label: &fl!(I18N, "device-not-found", kind = "OpenCL"),
|
||||
set_halign: gtk::Align::Start,
|
||||
},
|
||||
None => {
|
||||
PageSection::new("Vulkan") {
|
||||
append_child = >k::Label {
|
||||
set_label: &fl!(I18N, "device-not-found", kind = "Vulkan"),
|
||||
set_halign: gtk::Align::Start,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[name = "opencl_stack"]
|
||||
match model.selected_opencl_info() {
|
||||
Some(info) => {
|
||||
PageSection::new("OpenCL") {
|
||||
append_child = >k::FlowBox {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_column_spacing: 10,
|
||||
set_homogeneous: true,
|
||||
set_min_children_per_line: 2,
|
||||
set_max_children_per_line: 4,
|
||||
set_selection_mode: gtk::SelectionMode::None,
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "platform-name"),
|
||||
append_child = model.opencl_platform_selector.widget(),
|
||||
} -> opencl_platform_item: gtk::FlowBoxChild {
|
||||
#[watch]
|
||||
set_visible: model.opencl_platform_selector.model().variants.len() > 1,
|
||||
},
|
||||
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "platform-name"),
|
||||
#[watch]
|
||||
set_value: info.platform_name.as_str(),
|
||||
set_selectable: true,
|
||||
} -> opencl_platform_name_item: gtk::FlowBoxChild {
|
||||
#[watch]
|
||||
set_visible: model.opencl_platform_selector.model().variants.len() == 1,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "device-name"),
|
||||
#[watch]
|
||||
set_value: info.device_name.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "version"),
|
||||
#[watch]
|
||||
set_value: info.version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "driver-version"),
|
||||
#[watch]
|
||||
set_value: info.driver_version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "cl-c-version"),
|
||||
#[watch]
|
||||
set_value: info.c_version.as_str(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "compute-units"),
|
||||
#[watch]
|
||||
set_value: info.compute_units.to_string(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "workgroup-size"),
|
||||
#[watch]
|
||||
set_value: info.workgroup_size.to_string(),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "global-memory"),
|
||||
#[watch]
|
||||
set_value: formatting::fmt_human_bytes(info.global_memory, None),
|
||||
set_selectable: true,
|
||||
},
|
||||
append_child = &InfoRow {
|
||||
set_name: fl!(I18N, "local-memory"),
|
||||
#[watch]
|
||||
set_value: formatting::fmt_human_bytes(info.local_memory, None),
|
||||
set_selectable: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
None => {
|
||||
PageSection::new("OpenCL") {
|
||||
append_child = >k::Label {
|
||||
set_label: &fl!(I18N, "device-not-found", kind = "OpenCL"),
|
||||
set_halign: gtk::Align::Start,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -244,10 +261,10 @@ impl relm4::SimpleComponent for SoftwarePage {
|
||||
.forward(sender.input_sender(), |_| SoftwarePageMsg::SelectionChanged);
|
||||
|
||||
let model = Self {
|
||||
device_info: None,
|
||||
vulkan_driver_selector,
|
||||
opencl_platform_selector,
|
||||
vulkan_window: None,
|
||||
device_api_info: None,
|
||||
};
|
||||
|
||||
let mut daemon_version = format!("{}-{}", system_info.version, system_info.profile);
|
||||
@@ -273,6 +290,8 @@ impl relm4::SimpleComponent for SoftwarePage {
|
||||
"{GUI_VERSION}-{gui_profile} (commit <a href=\"{gui_commit_link}\">{GIT_COMMIT}</a>)"
|
||||
);
|
||||
|
||||
let loader_picture = loader::new();
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
widgets.vulkan_stack.set_vhomogeneous(false);
|
||||
@@ -283,7 +302,7 @@ impl relm4::SimpleComponent for SoftwarePage {
|
||||
|
||||
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
|
||||
match msg {
|
||||
SoftwarePageMsg::DeviceInfo(info) => {
|
||||
SoftwarePageMsg::DeviceApiInfo(Some(info)) => {
|
||||
let mut vulkan_drivers = Vec::new();
|
||||
|
||||
for info in &info.vulkan_instances {
|
||||
@@ -323,7 +342,10 @@ impl relm4::SimpleComponent for SoftwarePage {
|
||||
active_index: selected_platform,
|
||||
}));
|
||||
|
||||
self.device_info = Some(info);
|
||||
self.device_api_info = Some(info);
|
||||
}
|
||||
SoftwarePageMsg::DeviceApiInfo(None) => {
|
||||
self.device_api_info = None;
|
||||
}
|
||||
SoftwarePageMsg::ShowVulkanFeatures => {
|
||||
if let Some(vulkan_info) = &self.selected_vulkan_info() {
|
||||
@@ -352,7 +374,7 @@ impl SoftwarePage {
|
||||
.model()
|
||||
.active_index
|
||||
.and_then(|idx| {
|
||||
self.device_info
|
||||
self.device_api_info
|
||||
.as_ref()
|
||||
.and_then(|info| info.vulkan_instances.get(idx))
|
||||
})
|
||||
@@ -363,7 +385,7 @@ impl SoftwarePage {
|
||||
.model()
|
||||
.active_index
|
||||
.and_then(|idx| {
|
||||
self.device_info
|
||||
self.device_api_info
|
||||
.as_ref()
|
||||
.and_then(|info| info.opencl_instances.get(idx))
|
||||
})
|
||||
|
||||
+10
-4
@@ -133,10 +133,8 @@ pub enum DeviceFlag {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct DeviceInfo {
|
||||
pub pci_info: Option<GpuPciInfo>,
|
||||
#[serde(default)]
|
||||
pub vulkan_instances: Vec<VulkanInfo>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub opencl_instances: Vec<OpenCLInfo>,
|
||||
#[serde(flatten)]
|
||||
pub api_info: DeviceApiInfo,
|
||||
pub driver: String,
|
||||
pub vbios_version: Option<String>,
|
||||
pub link_info: LinkInfo,
|
||||
@@ -330,6 +328,14 @@ impl DeviceInfo {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
pub struct DeviceApiInfo {
|
||||
#[serde(default)]
|
||||
pub vulkan_instances: Vec<VulkanInfo>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub opencl_instances: Vec<OpenCLInfo>,
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
pub struct DrmInfo {
|
||||
|
||||
@@ -15,6 +15,11 @@ pub enum Request<'a> {
|
||||
SystemInfo,
|
||||
DeviceInfo {
|
||||
id: &'a str,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
include_api_info: Option<bool>,
|
||||
},
|
||||
DeviceApiInfo {
|
||||
id: &'a str,
|
||||
},
|
||||
DeviceStats {
|
||||
id: &'a str,
|
||||
|
||||
Reference in New Issue
Block a user