From 0f120ca3eee991566cda704be13b0b1e41dc8d66 Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sat, 18 Jan 2025 01:21:46 +0100 Subject: more profiler things --- client/src/interfaces/mod.rs | 3 ++- client/src/interfaces/profiler.rs | 50 +++++++++++++++++++++++++++++++++++++-- client/src/renderer.rs | 21 +++++++++++++--- client/src/scene_prepare.rs | 18 ++++++++++---- client/src/state.rs | 1 + 5 files changed, 82 insertions(+), 11 deletions(-) (limited to 'client/src') diff --git a/client/src/interfaces/mod.rs b/client/src/interfaces/mod.rs index 09db60f..eb0eb86 100644 --- a/client/src/interfaces/mod.rs +++ b/client/src/interfaces/mod.rs @@ -20,7 +20,7 @@ pub mod profiler; use crate::{download::Downloader, network::Network, scene_prepare::ScenePreparer}; use egui::Widget; use prefabindex::PrefabIndexInterface; -use profiler::Profiler; +use profiler::{Profiler, TimingProfiler}; use std::sync::{Arc, Mutex}; use weareshared::resources::PrefabIndex; @@ -35,6 +35,7 @@ pub struct InterfaceData { pub network: Arc, pub downloader: Arc, pub prefab_index: Arc, + pub render_timing: Arc>, } pub fn ui_selector(idata: Arc) -> impl Fn(&egui::Context) -> bool { diff --git a/client/src/interfaces/profiler.rs b/client/src/interfaces/profiler.rs index 5c8737b..85b5858 100644 --- a/client/src/interfaces/profiler.rs +++ b/client/src/interfaces/profiler.rs @@ -15,8 +15,8 @@ along with this program. If not, see . */ use super::InterfaceData; -use egui::Widget; -use std::sync::Arc; +use egui::{Grid, Widget}; +use std::{sync::Arc, time::Instant}; pub struct Profiler { pub idata: Arc, @@ -28,6 +28,52 @@ impl Widget for &mut Profiler { ui.add(&*self.idata.scene_prepare); ui.heading("Download"); ui.add(&*self.idata.downloader); + ui.heading("Render"); + ui.add(&*self.idata.render_timing.lock().unwrap()); ui.response() } } + +pub struct TimingProfiler { + last_cp: Instant, + cur_cp: &'static str, + checkpoints: Vec<(&'static str, f32)>, +} + +impl Default for TimingProfiler { + fn default() -> Self { + Self { + last_cp: Instant::now(), + checkpoints: Default::default(), + cur_cp: "none", + } + } +} +impl TimingProfiler { + pub fn begin(&mut self, name: &'static str) { + self.checkpoints.clear(); + self.last_cp = Instant::now(); + self.cur_cp = name; + } + pub fn checkpoint(&mut self, name: &'static str) { + let now = Instant::now(); + let dur = (now - self.last_cp).as_secs_f32(); + self.last_cp = now; + self.checkpoints.push((self.cur_cp, dur)); + self.cur_cp = name; + } +} +impl Widget for &TimingProfiler { + fn ui(self, ui: &mut egui::Ui) -> egui::Response { + Grid::new("tp") + .num_columns(2) + .show(ui, |ui| { + for (name, dur) in &self.checkpoints { + ui.label(*name); + ui.label(format!("{:.02}ms", dur * 1000.)); + ui.end_row(); + } + }) + .response + } +} diff --git a/client/src/renderer.rs b/client/src/renderer.rs index b4c2c05..2777526 100644 --- a/client/src/renderer.rs +++ b/client/src/renderer.rs @@ -15,14 +15,15 @@ along with this program. If not, see . */ use crate::{ - camera::Camera, download::Downloader, scene_prepare::ScenePreparer, - scene_render::ScenePipeline, state::InputState, ui::UiRenderer, + camera::Camera, download::Downloader, interfaces::profiler::TimingProfiler, + scene_prepare::ScenePreparer, scene_render::ScenePipeline, state::InputState, ui::UiRenderer, }; use anyhow::{Result, anyhow}; use log::{info, warn}; use pollster::FutureExt; use std::{ - sync::Arc, + mem::swap, + sync::{Arc, Mutex}, thread::{sleep, spawn}, time::Duration, }; @@ -45,6 +46,8 @@ pub struct Renderer<'a> { pub scene_prepare: Arc, surface_needs_reconfigure: bool, depth: TextureView, + pub timing: TimingProfiler, + pub timing_submit: Arc>, } impl<'a> Renderer<'a> { pub fn new(window: &'a Window, downloader: Arc) -> Result { @@ -138,6 +141,8 @@ impl<'a> Renderer<'a> { surface_configuration, ui_renderer, surface_needs_reconfigure: false, + timing: Default::default(), + timing_submit: Default::default(), }) } @@ -172,6 +177,7 @@ impl<'a> Renderer<'a> { camera: &Camera, input_state: &mut InputState, ) -> Result<()> { + self.timing.begin("prepare"); if self.surface_needs_reconfigure { self.surface .configure(&self.device, &self.surface_configuration); @@ -192,6 +198,7 @@ impl<'a> Renderer<'a> { let projection = camera.to_matrix(); + self.timing.checkpoint("draw scene"); self.scene_pipeline.draw( &mut commands, &target_view, @@ -201,6 +208,7 @@ impl<'a> Renderer<'a> { projection, ); + self.timing.checkpoint("draw ui"); self.ui_renderer.draw( &mut commands, &target_view, @@ -210,11 +218,18 @@ impl<'a> Renderer<'a> { &self.surface_configuration, ); + self.timing.checkpoint("submit"); let i = self.queue.submit(Some(commands.finish())); + self.timing.checkpoint("poll"); self.device.poll(MaintainBase::WaitForSubmissionIndex(i)); + self.timing.checkpoint("present"); target.present(); + self.timing.checkpoint(""); + + let mut ts = self.timing_submit.lock().unwrap(); + swap(&mut *ts, &mut self.timing); Ok(()) } } diff --git a/client/src/scene_prepare.rs b/client/src/scene_prepare.rs index cee55f7..5c5102d 100644 --- a/client/src/scene_prepare.rs +++ b/client/src/scene_prepare.rs @@ -17,6 +17,7 @@ use crate::download::Downloader; use anyhow::Result; use egui::{Grid, Widget}; +use humansize::DECIMAL; use image::ImageReader; use log::debug; use std::{ @@ -45,6 +46,7 @@ pub struct DemandMap { struct DemandMapState { values: HashMap, needed: HashSet, + size_metric: usize, } impl DemandMap { pub fn new() -> Self { @@ -52,6 +54,7 @@ impl DemandMap { inner: DemandMapState { needed: HashSet::new(), values: HashMap::new(), + size_metric: 0, } .into(), } @@ -59,10 +62,11 @@ impl DemandMap { pub fn needed(&self) -> Vec { self.inner.read().unwrap().needed.iter().cloned().collect() } - pub fn insert(&self, key: K, value: V) { + pub fn insert(&self, key: K, value: V, size: usize) { let mut s = self.inner.write().unwrap(); s.needed.remove(&key); s.values.insert(key, value); + s.size_metric += size; } pub fn try_get(&self, key: K) -> Option { let mut s = self.inner.write().unwrap(); @@ -127,7 +131,7 @@ impl ScenePreparer { } } if rprefab.0.len() == prefab.mesh.len() { - self.prefabs.insert(pres.clone(), Arc::new(rprefab)); + self.prefabs.insert(pres.clone(), Arc::new(rprefab), 0); debug!("prefab created ({pres})"); num_done += 1; } @@ -149,6 +153,7 @@ impl ScenePreparer { self.index_buffers.insert( pres.clone(), (Arc::new(buffer), (buf.len() / size_of::()) as u32), + buf.len(), ); debug!( "index buffer created (len={}, took {:?}) {pres}", @@ -173,6 +178,7 @@ impl ScenePreparer { self.vertex_buffers.insert( pres.clone(), (Arc::new(buffer), (buf.len() / size_of::()) as u32), + buf.len(), ); debug!( "vertex attribute buffer created (len={}, took {:?}) {pres}", @@ -198,7 +204,7 @@ impl ScenePreparer { dims.0, dims.1, ); - self.textures.insert(pres.clone(), tex_bg); + self.textures.insert(pres.clone(), tex_bg, image.len()); debug!( "texture created (res={}x{}, took {:?})", dims.0, @@ -218,7 +224,7 @@ impl ScenePreparer { 1, 1, ); - self.placeholder_textures.insert(variant, tex_bg); + self.placeholder_textures.insert(variant, tex_bg, 4); num_done += 1; } for pres in self.mesh_parts.needed() { @@ -294,6 +300,7 @@ impl ScenePreparer { tex_normal, double_sided: part.g_double_sided.is_some(), }), + 0, ); num_done += 1; } @@ -361,6 +368,7 @@ impl Widget for &DemandMap { let state = self.inner.read().unwrap(); ui.label(state.needed.len().to_string()); ui.label(state.values.len().to_string()); + ui.label(humansize::format_size(state.size_metric, DECIMAL)); ui.end_row(); ui.response() } @@ -369,7 +377,7 @@ impl Widget for &DemandMap { impl Widget for &ScenePreparer { fn ui(self, ui: &mut egui::Ui) -> egui::Response { Grid::new("sp") - .num_columns(3) + .num_columns(4) .show(ui, |ui| { ui.label("prefabs"); self.prefabs.ui(ui); diff --git a/client/src/state.rs b/client/src/state.rs index 439b7ca..2912e14 100644 --- a/client/src/state.rs +++ b/client/src/state.rs @@ -108,6 +108,7 @@ impl<'a> State<'a> { downloader: self.downloader.clone(), network: self.network.clone(), prefab_index: self.prefab_index.clone(), + render_timing: self.renderer.timing_submit.clone(), }); self.renderer .ui_renderer -- cgit v1.2.3-70-g09d2