Move multiple-object logic out of BVH4.

This allows each part of Psychopath tp handle the logic in the
best way, instead of a one-size-fits-all approach.
This commit is contained in:
Nathan Vegdahl 2019-06-29 08:28:41 +09:00
parent 874b07df02
commit 4ef376dc89
4 changed files with 163 additions and 164 deletions

View File

@ -96,14 +96,9 @@ impl<'a> BVH4<'a> {
self.depth
}
pub fn traverse<T, F>(
&self,
rays: &mut RayBatch,
ray_stack: &mut RayStack,
objects: &[T],
mut obj_ray_test: F,
) where
F: FnMut(&T, &mut RayBatch, &mut RayStack),
pub fn traverse<F>(&self, rays: &mut RayBatch, ray_stack: &mut RayStack, mut obj_ray_test: F)
where
F: FnMut(std::ops::Range<usize>, &mut RayBatch, &mut RayStack),
{
if self.root.is_none() {
return;
@ -170,16 +165,8 @@ impl<'a> BVH4<'a> {
&BVH4Node::Leaf { object_range } => {
trav_time += timer.tick() as f64;
// Set up the tasks for each object.
let obj_count = object_range.1 - object_range.0;
for _ in 0..(obj_count - 1) {
ray_stack.duplicate_next_task();
}
// Do the ray tests.
for obj in &objects[object_range.0..object_range.1] {
obj_ray_test(obj, rays, ray_stack);
}
obj_ray_test(object_range.0..object_range.1, rays, ray_stack);
timer.tick();

View File

@ -292,24 +292,37 @@ impl RayStack {
self.lanes[l].end_len = self.lanes[l].idxs.len();
}
/// Pops the next task off the stack, and executes the provided closure for
/// each ray index in the task.
pub fn pop_do_next_task<F>(&mut self, mut handle_ray: F)
// Pops the next task off the stack.
pub fn pop_task(&mut self) {
let task = self.tasks.pop().unwrap();
self.lanes[task.lane].end_len = task.start_idx;
self.lanes[task.lane].idxs.truncate(task.start_idx);
}
// Executes a task without popping it from the task stack.
pub fn do_next_task<F>(&mut self, mut handle_ray: F)
where
F: FnMut(usize),
{
// Pop the task and do necessary bookkeeping.
let task = self.tasks.pop().unwrap();
let task = self.tasks.last().unwrap();
let task_range = (task.start_idx, self.lanes[task.lane].end_len);
self.lanes[task.lane].end_len = task.start_idx;
// Execute task.
for i in task_range.0..task_range.1 {
let ray_idx = self.lanes[task.lane].idxs[i];
handle_ray(ray_idx as usize);
}
}
self.lanes[task.lane].idxs.truncate(task_range.0);
/// Pops the next task off the stack, and executes the provided closure for
/// each ray index in the task.
#[inline(always)]
pub fn pop_do_next_task<F>(&mut self, handle_ray: F)
where
F: FnMut(usize),
{
self.do_next_task(handle_ray);
self.pop_task();
}
/// Pops the next task off the stack, executes the provided closure for

View File

@ -130,11 +130,11 @@ impl<'a> Surface for TriangleMesh<'a> {
Matrix4x4::new()
};
self.accel.traverse(
rays,
ray_stack,
self.indices,
|tri_indices, rays, ray_stack| {
self.accel
.traverse(rays, ray_stack, |idx_range, rays, ray_stack| {
for tri_idx in idx_range {
let tri_indices = self.indices[tri_idx];
// For static triangles with static transforms, cache them.
let is_cached = self.time_sample_count == 1 && space.len() <= 1;
let mut tri = if is_cached {
@ -157,7 +157,7 @@ impl<'a> Surface for TriangleMesh<'a> {
};
// Test each ray against the current triangle.
ray_stack.pop_do_next_task(|ray_idx| {
ray_stack.do_next_task(|ray_idx| {
let ray_idx = ray_idx as usize;
let ray_time = rays.time(ray_idx);
@ -276,7 +276,8 @@ impl<'a> Surface for TriangleMesh<'a> {
}
}
});
},
);
}
ray_stack.pop_task();
});
}
}

View File

@ -85,11 +85,11 @@ impl<'a> TracerInner<'a> {
rays: &mut RayBatch,
ray_stack: &mut RayStack,
) {
assembly.object_accel.traverse(
rays,
ray_stack,
&assembly.instances[..],
|inst, rays, ray_stack| {
assembly
.object_accel
.traverse(rays, ray_stack, |idx_range, rays, ray_stack| {
let inst = &assembly.instances[idx_range.start];
// Transform rays if needed
if let Some((xstart, xend)) = inst.transform_indices {
// Push transforms to stack
@ -98,12 +98,11 @@ impl<'a> TracerInner<'a> {
// Do transforms
// TODO: re-divide rays based on direction (maybe?).
let xforms = self.xform_stack.top();
ray_stack.pop_do_next_task_and_push_rays(2, |ray_idx| {
ray_stack.do_next_task(|ray_idx| {
let t = rays.time(ray_idx);
rays.update_local(ray_idx, &lerp_slice(xforms, t));
(Bool4::new(true, true, false, false), 2)
});
ray_stack.push_lanes_to_tasks(&[0, 1]);
ray_stack.duplicate_next_task();
}
// Trace rays
@ -142,8 +141,7 @@ impl<'a> TracerInner<'a> {
});
}
}
},
);
});
}
fn trace_object<'b>(