From 69452294a7fa4ea48aefcbe2913399d877bf761b Mon Sep 17 00:00:00 2001 From: Ben Wallis Date: Sun, 3 Jul 2022 23:05:53 +0100 Subject: [PATCH] Added Engine Performance EGUI window --- Cargo.lock | 1 + common/frontend/src/lib.rs | 1 + voxygen/egui/Cargo.toml | 1 + voxygen/egui/src/lib.rs | 152 +++++++++++++++++++++++++---------- voxygen/src/scene/terrain.rs | 4 + voxygen/src/session/mod.rs | 1 + 6 files changed, 118 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6378f84af..5bc38c8590 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6991,6 +6991,7 @@ dependencies = [ "egui", "egui_winit_platform", "lazy_static", + "num 0.4.0", "veloren-client", "veloren-common", "veloren-voxygen-dynlib", diff --git a/common/frontend/src/lib.rs b/common/frontend/src/lib.rs index 504b359cfd..0a08e75731 100644 --- a/common/frontend/src/lib.rs +++ b/common/frontend/src/lib.rs @@ -73,6 +73,7 @@ where "quinn_proto::connection=info", "veloren_server::persistence::character=info", "veloren_server::settings=info", + "veloren_voxygen::audio::sfx=info", ]; for s in default_directives { diff --git a/voxygen/egui/Cargo.toml b/voxygen/egui/Cargo.toml index 1a32adbf90..7b0bd77758 100644 --- a/voxygen/egui/Cargo.toml +++ b/voxygen/egui/Cargo.toml @@ -14,6 +14,7 @@ common = {package = "veloren-common", path = "../../common"} egui = "0.12" egui_winit_platform = "0.8" lazy_static = "1.4.0" +num = "0.4" voxygen-dynlib = {package = "veloren-voxygen-dynlib", path = "../dynlib", optional = true} diff --git a/voxygen/egui/src/lib.rs b/voxygen/egui/src/lib.rs index c5b7743681..ef0ef40ad7 100644 --- a/voxygen/egui/src/lib.rs +++ b/voxygen/egui/src/lib.rs @@ -19,6 +19,7 @@ use egui::{ widgets::plot::Curve, CollapsingHeader, Color32, Grid, Pos2, ScrollArea, Slider, Ui, Window, }; +use num::{ToPrimitive, Zero}; use crate::{ admin::draw_admin_commands_window, character_states::draw_char_state_group, @@ -82,6 +83,7 @@ impl AdminCommandState { pub struct EguiDebugInfo { pub frame_time: Duration, pub ping_ms: f64, + pub mesh_active: usize, pub mesh_todo: usize, } @@ -90,11 +92,73 @@ pub struct EguiInnerState { admin_command_state: AdminCommandState, max_entity_distance: f32, selected_entity_cylinder_height: f32, - frame_times: Vec, - mesh_todos: Vec, + plots: EguiPlots, windows: EguiWindows, } +pub struct EguiPlots { + frame_times: EguiPlot, + chunks_active_meshing: EguiPlot, + chunks_pending_meshing: EguiPlot, +} + +impl Default for EguiPlots { + fn default() -> Self { + const DATA_POINT_LIMIT: usize = 2000; + + Self { + frame_times: EguiPlot::::new("Frame Times".to_owned(), DATA_POINT_LIMIT), + chunks_active_meshing: EguiPlot::::new( + "Chunks Active Meshing".to_owned(), + DATA_POINT_LIMIT, + ), + chunks_pending_meshing: EguiPlot::::new( + "Chunks Pending Meshing".to_owned(), + DATA_POINT_LIMIT, + ), + } + } +} + +pub struct EguiPlot { + title: String, + data_points: Vec, + /// The number of data points that will be retained and displayed in the + /// plot + data_point_limit: usize, +} + +impl EguiPlot { + fn new(title: String, data_point_limit: usize) -> Self { + Self { + title, + data_points: vec![T::zero(); data_point_limit], + data_point_limit, + } + } + + fn maintain(&mut self, value: T) { + self.data_points.push(value); + if self.data_points.len() > self.data_point_limit { + self.data_points.remove(0); + } + } + + fn current_value(&self) -> T { self.data_points.last().map(|x| *x).unwrap_or(T::zero()) } + + fn plot(&self, color: Color32) -> Plot { + Plot::new(self.title.to_owned()).curve( + Curve::from_values_iter( + self.data_points + .iter() + .enumerate() + .map(|(i, x)| Value::new(i as f64, x.to_f64().unwrap())), + ) + .color(color), + ) + } +} + #[derive(Clone, Default)] pub struct EguiWindows { admin_commands: bool, @@ -102,6 +166,7 @@ pub struct EguiWindows { egui_settings: bool, egui_memory: bool, frame_time: bool, + engine_performance: bool, ecs_entities: bool, experimental_shaders: bool, } @@ -113,8 +178,7 @@ impl Default for EguiInnerState { selected_entity_info: None, max_entity_distance: 100000.0, selected_entity_cylinder_height: 10.0, - frame_times: Vec::new(), - mesh_todos: Vec::new(), + plots: EguiPlots::default(), windows: EguiWindows::default(), } } @@ -231,16 +295,17 @@ pub fn maintain_egui_inner( if let Some(debug_info) = debug_info.as_ref() { egui_state + .plots .frame_times - .push(debug_info.frame_time.as_nanos() as f32); - if egui_state.frame_times.len() > 250 { - egui_state.frame_times.remove(0); - } - - egui_state.mesh_todos.push(debug_info.mesh_todo); - if egui_state.mesh_todos.len() > 2000 { - egui_state.mesh_todos.remove(0); - } + .maintain(debug_info.frame_time.as_nanos() as f32); + egui_state + .plots + .chunks_active_meshing + .maintain(debug_info.mesh_active); + egui_state + .plots + .chunks_pending_meshing + .maintain(debug_info.mesh_todo); }; let start_pos = Pos2 { x: 300.0, y: 0.0 }; @@ -260,6 +325,7 @@ pub fn maintain_egui_inner( ui.checkbox(&mut windows.admin_commands, "Admin Commands"); ui.checkbox(&mut windows.ecs_entities, "ECS Entities"); ui.checkbox(&mut windows.frame_time, "Frame Time"); + ui.checkbox(&mut windows.engine_performance, "Engine Performance"); ui.checkbox(&mut windows.experimental_shaders, "Experimental Shaders"); }); }); @@ -296,41 +362,43 @@ pub fn maintain_egui_inner( ctx.memory_ui(ui); }); + Window::new("Engine Performance") + .open(&mut windows.engine_performance) + .default_width(200.0) + .default_height(400.0) + .show(ctx, |ui| { + ui.label(format!( + "Active Meshing: {}", + egui_state.plots.chunks_active_meshing.current_value() + )); + let chunks_active_meshing_plot = egui_state + .plots + .chunks_active_meshing + .plot(Color32::from_rgb(241, 80, 88)) + .height(250.0); + ui.add(chunks_active_meshing_plot); + + ui.add_space(10.0); + + ui.label(format!( + "Pending Meshing: {}", + egui_state.plots.chunks_pending_meshing.current_value() + )); + let chunks_pending_meshing_plot = egui_state + .plots + .chunks_pending_meshing + .plot(Color32::from_rgb(45, 91, 215)) + .height(250.0); + ui.add(chunks_pending_meshing_plot); + }); + Window::new("Frame Time") .open(&mut windows.frame_time) .default_width(200.0) .default_height(200.0) .show(ctx, |ui| { - let plot = Plot::new("Frame Time") - .curve(Curve::from_values_iter( - egui_state - .frame_times - .iter() - .enumerate() - .map(|(i, x)| Value::new(i as f64, *x)), - )) - .height(50.0); + let plot = egui_state.plots.frame_times.plot(Color32::RED).height(50.0); ui.add(plot); - - ui.add_space(20.0); - - ui.label(format!( - "Pending Meshing: {}", - &egui_state.mesh_todos.last().unwrap_or(&0usize) - )); - let mesh_todo_plot = Plot::new("Chunks Pending Meshing") - .curve( - Curve::from_values_iter( - egui_state - .mesh_todos - .iter() - .enumerate() - .map(|(i, x)| Value::new(i as f64, (*x) as f64)), - ) - .color(Color32::from_rgb(45, 91, 215)), - ) - .height(200.0); - ui.add(mesh_todo_plot); }); if windows.ecs_entities { diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 3c9b55739d..023d1d370a 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -362,6 +362,10 @@ pub struct Terrain { impl Terrain { pub fn chunks_pending_meshing_count(&self) -> usize { self.mesh_todo.iter().len() } + + pub fn chunks_active_meshing_count(&self) -> usize { + self.mesh_todos_active.load(Ordering::Relaxed) as usize + } } impl TerrainChunkData { diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index c6c667e1fc..e507616609 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1106,6 +1106,7 @@ impl PlayState for SessionState { let debug_info = debug_info.map(|debug_info| EguiDebugInfo { frame_time: debug_info.frame_time, ping_ms: debug_info.ping_ms, + mesh_active: self.scene.terrain().chunks_active_meshing_count(), mesh_todo: self.scene.terrain().chunks_pending_meshing_count(), });