Skip to content

Commit

Permalink
Add opt-in puffin feature to egui (#3298)
Browse files Browse the repository at this point in the history
* Add opt-in `puffin` feature to egui

* fix web build

* Fix web for realz
  • Loading branch information
emilk authored Sep 4, 2023
1 parent 72adf3b commit 9e86bb8
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/eframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ persistence = [

## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
##
## Only enabled on native, because of the low resolution (1ms) of time keeping in browsers.
## Only enabled on native, because of the low resolution (1ms) of clocks in browsers.
## `eframe` will call `puffin::GlobalProfiler::lock().new_frame()` for you
puffin = ["dep:puffin", "egui_glow?/puffin", "egui-wgpu?/puffin"]
puffin = ["dep:puffin", "egui/puffin", "egui_glow?/puffin", "egui-wgpu?/puffin"]

## Enable screen reader support (requires `ctx.options_mut(|o| o.screen_reader = true);`) on web.
##
Expand Down
2 changes: 1 addition & 1 deletion crates/egui-winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ clipboard = ["arboard", "smithay-clipboard"]
links = ["webbrowser"]

## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
puffin = ["dep:puffin"]
puffin = ["dep:puffin", "egui/puffin"]

## Allow serialization of [`WindowSettings`] using [`serde`](https://docs.rs/serde).
serde = ["egui/serde", "dep:serde"]
Expand Down
6 changes: 6 additions & 0 deletions crates/egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ mint = ["epaint/mint"]
## Enable persistence of memory (window positions etc).
persistence = ["serde", "epaint/serde", "ron"]

## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
##
## Only enabled on native, because of the low resolution (1ms) of clocks in browsers.
puffin = ["dep:puffin"]

## Allow serialization using [`serde`](https://docs.rs/serde).
serde = ["dep:serde", "epaint/serde", "accesskit?/serde"]

Expand All @@ -79,5 +84,6 @@ accesskit = { version = "0.11", optional = true }
document-features = { version = "0.2", optional = true }

log = { version = "0.4", optional = true, features = ["std"] }
puffin = { version = "0.16", optional = true }
ron = { version = "0.8", optional = true }
serde = { version = "1", optional = true, features = ["derive", "rc"] }
36 changes: 27 additions & 9 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ impl ContextImpl {

#[cfg(feature = "accesskit")]
if self.is_accesskit_enabled {
crate::profile_scope!("accesskit");
use crate::frame_state::AccessKitFrameState;
let id = crate::accesskit_root_id();
let mut builder = accesskit::NodeBuilder::new(accesskit::Role::Window);
Expand All @@ -224,24 +225,32 @@ impl ContextImpl {

/// Load fonts unless already loaded.
fn update_fonts_mut(&mut self) {
crate::profile_function!();

let pixels_per_point = self.input.pixels_per_point();
let max_texture_side = self.input.max_texture_side;

if let Some(font_definitions) = self.memory.new_font_definitions.take() {
crate::profile_scope!("Fonts::new");
let fonts = Fonts::new(pixels_per_point, max_texture_side, font_definitions);
self.fonts = Some(fonts);
}

let fonts = self.fonts.get_or_insert_with(|| {
let font_definitions = FontDefinitions::default();
crate::profile_scope!("Fonts::new");
Fonts::new(pixels_per_point, max_texture_side, font_definitions)
});

fonts.begin_frame(pixels_per_point, max_texture_side);
{
crate::profile_scope!("Fonts::begin_frame");
fonts.begin_frame(pixels_per_point, max_texture_side);
}

if self.memory.options.preload_font_glyphs {
crate::profile_scope!("preload_font_glyphs");
// Preload the most common characters for the most common fonts.
// This is not very important to do, but may a few GPU operations.
// This is not very important to do, but may save a few GPU operations.
for font_id in self.memory.options.style.text_styles.values() {
fonts.lock().fonts.font(font_id).preload_common_characters();
}
Expand Down Expand Up @@ -370,6 +379,7 @@ impl Context {
/// ```
#[must_use]
pub fn run(&self, new_input: RawInput, run_ui: impl FnOnce(&Context)) -> FullOutput {
crate::profile_function!();
self.begin_frame(new_input);
run_ui(self);
self.end_frame()
Expand All @@ -393,6 +403,7 @@ impl Context {
/// // handle full_output
/// ```
pub fn begin_frame(&self, new_input: RawInput) {
crate::profile_function!();
self.write(|ctx| ctx.begin_frame_mut(new_input));
}
}
Expand Down Expand Up @@ -1207,6 +1218,7 @@ impl Context {
/// Call at the end of each frame.
#[must_use]
pub fn end_frame(&self) -> FullOutput {
crate::profile_function!();
if self.input(|i| i.wants_repaint()) {
self.request_repaint();
}
Expand All @@ -1230,6 +1242,7 @@ impl Context {

#[cfg(feature = "accesskit")]
{
crate::profile_scope!("accesskit");
let state = self.frame_state_mut(|fs| fs.accesskit_state.take());
if let Some(state) = state {
let has_focus = self.input(|i| i.raw.focused);
Expand Down Expand Up @@ -1269,11 +1282,13 @@ impl Context {
}

fn drain_paint_lists(&self) -> Vec<ClippedShape> {
crate::profile_function!();
self.write(|ctx| ctx.graphics.drain(ctx.memory.areas.order()).collect())
}

/// Tessellate the given shapes into triangle meshes.
pub fn tessellate(&self, shapes: Vec<ClippedShape>) -> Vec<ClippedPrimitive> {
crate::profile_function!();
// A tempting optimization is to reuse the tessellation from last frame if the
// shapes are the same, but just comparing the shapes takes about 50% of the time
// it takes to tessellate them, so it is not a worth optimization.
Expand All @@ -1293,13 +1308,16 @@ impl Context {
};

let paint_stats = PaintStats::from_shapes(&shapes);
let clipped_primitives = tessellator::tessellate_shapes(
pixels_per_point,
tessellation_options,
font_tex_size,
prepared_discs,
shapes,
);
let clipped_primitives = {
crate::profile_scope!("tessellator::tessellate_shapes");
tessellator::tessellate_shapes(
pixels_per_point,
tessellation_options,
font_tex_size,
prepared_discs,
shapes,
)
};
ctx.paint_stats = paint_stats.with_clipped_primitives(&clipped_primitives);
clipped_primitives
})
Expand Down
1 change: 1 addition & 0 deletions crates/egui/src/frame_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl Default for FrameState {

impl FrameState {
pub(crate) fn begin_frame(&mut self, input: &InputState) {
crate::profile_function!();
let Self {
used_ids,
available_rect,
Expand Down
1 change: 1 addition & 0 deletions crates/egui/src/input_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ impl InputState {
mut new: RawInput,
requested_repaint_last_frame: bool,
) -> InputState {
crate::profile_function!();
let time = new.time.unwrap_or(self.time + new.predicted_dt as f64);
let unstable_dt = (time - self.time) as f32;

Expand Down
29 changes: 29 additions & 0 deletions crates/egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,3 +579,32 @@ pub fn __run_test_ui(mut add_contents: impl FnMut(&mut Ui)) {
pub fn accesskit_root_id() -> Id {
Id::new("accesskit_root")
}

// ---------------------------------------------------------------------------

mod profiling_scopes {
#![allow(unused_macros)]
#![allow(unused_imports)]

/// Profiling macro for feature "puffin"
macro_rules! profile_function {
($($arg: tt)*) => {
#[cfg(not(target_arch = "wasm32"))] // Disabled on web because of the coarse 1ms clock resolution there.
#[cfg(feature = "puffin")]
puffin::profile_function!($($arg)*);
};
}
pub(crate) use profile_function;

/// Profiling macro for feature "puffin"
macro_rules! profile_scope {
($($arg: tt)*) => {
#[cfg(not(target_arch = "wasm32"))] // Disabled on web because of the coarse 1ms clock resolution there.
#[cfg(feature = "puffin")]
puffin::profile_scope!($($arg)*);
};
}
pub(crate) use profile_scope;
}

pub(crate) use profiling_scopes::*;
1 change: 1 addition & 0 deletions crates/egui/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ impl Memory {
prev_input: &crate::input_state::InputState,
new_input: &crate::data::input::RawInput,
) {
crate::profile_function!();
self.interaction.begin_frame(prev_input, new_input);

if !prev_input.pointer.any_down() {
Expand Down
4 changes: 4 additions & 0 deletions crates/egui/src/util/id_type_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ struct PersistedMap(Vec<(u64, SerializedElement)>);
#[cfg(feature = "persistence")]
impl PersistedMap {
fn from_map(map: &IdTypeMap) -> Self {
crate::profile_function!();
// filter out the elements which cannot be serialized:
Self(
map.0
Expand All @@ -525,6 +526,7 @@ impl PersistedMap {
}

fn into_map(self) -> IdTypeMap {
crate::profile_function!();
IdTypeMap(
self.0
.into_iter()
Expand All @@ -542,6 +544,7 @@ impl serde::Serialize for IdTypeMap {
where
S: serde::Serializer,
{
crate::profile_scope!("IdTypeMap::serialize");
PersistedMap::from_map(self).serialize(serializer)
}
}
Expand All @@ -552,6 +555,7 @@ impl<'de> serde::Deserialize<'de> for IdTypeMap {
where
D: serde::Deserializer<'de>,
{
crate::profile_scope!("IdTypeMap::deserialize");
<PersistedMap>::deserialize(deserializer).map(PersistedMap::into_map)
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/egui_glow/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ clipboard = ["egui-winit?/clipboard"]
links = ["egui-winit?/links"]

## Enable profiling with the [`puffin`](https://docs.rs/puffin) crate.
puffin = ["dep:puffin", "egui-winit?/puffin"]
puffin = ["dep:puffin", "egui-winit?/puffin", "egui/puffin"]

## Enable [`winit`](https://docs.rs/winit) integration.
winit = ["egui-winit"]
Expand Down

0 comments on commit 9e86bb8

Please sign in to comment.