Compare commits

...

2 Commits

Author SHA1 Message Date
Jarrod Doyle ea4b69f666
Implement basic profilng output 2024-05-18 17:34:18 +01:00
Jarrod Doyle ead95e72e9
Add wgpu_profiler 2024-05-18 17:33:58 +01:00
3 changed files with 56 additions and 4 deletions

View File

@ -11,4 +11,5 @@ bytemuck = "1.15.0"
log = "0.4.21" log = "0.4.21"
thiserror = "1.0.59" thiserror = "1.0.59"
wgpu = "0.19.4" wgpu = "0.19.4"
wgpu-profiler = "0.16.2"
winit = "0.29.15" winit = "0.29.15"

View File

@ -1,6 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use thiserror::Error; use thiserror::Error;
use wgpu_profiler::{GpuProfiler, GpuProfilerSettings, GpuTimerQueryResult};
use winit::{ use winit::{
dpi::PhysicalSize, dpi::PhysicalSize,
error::{EventLoopError, OsError}, error::{EventLoopError, OsError},
@ -9,7 +10,13 @@ use winit::{
window::{Window, WindowBuilder}, window::{Window, WindowBuilder},
}; };
pub trait Pass { pub trait Pass {
fn execute(&self, encoder: &mut wgpu::CommandEncoder, view: &wgpu::TextureView); fn execute(
&self,
profiler: &GpuProfiler,
device: &wgpu::Device,
encoder: &mut wgpu::CommandEncoder,
view: &wgpu::TextureView,
);
} }
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -28,6 +35,8 @@ pub enum ContextError {
Os(#[from] OsError), Os(#[from] OsError),
#[error("Render failed: {0}")] #[error("Render failed: {0}")]
Render(#[from] wgpu::SurfaceError), Render(#[from] wgpu::SurfaceError),
#[error("Profiler creation failed: {0}")]
Profiler(#[from] wgpu_profiler::CreationError),
} }
pub struct Context<'window> { pub struct Context<'window> {
@ -39,6 +48,8 @@ pub struct Context<'window> {
pub adapter: wgpu::Adapter, pub adapter: wgpu::Adapter,
pub device: wgpu::Device, pub device: wgpu::Device,
pub queue: wgpu::Queue, pub queue: wgpu::Queue,
pub profiler: GpuProfiler,
pub latest_profiler_results: Option<Vec<GpuTimerQueryResult>>,
} }
impl<'window> Context<'window> { impl<'window> Context<'window> {
@ -100,6 +111,9 @@ impl<'window> Context<'window> {
}; };
surface.configure(&device, &surface_config); surface.configure(&device, &surface_config);
log::info!("Creating GPU profiler...");
let profiler = GpuProfiler::new(GpuProfilerSettings::default())?;
Ok(Self { Ok(Self {
window, window,
instance, instance,
@ -109,6 +123,8 @@ impl<'window> Context<'window> {
adapter, adapter,
device, device,
queue, queue,
profiler,
latest_profiler_results: None,
}) })
} }
@ -144,7 +160,7 @@ impl<'window> Context<'window> {
handled handled
} }
pub fn render(&self, passes: &[Box<dyn Pass>]) -> Result<(), ContextError> { pub fn render(&mut self, passes: &[Box<dyn Pass>]) -> Result<(), ContextError> {
let frame = self.surface.get_current_texture()?; let frame = self.surface.get_current_texture()?;
let view = frame let view = frame
.texture .texture
@ -157,12 +173,22 @@ impl<'window> Context<'window> {
}); });
for pass in passes.iter() { for pass in passes.iter() {
pass.execute(&mut encoder, &view); pass.execute(&self.profiler, &self.device, &mut encoder, &view);
} }
self.profiler.resolve_queries(&mut encoder);
self.queue.submit(Some(encoder.finish())); self.queue.submit(Some(encoder.finish()));
frame.present(); frame.present();
// Signal to the profiler that the frame is finished.
self.profiler.end_frame().unwrap();
// Query for oldest finished frame (this is almost certainly not the one we just submitted!) and display results in the command line.
self.latest_profiler_results = self
.profiler
.process_finished_frame(self.queue.get_timestamp_period());
console_output(&self.latest_profiler_results);
Ok(()) Ok(())
} }
} }
@ -238,3 +264,28 @@ impl ContextBuilder {
Ok((context, event_loop)) Ok((context, event_loop))
} }
} }
fn scopes_to_console_recursive(results: &[GpuTimerQueryResult], indentation: u32) {
for scope in results {
if indentation > 0 {
print!("{:<width$}", "|", width = 4);
}
println!(
"{:.3}μs - {}",
(scope.time.end - scope.time.start) * 1000.0 * 1000.0,
scope.label
);
if !scope.nested_queries.is_empty() {
scopes_to_console_recursive(&scope.nested_queries, indentation + 1);
}
}
}
fn console_output(results: &Option<Vec<GpuTimerQueryResult>>) {
print!("\x1B[2J\x1B[1;1H"); // Clear terminal and put cursor to first row first column
if let Some(results) = results {
scopes_to_console_recursive(results, 0);
}
}

View File

@ -12,4 +12,4 @@ pub use self::{
texture::{Texture, TextureBuilder}, texture::{Texture, TextureBuilder},
}; };
pub use {wgpu, winit}; pub use {wgpu, wgpu_profiler, winit};