forked from nonsensical-dev/zenyx-engine
add window icon
This commit is contained in:
parent
7d4f7cbc1d
commit
9088d0aa49
12 changed files with 165 additions and 117 deletions
|
@ -35,6 +35,7 @@ serde = { version = "1.0.219", features = ["derive"] }
|
|||
native-dialog = "0.7.0"
|
||||
sysinfo = "0.34.2"
|
||||
raw-cpuid = "11.5.0"
|
||||
image = "0.25.6"
|
||||
|
||||
[build-dependencies]
|
||||
built = { version = "0.7.7", features = ["chrono"] }
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
fn main() {
|
||||
built::write_built_file().expect("Failed to write build information");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::str::FromStr;
|
||||
use std::{error::Error, path::PathBuf};
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::mem;
|
||||
use std::str::FromStr;
|
||||
use std::{error::Error, path::PathBuf};
|
||||
|
||||
use backtrace::Backtrace;
|
||||
use native_dialog::{MessageDialog, MessageType};
|
||||
|
@ -25,9 +25,9 @@ pub fn set_panic_hook() {
|
|||
}
|
||||
|
||||
fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box<dyn Error>> {
|
||||
use std::io::Write;
|
||||
|
||||
use colored::Colorize;
|
||||
use std::io::Write;
|
||||
|
||||
let log_dir = PathBuf::from_str("./").expect("wtf, The current directory no longer exists?");
|
||||
if !log_dir.exists() {
|
||||
|
|
|
@ -13,8 +13,9 @@ use wgpu_text::glyph_brush::ab_glyph::FontRef;
|
|||
use wgpu_text::glyph_brush::{HorizontalAlign, Layout, OwnedSection, OwnedText, VerticalAlign};
|
||||
use wgpu_text::{BrushBuilder, TextBrush};
|
||||
use winit::window::Window;
|
||||
use crate::error::{ZenyxError, ZenyxErrorKind};
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::error::{ZenyxError, ZenyxErrorKind};
|
||||
|
||||
const SHADER_SRC: &str = include_str!("shader.wgsl");
|
||||
|
||||
|
@ -130,7 +131,7 @@ struct Model {
|
|||
bind_group: wgpu::BindGroup,
|
||||
index_count: u32,
|
||||
transform: Matrix4<f32>,
|
||||
version: u32,
|
||||
version: u32,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
|
@ -174,7 +175,7 @@ impl Model {
|
|||
bind_group,
|
||||
index_count: indices.len() as u32,
|
||||
transform: Matrix4::identity(),
|
||||
version: 1
|
||||
version: 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +191,6 @@ impl Model {
|
|||
self.version += 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct Renderer<'window> {
|
||||
|
@ -211,7 +211,7 @@ pub struct Renderer<'window> {
|
|||
frame_count: u32,
|
||||
fps: f32,
|
||||
font_state: FontState,
|
||||
model_versions: Vec<u32>,
|
||||
model_versions: Vec<u32>,
|
||||
}
|
||||
|
||||
struct FontState {
|
||||
|
@ -368,11 +368,8 @@ impl<'window> Renderer<'window> {
|
|||
desired_maximum_frame_latency: 3,
|
||||
};
|
||||
surface.configure(&device, &surface_config);
|
||||
let (depth_texture, depth_texture_view) = create_depth_texture(
|
||||
&device,
|
||||
surface_config.width,
|
||||
surface_config.height,
|
||||
);
|
||||
let (depth_texture, depth_texture_view) =
|
||||
create_depth_texture(&device, surface_config.width, surface_config.height);
|
||||
let (depth_texture, depth_texture_view) =
|
||||
create_depth_texture(&device, surface_config.width, surface_config.height);
|
||||
|
||||
|
@ -390,8 +387,6 @@ impl<'window> Renderer<'window> {
|
|||
let scale = base_scale * (surface_config.width as f32 / base_width as f32).clamp(0.5, 2.0);
|
||||
let color = wgpu::Color::WHITE;
|
||||
|
||||
|
||||
|
||||
let section = OwnedSection::default()
|
||||
.add_text(OwnedText::new("FPS: 0.00").with_scale(scale).with_color([
|
||||
color.r as f32,
|
||||
|
@ -435,7 +430,7 @@ impl<'window> Renderer<'window> {
|
|||
scale,
|
||||
color,
|
||||
},
|
||||
model_versions: vec![]
|
||||
model_versions: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -480,16 +475,16 @@ impl<'window> Renderer<'window> {
|
|||
for (i, model) in self.models.iter_mut().enumerate() {
|
||||
let angle = Rad(elapsed * 0.8 + i as f32 * 0.3);
|
||||
if i % 2 == 0 {
|
||||
model.set_transform(Matrix4::from_angle_y(angle));
|
||||
model.set_transform(Matrix4::from_angle_y(angle));
|
||||
} else {
|
||||
model.set_transform(Matrix4::from_angle_x(angle) * Matrix4::from_angle_y(angle));
|
||||
model.set_transform(Matrix4::from_angle_x(angle) * Matrix4::from_angle_y(angle));
|
||||
}
|
||||
}
|
||||
for (i, model) in self.models.iter().enumerate() {
|
||||
if model.version > self.model_versions[i] {
|
||||
model.update(&self.queue);
|
||||
#[cfg(debug_assertions)]
|
||||
trace!("Updating model: {:#?}",model);
|
||||
trace!("Updating model: {:#?}", model);
|
||||
self.model_versions[i] = model.version;
|
||||
}
|
||||
}
|
||||
|
@ -609,9 +604,11 @@ impl<'window> Renderer<'window> {
|
|||
pub fn bg_color(&self) -> &wgpu::Color {
|
||||
&self.bg_color
|
||||
}
|
||||
|
||||
pub fn text_color(&self) -> &wgpu::Color {
|
||||
&self.font_state.color
|
||||
}
|
||||
|
||||
pub fn set_text_color(&mut self, color: wgpu::Color) {
|
||||
self.font_state.color = color;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
use std::env;
|
||||
use std::fs;
|
||||
use std::io::Cursor;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ctx::{Renderer, Vertex};
|
||||
use winit::dpi::LogicalSize;
|
||||
use winit::dpi::Size;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use image::ImageDecoder;
|
||||
use image::ImageFormat;
|
||||
use tobj::Mesh;
|
||||
use tobj::{LoadOptions, Model};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use wgpu::rwh::HasWindowHandle;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::dpi::LogicalSize;
|
||||
use winit::dpi::Size;
|
||||
use winit::event::{KeyEvent, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||
use winit::monitor::MonitorHandle;
|
||||
use winit::platform::windows::WindowAttributesExtWindows;
|
||||
use winit::window::Fullscreen;
|
||||
use winit::window::Icon;
|
||||
use winit::window::Window;
|
||||
use winit::window::WindowId;
|
||||
|
||||
|
@ -90,7 +95,14 @@ f 6/11/6 5/10/6 1/1/6 2/13/6
|
|||
|
||||
impl App<'_> {
|
||||
fn create_main_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||
let win_attr = Window::default_attributes().with_title("Zenyx").with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)));
|
||||
let icon = self.load_icon_from_bytes(Self::ICON).unwrap();
|
||||
|
||||
let win_attr = Window::default_attributes()
|
||||
.with_title("Zenyx")
|
||||
.with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
|
||||
.with_window_icon(icon.clone())
|
||||
.with_taskbar_icon(icon);
|
||||
|
||||
match event_loop.create_window(win_attr) {
|
||||
Ok(window) => {
|
||||
let window = Arc::new(window);
|
||||
|
@ -160,7 +172,7 @@ impl App<'_> {
|
|||
) {
|
||||
if !key_event.state.is_pressed() || key_event.repeat {
|
||||
return;
|
||||
}
|
||||
}
|
||||
match key_event.physical_key {
|
||||
winit::keyboard::PhysicalKey::Code(code) => match code {
|
||||
winit::keyboard::KeyCode::Space => {
|
||||
|
@ -199,6 +211,7 @@ impl App<'_> {
|
|||
warn!("No window context for toggling background: {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_fullscreen(&mut self, window_id: WindowId) {
|
||||
if let Some(ctx) = self.windows.get_mut(&window_id) {
|
||||
let is_fullscreen = ctx.window.fullscreen().is_some();
|
||||
|
@ -216,13 +229,43 @@ impl App<'_> {
|
|||
warn!("No window found for fullscreen toggle: {:?}", window_id);
|
||||
}
|
||||
}
|
||||
fn load_icon_from_bytes(&self, bytes: &[u8]) -> Result<Option<Icon>, String> {
|
||||
const IMAGE_DIR: &str = env!("CARGO_MANIFEST_DIR");
|
||||
let cursor = Cursor::new(bytes);
|
||||
let format = image::guess_format(bytes).map_err(|_| "Failed to guess image format")?;
|
||||
let decoder = match format {
|
||||
ImageFormat::Png => image::codecs::png::PngDecoder::new(cursor).map_err(|e| format!("Failed to decode PNG: {}", e))?,
|
||||
_ => {
|
||||
let img = image::load_from_memory(bytes).map_err(|e| format!("Failed to load image: {}", e))?.into_rgba8();
|
||||
let (width, height) = img.dimensions();
|
||||
return Icon::from_rgba(img.into_raw(), width, height)
|
||||
.map(Some)
|
||||
.map_err(|e| format!("Failed to create icon from bytes: {}", e));
|
||||
}
|
||||
};
|
||||
|
||||
let (width, height) = decoder.dimensions();
|
||||
let mut image_data = vec![0; decoder.total_bytes() as usize];
|
||||
decoder.read_image(&mut image_data).map_err(|e| format!("Failed to read image data: {}", e))?;
|
||||
|
||||
Icon::from_rgba(image_data, width, height)
|
||||
.map(Some)
|
||||
.map_err(|e| format!("Failed to create icon from bytes: {}", e))
|
||||
}
|
||||
|
||||
const ICON: &'static [u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/Badge.png"));
|
||||
fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
||||
let title = format!("Zenyx - New Window {}", self.windows.len());
|
||||
// TODO: Verify that this is safe instead of matching on it
|
||||
let icon = self.load_icon_from_bytes(Self::ICON).unwrap();
|
||||
|
||||
let win_attr = unsafe {
|
||||
let base = Window::default_attributes().with_title(title).with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)));
|
||||
let base = Window::default_attributes()
|
||||
.with_title(title)
|
||||
.with_min_inner_size(Size::Logical(LogicalSize::new(100.0, 100.0)))
|
||||
.with_window_icon(icon.clone())
|
||||
.with_taskbar_icon(icon);
|
||||
|
||||
match main_ctx.window_handle() {
|
||||
Ok(handle) => {
|
||||
if !cfg!(target_os = "windows") {
|
||||
|
@ -230,11 +273,11 @@ impl App<'_> {
|
|||
} else {
|
||||
base
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
base
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
match event_loop.create_window(win_attr) {
|
||||
|
|
|
@ -5,7 +5,7 @@ use regex::Regex;
|
|||
|
||||
use super::{handler::Command, input::tokenize};
|
||||
use crate::core::repl::handler::COMMAND_MANAGER;
|
||||
use crate::error::{ZenyxError,ZenyxErrorKind};
|
||||
use crate::error::{ZenyxError, ZenyxErrorKind};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct HelpCommand;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use colored::Colorize;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use crate::error::{ZenyxError, ZenyxErrorKind};
|
||||
|
||||
pub static COMMAND_MANAGER: LazyLock<RwLock<CommandManager>> = LazyLock::new(|| { RwLock::new(CommandManager::init()) });
|
||||
pub static COMMAND_MANAGER: LazyLock<RwLock<CommandManager>> =
|
||||
LazyLock::new(|| RwLock::new(CommandManager::init()));
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! commands {
|
||||
|
|
|
@ -6,9 +6,6 @@ pub mod commands;
|
|||
pub mod handler;
|
||||
pub mod input;
|
||||
|
||||
|
||||
|
||||
|
||||
pub fn setup() {
|
||||
commands!(
|
||||
HelpCommand,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use colored::Colorize;
|
||||
use thiserror::Error;
|
||||
use std::fmt::Write;
|
||||
|
||||
use colored::Colorize;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error,PartialEq)]
|
||||
#[derive(Debug, Error, PartialEq)]
|
||||
pub enum ZenyxErrorKind {
|
||||
#[error("Surface creation failed")]
|
||||
SurfaceCreation,
|
||||
|
@ -48,6 +48,7 @@ impl ZenyxError {
|
|||
source: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> &ZenyxErrorKind {
|
||||
&self.kind
|
||||
}
|
||||
|
@ -87,45 +88,21 @@ impl ZenyxError {
|
|||
|
||||
if let Some(msg) = &self.message {
|
||||
let line_padding = " ".repeat(padding_spaces);
|
||||
writeln!(
|
||||
output,
|
||||
"{}>> {}\x1b[0m",
|
||||
line_padding,
|
||||
msg.bright_white()
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, "{}>> {}\x1b[0m", line_padding, msg.bright_white()).unwrap();
|
||||
}
|
||||
if let Some(ctx) = &self.context {
|
||||
let line_padding = " ".repeat(padding_spaces);
|
||||
writeln!(output, "{}│\x1b[0m", line_padding.bright_white().bold()).unwrap();
|
||||
writeln!(
|
||||
output,
|
||||
"{}╰─ Note: {}\x1b[0m",
|
||||
line_padding,
|
||||
ctx
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, "{}╰─ Note: {}\x1b[0m", line_padding, ctx).unwrap();
|
||||
}
|
||||
if let Some(source) = &self.source {
|
||||
let line_padding = " ".repeat(padding_spaces);
|
||||
writeln!(
|
||||
output,
|
||||
"{}╰─ Caused by: {}\x1b[0m",
|
||||
line_padding,
|
||||
source
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, "{}╰─ Caused by: {}\x1b[0m", line_padding, source).unwrap();
|
||||
let mut current = source.source();
|
||||
let mut depth = 1;
|
||||
while let Some(err) = current {
|
||||
let indent = " ".repeat(padding_spaces * depth);
|
||||
writeln!(
|
||||
output,
|
||||
"{}↳ {}\x1b[0m",
|
||||
indent,
|
||||
err
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, "{}↳ {}\x1b[0m", indent, err).unwrap();
|
||||
depth += 1;
|
||||
current = err.source();
|
||||
}
|
||||
|
@ -136,22 +113,31 @@ impl ZenyxError {
|
|||
|
||||
impl std::fmt::Display for ZenyxError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Error: {}{}{}{}",
|
||||
write!(
|
||||
f,
|
||||
"Error: {}{}{}{}",
|
||||
self.kind,
|
||||
self.message.as_ref().map_or("".to_string(), |msg| format!(" - {}", msg)),
|
||||
self.context.as_ref().map_or("".to_string(), |ctx| format!(" [{}]", ctx)),
|
||||
self.source.as_ref().map_or("".to_string(), |src| format!(" - caused by: {}", src))
|
||||
self.message
|
||||
.as_ref()
|
||||
.map_or("".to_string(), |msg| format!(" - {}", msg)),
|
||||
self.context
|
||||
.as_ref()
|
||||
.map_or("".to_string(), |ctx| format!(" [{}]", ctx)),
|
||||
self.source
|
||||
.as_ref()
|
||||
.map_or("".to_string(), |src| format!(" - caused by: {}", src))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ZenyxError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
self.source.as_ref().map(|s| s.as_ref() as &(dyn std::error::Error + 'static))
|
||||
self.source
|
||||
.as_ref()
|
||||
.map(|s| s.as_ref() as &(dyn std::error::Error + 'static))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<std::io::Error> for ZenyxError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
Self::builder(ZenyxErrorKind::Io)
|
||||
|
@ -230,7 +216,6 @@ mod tests {
|
|||
assert!(error.source.is_some());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_from_rustyline_error() {
|
||||
let readline_error = rustyline::error::ReadlineError::Interrupted;
|
||||
|
@ -256,7 +241,6 @@ mod tests {
|
|||
error.pretty_print();
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_error_source_chain() {
|
||||
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use core::{panic::set_panic_hook, repl::setup, splash};
|
||||
use thiserror::Error;
|
||||
|
||||
use colored::Colorize;
|
||||
use tokio::runtime;
|
||||
#[allow(unused_imports)]
|
||||
|
@ -29,31 +29,26 @@ async fn main() {
|
|||
init_logger();
|
||||
let sysinfo = crate::metadata::SystemMetadata::current();
|
||||
|
||||
|
||||
set_panic_hook();
|
||||
setup();
|
||||
|
||||
|
||||
|
||||
splash::print_splash();
|
||||
if !cfg!(debug_assertions) {
|
||||
info!("{}", "Debug mode disabled".bright_blue());
|
||||
set_panic_hook();
|
||||
} else {
|
||||
println!("{}",sysinfo.verbose_summary());
|
||||
println!("{}", sysinfo.verbose_summary());
|
||||
}
|
||||
|
||||
|
||||
info!("Type 'help' for a list of commands.");
|
||||
let repl_thread = std::thread::spawn(|| {
|
||||
let rt = match runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build() {
|
||||
Ok(rt) => rt,
|
||||
Err(e) => {
|
||||
error!("A fatal error has occured: {e}");
|
||||
std::process::exit(1)
|
||||
},
|
||||
};
|
||||
let rt = match runtime::Builder::new_current_thread().enable_all().build() {
|
||||
Ok(rt) => rt,
|
||||
Err(e) => {
|
||||
error!("A fatal error has occured: {e}");
|
||||
std::process::exit(1)
|
||||
}
|
||||
};
|
||||
rt.block_on(core::repl::input::handle_repl())
|
||||
});
|
||||
splash::print_splash();
|
||||
|
@ -71,5 +66,4 @@ async fn main() {
|
|||
if let Err(_) = repl_thread.join() {
|
||||
error!("REPL thread panicked");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use sysinfo::{CpuRefreshKind, RefreshKind, System};
|
||||
|
||||
use raw_cpuid::CpuId;
|
||||
use sysinfo::{CpuRefreshKind, RefreshKind, System};
|
||||
use wgpu::DeviceType;
|
||||
use std::collections::HashSet;
|
||||
|
||||
mod build_info {
|
||||
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
||||
|
@ -24,11 +25,15 @@ impl Memory {
|
|||
}
|
||||
|
||||
pub const fn from_mb(mb: u64) -> Self {
|
||||
Self { bytes: mb * 1024 * 1024 }
|
||||
Self {
|
||||
bytes: mb * 1024 * 1024,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn from_gb(gb: u64) -> Self {
|
||||
Self { bytes: gb * 1024 * 1024 * 1024 }
|
||||
Self {
|
||||
bytes: gb * 1024 * 1024 * 1024,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn as_bytes(&self) -> u64 {
|
||||
|
@ -185,18 +190,24 @@ pub struct CPU {
|
|||
|
||||
impl CPU {
|
||||
pub fn current() -> Self {
|
||||
let mut sys = System::new_with_specifics(RefreshKind::default().with_cpu(CpuRefreshKind::everything()));
|
||||
let mut sys = System::new_with_specifics(
|
||||
RefreshKind::default().with_cpu(CpuRefreshKind::everything()),
|
||||
);
|
||||
sys.refresh_cpu_all();
|
||||
|
||||
let cpu_opt = sys.cpus().first();
|
||||
|
||||
let brand = cpu_opt.map(|cpu| cpu.brand().into())
|
||||
let brand = cpu_opt
|
||||
.map(|cpu| cpu.brand().into())
|
||||
.unwrap_or(CPUBrand::Other("unknown".into()));
|
||||
let name = cpu_opt.map(|cpu| cpu.name().to_string())
|
||||
let name = cpu_opt
|
||||
.map(|cpu| cpu.name().to_string())
|
||||
.unwrap_or_else(|| "unknown".into());
|
||||
let vendor_id = cpu_opt.map(|cpu| cpu.vendor_id().to_string())
|
||||
let vendor_id = cpu_opt
|
||||
.map(|cpu| cpu.vendor_id().to_string())
|
||||
.unwrap_or_else(|| "unknown".into());
|
||||
let max_clock_speed = cpu_opt.map(|cpu| ClockSpeed(cpu.frequency() as u32))
|
||||
let max_clock_speed = cpu_opt
|
||||
.map(|cpu| ClockSpeed(cpu.frequency() as u32))
|
||||
.unwrap_or(ClockSpeed(0));
|
||||
let current_clock_speed = max_clock_speed;
|
||||
|
||||
|
@ -214,20 +225,26 @@ impl CPU {
|
|||
let size = cache.physical_line_partitions()
|
||||
* cache.coherency_line_size()
|
||||
* cache.associativity();
|
||||
if size > 0 { l1_cache = Some(Memory::from_bytes(size.try_into().unwrap())); }
|
||||
},
|
||||
if size > 0 {
|
||||
l1_cache = Some(Memory::from_bytes(size.try_into().unwrap()));
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
let size = cache.physical_line_partitions()
|
||||
* cache.coherency_line_size()
|
||||
* cache.associativity();
|
||||
if size > 0 { l2_cache = Some(Memory::from_bytes(size.try_into().unwrap())); }
|
||||
},
|
||||
if size > 0 {
|
||||
l2_cache = Some(Memory::from_bytes(size.try_into().unwrap()));
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
let size = (cache.physical_line_partitions() as u64)
|
||||
* (cache.coherency_line_size() as u64)
|
||||
* (cache.associativity() as u64);
|
||||
if size > 0 { l3_cache = Some(Memory::from_bytes(size)); }
|
||||
},
|
||||
if size > 0 {
|
||||
l3_cache = Some(Memory::from_bytes(size));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +252,9 @@ impl CPU {
|
|||
|
||||
Self {
|
||||
brand,
|
||||
arch: std::env::consts::ARCH.parse().unwrap_or(CPUArch::Other("unknown".into())),
|
||||
arch: std::env::consts::ARCH
|
||||
.parse()
|
||||
.unwrap_or(CPUArch::Other("unknown".into())),
|
||||
name,
|
||||
vendor_id,
|
||||
physical_cores,
|
||||
|
@ -257,7 +276,7 @@ impl CPU {
|
|||
}
|
||||
|
||||
pub fn is_arm(&self) -> bool {
|
||||
matches!(self.brand,CPUBrand::Intel)
|
||||
matches!(self.brand, CPUBrand::Intel)
|
||||
}
|
||||
|
||||
pub fn is_high_clock(&self) -> bool {
|
||||
|
@ -278,13 +297,23 @@ impl CPU {
|
|||
self.arch,
|
||||
self.name,
|
||||
self.vendor_id,
|
||||
self.physical_cores.map(|c| c.to_string()).unwrap_or_else(|| "unknown".into()),
|
||||
self.logical_cores.map(|c| c.to_string()).unwrap_or_else(|| "unknown".into()),
|
||||
self.physical_cores
|
||||
.map(|c| c.to_string())
|
||||
.unwrap_or_else(|| "unknown".into()),
|
||||
self.logical_cores
|
||||
.map(|c| c.to_string())
|
||||
.unwrap_or_else(|| "unknown".into()),
|
||||
self.max_clock_speed,
|
||||
self.current_clock_speed,
|
||||
self.l1_cache.map(|c| c.format_human()).unwrap_or_else(|| "unknown".into()),
|
||||
self.l2_cache.map(|c| c.format_human()).unwrap_or_else(|| "unknown".into()),
|
||||
self.l3_cache.map(|c| c.format_human()).unwrap_or_else(|| "unknown".into()),
|
||||
self.l1_cache
|
||||
.map(|c| c.format_human())
|
||||
.unwrap_or_else(|| "unknown".into()),
|
||||
self.l2_cache
|
||||
.map(|c| c.format_human())
|
||||
.unwrap_or_else(|| "unknown".into()),
|
||||
self.l3_cache
|
||||
.map(|c| c.format_human())
|
||||
.unwrap_or_else(|| "unknown".into()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +361,6 @@ pub struct GPU {
|
|||
pub driver_version: Option<String>,
|
||||
}
|
||||
|
||||
|
||||
impl GPU {
|
||||
pub fn current() -> Vec<Self> {
|
||||
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
|
||||
|
@ -363,6 +391,7 @@ impl GPU {
|
|||
pub fn is_dedicated(&self) -> bool {
|
||||
!self.is_integrated()
|
||||
}
|
||||
|
||||
pub fn is_mobile(&self) -> bool {
|
||||
let lower_name = self.name.to_lowercase();
|
||||
lower_name.contains("adreno")
|
||||
|
@ -490,6 +519,7 @@ impl SystemMetadata {
|
|||
compile_info: CompileInfo::current(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_gpu(&self) -> Option<&GPU> {
|
||||
self.gpus
|
||||
.iter()
|
||||
|
@ -498,7 +528,6 @@ impl SystemMetadata {
|
|||
.or_else(|| self.gpus.first())
|
||||
}
|
||||
|
||||
|
||||
pub fn verbose_summary(&self) -> String {
|
||||
let main_gpu = self.main_gpu();
|
||||
let main_gpu_info = main_gpu
|
||||
|
@ -556,4 +585,4 @@ mod tests {
|
|||
assert!(metadata.memory.total.as_bytes() > 0);
|
||||
assert!(!metadata.compile_info.pkg_version.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue