summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.toml7
-rw-r--r--glow/Cargo.toml4
-rw-r--r--glow/src/image.rs6
-rw-r--r--glow/src/quad.rs6
-rw-r--r--glow/src/triangle.rs6
-rw-r--r--glutin/Cargo.toml5
-rw-r--r--glutin/src/application.rs44
-rw-r--r--wgpu/Cargo.toml4
-rw-r--r--wgpu/src/backend.rs5
-rw-r--r--wgpu/src/image.rs6
-rw-r--r--wgpu/src/quad.rs9
-rw-r--r--wgpu/src/triangle.rs8
-rw-r--r--winit/Cargo.toml20
-rw-r--r--winit/src/application.rs66
-rw-r--r--winit/src/application/profiler.rs101
-rw-r--r--winit/src/lib.rs2
17 files changed, 276 insertions, 24 deletions
diff --git a/.gitignore b/.gitignore
index 56faba09..0c46184f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ pkg/
Cargo.lock
.cargo/
dist/
+traces/
diff --git a/Cargo.toml b/Cargo.toml
index 9c45b2f5..681aae5e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,13 @@ smol = ["iced_futures/smol"]
palette = ["iced_core/palette"]
# Enables querying system information
system = ["iced_winit/system"]
+# Enables chrome traces
+chrome-trace = [
+ "iced_winit/chrome-trace",
+ "iced_glutin?/trace",
+ "iced_wgpu?/tracing",
+ "iced_glow?/tracing",
+]
[badges]
maintenance = { status = "actively-developed" }
diff --git a/glow/Cargo.toml b/glow/Cargo.toml
index f586d24d..c126a511 100644
--- a/glow/Cargo.toml
+++ b/glow/Cargo.toml
@@ -42,6 +42,10 @@ version = "0.5"
path = "../graphics"
features = ["font-fallback", "font-icons", "opengl"]
+[dependencies.tracing]
+version = "0.1.6"
+optional = true
+
[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]
all-features = true
diff --git a/glow/src/image.rs b/glow/src/image.rs
index 521a01e7..d3a25b5b 100644
--- a/glow/src/image.rs
+++ b/glow/src/image.rs
@@ -21,6 +21,9 @@ use glow::HasContext;
use std::cell::RefCell;
+#[cfg(feature = "tracing")]
+use tracing::info_span;
+
#[derive(Debug)]
pub(crate) struct Pipeline {
program: <glow::Context as HasContext>::Program,
@@ -148,6 +151,9 @@ impl Pipeline {
images: &[layer::Image],
layer_bounds: Rectangle<u32>,
) {
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Glow::Image", "DRAW").entered();
+
unsafe {
gl.use_program(Some(self.program));
gl.bind_vertex_array(Some(self.vertex_array));
diff --git a/glow/src/quad.rs b/glow/src/quad.rs
index d9f1c6ae..67d9a098 100644
--- a/glow/src/quad.rs
+++ b/glow/src/quad.rs
@@ -7,6 +7,9 @@ use glow::HasContext;
use iced_graphics::layer;
use iced_native::Rectangle;
+#[cfg(feature = "tracing")]
+use tracing::info_span;
+
#[derive(Debug)]
pub enum Pipeline {
Core(core::Pipeline),
@@ -42,6 +45,9 @@ impl Pipeline {
scale: f32,
bounds: Rectangle<u32>,
) {
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Glow::Quad", "DRAW").enter();
+
match self {
Pipeline::Core(pipeline) => {
pipeline.draw(
diff --git a/glow/src/triangle.rs b/glow/src/triangle.rs
index d0205e08..42c88455 100644
--- a/glow/src/triangle.rs
+++ b/glow/src/triangle.rs
@@ -9,6 +9,9 @@ use iced_graphics::triangle::{ColoredVertex2D, Vertex2D};
use glow::HasContext;
use std::marker::PhantomData;
+#[cfg(feature = "tracing")]
+use tracing::info_span;
+
const DEFAULT_VERTICES: usize = 1_000;
const DEFAULT_INDICES: usize = 1_000;
@@ -58,6 +61,9 @@ impl Pipeline {
transformation: Transformation,
scale_factor: f32,
) {
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Glow::Triangle", "DRAW").enter();
+
unsafe {
gl.enable(glow::MULTISAMPLE);
gl.enable(glow::SCISSOR_TEST);
diff --git a/glutin/Cargo.toml b/glutin/Cargo.toml
index 022457b1..304170cd 100644
--- a/glutin/Cargo.toml
+++ b/glutin/Cargo.toml
@@ -11,6 +11,7 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"]
categories = ["gui"]
[features]
+trace = ["iced_winit/trace"]
debug = ["iced_winit/debug"]
system = ["iced_winit/system"]
@@ -35,3 +36,7 @@ features = ["application"]
version = "0.5"
path = "../graphics"
features = ["opengl"]
+
+[dependencies.tracing]
+version = "0.1.6"
+optional = true \ No newline at end of file
diff --git a/glutin/src/application.rs b/glutin/src/application.rs
index 3e9d11f9..1464bb2d 100644
--- a/glutin/src/application.rs
+++ b/glutin/src/application.rs
@@ -17,6 +17,9 @@ use iced_winit::{Clipboard, Command, Debug, Proxy, Settings};
use glutin::window::Window;
use std::mem::ManuallyDrop;
+#[cfg(feature = "tracing")]
+use tracing::{info_span, instrument::Instrument};
+
/// Runs an [`Application`] with an executor, compositor, and the provided
/// settings.
pub fn run<A, E, C>(
@@ -35,9 +38,15 @@ where
use glutin::platform::run_return::EventLoopExtRunReturn;
use glutin::ContextBuilder;
+ #[cfg(feature = "trace")]
+ let _guard = iced_winit::Profiler::init();
+
let mut debug = Debug::new();
debug.startup_started();
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Application::Glutin", "RUN").entered();
+
let mut event_loop = EventLoopBuilder::with_user_event().build();
let proxy = event_loop.create_proxy();
@@ -124,18 +133,26 @@ where
let (mut sender, receiver) = mpsc::unbounded();
- let mut instance = Box::pin(run_instance::<A, E, C>(
- application,
- compositor,
- renderer,
- runtime,
- proxy,
- debug,
- receiver,
- context,
- init_command,
- settings.exit_on_close_request,
- ));
+ let mut instance = Box::pin({
+ let run_instance = run_instance::<A, E, C>(
+ application,
+ compositor,
+ renderer,
+ runtime,
+ proxy,
+ debug,
+ receiver,
+ context,
+ init_command,
+ settings.exit_on_close_request,
+ );
+
+ #[cfg(feature = "tracing")]
+ let run_instance =
+ run_instance.instrument(info_span!("Application", "LOOP"));
+
+ run_instance
+ });
let mut context = task::Context::from_waker(task::noop_waker_ref());
@@ -333,6 +350,9 @@ async fn run_instance<A, E, C>(
messages.push(message);
}
event::Event::RedrawRequested(_) => {
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Application", "FRAME").entered();
+
debug.render_started();
#[allow(unsafe_code)]
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml
index a40d9967..8dc4b990 100644
--- a/wgpu/Cargo.toml
+++ b/wgpu/Cargo.toml
@@ -50,6 +50,10 @@ version = "0.5"
path = "../graphics"
features = ["font-fallback", "font-icons"]
+[dependencies.tracing]
+version = "0.1.6"
+optional = true
+
[dependencies.encase]
version = "0.3.0"
features = ["glam"]
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index 946eb712..9ab12ce0 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -10,6 +10,9 @@ use iced_graphics::{Primitive, Viewport};
use iced_native::alignment;
use iced_native::{Font, Size};
+#[cfg(feature = "tracing")]
+use tracing::info_span;
+
#[cfg(any(feature = "image", feature = "svg"))]
use crate::image;
@@ -77,6 +80,8 @@ impl Backend {
overlay_text: &[T],
) {
log::debug!("Drawing");
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Wgpu::Backend", "PRESENT").entered();
let target_size = viewport.physical_size();
let scale_factor = viewport.scale_factor() as f32;
diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs
index 390bad90..a5e63b17 100644
--- a/wgpu/src/image.rs
+++ b/wgpu/src/image.rs
@@ -23,6 +23,9 @@ use iced_native::image;
#[cfg(feature = "svg")]
use iced_native::svg;
+#[cfg(feature = "tracing")]
+use tracing::info_span;
+
#[derive(Debug)]
pub struct Pipeline {
#[cfg(feature = "image")]
@@ -289,6 +292,9 @@ impl Pipeline {
target: &wgpu::TextureView,
_scale: f32,
) {
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Wgpu::Image", "DRAW").entered();
+
let instances: &mut Vec<Instance> = &mut Vec::new();
#[cfg(feature = "image")]
diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs
index 027a34be..2f5fcc6b 100644
--- a/wgpu/src/quad.rs
+++ b/wgpu/src/quad.rs
@@ -6,6 +6,9 @@ use bytemuck::{Pod, Zeroable};
use std::mem;
use wgpu::util::DeviceExt;
+#[cfg(feature = "tracing")]
+use tracing::info_span;
+
#[derive(Debug)]
pub struct Pipeline {
pipeline: wgpu::RenderPipeline,
@@ -173,6 +176,9 @@ impl Pipeline {
bounds: Rectangle<u32>,
target: &wgpu::TextureView,
) {
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Wgpu::Quad", "DRAW").entered();
+
let uniforms = Uniforms::new(transformation, scale);
{
@@ -207,6 +213,9 @@ impl Pipeline {
instance_buffer.copy_from_slice(instance_bytes);
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Wgpu::Quad", "BEGIN_RENDER_PASS").enter();
+
{
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs
index 061154b6..efdd214b 100644
--- a/wgpu/src/triangle.rs
+++ b/wgpu/src/triangle.rs
@@ -8,6 +8,8 @@ use crate::Transformation;
use iced_graphics::layer::mesh::{self, Mesh};
use iced_graphics::triangle::ColoredVertex2D;
use iced_graphics::Size;
+#[cfg(feature = "tracing")]
+use tracing::info_span;
#[derive(Debug)]
pub struct Pipeline {
@@ -53,6 +55,9 @@ impl Pipeline {
scale_factor: f32,
meshes: &[Mesh<'_>],
) {
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Wgpu::Triangle", "DRAW").entered();
+
// Count the total amount of vertices & indices we need to handle
let count = mesh::attribute_count_of(meshes);
@@ -247,6 +252,9 @@ impl Pipeline {
(target, None, wgpu::LoadOp::Load)
};
+ #[cfg(feature = "tracing")]
+ let _ = info_span!("Wgpu::Triangle", "BEGIN_RENDER_PASS").enter();
+
let mut render_pass =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("iced_wgpu::triangle render pass"),
diff --git a/winit/Cargo.toml b/winit/Cargo.toml
index ebbadb12..94aaa2ca 100644
--- a/winit/Cargo.toml
+++ b/winit/Cargo.toml
@@ -11,6 +11,8 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"]
categories = ["gui"]
[features]
+trace = ["tracing", "tracing-core", "tracing-subscriber"]
+chrome-trace = ["trace", "tracing-chrome"]
debug = ["iced_native/debug"]
system = ["sysinfo"]
application = []
@@ -37,6 +39,24 @@ path = "../graphics"
version = "0.5"
path = "../futures"
+[dependencies.tracing]
+version = "0.1.37"
+optional = true
+features = ["std"]
+
+[dependencies.tracing-core]
+version = "0.1.30"
+optional = true
+
+[dependencies.tracing-subscriber]
+version = "0.3.16"
+optional = true
+features = ["registry"]
+
+[dependencies.tracing-chrome]
+version = "0.7.0"
+optional = true
+
[target.'cfg(target_os = "windows")'.dependencies.winapi]
version = "0.3.6"
diff --git a/winit/src/application.rs b/winit/src/application.rs
index 1973fdce..74c73815 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -1,4 +1,6 @@
//! Create interactive, native cross-platform applications.
+#[cfg(feature = "trace")]
+mod profiler;
mod state;
pub use state::State;
@@ -24,6 +26,11 @@ pub use iced_native::application::{Appearance, StyleSheet};
use std::mem::ManuallyDrop;
+#[cfg(feature = "trace")]
+pub use profiler::Profiler;
+#[cfg(feature = "trace")]
+use tracing::{info_span, instrument::Instrument};
+
/// An interactive, native cross-platform application.
///
/// This trait is the main entrypoint of Iced. Once implemented, you can run
@@ -111,9 +118,15 @@ where
use futures::Future;
use winit::event_loop::EventLoopBuilder;
+ #[cfg(feature = "trace")]
+ let _guard = Profiler::init();
+
let mut debug = Debug::new();
debug.startup_started();
+ #[cfg(feature = "trace")]
+ let _ = info_span!("Application", "RUN").entered();
+
let event_loop = EventLoopBuilder::with_user_event().build();
let proxy = event_loop.create_proxy();
@@ -175,18 +188,26 @@ where
let (mut sender, receiver) = mpsc::unbounded();
- let mut instance = Box::pin(run_instance::<A, E, C>(
- application,
- compositor,
- renderer,
- runtime,
- proxy,
- debug,
- receiver,
- init_command,
- window,
- settings.exit_on_close_request,
- ));
+ let mut instance = Box::pin({
+ let run_instance = run_instance::<A, E, C>(
+ application,
+ compositor,
+ renderer,
+ runtime,
+ proxy,
+ debug,
+ receiver,
+ init_command,
+ window,
+ settings.exit_on_close_request,
+ );
+
+ #[cfg(feature = "trace")]
+ let run_instance =
+ run_instance.instrument(info_span!("Application", "LOOP"));
+
+ run_instance
+ });
let mut context = task::Context::from_waker(task::noop_waker_ref());
@@ -391,6 +412,9 @@ async fn run_instance<A, E, C>(
messages.push(message);
}
event::Event::RedrawRequested(_) => {
+ #[cfg(feature = "trace")]
+ let _ = info_span!("Application", "FRAME").entered();
+
let physical_size = state.physical_size();
if physical_size.width == 0 || physical_size.height == 0 {
@@ -529,12 +553,24 @@ pub fn build_user_interface<'a, A: Application>(
where
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
{
+ #[cfg(feature = "trace")]
+ let view_span = info_span!("Application", "VIEW").entered();
+
debug.view_started();
let view = application.view();
+
+ #[cfg(feature = "trace")]
+ let _ = view_span.exit();
debug.view_finished();
+ #[cfg(feature = "trace")]
+ let layout_span = info_span!("Application", "LAYOUT").entered();
+
debug.layout_started();
let user_interface = UserInterface::build(view, size, cache, renderer);
+
+ #[cfg(feature = "trace")]
+ let _ = layout_span.exit();
debug.layout_finished();
user_interface
@@ -559,10 +595,16 @@ pub fn update<A: Application, E: Executor>(
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
{
for message in messages.drain(..) {
+ #[cfg(feature = "trace")]
+ let update_span = info_span!("Application", "UPDATE").entered();
+
debug.log_message(&message);
debug.update_started();
let command = runtime.enter(|| application.update(message));
+
+ #[cfg(feature = "trace")]
+ let _ = update_span.exit();
debug.update_finished();
run_command(
diff --git a/winit/src/application/profiler.rs b/winit/src/application/profiler.rs
new file mode 100644
index 00000000..23eaa390
--- /dev/null
+++ b/winit/src/application/profiler.rs
@@ -0,0 +1,101 @@
+//! A simple profiler for Iced.
+use std::ffi::OsStr;
+use std::path::Path;
+use std::time::Duration;
+use tracing_subscriber::prelude::*;
+use tracing_subscriber::Registry;
+#[cfg(feature = "chrome-trace")]
+use {
+ tracing_chrome::FlushGuard,
+ tracing_subscriber::fmt::{format::DefaultFields, FormattedFields},
+};
+
+/// Profiler state. This will likely need to be updated or reworked when adding new tracing backends.
+#[allow(missing_debug_implementations)]
+pub struct Profiler {
+ #[cfg(feature = "chrome-trace")]
+ /// [`FlushGuard`] must not be dropped until the application scope is dropped for accurate tracing.
+ _guard: FlushGuard,
+}
+
+impl Profiler {
+ /// Initializes the [`Profiler`].
+ pub fn init() -> Self {
+ // Registry stores the spans & generates unique span IDs
+ let subscriber = Registry::default();
+
+ let default_path = Path::new(env!("CARGO_MANIFEST_DIR"));
+ let curr_exe = std::env::current_exe()
+ .unwrap_or_else(|_| default_path.to_path_buf());
+ let out_dir = curr_exe.parent().unwrap_or(default_path).join("traces");
+
+ #[cfg(feature = "chrome-trace")]
+ let (chrome_layer, guard) = {
+ let mut layer = tracing_chrome::ChromeLayerBuilder::new();
+
+ // Optional configurable env var: CHROME_TRACE_FILE=/path/to/trace_file/file.json,
+ // for uploading to chrome://tracing (old) or ui.perfetto.dev (new).
+ if let Ok(path) = std::env::var("CHROME_TRACE_FILE") {
+ layer = layer.file(path);
+ } else if std::fs::create_dir_all(&out_dir).is_ok() {
+ let time = std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap_or(Duration::from_millis(0))
+ .as_millis();
+
+ let curr_exe_name = curr_exe
+ .file_name()
+ .unwrap_or_else(|| OsStr::new("trace"))
+ .to_str()
+ .unwrap_or("trace");
+
+ let path = out_dir
+ .join(format!("{}_trace_{}.json", curr_exe_name, time));
+
+ layer = layer.file(path);
+ } else {
+ layer = layer.file(env!("CARGO_MANIFEST_DIR"))
+ }
+
+ let (chrome_layer, guard) = layer
+ .name_fn(Box::new(|event_or_span| match event_or_span {
+ tracing_chrome::EventOrSpan::Event(event) => {
+ event.metadata().name().into()
+ }
+ tracing_chrome::EventOrSpan::Span(span) => {
+ if let Some(fields) = span
+ .extensions()
+ .get::<FormattedFields<DefaultFields>>()
+ {
+ format!(
+ "{}: {}",
+ span.metadata().name(),
+ fields.fields.as_str()
+ )
+ } else {
+ span.metadata().name().into()
+ }
+ }
+ }))
+ .build();
+
+ (chrome_layer, guard)
+ };
+
+ let fmt_layer = tracing_subscriber::fmt::Layer::default();
+ let subscriber = subscriber.with(fmt_layer);
+
+ #[cfg(feature = "chrome-trace")]
+ let subscriber = subscriber.with(chrome_layer);
+
+ // create dispatcher which will forward span events to the subscriber
+ // this can only be set once or will panic
+ tracing::subscriber::set_global_default(subscriber)
+ .expect("Tracer could not set the global default subscriber.");
+
+ Profiler {
+ #[cfg(feature = "chrome-trace")]
+ _guard: guard,
+ }
+ }
+}
diff --git a/winit/src/lib.rs b/winit/src/lib.rs
index b8ed492d..06674109 100644
--- a/winit/src/lib.rs
+++ b/winit/src/lib.rs
@@ -51,6 +51,8 @@ mod proxy;
#[cfg(feature = "application")]
pub use application::Application;
+#[cfg(feature = "trace")]
+pub use application::Profiler;
pub use clipboard::Clipboard;
pub use error::Error;
pub use position::Position;