use std::collections::BTreeSet;
use criterion::{criterion_group, criterion_main, Criterion};
use embree3::{BufferUsage, Device, Format, GeometryKind, IntersectContext, Ray, RayHit, Scene};
const GRID: usize = 1024;
fn build_filtered_scene() -> Scene<'static> {
let device = Device::new().expect("failed to create embree device");
let mut scene = device.create_scene().unwrap();
let mut cube = device.create_geometry(GeometryKind::TRIANGLE).unwrap();
cube.set_new_buffer::<[f32; 3]>(BufferUsage::VERTEX, 0, Format::FLOAT3, 12, 8)
.unwrap()
.copy_from_slice(&[
[0.0, 0.0, 0.0],
[0.0, 0.0, 1.0],
[0.0, 1.0, 0.0],
[0.0, 1.0, 1.0],
[1.0, 0.0, 0.0],
[1.0, 0.0, 1.0],
[1.0, 1.0, 0.0],
[1.0, 1.0, 1.0],
]);
cube.set_new_buffer::<[u32; 3]>(BufferUsage::INDEX, 0, Format::UINT3, 12, 12)
.unwrap()
.copy_from_slice(&[
[0, 1, 2],
[1, 3, 2], [4, 6, 5],
[5, 6, 7], [0, 4, 1],
[1, 4, 5], [2, 3, 6],
[3, 7, 6], [0, 2, 4],
[2, 6, 4], [1, 5, 3],
[3, 5, 7], ]);
cube.set_intersect_filter_function::<_, ()>(|_r, _h, _v, _c, _ud| {});
let geom = cube.commit();
scene.attach_geometry(&geom);
scene.commit();
scene
}
fn cast_grid(scene: &Scene, threads: usize) -> u64 {
std::thread::scope(|s| {
let handles: Vec<_> = (0..threads)
.map(|t| {
s.spawn(move || {
let mut hits = 0u64;
let start = t * GRID / threads;
let end = (t + 1) * GRID / threads;
for gy in start..end {
for gx in 0..GRID {
let mut ctx = IntersectContext::coherent();
let x = gx as f32 / GRID as f32;
let y = gy as f32 / GRID as f32;
let mut rh = RayHit::from(Ray::segment(
[x, y, -1.0],
[0.0, 0.0, 1.0],
0.0,
f32::INFINITY,
));
scene.intersect(&mut ctx, &mut rh);
hits += rh.hit.is_valid() as u64;
}
}
hits
})
})
.collect();
handles.into_iter().map(|h| h.join().unwrap()).sum()
})
}
fn bench_filtered_traversal(c: &mut Criterion) {
let scene = build_filtered_scene();
let max = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(4);
let counts: BTreeSet<usize> = [1, 2, 4, 8, max]
.into_iter()
.filter(|&t| t <= max)
.collect();
let mut group = c.benchmark_group("filtered_traversal");
for &threads in &counts {
group.bench_function(format!("{threads}t"), |b| {
b.iter(|| std::hint::black_box(cast_grid(&scene, threads)))
});
}
group.finish();
}
criterion_group!(benches, bench_filtered_traversal);
criterion_main!(benches);