mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 06:40:06 -04:00
Optimize tessellation of filled circles (#1616)
When painting a scatter plot we sometimes want to paint hundreds of thousands of points (filled circles) on screen every frame. In this PR the font texture atlas is pre-populated with some filled circled of various radii. These are then used when painting (small) filled circled, which means A LOT less triangles and vertices are generated for them. In a new benchmark we can see a 10x speedup in circle tessellation, but the the real benefit comes in the painting of these circles: since we generate a lot less vertices, the backend painter has less to do. In a real-life scenario with a lot of things being painted (including around 100k points) I saw tessellation go from 35ms -> 7ms and painting go from 45ms -> 1ms. This means the total frame time went from 80ms to 8ms, or a 10x speedup.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
|
||||
use epaint::{pos2, Color32, Shape, Stroke};
|
||||
use epaint::*;
|
||||
|
||||
fn single_dashed_lines(c: &mut Criterion) {
|
||||
c.bench_function("single_dashed_lines", move |b| {
|
||||
@@ -39,5 +39,43 @@ fn many_dashed_lines(c: &mut Criterion) {
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, single_dashed_lines, many_dashed_lines);
|
||||
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);
|
||||
|
||||
let pixels_per_point = 2.0;
|
||||
let options = TessellationOptions::default();
|
||||
|
||||
let atlas = TextureAtlas::new([4096, 256]);
|
||||
let font_tex_size = atlas.size();
|
||||
let prepared_discs = atlas.prepared_discs();
|
||||
|
||||
b.iter(|| {
|
||||
let clipped_primitive = tessellate_shapes(
|
||||
pixels_per_point,
|
||||
options,
|
||||
font_tex_size,
|
||||
prepared_discs.clone(),
|
||||
clipped_shapes.clone(),
|
||||
);
|
||||
black_box(clipped_primitive);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
single_dashed_lines,
|
||||
many_dashed_lines,
|
||||
tessellate_circles
|
||||
);
|
||||
criterion_main!(benches);
|
||||
|
||||
Reference in New Issue
Block a user