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

Parallel tessellation with opt-in rayon feature #3934

Merged
merged 7 commits into from
Feb 1, 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
46 changes: 42 additions & 4 deletions Cargo.lock

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

7 changes: 6 additions & 1 deletion crates/egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ 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"]
puffin = ["dep:puffin", "epaint/puffin"]

## Enable parallel tessellation using [`rayon`](https://docs.rs/rayon).
##
## This can help performance for graphics-intense applications.
rayon = ["epaint/rayon"]

## Allow serialization using [`serde`](https://docs.rs/serde).
serde = ["dep:serde", "epaint/serde", "accesskit?/serde"]
Expand Down
4 changes: 2 additions & 2 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1977,13 +1977,13 @@ impl Context {
let paint_stats = PaintStats::from_shapes(&shapes);
let clipped_primitives = {
crate::profile_scope!("tessellator::tessellate_shapes");
tessellator::tessellate_shapes(
tessellator::Tessellator::new(
pixels_per_point,
tessellation_options,
font_tex_size,
prepared_discs,
shapes,
)
.tessellate_shapes(shapes)
};
ctx.paint_stats = paint_stats.with_clipped_primitives(&clipped_primitives);
clipped_primitives
Expand Down
8 changes: 8 additions & 0 deletions crates/egui/src/introspection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ impl Widget for &mut epaint::TessellationOptions {
debug_ignore_clip_rects,
bezier_tolerance,
epsilon: _,
parallel_tessellation,
validate_meshes,
} = self;

ui.checkbox(feathering, "Feathering (antialias)")
Expand Down Expand Up @@ -176,6 +178,12 @@ impl Widget for &mut epaint::TessellationOptions {
ui.checkbox(debug_paint_clip_rects, "Paint clip rectangles");
ui.checkbox(debug_paint_text_rects, "Paint text bounds");
});

ui.add_enabled(epaint::HAS_RAYON, crate::Checkbox::new(parallel_tessellation, "Parallelize tessellation")
).on_hover_text("Only available if epaint was compiled with the rayon feature")
.on_disabled_hover_text("epaint was not compiled with the rayon feature");

ui.checkbox(validate_meshes, "Validate meshes").on_hover_text("Check that incoming meshes are valid, i.e. that all indices are in range, etc.");
})
.response
}
Expand Down
12 changes: 12 additions & 0 deletions crates/epaint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ log = ["dep:log"]
## [`mint`](https://docs.rs/mint) enables interoperability with other math libraries such as [`glam`](https://docs.rs/glam) and [`nalgebra`](https://docs.rs/nalgebra).
mint = ["emath/mint"]

## 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"]

## Enable parallel tessellation using [`rayon`](https://docs.rs/rayon).
##
## This can help performance for graphics-intense applications.
rayon = ["dep:rayon"]

## Allow serialization using [`serde`](https://docs.rs/serde).
serde = ["dep:serde", "ahash/serde", "emath/serde", "ecolor/serde"]

Expand All @@ -88,6 +98,8 @@ bytemuck = { version = "1.7.2", optional = true, features = ["derive"] }
document-features = { version = "0.2", optional = true }

log = { version = "0.4", optional = true, features = ["std"] }
puffin = { workspace = true, optional = true }
rayon = { version = "1.7", optional = true }

## Allow serialization using [`serde`](https://docs.rs/serde) .
serde = { version = "1", optional = true, features = ["derive", "rc"] }
Expand Down
6 changes: 3 additions & 3 deletions crates/epaint/benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ fn tessellate_circles(c: &mut Criterion) {
let prepared_discs = atlas.prepared_discs();

b.iter(|| {
let clipped_primitive = tessellate_shapes(
let mut tessellator = Tessellator::new(
pixels_per_point,
options,
font_tex_size,
prepared_discs.clone(),
clipped_shapes.clone(),
);
black_box(clipped_primitive);
let clipped_primitives = tessellator.tessellate_shapes(clipped_shapes.clone());
black_box(clipped_primitives);
});
});
}
Expand Down
40 changes: 39 additions & 1 deletion crates/epaint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,16 @@ pub use {
},
stats::PaintStats,
stroke::Stroke,
tessellator::{tessellate_shapes, TessellationOptions, Tessellator},
tessellator::{TessellationOptions, Tessellator},
text::{FontFamily, FontId, Fonts, Galley},
texture_atlas::TextureAtlas,
texture_handle::TextureHandle,
textures::TextureManager,
};

#[allow(deprecated)]
pub use tessellator::tessellate_shapes;

pub use ecolor::{Color32, Hsva, HsvaGamma, Rgba};
pub use emath::{pos2, vec2, Pos2, Rect, Vec2};

Expand Down Expand Up @@ -172,3 +175,38 @@ pub(crate) fn f64_hash<H: std::hash::Hasher>(state: &mut H, f: f64) {
f.to_bits().hash(state);
}
}

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

/// Was epaint compiled with the `rayon` feature?
pub const HAS_RAYON: bool = cfg!(feature = "rayon");

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

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

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

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

#[allow(unused_imports)]
pub(crate) use profiling_scopes::*;
3 changes: 3 additions & 0 deletions crates/epaint/src/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ impl Mesh {

/// Are all indices within the bounds of the contained vertices?
pub fn is_valid(&self) -> bool {
crate::profile_function!();

if let Ok(n) = u32::try_from(self.vertices.len()) {
self.indices.iter().all(|&i| i < n)
} else {
Expand All @@ -106,6 +108,7 @@ impl Mesh {

/// Append all the indices and vertices of `other` to `self`.
pub fn append(&mut self, other: Self) {
crate::profile_function!();
crate::epaint_assert!(other.is_valid());

if self.is_empty() {
Expand Down
Loading
Loading