Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Client::plot_config + relevant types + example #125

Merged
merged 1 commit into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions examples/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod plots;
mod secondary_frames;
mod threads;
mod wgpu_frame_images;
Expand Down Expand Up @@ -30,6 +31,11 @@ const EXAMPLES: &[ExampleDesc] = &[
description: "Demonstrates the use of zones across threads",
function: threads::main,
},
ExampleDesc {
name: "plots",
description: "Demonstrates plotting values",
function: plots::main,
},
];

fn main() {
Expand Down
43 changes: 43 additions & 0 deletions examples/src/plots/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use rand::Rng;
use std::thread::sleep;
use std::time::Duration;
use tracy_client::{Client, PlotConfiguration, PlotFormat, PlotLineStyle, PlotName};

// Plots you know statically can be defined freely like so
const PLOT_PLAYER_COUNT: PlotName = tracy_client::plot_name!("Player Count");
const PLOT_DISK_SPACE: PlotName = tracy_client::plot_name!("Disk Space");

pub fn main() {
let client = Client::start();
let mut rng = rand::thread_rng();

// Anything at runtime needs to be created via PlotName
let bandwidth = PlotName::new_leak("Bandwidth".to_string());

// You can configure how plots display, this only needs to be done once
client.plot_config(
PLOT_DISK_SPACE,
PlotConfiguration::default()
.format(PlotFormat::Memory)
.fill(false),
);
client.plot_config(
bandwidth,
PlotConfiguration::default()
.format(PlotFormat::Percentage)
.color(Some(0xFF0000))
.line_style(PlotLineStyle::Stepped),
);

for _ in 0..50 {
// You don't need to constantly send a value!
if rng.gen_bool(0.75) {
client.plot(PLOT_PLAYER_COUNT, rng.gen_range(0..10) as f64);
}

client.plot(PLOT_DISK_SPACE, rng.gen_range(0..1000000) as f64);
client.plot(bandwidth, rng.gen_range(0..100) as f64);

sleep(Duration::from_millis(20));
}
}
2 changes: 1 addition & 1 deletion tracy-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub use crate::frame::{frame_image, frame_mark, Frame, FrameName};
pub use crate::gpu::{
GpuContext, GpuContextCreationError, GpuContextType, GpuSpan, GpuSpanCreationError,
};
pub use crate::plot::PlotName;
pub use crate::plot::{PlotConfiguration, PlotFormat, PlotLineStyle, PlotName};
pub use crate::span::{Span, SpanLocation};
use std::alloc;
use std::ffi::CString;
Expand Down
117 changes: 117 additions & 0 deletions tracy-client/src/plot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,89 @@ use crate::Client;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct PlotName(pub(crate) &'static str);

/// The format of a plot to be shown in the Tracy profiler UI.
#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
#[non_exhaustive]
pub enum PlotFormat {
/// Values will be displayed as plain numbers. This is the default.
#[default]
Number,

/// Values will be displayed as byte counts, showing as kilobytes, megabytes, etc.
Memory,

/// Values will be shown as a percentage (with 100 being equal to 100%).
Percentage,

/// Values will be shown as watts.
Watts,
}

/// The style of lines of a plot, shown in the Tracy profiler UI.
#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
#[non_exhaustive]
pub enum PlotLineStyle {
/// Lines will be stepped (ie look like a staircase).
Stepped,

/// Lines will be smooth (interpolating a line between two values).
#[default]
Smooth,
}

/// Configuration for how a plot appears in the Tracy profiling UI.
Copy link
Owner

@nagisa nagisa Dec 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding a code example here just for constructing the type and changing a field or two. I found it to be pretty common for people to struggle to figure out how to construct stuff, when the construction is not a fn new() (even if it is as simple as using default() instead.) A plain example would help with that.

#[derive(Clone, PartialEq, Debug)]
pub struct PlotConfiguration {
Dinnerbone marked this conversation as resolved.
Show resolved Hide resolved
/// The format of values on the plot.
format: PlotFormat,

/// The style of lines on the plot.
line_style: PlotLineStyle,

/// Whether the plot should be filled with a solid color below the line.
fill: bool,

/// A custom color of this plot. None means a default color will be generated by Tracy.
color: Option<u32>,
}

impl PlotConfiguration {
/// Sets the format of values on the plot.
pub fn format(mut self, format: PlotFormat) -> Self {
self.format = format;
self
}

/// Sets the style of lines on the plot.
pub fn line_style(mut self, line_style: PlotLineStyle) -> Self {
self.line_style = line_style;
self
}

/// Sets whether the plot should be filled with a solid color below the line.
pub fn fill(mut self, fill: bool) -> Self {
self.fill = fill;
self
}

/// Sets a custom color of the plot. A value of `None` will cause Tracy to create its own color.
pub fn color(mut self, color: Option<u32>) -> Self {
self.color = color;
self
}
}

impl Default for PlotConfiguration {
fn default() -> Self {
Self {
format: Default::default(),
line_style: Default::default(),
fill: true,
color: None,
}
}
}

impl PlotName {
/// Construct a `PlotName` dynamically, leaking the provided String.
///
Expand Down Expand Up @@ -53,6 +136,40 @@ impl Client {
let () = sys::___tracy_emit_plot(plot_name.0.as_ptr().cast(), value);
}
}

/// Sets the display configuration of the plot named `plot_name`.
///
/// # Examples
///
/// ```
/// use tracy_client::{PlotConfiguration, PlotFormat};
/// # let client = tracy_client::Client::start();
/// tracy_client::Client::running()
/// .expect("client must be running")
/// .plot_config(tracy_client::plot_name!("memory"), PlotConfiguration::default().format(PlotFormat::Memory));
/// ```
pub fn plot_config(&self, plot_name: PlotName, configuration: PlotConfiguration) {
let format = match configuration.format {
PlotFormat::Number => sys::TracyPlotFormatEnum_TracyPlotFormatNumber,
PlotFormat::Memory => sys::TracyPlotFormatEnum_TracyPlotFormatMemory,
PlotFormat::Percentage => sys::TracyPlotFormatEnum_TracyPlotFormatPercentage,
PlotFormat::Watts => sys::TracyPlotFormatEnum_TracyPlotFormatWatt,
} as std::os::raw::c_int;
let stepped = configuration.line_style == PlotLineStyle::Stepped;
let filled = configuration.fill;
let color = configuration.color.unwrap_or(0);
#[cfg(feature = "enable")]
unsafe {
// SAFE: We made sure the `plot` refers to a null-terminated string.
let () = sys::___tracy_emit_plot_config(
plot_name.0.as_ptr().cast(),
format,
stepped.into(),
filled.into(),
color,
);
}
}
}

/// Construct a [`PlotName`].
Expand Down
2 changes: 1 addition & 1 deletion tracy-client/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl Client {
function.len(),
name.map_or(std::ptr::null(), |n| n.as_ptr().cast()),
name.unwrap_or("").len(),
0
0,
);
let zone = if callstack_depth == 0 {
sys::___tracy_emit_zone_begin_alloc(loc, 1)
Expand Down
Loading