mirror of
https://github.com/emilk/egui.git
synced 2026-06-27 07:03:14 -04:00
* [x] I have followed the instructions in the PR template Splitting this out from the Parley work as requested. This removes `FontImage` and makes the font atlas use a `ColorImage`. It converts alpha to coverage at glyph-drawing time, not at delta-upload time. This doesn't do much now, but will allow for color emoji rendering once we start using Parley. I've changed things around so that we pass in `text_alpha_to_coverage` to the `Fonts` the same way we do with `pixels_per_point` and `max_texture_side`, reusing the existing code to check if the setting differs and recreating the font atlas if so. I'm not quite sure why this wasn't done in the first place. I've left `ImageData` as an enum for now, in case we want to add support for more texture pixel formats in the future (which I personally think would be worthwhile). If you'd like, I can just remove that enum entirely.
292 lines
8.5 KiB
Rust
292 lines
8.5 KiB
Rust
use criterion::{Criterion, black_box, criterion_group, criterion_main};
|
|
|
|
use epaint::{
|
|
AlphaFromCoverage, ClippedShape, Color32, Mesh, PathStroke, Pos2, Rect, Shape, Stroke,
|
|
TessellationOptions, Tessellator, TextureAtlas, Vec2, pos2, tessellator::Path,
|
|
};
|
|
|
|
#[global_allocator]
|
|
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; // Much faster allocator
|
|
|
|
fn single_dashed_lines(c: &mut Criterion) {
|
|
c.bench_function("single_dashed_lines", move |b| {
|
|
b.iter(|| {
|
|
let mut v = Vec::new();
|
|
|
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
|
|
|
for _ in 0..100 {
|
|
v.extend(Shape::dashed_line(
|
|
&line,
|
|
Stroke::new(1.5, Color32::RED),
|
|
10.0,
|
|
2.5,
|
|
));
|
|
}
|
|
|
|
black_box(v);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn many_dashed_lines(c: &mut Criterion) {
|
|
c.bench_function("many_dashed_lines", move |b| {
|
|
b.iter(|| {
|
|
let mut v = Vec::new();
|
|
|
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
|
|
|
for _ in 0..100 {
|
|
Shape::dashed_line_many(&line, Stroke::new(1.5, Color32::RED), 10.0, 2.5, &mut v);
|
|
}
|
|
|
|
black_box(v);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn tessellate_circles(c: &mut Criterion) {
|
|
c.bench_function("tessellate_circles_100k", move |b| {
|
|
let radii: [f32; 10] = [1.0, 2.0, 3.6, 4.0, 5.7, 8.0, 10.0, 13.0, 15.0, 17.0];
|
|
let mut clipped_shapes = vec![];
|
|
for r in radii {
|
|
for _ in 0..10_000 {
|
|
let clip_rect = Rect::from_min_size(Pos2::ZERO, Vec2::splat(1024.0));
|
|
let shape = Shape::circle_filled(Pos2::new(10.0, 10.0), r, Color32::WHITE);
|
|
clipped_shapes.push(ClippedShape { clip_rect, shape });
|
|
}
|
|
}
|
|
assert_eq!(
|
|
clipped_shapes.len(),
|
|
100_000,
|
|
"length of clipped shapes should be 100k, but was {}",
|
|
clipped_shapes.len()
|
|
);
|
|
|
|
let pixels_per_point = 2.0;
|
|
let options = TessellationOptions::default();
|
|
|
|
let atlas = TextureAtlas::new([4096, 256], AlphaFromCoverage::default());
|
|
let font_tex_size = atlas.size();
|
|
let prepared_discs = atlas.prepared_discs();
|
|
|
|
b.iter(|| {
|
|
let mut tessellator = Tessellator::new(
|
|
pixels_per_point,
|
|
options,
|
|
font_tex_size,
|
|
prepared_discs.clone(),
|
|
);
|
|
let clipped_primitives = tessellator.tessellate_shapes(clipped_shapes.clone());
|
|
black_box(clipped_primitives);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thick_line_solid(c: &mut Criterion) {
|
|
c.bench_function("thick_solid_line", move |b| {
|
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(1.5, &Stroke::new(2.0, Color32::RED).into(), &mut mesh);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thick_large_line_solid(c: &mut Criterion) {
|
|
c.bench_function("thick_large_solid_line", move |b| {
|
|
let line = (0..1000).map(|i| pos2(i as f32, 10.0)).collect::<Vec<_>>();
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(1.5, &Stroke::new(2.0, Color32::RED).into(), &mut mesh);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thin_line_solid(c: &mut Criterion) {
|
|
c.bench_function("thin_solid_line", move |b| {
|
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(1.5, &Stroke::new(0.5, Color32::RED).into(), &mut mesh);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thin_large_line_solid(c: &mut Criterion) {
|
|
c.bench_function("thin_large_solid_line", move |b| {
|
|
let line = (0..1000).map(|i| pos2(i as f32, 10.0)).collect::<Vec<_>>();
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(1.5, &Stroke::new(0.5, Color32::RED).into(), &mut mesh);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thick_line_uv(c: &mut Criterion) {
|
|
c.bench_function("thick_uv_line", move |b| {
|
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(
|
|
1.5,
|
|
&PathStroke::new_uv(2.0, |_, p| {
|
|
black_box(p * 2.0);
|
|
Color32::RED
|
|
}),
|
|
&mut mesh,
|
|
);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thick_large_line_uv(c: &mut Criterion) {
|
|
c.bench_function("thick_large_uv_line", move |b| {
|
|
let line = (0..1000).map(|i| pos2(i as f32, 10.0)).collect::<Vec<_>>();
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(
|
|
1.5,
|
|
&PathStroke::new_uv(2.0, |_, p| {
|
|
black_box(p * 2.0);
|
|
Color32::RED
|
|
}),
|
|
&mut mesh,
|
|
);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thin_line_uv(c: &mut Criterion) {
|
|
c.bench_function("thin_uv_line", move |b| {
|
|
let line = [pos2(0.0, 0.0), pos2(50.0, 0.0), pos2(100.0, 1.0)];
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(
|
|
1.5,
|
|
&PathStroke::new_uv(2.0, |_, p| {
|
|
black_box(p * 2.0);
|
|
Color32::RED
|
|
}),
|
|
&mut mesh,
|
|
);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn thin_large_line_uv(c: &mut Criterion) {
|
|
c.bench_function("thin_large_uv_line", move |b| {
|
|
let line = (0..1000).map(|i| pos2(i as f32, 10.0)).collect::<Vec<_>>();
|
|
let mut path = Path::default();
|
|
path.add_open_points(&line);
|
|
|
|
b.iter(|| {
|
|
let mut mesh = Mesh::default();
|
|
path.stroke_closed(
|
|
1.5,
|
|
&PathStroke::new_uv(2.0, |_, p| {
|
|
black_box(p * 2.0);
|
|
Color32::RED
|
|
}),
|
|
&mut mesh,
|
|
);
|
|
|
|
black_box(mesh);
|
|
});
|
|
});
|
|
}
|
|
|
|
fn rgba_values() -> [[u8; 4]; 1000] {
|
|
core::array::from_fn(|i| [5, 7, 11, 13].map(|m| (i * m) as u8))
|
|
}
|
|
|
|
fn from_rgba_unmultiplied_0(c: &mut Criterion) {
|
|
c.bench_function("from_rgba_unmultiplied_0", move |b| {
|
|
let values = black_box(rgba_values().map(|[r, g, b, _]| [r, g, b, 0]));
|
|
b.iter(|| {
|
|
for [r, g, b, a] in values {
|
|
let color = ecolor::Color32::from_rgba_unmultiplied(r, g, b, a);
|
|
black_box(color);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
fn from_rgba_unmultiplied_other(c: &mut Criterion) {
|
|
c.bench_function("from_rgba_unmultiplied_other", move |b| {
|
|
let values = black_box(rgba_values().map(|[r, g, b, a]| [r, g, b, a.clamp(1, 254)]));
|
|
b.iter(|| {
|
|
for [r, g, b, a] in values {
|
|
let color = ecolor::Color32::from_rgba_unmultiplied(r, g, b, a);
|
|
black_box(color);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
fn from_rgba_unmultiplied_255(c: &mut Criterion) {
|
|
c.bench_function("from_rgba_unmultiplied_255", move |b| {
|
|
let values = black_box(rgba_values().map(|[r, g, b, _]| [r, g, b, 255]));
|
|
b.iter(|| {
|
|
for [r, g, b, a] in values {
|
|
let color = ecolor::Color32::from_rgba_unmultiplied(r, g, b, a);
|
|
black_box(color);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
criterion_group!(
|
|
benches,
|
|
single_dashed_lines,
|
|
many_dashed_lines,
|
|
tessellate_circles,
|
|
thick_line_solid,
|
|
thick_large_line_solid,
|
|
thin_line_solid,
|
|
thin_large_line_solid,
|
|
thick_line_uv,
|
|
thick_large_line_uv,
|
|
thin_line_uv,
|
|
thin_large_line_uv,
|
|
from_rgba_unmultiplied_0,
|
|
from_rgba_unmultiplied_other,
|
|
from_rgba_unmultiplied_255,
|
|
);
|
|
criterion_main!(benches);
|