diff --git a/Cargo.lock b/Cargo.lock index fe082dc7..d1e610ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2556,6 +2556,7 @@ version = "0.14.0-dev" dependencies = [ "bytemuck", "cosmic-text", + "iced_debug", "iced_graphics", "kurbo 0.10.4", "log", @@ -2575,6 +2576,7 @@ dependencies = [ "futures", "glam", "guillotiere", + "iced_debug", "iced_graphics", "log", "lyon", diff --git a/beacon/src/lib.rs b/beacon/src/lib.rs index 36d19e30..b96bf754 100644 --- a/beacon/src/lib.rs +++ b/beacon/src/lib.rs @@ -94,6 +94,7 @@ pub fn run() -> impl Stream { let mut last_message = String::new(); let mut last_commands_spawned = 0; + let mut last_present_window = None; loop { match receive(&mut stream, &mut buffer).await { @@ -146,6 +147,11 @@ pub fn run() -> impl Stream { last_message.clear(); last_commands_spawned = 0; } + client::Event::SpanStarted( + span::Stage::Present(window), + ) => { + last_present_window = Some(window); + } client::Event::SpanStarted(_) => {} client::Event::SpanFinished( stage, @@ -173,6 +179,30 @@ pub fn run() -> impl Stream { span::Stage::Draw(window) => { Span::Draw { window } } + span::Stage::Prepare(primitive) => { + let Some(window) = + last_present_window + else { + continue; + }; + + Span::Prepare { + window, + primitive, + } + } + span::Stage::Render(primitive) => { + let Some(window) = + last_present_window + else { + continue; + }; + + Span::Render { + window, + primitive, + } + } span::Stage::Present(window) => { Span::Present { window } } diff --git a/beacon/src/span.rs b/beacon/src/span.rs index 38f19acb..8d163a2f 100644 --- a/beacon/src/span.rs +++ b/beacon/src/span.rs @@ -21,6 +21,14 @@ pub enum Span { Draw { window: window::Id, }, + Prepare { + window: window::Id, + primitive: Primitive, + }, + Render { + window: window::Id, + primitive: Primitive, + }, Present { window: window::Id, }, @@ -30,6 +38,26 @@ pub enum Span { }, } +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Serialize, + Deserialize, +)] +pub enum Primitive { + Quad, + Triangle, + Shader, + Text, + Image, +} + impl Span { pub fn stage(&self) -> Stage { match self { @@ -39,6 +67,8 @@ impl Span { Span::Layout { window } => Stage::Layout(*window), Span::Interact { window } => Stage::Interact(*window), Span::Draw { window } => Stage::Draw(*window), + Span::Prepare { primitive, .. } => Stage::Prepare(*primitive), + Span::Render { primitive, .. } => Stage::Render(*primitive), Span::Present { window } => Stage::Present(*window), Span::Custom { window, name } => { Stage::Custom(*window, name.clone()) @@ -58,6 +88,8 @@ pub enum Stage { Interact(window::Id), Draw(window::Id), Present(window::Id), + Prepare(Primitive), + Render(Primitive), Custom(window::Id, String), } @@ -70,6 +102,8 @@ impl std::fmt::Display for Stage { Stage::Layout(_) => "Layout", Stage::Interact(_) => "Interact", Stage::Draw(_) => "Draw", + Stage::Prepare(_) => "Prepare", + Stage::Render(_) => "Render", Stage::Present(_) => "Present", Stage::Custom(_, name) => name, }) diff --git a/debug/src/lib.rs b/debug/src/lib.rs index a15f05c9..6036222b 100644 --- a/debug/src/lib.rs +++ b/debug/src/lib.rs @@ -7,6 +7,15 @@ pub use internal::Span; use std::io; +#[derive(Debug, Clone, Copy)] +pub enum Primitive { + Quad, + Triangle, + Shader, + Image, + Text, +} + pub fn init(name: &str) { internal::init(name); } @@ -51,6 +60,14 @@ pub fn draw(window: window::Id) -> Span { internal::draw(window) } +pub fn prepare(primitive: Primitive) -> Span { + internal::prepare(primitive) +} + +pub fn render(primitive: Primitive) -> Span { + internal::render(primitive) +} + pub fn present(window: window::Id) -> Span { internal::present(window) } @@ -65,6 +82,7 @@ pub fn skip_next_timing() { #[cfg(all(feature = "enable", not(target_arch = "wasm32")))] mod internal { + use crate::Primitive; use crate::core::theme; use crate::core::time::Instant; use crate::core::window; @@ -171,6 +189,14 @@ mod internal { span(span::Stage::Draw(window)) } + pub fn prepare(primitive: Primitive) -> Span { + span(span::Stage::Prepare(to_primitive(primitive))) + } + + pub fn render(primitive: Primitive) -> Span { + span(span::Stage::Render(to_primitive(primitive))) + } + pub fn present(window: window::Id) -> Span { span(span::Stage::Present(window)) } @@ -192,6 +218,16 @@ mod internal { } } + fn to_primitive(primitive: Primitive) -> span::Primitive { + match primitive { + Primitive::Quad => span::Primitive::Quad, + Primitive::Triangle => span::Primitive::Triangle, + Primitive::Shader => span::Primitive::Shader, + Primitive::Text => span::Primitive::Text, + Primitive::Image => span::Primitive::Image, + } + } + #[derive(Debug)] pub struct Span { span: span::Stage, @@ -222,6 +258,7 @@ mod internal { #[cfg(any(not(feature = "enable"), target_arch = "wasm32"))] mod internal { + use crate::Primitive; use crate::core::theme; use crate::core::window; @@ -263,6 +300,14 @@ mod internal { Span } + pub fn prepare(_primitive: Primitive) -> Span { + Span + } + + pub fn render(_primitive: Primitive) -> Span { + Span + } + pub fn present(_window: window::Id) -> Span { Span } diff --git a/devtools/src/lib.rs b/devtools/src/lib.rs index 51ded4c6..b41b782a 100644 --- a/devtools/src/lib.rs +++ b/devtools/src/lib.rs @@ -196,7 +196,7 @@ where "--git", "https://github.com/iced-rs/comet.git", "--rev", - "5efd34550e42974a0e85af7560c60401bfc13919", + "fc9832833f81a8e95e2c4ab8e7e65dcc3c000253", ]) .stdin(Stdio::null()) .stdout(Stdio::null()) diff --git a/tiny_skia/Cargo.toml b/tiny_skia/Cargo.toml index 323233f0..87aa74e5 100644 --- a/tiny_skia/Cargo.toml +++ b/tiny_skia/Cargo.toml @@ -19,6 +19,7 @@ svg = ["iced_graphics/svg", "resvg"] geometry = ["iced_graphics/geometry"] [dependencies] +iced_debug.workspace = true iced_graphics.workspace = true bytemuck.workspace = true diff --git a/tiny_skia/src/lib.rs b/tiny_skia/src/lib.rs index 5ea3cbe9..a222e23c 100644 --- a/tiny_skia/src/lib.rs +++ b/tiny_skia/src/lib.rs @@ -17,6 +17,7 @@ mod vector; #[cfg(feature = "geometry")] pub mod geometry; +use iced_debug as debug; pub use iced_graphics as graphics; pub use iced_graphics::core; @@ -112,62 +113,84 @@ impl Renderer { engine::adjust_clip_mask(clip_mask, clip_bounds); - for (quad, background) in &layer.quads { - self.engine.draw_quad( - quad, - background, - Transformation::scale(scale_factor), - pixels, - clip_mask, - clip_bounds, - ); + if !layer.quads.is_empty() { + let render_span = debug::render(debug::Primitive::Quad); + for (quad, background) in &layer.quads { + self.engine.draw_quad( + quad, + background, + Transformation::scale(scale_factor), + pixels, + clip_mask, + clip_bounds, + ); + } + render_span.finish(); } - for group in &layer.primitives { - let Some(new_clip_bounds) = (group.clip_bounds() - * scale_factor) - .intersection(&clip_bounds) - else { - continue; - }; + if !layer.primitives.is_empty() { + let render_span = debug::render(debug::Primitive::Triangle); - engine::adjust_clip_mask(clip_mask, new_clip_bounds); + for group in &layer.primitives { + let Some(new_clip_bounds) = (group.clip_bounds() + * scale_factor) + .intersection(&clip_bounds) + else { + continue; + }; - for primitive in group.as_slice() { - self.engine.draw_primitive( - primitive, - group.transformation() - * Transformation::scale(scale_factor), + engine::adjust_clip_mask(clip_mask, new_clip_bounds); + + for primitive in group.as_slice() { + self.engine.draw_primitive( + primitive, + group.transformation() + * Transformation::scale(scale_factor), + pixels, + clip_mask, + clip_bounds, + ); + } + + engine::adjust_clip_mask(clip_mask, clip_bounds); + } + + render_span.finish(); + } + + if !layer.images.is_empty() { + let render_span = debug::render(debug::Primitive::Image); + + for image in &layer.images { + self.engine.draw_image( + image, + Transformation::scale(scale_factor), pixels, clip_mask, clip_bounds, ); } - engine::adjust_clip_mask(clip_mask, clip_bounds); + render_span.finish(); } - for image in &layer.images { - self.engine.draw_image( - image, - Transformation::scale(scale_factor), - pixels, - clip_mask, - clip_bounds, - ); - } + if !layer.text.is_empty() { + let render_span = debug::render(debug::Primitive::Image); - for group in &layer.text { - for text in group.as_slice() { - self.engine.draw_text( - text, - group.transformation() - * Transformation::scale(scale_factor), - pixels, - clip_mask, - clip_bounds, - ); + for group in &layer.text { + for text in group.as_slice() { + self.engine.draw_text( + text, + group.transformation() + * Transformation::scale(scale_factor), + pixels, + clip_mask, + clip_bounds, + ); + } } + + render_span.finish(); } } } diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 50c9f588..7160421b 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -26,6 +26,7 @@ webgl = ["wgpu/webgl"] strict-assertions = [] [dependencies] +iced_debug.workspace = true iced_graphics.workspace = true bitflags.workspace = true diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index cfb6a64f..3fe2fbbe 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -47,6 +47,7 @@ mod image; use buffer::Buffer; +use iced_debug as debug; pub use iced_graphics as graphics; pub use iced_graphics::core; @@ -320,6 +321,8 @@ impl Renderer { } if !layer.quads.is_empty() { + let prepare_span = debug::prepare(debug::Primitive::Quad); + self.quad.prepare( &self.engine.quad_pipeline, &self.engine.device, @@ -329,9 +332,13 @@ impl Renderer { viewport.projection(), scale_factor, ); + + prepare_span.finish(); } if !layer.triangles.is_empty() { + let prepare_span = debug::prepare(debug::Primitive::Triangle); + self.triangle.prepare( &self.engine.triangle_pipeline, &self.engine.device, @@ -341,9 +348,13 @@ impl Renderer { Transformation::scale(scale_factor), viewport.physical_size(), ); + + prepare_span.finish(); } if !layer.primitives.is_empty() { + let prepare_span = debug::prepare(debug::Primitive::Shader); + let mut primitive_storage = self .engine .primitive_storage @@ -360,10 +371,14 @@ impl Renderer { viewport, ); } + + prepare_span.finish(); } #[cfg(any(feature = "svg", feature = "image"))] if !layer.images.is_empty() { + let prepare_span = debug::prepare(debug::Primitive::Image); + self.image.prepare( &self.engine.image_pipeline, &self.engine.device, @@ -374,9 +389,13 @@ impl Renderer { viewport.projection(), scale_factor, ); + + prepare_span.finish(); } if !layer.text.is_empty() { + let prepare_span = debug::prepare(debug::Primitive::Text); + self.text.prepare( &self.engine.text_pipeline, &self.engine.device, @@ -387,6 +406,8 @@ impl Renderer { layer.bounds, Transformation::scale(scale_factor), ); + + prepare_span.finish(); } } } @@ -459,6 +480,7 @@ impl Renderer { }; if !layer.quads.is_empty() { + let render_span = debug::render(debug::Primitive::Quad); self.quad.render( &self.engine.quad_pipeline, quad_layer, @@ -466,6 +488,7 @@ impl Renderer { &layer.quads, &mut render_pass, ); + render_span.finish(); quad_layer += 1; } @@ -473,6 +496,7 @@ impl Renderer { if !layer.triangles.is_empty() { let _ = ManuallyDrop::into_inner(render_pass); + let render_span = debug::render(debug::Primitive::Triangle); mesh_layer += self.triangle.render( &self.engine.triangle_pipeline, encoder, @@ -482,6 +506,7 @@ impl Renderer { physical_bounds, scale, ); + render_span.finish(); render_pass = ManuallyDrop::new(encoder.begin_render_pass( &wgpu::RenderPassDescriptor { @@ -504,6 +529,7 @@ impl Renderer { } if !layer.primitives.is_empty() { + let render_span = debug::render(debug::Primitive::Shader); let _ = ManuallyDrop::into_inner(render_pass); let primitive_storage = self @@ -526,6 +552,8 @@ impl Renderer { } } + render_span.finish(); + render_pass = ManuallyDrop::new(encoder.begin_render_pass( &wgpu::RenderPassDescriptor { label: Some("iced_wgpu render pass"), @@ -548,6 +576,7 @@ impl Renderer { #[cfg(any(feature = "svg", feature = "image"))] if !layer.images.is_empty() { + let render_span = debug::render(debug::Primitive::Image); self.image.render( &self.engine.image_pipeline, &image_cache, @@ -555,11 +584,13 @@ impl Renderer { scissor_rect, &mut render_pass, ); + render_span.finish(); image_layer += 1; } if !layer.text.is_empty() { + let render_span = debug::render(debug::Primitive::Text); text_layer += self.text.render( &self.engine.text_pipeline, &self.text_viewport, @@ -568,6 +599,7 @@ impl Renderer { scissor_rect, &mut render_pass, ); + render_span.finish(); } }