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:
parent
874b07df02
commit
4ef376dc89
|
@ -96,14 +96,9 @@ impl<'a> BVH4<'a> {
|
||||||
self.depth
|
self.depth
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn traverse<T, F>(
|
pub fn traverse<F>(&self, rays: &mut RayBatch, ray_stack: &mut RayStack, mut obj_ray_test: F)
|
||||||
&self,
|
where
|
||||||
rays: &mut RayBatch,
|
F: FnMut(std::ops::Range<usize>, &mut RayBatch, &mut RayStack),
|
||||||
ray_stack: &mut RayStack,
|
|
||||||
objects: &[T],
|
|
||||||
mut obj_ray_test: F,
|
|
||||||
) where
|
|
||||||
F: FnMut(&T, &mut RayBatch, &mut RayStack),
|
|
||||||
{
|
{
|
||||||
if self.root.is_none() {
|
if self.root.is_none() {
|
||||||
return;
|
return;
|
||||||
|
@ -170,16 +165,8 @@ impl<'a> BVH4<'a> {
|
||||||
&BVH4Node::Leaf { object_range } => {
|
&BVH4Node::Leaf { object_range } => {
|
||||||
trav_time += timer.tick() as f64;
|
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.
|
// Do the ray tests.
|
||||||
for obj in &objects[object_range.0..object_range.1] {
|
obj_ray_test(object_range.0..object_range.1, rays, ray_stack);
|
||||||
obj_ray_test(obj, rays, ray_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
timer.tick();
|
timer.tick();
|
||||||
|
|
||||||
|
|
27
src/ray.rs
27
src/ray.rs
|
@ -292,24 +292,37 @@ impl RayStack {
|
||||||
self.lanes[l].end_len = self.lanes[l].idxs.len();
|
self.lanes[l].end_len = self.lanes[l].idxs.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pops the next task off the stack, and executes the provided closure for
|
// Pops the next task off the stack.
|
||||||
/// each ray index in the task.
|
pub fn pop_task(&mut self) {
|
||||||
pub fn pop_do_next_task<F>(&mut self, mut handle_ray: F)
|
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
|
where
|
||||||
F: FnMut(usize),
|
F: FnMut(usize),
|
||||||
{
|
{
|
||||||
// Pop the task and do necessary bookkeeping.
|
let task = self.tasks.last().unwrap();
|
||||||
let task = self.tasks.pop().unwrap();
|
|
||||||
let task_range = (task.start_idx, self.lanes[task.lane].end_len);
|
let task_range = (task.start_idx, self.lanes[task.lane].end_len);
|
||||||
self.lanes[task.lane].end_len = task.start_idx;
|
|
||||||
|
|
||||||
// Execute task.
|
// Execute task.
|
||||||
for i in task_range.0..task_range.1 {
|
for i in task_range.0..task_range.1 {
|
||||||
let ray_idx = self.lanes[task.lane].idxs[i];
|
let ray_idx = self.lanes[task.lane].idxs[i];
|
||||||
handle_ray(ray_idx as usize);
|
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
|
/// Pops the next task off the stack, executes the provided closure for
|
||||||
|
|
|
@ -130,11 +130,11 @@ impl<'a> Surface for TriangleMesh<'a> {
|
||||||
Matrix4x4::new()
|
Matrix4x4::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
self.accel.traverse(
|
self.accel
|
||||||
rays,
|
.traverse(rays, ray_stack, |idx_range, rays, ray_stack| {
|
||||||
ray_stack,
|
for tri_idx in idx_range {
|
||||||
self.indices,
|
let tri_indices = self.indices[tri_idx];
|
||||||
|tri_indices, rays, ray_stack| {
|
|
||||||
// For static triangles with static transforms, cache them.
|
// For static triangles with static transforms, cache them.
|
||||||
let is_cached = self.time_sample_count == 1 && space.len() <= 1;
|
let is_cached = self.time_sample_count == 1 && space.len() <= 1;
|
||||||
let mut tri = if is_cached {
|
let mut tri = if is_cached {
|
||||||
|
@ -157,7 +157,7 @@ impl<'a> Surface for TriangleMesh<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test each ray against the current triangle.
|
// 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_idx = ray_idx as usize;
|
||||||
let ray_time = rays.time(ray_idx);
|
let ray_time = rays.time(ray_idx);
|
||||||
|
|
||||||
|
@ -276,7 +276,8 @@ impl<'a> Surface for TriangleMesh<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
);
|
ray_stack.pop_task();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,11 +85,11 @@ impl<'a> TracerInner<'a> {
|
||||||
rays: &mut RayBatch,
|
rays: &mut RayBatch,
|
||||||
ray_stack: &mut RayStack,
|
ray_stack: &mut RayStack,
|
||||||
) {
|
) {
|
||||||
assembly.object_accel.traverse(
|
assembly
|
||||||
rays,
|
.object_accel
|
||||||
ray_stack,
|
.traverse(rays, ray_stack, |idx_range, rays, ray_stack| {
|
||||||
&assembly.instances[..],
|
let inst = &assembly.instances[idx_range.start];
|
||||||
|inst, rays, ray_stack| {
|
|
||||||
// Transform rays if needed
|
// Transform rays if needed
|
||||||
if let Some((xstart, xend)) = inst.transform_indices {
|
if let Some((xstart, xend)) = inst.transform_indices {
|
||||||
// Push transforms to stack
|
// Push transforms to stack
|
||||||
|
@ -98,12 +98,11 @@ impl<'a> TracerInner<'a> {
|
||||||
// Do transforms
|
// Do transforms
|
||||||
// TODO: re-divide rays based on direction (maybe?).
|
// TODO: re-divide rays based on direction (maybe?).
|
||||||
let xforms = self.xform_stack.top();
|
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);
|
let t = rays.time(ray_idx);
|
||||||
rays.update_local(ray_idx, &lerp_slice(xforms, t));
|
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
|
// Trace rays
|
||||||
|
@ -142,8 +141,7 @@ impl<'a> TracerInner<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trace_object<'b>(
|
fn trace_object<'b>(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user