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"
|
native-dialog = "0.7.0"
|
||||||
sysinfo = "0.34.2"
|
sysinfo = "0.34.2"
|
||||||
raw-cpuid = "11.5.0"
|
raw-cpuid = "11.5.0"
|
||||||
|
image = "0.25.6"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
built = { version = "0.7.7", features = ["chrono"] }
|
built = { version = "0.7.7", features = ["chrono"] }
|
||||||
|
|
|
@ -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::fmt::Write as FmtWrite;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::{error::Error, path::PathBuf};
|
||||||
|
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
use native_dialog::{MessageDialog, MessageType};
|
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>> {
|
fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box<dyn Error>> {
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
let log_dir = PathBuf::from_str("./").expect("wtf, The current directory no longer exists?");
|
let log_dir = PathBuf::from_str("./").expect("wtf, The current directory no longer exists?");
|
||||||
if !log_dir.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::glyph_brush::{HorizontalAlign, Layout, OwnedSection, OwnedText, VerticalAlign};
|
||||||
use wgpu_text::{BrushBuilder, TextBrush};
|
use wgpu_text::{BrushBuilder, TextBrush};
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
use crate::error::{ZenyxError, ZenyxErrorKind};
|
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
|
use crate::error::{ZenyxError, ZenyxErrorKind};
|
||||||
|
|
||||||
const SHADER_SRC: &str = include_str!("shader.wgsl");
|
const SHADER_SRC: &str = include_str!("shader.wgsl");
|
||||||
|
|
||||||
|
@ -174,7 +175,7 @@ impl Model {
|
||||||
bind_group,
|
bind_group,
|
||||||
index_count: indices.len() as u32,
|
index_count: indices.len() as u32,
|
||||||
transform: Matrix4::identity(),
|
transform: Matrix4::identity(),
|
||||||
version: 1
|
version: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +191,6 @@ impl Model {
|
||||||
self.version += 1;
|
self.version += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Renderer<'window> {
|
pub struct Renderer<'window> {
|
||||||
|
@ -368,11 +368,8 @@ impl<'window> Renderer<'window> {
|
||||||
desired_maximum_frame_latency: 3,
|
desired_maximum_frame_latency: 3,
|
||||||
};
|
};
|
||||||
surface.configure(&device, &surface_config);
|
surface.configure(&device, &surface_config);
|
||||||
let (depth_texture, depth_texture_view) = create_depth_texture(
|
let (depth_texture, depth_texture_view) =
|
||||||
&device,
|
create_depth_texture(&device, surface_config.width, surface_config.height);
|
||||||
surface_config.width,
|
|
||||||
surface_config.height,
|
|
||||||
);
|
|
||||||
let (depth_texture, depth_texture_view) =
|
let (depth_texture, depth_texture_view) =
|
||||||
create_depth_texture(&device, surface_config.width, surface_config.height);
|
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 scale = base_scale * (surface_config.width as f32 / base_width as f32).clamp(0.5, 2.0);
|
||||||
let color = wgpu::Color::WHITE;
|
let color = wgpu::Color::WHITE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let section = OwnedSection::default()
|
let section = OwnedSection::default()
|
||||||
.add_text(OwnedText::new("FPS: 0.00").with_scale(scale).with_color([
|
.add_text(OwnedText::new("FPS: 0.00").with_scale(scale).with_color([
|
||||||
color.r as f32,
|
color.r as f32,
|
||||||
|
@ -435,7 +430,7 @@ impl<'window> Renderer<'window> {
|
||||||
scale,
|
scale,
|
||||||
color,
|
color,
|
||||||
},
|
},
|
||||||
model_versions: vec![]
|
model_versions: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +484,7 @@ impl<'window> Renderer<'window> {
|
||||||
if model.version > self.model_versions[i] {
|
if model.version > self.model_versions[i] {
|
||||||
model.update(&self.queue);
|
model.update(&self.queue);
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
trace!("Updating model: {:#?}",model);
|
trace!("Updating model: {:#?}", model);
|
||||||
self.model_versions[i] = model.version;
|
self.model_versions[i] = model.version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -609,9 +604,11 @@ impl<'window> Renderer<'window> {
|
||||||
pub fn bg_color(&self) -> &wgpu::Color {
|
pub fn bg_color(&self) -> &wgpu::Color {
|
||||||
&self.bg_color
|
&self.bg_color
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_color(&self) -> &wgpu::Color {
|
pub fn text_color(&self) -> &wgpu::Color {
|
||||||
&self.font_state.color
|
&self.font_state.color
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_text_color(&mut self, color: wgpu::Color) {
|
pub fn set_text_color(&mut self, color: wgpu::Color) {
|
||||||
self.font_state.color = 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::ops::Deref;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ctx::{Renderer, Vertex};
|
use ctx::{Renderer, Vertex};
|
||||||
use winit::dpi::LogicalSize;
|
use image::ImageDecoder;
|
||||||
use winit::dpi::Size;
|
use image::ImageFormat;
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use tobj::Mesh;
|
use tobj::Mesh;
|
||||||
use tobj::{LoadOptions, Model};
|
use tobj::{LoadOptions, Model};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
use wgpu::rwh::HasWindowHandle;
|
use wgpu::rwh::HasWindowHandle;
|
||||||
use winit::application::ApplicationHandler;
|
use winit::application::ApplicationHandler;
|
||||||
|
use winit::dpi::LogicalSize;
|
||||||
|
use winit::dpi::Size;
|
||||||
use winit::event::{KeyEvent, WindowEvent};
|
use winit::event::{KeyEvent, WindowEvent};
|
||||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||||
use winit::monitor::MonitorHandle;
|
use winit::monitor::MonitorHandle;
|
||||||
|
use winit::platform::windows::WindowAttributesExtWindows;
|
||||||
use winit::window::Fullscreen;
|
use winit::window::Fullscreen;
|
||||||
|
use winit::window::Icon;
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
use winit::window::WindowId;
|
use winit::window::WindowId;
|
||||||
|
|
||||||
|
@ -90,7 +95,14 @@ f 6/11/6 5/10/6 1/1/6 2/13/6
|
||||||
|
|
||||||
impl App<'_> {
|
impl App<'_> {
|
||||||
fn create_main_window(&mut self, event_loop: &ActiveEventLoop) {
|
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) {
|
match event_loop.create_window(win_attr) {
|
||||||
Ok(window) => {
|
Ok(window) => {
|
||||||
let window = Arc::new(window);
|
let window = Arc::new(window);
|
||||||
|
@ -199,6 +211,7 @@ impl App<'_> {
|
||||||
warn!("No window context for toggling background: {:?}", window_id);
|
warn!("No window context for toggling background: {:?}", window_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_fullscreen(&mut self, window_id: WindowId) {
|
fn toggle_fullscreen(&mut self, window_id: WindowId) {
|
||||||
if let Some(ctx) = self.windows.get_mut(&window_id) {
|
if let Some(ctx) = self.windows.get_mut(&window_id) {
|
||||||
let is_fullscreen = ctx.window.fullscreen().is_some();
|
let is_fullscreen = ctx.window.fullscreen().is_some();
|
||||||
|
@ -216,13 +229,43 @@ impl App<'_> {
|
||||||
warn!("No window found for fullscreen toggle: {:?}", window_id);
|
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) {
|
fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
||||||
let title = format!("Zenyx - New Window {}", self.windows.len());
|
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 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() {
|
match main_ctx.window_handle() {
|
||||||
Ok(handle) => {
|
Ok(handle) => {
|
||||||
if !cfg!(target_os = "windows") {
|
if !cfg!(target_os = "windows") {
|
||||||
|
@ -230,11 +273,11 @@ impl App<'_> {
|
||||||
} else {
|
} else {
|
||||||
base
|
base
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("{e}");
|
error!("{e}");
|
||||||
base
|
base
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match event_loop.create_window(win_attr) {
|
match event_loop.create_window(win_attr) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use regex::Regex;
|
||||||
|
|
||||||
use super::{handler::Command, input::tokenize};
|
use super::{handler::Command, input::tokenize};
|
||||||
use crate::core::repl::handler::COMMAND_MANAGER;
|
use crate::core::repl::handler::COMMAND_MANAGER;
|
||||||
use crate::error::{ZenyxError,ZenyxErrorKind};
|
use crate::error::{ZenyxError, ZenyxErrorKind};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct HelpCommand;
|
pub struct HelpCommand;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use std::sync::LazyLock;
|
|
||||||
use crate::error::{ZenyxError, ZenyxErrorKind};
|
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_export]
|
||||||
macro_rules! commands {
|
macro_rules! commands {
|
||||||
|
|
|
@ -6,9 +6,6 @@ pub mod commands;
|
||||||
pub mod handler;
|
pub mod handler;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn setup() {
|
pub fn setup() {
|
||||||
commands!(
|
commands!(
|
||||||
HelpCommand,
|
HelpCommand,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use colored::Colorize;
|
|
||||||
use thiserror::Error;
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
use colored::Colorize;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error,PartialEq)]
|
#[derive(Debug, Error, PartialEq)]
|
||||||
pub enum ZenyxErrorKind {
|
pub enum ZenyxErrorKind {
|
||||||
#[error("Surface creation failed")]
|
#[error("Surface creation failed")]
|
||||||
SurfaceCreation,
|
SurfaceCreation,
|
||||||
|
@ -48,6 +48,7 @@ impl ZenyxError {
|
||||||
source: None,
|
source: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kind(&self) -> &ZenyxErrorKind {
|
pub fn kind(&self) -> &ZenyxErrorKind {
|
||||||
&self.kind
|
&self.kind
|
||||||
}
|
}
|
||||||
|
@ -87,45 +88,21 @@ impl ZenyxError {
|
||||||
|
|
||||||
if let Some(msg) = &self.message {
|
if let Some(msg) = &self.message {
|
||||||
let line_padding = " ".repeat(padding_spaces);
|
let line_padding = " ".repeat(padding_spaces);
|
||||||
writeln!(
|
writeln!(output, "{}>> {}\x1b[0m", line_padding, msg.bright_white()).unwrap();
|
||||||
output,
|
|
||||||
"{}>> {}\x1b[0m",
|
|
||||||
line_padding,
|
|
||||||
msg.bright_white()
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
if let Some(ctx) = &self.context {
|
if let Some(ctx) = &self.context {
|
||||||
let line_padding = " ".repeat(padding_spaces);
|
let line_padding = " ".repeat(padding_spaces);
|
||||||
writeln!(output, "{}│\x1b[0m", line_padding.bright_white().bold()).unwrap();
|
writeln!(output, "{}│\x1b[0m", line_padding.bright_white().bold()).unwrap();
|
||||||
writeln!(
|
writeln!(output, "{}╰─ Note: {}\x1b[0m", line_padding, ctx).unwrap();
|
||||||
output,
|
|
||||||
"{}╰─ Note: {}\x1b[0m",
|
|
||||||
line_padding,
|
|
||||||
ctx
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
if let Some(source) = &self.source {
|
if let Some(source) = &self.source {
|
||||||
let line_padding = " ".repeat(padding_spaces);
|
let line_padding = " ".repeat(padding_spaces);
|
||||||
writeln!(
|
writeln!(output, "{}╰─ Caused by: {}\x1b[0m", line_padding, source).unwrap();
|
||||||
output,
|
|
||||||
"{}╰─ Caused by: {}\x1b[0m",
|
|
||||||
line_padding,
|
|
||||||
source
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let mut current = source.source();
|
let mut current = source.source();
|
||||||
let mut depth = 1;
|
let mut depth = 1;
|
||||||
while let Some(err) = current {
|
while let Some(err) = current {
|
||||||
let indent = " ".repeat(padding_spaces * depth);
|
let indent = " ".repeat(padding_spaces * depth);
|
||||||
writeln!(
|
writeln!(output, "{}↳ {}\x1b[0m", indent, err).unwrap();
|
||||||
output,
|
|
||||||
"{}↳ {}\x1b[0m",
|
|
||||||
indent,
|
|
||||||
err
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
depth += 1;
|
depth += 1;
|
||||||
current = err.source();
|
current = err.source();
|
||||||
}
|
}
|
||||||
|
@ -136,22 +113,31 @@ impl ZenyxError {
|
||||||
|
|
||||||
impl std::fmt::Display for ZenyxError {
|
impl std::fmt::Display for ZenyxError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "Error: {}{}{}{}",
|
write!(
|
||||||
|
f,
|
||||||
|
"Error: {}{}{}{}",
|
||||||
self.kind,
|
self.kind,
|
||||||
self.message.as_ref().map_or("".to_string(), |msg| format!(" - {}", msg)),
|
self.message
|
||||||
self.context.as_ref().map_or("".to_string(), |ctx| format!(" [{}]", ctx)),
|
.as_ref()
|
||||||
self.source.as_ref().map_or("".to_string(), |src| format!(" - caused by: {}", src))
|
.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 {
|
impl std::error::Error for ZenyxError {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
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 {
|
impl From<std::io::Error> for ZenyxError {
|
||||||
fn from(err: std::io::Error) -> Self {
|
fn from(err: std::io::Error) -> Self {
|
||||||
Self::builder(ZenyxErrorKind::Io)
|
Self::builder(ZenyxErrorKind::Io)
|
||||||
|
@ -230,7 +216,6 @@ mod tests {
|
||||||
assert!(error.source.is_some());
|
assert!(error.source.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_rustyline_error() {
|
fn test_from_rustyline_error() {
|
||||||
let readline_error = rustyline::error::ReadlineError::Interrupted;
|
let readline_error = rustyline::error::ReadlineError::Interrupted;
|
||||||
|
@ -256,7 +241,6 @@ mod tests {
|
||||||
error.pretty_print();
|
error.pretty_print();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_source_chain() {
|
fn test_error_source_chain() {
|
||||||
let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
|
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 core::{panic::set_panic_hook, repl::setup, splash};
|
||||||
use thiserror::Error;
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use tokio::runtime;
|
use tokio::runtime;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
|
@ -29,30 +29,25 @@ async fn main() {
|
||||||
init_logger();
|
init_logger();
|
||||||
let sysinfo = crate::metadata::SystemMetadata::current();
|
let sysinfo = crate::metadata::SystemMetadata::current();
|
||||||
|
|
||||||
|
|
||||||
set_panic_hook();
|
set_panic_hook();
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
splash::print_splash();
|
splash::print_splash();
|
||||||
if !cfg!(debug_assertions) {
|
if !cfg!(debug_assertions) {
|
||||||
info!("{}", "Debug mode disabled".bright_blue());
|
info!("{}", "Debug mode disabled".bright_blue());
|
||||||
set_panic_hook();
|
set_panic_hook();
|
||||||
} else {
|
} else {
|
||||||
println!("{}",sysinfo.verbose_summary());
|
println!("{}", sysinfo.verbose_summary());
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Type 'help' for a list of commands.");
|
info!("Type 'help' for a list of commands.");
|
||||||
let repl_thread = std::thread::spawn(|| {
|
let repl_thread = std::thread::spawn(|| {
|
||||||
let rt = match runtime::Builder::new_current_thread()
|
let rt = match runtime::Builder::new_current_thread().enable_all().build() {
|
||||||
.enable_all()
|
|
||||||
.build() {
|
|
||||||
Ok(rt) => rt,
|
Ok(rt) => rt,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("A fatal error has occured: {e}");
|
error!("A fatal error has occured: {e}");
|
||||||
std::process::exit(1)
|
std::process::exit(1)
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
rt.block_on(core::repl::input::handle_repl())
|
rt.block_on(core::repl::input::handle_repl())
|
||||||
});
|
});
|
||||||
|
@ -71,5 +66,4 @@ async fn main() {
|
||||||
if let Err(_) = repl_thread.join() {
|
if let Err(_) = repl_thread.join() {
|
||||||
error!("REPL thread panicked");
|
error!("REPL thread panicked");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use sysinfo::{CpuRefreshKind, RefreshKind, System};
|
|
||||||
use raw_cpuid::CpuId;
|
use raw_cpuid::CpuId;
|
||||||
|
use sysinfo::{CpuRefreshKind, RefreshKind, System};
|
||||||
use wgpu::DeviceType;
|
use wgpu::DeviceType;
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
mod build_info {
|
mod build_info {
|
||||||
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
||||||
|
@ -24,11 +25,15 @@ impl Memory {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn from_mb(mb: u64) -> Self {
|
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 {
|
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 {
|
pub const fn as_bytes(&self) -> u64 {
|
||||||
|
@ -185,18 +190,24 @@ pub struct CPU {
|
||||||
|
|
||||||
impl CPU {
|
impl CPU {
|
||||||
pub fn current() -> Self {
|
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();
|
sys.refresh_cpu_all();
|
||||||
|
|
||||||
let cpu_opt = sys.cpus().first();
|
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()));
|
.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());
|
.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());
|
.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));
|
.unwrap_or(ClockSpeed(0));
|
||||||
let current_clock_speed = max_clock_speed;
|
let current_clock_speed = max_clock_speed;
|
||||||
|
|
||||||
|
@ -214,20 +225,26 @@ impl CPU {
|
||||||
let size = cache.physical_line_partitions()
|
let size = cache.physical_line_partitions()
|
||||||
* cache.coherency_line_size()
|
* cache.coherency_line_size()
|
||||||
* cache.associativity();
|
* 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 => {
|
2 => {
|
||||||
let size = cache.physical_line_partitions()
|
let size = cache.physical_line_partitions()
|
||||||
* cache.coherency_line_size()
|
* cache.coherency_line_size()
|
||||||
* cache.associativity();
|
* 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 => {
|
3 => {
|
||||||
let size = (cache.physical_line_partitions() as u64)
|
let size = (cache.physical_line_partitions() as u64)
|
||||||
* (cache.coherency_line_size() as u64)
|
* (cache.coherency_line_size() as u64)
|
||||||
* (cache.associativity() 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 {
|
Self {
|
||||||
brand,
|
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,
|
name,
|
||||||
vendor_id,
|
vendor_id,
|
||||||
physical_cores,
|
physical_cores,
|
||||||
|
@ -257,7 +276,7 @@ impl CPU {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_arm(&self) -> bool {
|
pub fn is_arm(&self) -> bool {
|
||||||
matches!(self.brand,CPUBrand::Intel)
|
matches!(self.brand, CPUBrand::Intel)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_high_clock(&self) -> bool {
|
pub fn is_high_clock(&self) -> bool {
|
||||||
|
@ -278,13 +297,23 @@ impl CPU {
|
||||||
self.arch,
|
self.arch,
|
||||||
self.name,
|
self.name,
|
||||||
self.vendor_id,
|
self.vendor_id,
|
||||||
self.physical_cores.map(|c| c.to_string()).unwrap_or_else(|| "unknown".into()),
|
self.physical_cores
|
||||||
self.logical_cores.map(|c| c.to_string()).unwrap_or_else(|| "unknown".into()),
|
.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.max_clock_speed,
|
||||||
self.current_clock_speed,
|
self.current_clock_speed,
|
||||||
self.l1_cache.map(|c| c.format_human()).unwrap_or_else(|| "unknown".into()),
|
self.l1_cache
|
||||||
self.l2_cache.map(|c| c.format_human()).unwrap_or_else(|| "unknown".into()),
|
.map(|c| c.format_human())
|
||||||
self.l3_cache.map(|c| c.format_human()).unwrap_or_else(|| "unknown".into()),
|
.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>,
|
pub driver_version: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl GPU {
|
impl GPU {
|
||||||
pub fn current() -> Vec<Self> {
|
pub fn current() -> Vec<Self> {
|
||||||
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
|
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
|
||||||
|
@ -363,6 +391,7 @@ impl GPU {
|
||||||
pub fn is_dedicated(&self) -> bool {
|
pub fn is_dedicated(&self) -> bool {
|
||||||
!self.is_integrated()
|
!self.is_integrated()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_mobile(&self) -> bool {
|
pub fn is_mobile(&self) -> bool {
|
||||||
let lower_name = self.name.to_lowercase();
|
let lower_name = self.name.to_lowercase();
|
||||||
lower_name.contains("adreno")
|
lower_name.contains("adreno")
|
||||||
|
@ -490,6 +519,7 @@ impl SystemMetadata {
|
||||||
compile_info: CompileInfo::current(),
|
compile_info: CompileInfo::current(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_gpu(&self) -> Option<&GPU> {
|
pub fn main_gpu(&self) -> Option<&GPU> {
|
||||||
self.gpus
|
self.gpus
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -498,7 +528,6 @@ impl SystemMetadata {
|
||||||
.or_else(|| self.gpus.first())
|
.or_else(|| self.gpus.first())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn verbose_summary(&self) -> String {
|
pub fn verbose_summary(&self) -> String {
|
||||||
let main_gpu = self.main_gpu();
|
let main_gpu = self.main_gpu();
|
||||||
let main_gpu_info = main_gpu
|
let main_gpu_info = main_gpu
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue