Skip to content

Commit

Permalink
Improved creation and configuration (#47)
Browse files Browse the repository at this point in the history
* GpuProfiler::new takes now a settings object and returns a Result
* unity device creation accross tests
* simplify new method, split out tracy new method
* new test suite for nesting scopes
* allow disabling profiler on startup and change all settings at a later point
* fix doc errors
* fix enable_debug_groups==false clearing resources, improved doc strings
* comment fixes, better partialeq impl for CreationError
  • Loading branch information
Wumpf authored Oct 8, 2023
1 parent aa5d6db commit 8824a2b
Show file tree
Hide file tree
Showing 10 changed files with 495 additions and 138 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ Simple profiler scopes for wgpu using timer queries
* chrome trace flamegraph json export
* Tracy integration (behind `tracy` feature flag)

TODO:
* Disable via feature flag

## How to use

Create a new profiler object:
Expand Down Expand Up @@ -79,7 +76,11 @@ dual licensed as above, without any additional terms or conditions.
## Changelog
* unreleased
* sample & doc fixes, by @waywardmonkeys in [#41](https://github.com/Wumpf/wgpu-profiler/pull/41), [#44](https://github.com/Wumpf/wgpu-profiler/pull/44)
* `end_scope` & `end_frame` return `thiserror` errors instead of internal unwrap/except on user errors, by @Wumpf in [#45](https://github.com/Wumpf/wgpu-profiler/pull/45)
* various methods return `thiserror` errors instead of internal unwrap/except on user errors, by @Wumpf in [#45](https://github.com/Wumpf/wgpu-profiler/pull/45) and following PRs
* overhauled `GpuProfiler` creation & configuration:
* takes settings object that can be changed after the fact (allows disabling on the fly!)
* adapter/queue/device no longer needed on creation unless tracy client is required.
* separate creation method for tracy support
* 0.14.2
* Fix pointing to wrong tracy version, by @waywardmonkeys in [#36](https://github.com/Wumpf/wgpu-profiler/pull/35)
* Doc fixes, by @waywardmonkeys in [#38](https://github.com/Wumpf/wgpu-profiler/pull/35)
Expand Down
21 changes: 17 additions & 4 deletions examples/demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn scopes_to_console_recursive(results: &[GpuTimerScopeResult], indentation: u32
print!("{:<width$}", "|", width = 4);
}

println!("{:.3}μs - {}", (&scope.time.end - &scope.time.start) * 1000.0 * 1000.0, scope.label);
println!("{:.3}μs - {}", (scope.time.end - scope.time.start) * 1000.0 * 1000.0, scope.label);

if !scope.nested_scopes.is_empty() {
scopes_to_console_recursive(&scope.nested_scopes, indentation + 1);
Expand Down Expand Up @@ -113,8 +113,21 @@ async fn run(event_loop: EventLoop<()>, window: Window) {

surface.configure(&device, &sc_desc);

// Create a new profiler instance
let mut profiler = GpuProfiler::new(&adapter, &device, &queue, 4);
// Create a new profiler instance.
#[cfg(feature = "tracy")]
let mut profiler = GpuProfiler::new_with_tracy_client(GpuProfilerSettings::default(), adapter.get_info().backend, &device, &queue)
.unwrap_or_else(|err| match err {
CreationError::TracyClientNotRunning | CreationError::TracyGpuContextCreationError(_) => {
println!("Failed to connect to Tracy. Continuing without Tracy integration.");
GpuProfiler::new(GpuProfilerSettings::default()).expect("Failed to create profiler")
}
_ => {
panic!("Failed to create profiler: {}", err);
}
});
#[cfg(not(feature = "tracy"))]
let mut profiler = GpuProfiler::new(GpuProfilerSettings::default()).expect("Failed to create profiler");

let mut latest_profiler_results = None;

event_loop.run(move |event, _, control_flow| {
Expand Down Expand Up @@ -209,7 +222,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
// Signal to the profiler that the frame is finished.
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.
if let Some(results) = profiler.process_finished_frame() {
if let Some(results) = profiler.process_finished_frame(queue.get_timestamp_period()) {
latest_profiler_results = Some(results);
}
console_output(&latest_profiler_results, device.features());
Expand Down
67 changes: 67 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/// Errors that can occur during profiler creation.
#[cfg_attr(not(feature = "tracy"), derive(PartialEq))]
#[derive(thiserror::Error, Debug)]
pub enum CreationError {
#[error(transparent)]
InvalidSettings(#[from] SettingsError),

#[cfg(feature = "tracy")]
#[error("Tracy client doesn't run yet.")]
TracyClientNotRunning,

#[cfg(feature = "tracy")]
#[error("Failed to create Tracy GPU context: {0}")]
TracyGpuContextCreationError(#[from] tracy_client::GpuContextCreationError),
}

#[cfg(feature = "tracy")]
impl PartialEq for CreationError {
fn eq(&self, other: &Self) -> bool {
match self {
CreationError::InvalidSettings(left) => match other {
CreationError::InvalidSettings(right) => left == right,
_ => false,
},
CreationError::TracyClientNotRunning => matches!(other, CreationError::TracyClientNotRunning),
CreationError::TracyGpuContextCreationError(left) => match left {
tracy_client::GpuContextCreationError::TooManyContextsCreated => matches!(
other,
CreationError::TracyGpuContextCreationError(tracy_client::GpuContextCreationError::TooManyContextsCreated)
),
},
}
}
}

impl Eq for CreationError {}

/// Errors that can occur during settings validation and change.
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
pub enum SettingsError {
#[error("GpuProfilerSettings::max_num_pending_frames must be at least 1.")]
InvalidMaxNumPendingFrames,

#[error("Can't change settings while there's open profiling scopes.")]
HasOpenScopes,
}

/// Errors that can occur during [`crate::GpuProfiler::end_frame`].
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
pub enum EndFrameError {
#[error("All profiling scopes need to be closed before ending a frame. The following scopes were still open: {0:?}")]
UnclosedScopes(Vec<String>),

#[error(
"Not all queries were resolved before ending a frame.\n
Call `GpuProfiler::resolve_queries` after all profiling scopes have been closed and before ending the frame.\n
There were still {0} queries unresolved"
)]
UnresolvedQueries(u32),
}

/// Errors that can occur during [`crate::GpuProfiler::end_scope`].
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
pub enum ScopeError {
#[error("No profiler GpuProfiler scope was previously opened. For each call to `end_scope` you first need to call `begin_scope`.")]
NoOpenScope,
}
Loading

0 comments on commit 8824a2b

Please sign in to comment.