Got BVH4 working. Woo hoo!

This commit is contained in:
Nathan Vegdahl 2017-04-13 22:44:34 -07:00
parent 53a14996c9
commit 573c5da5ab
5 changed files with 53 additions and 61 deletions

View File

@ -98,47 +98,41 @@ impl<'a> BVH4<'a> {
TRAVERSAL_TABLE[ray_code as usize][traversal_code as usize] TRAVERSAL_TABLE[ray_code as usize][traversal_code as usize]
}; };
let mut all_hits = 0; // Accumulate // Ray testing
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| { let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
if (!r.is_done()) && (first_loop || r.trav_stack.pop()) { if (!r.is_done()) && (first_loop || r.trav_stack.pop()) {
let hits = lerp_slice(bounds, r.time) let hits = lerp_slice(bounds, r.time)
.intersect_accel_ray(r) .intersect_accel_ray(r)
.to_bitmask(); .to_bitmask();
all_hits |= hits;
if hits != 0 {
// Push hit bits onto ray's traversal stack // Push hit bits onto ray's traversal stack
let mut shuffled_hits = 0; let mut shuffled_hits = 0;
for i in 0..3 { for i in 0..children.len() {
let ii = (node_order_code >> (i * 2)) & 3; let ii = (node_order_code >> (i * 2)) & 3;
shuffled_hits |= ((hits >> ii) & 1) << i; shuffled_hits |= ((hits >> ii) & 1) << i;
} }
r.trav_stack.push_3(shuffled_hits); r.trav_stack.push_n(shuffled_hits, children.len() as u8);
true true
} else { } else {
false false
} }
} else {
false
}
}); });
if part > 0 {
node_stack[stack_ptr] = {
Some(&children[(node_order_code & 3) as usize])
};
node_stack[stack_ptr + 1] = {
Some(&children[((node_order_code >> 2) & 3) as usize])
};
node_stack[stack_ptr + 2] = if children.len() > 2 {
Some(&children[((node_order_code >> 4) & 3) as usize])
} else {
None
};
node_stack[stack_ptr + 3] = if children.len() > 3 {
Some(&children[((node_order_code >> 6) & 3) as usize])
} else {
None
};
ray_i_stack[stack_ptr] = part; // Update stack based on ray testing results
ray_i_stack[stack_ptr + 1] = part; if part > 0 {
for i in 0..children.len() {
let inv_i = (children.len() - 1) - i;
node_stack[stack_ptr + i] =
Some(&children[((node_order_code >> (inv_i * 2)) & 3) as
usize]);
ray_i_stack[stack_ptr + i] = part;
}
stack_ptr += children.len() - 1; stack_ptr += children.len() - 1;
} else { } else {
stack_ptr -= 1; stack_ptr -= 1;
@ -298,7 +292,11 @@ impl<'a> BVH4<'a> {
}; };
calc_traversal_code(split_axis, calc_traversal_code(split_axis,
split_axis_l.unwrap_or(split_axis_r.unwrap_or(0)), split_axis_l.unwrap_or(split_axis_r.unwrap_or(0)),
split_axis_r.unwrap_or(0), if child_count == 4 {
split_axis_r.unwrap()
} else {
0
},
topology_code) topology_code)
}; };
*fill_node = BVH4Node::Internal { *fill_node = BVH4Node::Internal {

View File

@ -24,20 +24,24 @@ impl BitStack128 {
self.data.0 |= value as u64; self.data.0 |= value as u64;
} }
/// Push 3 bits onto the top of the stack. The input /// Push n bits onto the top of the stack. The input
/// bits are passed as an integer, with the bit that /// bits are passed as an integer, with the bit that
/// will be on top in the least significant digit, and /// will be on top in the least significant digit, and
/// the rest following in order from there. /// the rest following in order from there.
/// ///
/// Note that unless you are running a debug build, no /// Note that unless you are running a debug build, no
/// effort is made to verify that only the first three /// effort is made to verify that only the first n
/// bits of the passed value are used. So if other /// bits of the passed value are used. So if other
/// bits are non-zero this will produce incorrect results. /// bits are non-zero this will produce incorrect results.
pub fn push_3(&mut self, value: u8) { pub fn push_n(&mut self, value: u8, count: u8) {
debug_assert!((self.data.1 >> (size_of::<u64>() - 3)) == 0); // Verify no stack overflow // Verify no bitstack overflow
debug_assert!(value & (!((1 << 3) - 1)) == 0); // Verify no bits outside of the 3-bit range debug_assert!((self.data.1 >> (size_of::<u64>() - count as usize)) == 0);
self.data.1 = (self.data.1 << 3) | (self.data.0 >> (size_of::<u64>() - 3)); // Verify no bits outside of the n-bit range
self.data.0 <<= 3; debug_assert!(value & (!((1 << count) - 1)) == 0);
self.data.1 = (self.data.1 << count as usize) |
(self.data.0 >> (size_of::<u64>() - count as usize));
self.data.0 <<= count as u64;
self.data.0 |= value as u64; self.data.0 |= value as u64;
} }
@ -61,16 +65,6 @@ impl BitStack128 {
return b; return b;
} }
/// Pop the top n bits off the stack, returning only the first
/// one.
pub fn pop_1_remove_n(&mut self, n: usize) -> bool {
debug_assert!(n < size_of::<BitStack128>()); // Can't pop more than we have
let b = (self.data.0 & 1) != 0;
self.data.0 = (self.data.0 >> n) | (self.data.1 << (size_of::<u64>() - n));
self.data.1 >>= n;
return b;
}
/// Read the top bit of the stack without popping it. /// Read the top bit of the stack without popping it.
pub fn peek(&self) -> bool { pub fn peek(&self) -> bool {
(self.data.0 & 1) != 0 (self.data.0 & 1) != 0

View File

@ -520,7 +520,7 @@ impl Bool4 {
} }
pub fn to_bitmask(&self) -> u8 { pub fn to_bitmask(&self) -> u8 {
(self.get_0() as u8) & ((self.get_1() as u8) << 1) & ((self.get_2() as u8) << 2) & (self.get_0() as u8) | ((self.get_1() as u8) << 1) | ((self.get_2() as u8) << 2) |
((self.get_3() as u8) << 3) ((self.get_3() as u8) << 3)
} }
} }

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use mem_arena::MemArena; use mem_arena::MemArena;
use accel::{LightAccel, LightTree}; use accel::{LightAccel, LightTree};
use accel::BVH; use accel::BVH4;
use bbox::{BBox, transform_bbox_slice_from}; use bbox::{BBox, transform_bbox_slice_from};
use boundable::Boundable; use boundable::Boundable;
use color::SpectralSample; use color::SpectralSample;
@ -28,7 +28,7 @@ pub struct Assembly<'a> {
pub assemblies: &'a [Assembly<'a>], pub assemblies: &'a [Assembly<'a>],
// Object accel // Object accel
pub object_accel: BVH<'a>, pub object_accel: BVH4<'a>,
// Light accel // Light accel
pub light_accel: LightTree<'a>, pub light_accel: LightTree<'a>,
@ -231,7 +231,7 @@ impl<'a> AssemblyBuilder<'a> {
let (bis, bbs) = self.instance_bounds(); let (bis, bbs) = self.instance_bounds();
// Build object accel // Build object accel
let object_accel = BVH::from_objects(self.arena, let object_accel = BVH4::from_objects(self.arena,
&mut self.instances[..], &mut self.instances[..],
1, 1,
|inst| &bbs[bis[inst.id]..bis[inst.id + 1]]); |inst| &bbs[bis[inst.id]..bis[inst.id + 1]]);
@ -288,7 +288,7 @@ impl<'a> AssemblyBuilder<'a> {
/// Returns a pair of vectors with the bounds of all instances. /// Returns a pair of vectors with the bounds of all instances.
/// This is used for building the assembly's BVH. /// This is used for building the assembly's BVH4.
fn instance_bounds(&self) -> (Vec<usize>, Vec<BBox>) { fn instance_bounds(&self) -> (Vec<usize>, Vec<BBox>) {
let mut indices = vec![0]; let mut indices = vec![0];
let mut bounds = Vec::new(); let mut bounds = Vec::new();

View File

@ -2,7 +2,7 @@
use mem_arena::MemArena; use mem_arena::MemArena;
use accel::BVH; use accel::BVH4;
use bbox::BBox; use bbox::BBox;
use boundable::Boundable; use boundable::Boundable;
use color::XYZ; use color::XYZ;
@ -20,7 +20,7 @@ pub struct TriangleMesh<'a> {
time_samples: usize, time_samples: usize,
geo: &'a [(Point, Point, Point)], geo: &'a [(Point, Point, Point)],
indices: &'a [usize], indices: &'a [usize],
accel: BVH<'a>, accel: BVH4<'a>,
} }
impl<'a> TriangleMesh<'a> { impl<'a> TriangleMesh<'a> {
@ -44,7 +44,7 @@ impl<'a> TriangleMesh<'a> {
bounds bounds
}; };
let accel = BVH::from_objects(arena, let accel = BVH4::from_objects(arena,
&mut indices[..], &mut indices[..],
3, 3,
|tri_i| &bounds[*tri_i..(*tri_i + time_samples)]); |tri_i| &bounds[*tri_i..(*tri_i + time_samples)]);