Skip to content

Commit 89e00b1

Browse files
authored
Add compute_*_normals benchmarks (#18648)
# Objective Benchmark current `compute_*_normals` methods to get a baseline as requested in #18552 (comment) ## Solution Since the change to the default smooth normals method will definitely cause a regression, but the previous method will remain as an option, I added two technically-redundant benchmarks but with different names: `smooth_normals` for whatever default weighting method is used, and `face_weighted_normals` to benchmark the area-weighted method regardless of what the default is. Then I'm adding `angle_weighted_normals` in #18552. I also added `flat_normals` for completeness.
1 parent 301f618 commit 89e00b1

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use core::hint::black_box;
2+
3+
use criterion::{criterion_group, Criterion};
4+
use rand::random;
5+
use std::time::{Duration, Instant};
6+
7+
use bevy_render::{
8+
mesh::{Indices, Mesh, PrimitiveTopology},
9+
render_asset::RenderAssetUsages,
10+
};
11+
12+
const GRID_SIZE: usize = 256;
13+
14+
fn compute_normals(c: &mut Criterion) {
15+
let indices = Indices::U32(
16+
(0..GRID_SIZE - 1)
17+
.flat_map(|i| std::iter::repeat(i).zip(0..GRID_SIZE - 1))
18+
.flat_map(|(i, j)| {
19+
let tl = ((GRID_SIZE * j) + i) as u32;
20+
let tr = tl + 1;
21+
let bl = ((GRID_SIZE * (j + 1)) + i) as u32;
22+
let br = bl + 1;
23+
[tl, bl, tr, tr, bl, br]
24+
})
25+
.collect(),
26+
);
27+
28+
let new_mesh = || {
29+
let positions = (0..GRID_SIZE)
30+
.flat_map(|i| std::iter::repeat(i).zip(0..GRID_SIZE))
31+
.map(|(i, j)| [i as f32, j as f32, random::<f32>()])
32+
.collect::<Vec<_>>();
33+
Mesh::new(
34+
PrimitiveTopology::TriangleList,
35+
RenderAssetUsages::MAIN_WORLD,
36+
)
37+
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, positions)
38+
.with_inserted_indices(indices.clone())
39+
};
40+
41+
c.bench_function("smooth_normals", |b| {
42+
b.iter_custom(|iters| {
43+
let mut total = Duration::default();
44+
for _ in 0..iters {
45+
let mut mesh = new_mesh();
46+
black_box(mesh.attribute(Mesh::ATTRIBUTE_NORMAL));
47+
let start = Instant::now();
48+
mesh.compute_smooth_normals();
49+
let end = Instant::now();
50+
black_box(mesh.attribute(Mesh::ATTRIBUTE_NORMAL));
51+
total += end.duration_since(start);
52+
}
53+
total
54+
});
55+
});
56+
57+
c.bench_function("face_weighted_normals", |b| {
58+
b.iter_custom(|iters| {
59+
let mut total = Duration::default();
60+
for _ in 0..iters {
61+
let mut mesh = new_mesh();
62+
black_box(mesh.attribute(Mesh::ATTRIBUTE_NORMAL));
63+
let start = Instant::now();
64+
mesh.compute_smooth_normals();
65+
let end = Instant::now();
66+
black_box(mesh.attribute(Mesh::ATTRIBUTE_NORMAL));
67+
total += end.duration_since(start);
68+
}
69+
total
70+
});
71+
});
72+
73+
let new_mesh = || {
74+
new_mesh()
75+
.with_duplicated_vertices()
76+
.with_computed_flat_normals()
77+
};
78+
79+
c.bench_function("flat_normals", |b| {
80+
b.iter_custom(|iters| {
81+
let mut total = Duration::default();
82+
for _ in 0..iters {
83+
let mut mesh = new_mesh();
84+
black_box(mesh.attribute(Mesh::ATTRIBUTE_NORMAL));
85+
let start = Instant::now();
86+
mesh.compute_flat_normals();
87+
let end = Instant::now();
88+
black_box(mesh.attribute(Mesh::ATTRIBUTE_NORMAL));
89+
total += end.duration_since(start);
90+
}
91+
total
92+
});
93+
});
94+
}
95+
96+
criterion_group!(benches, compute_normals);

benches/benches/bevy_render/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
use criterion::criterion_main;
22

3+
mod compute_normals;
34
mod render_layers;
45
mod torus;
56

6-
criterion_main!(render_layers::benches, torus::benches);
7+
criterion_main!(
8+
render_layers::benches,
9+
compute_normals::benches,
10+
torus::benches
11+
);

0 commit comments

Comments
 (0)