Beginnings of BVH4 implementation.

- Created a traversal-order table.
- Created a function to help index into that table.
This commit is contained in:
Nathan Vegdahl 2017-04-11 23:10:54 -07:00
parent a2d7f9e149
commit e0c6dfbd76
3 changed files with 133 additions and 0 deletions

View File

@ -1,15 +1,49 @@
//! This BVH4 implementation pulls a lot of ideas from the paper
//! "Efficient Ray Tracing Kernels for Modern CPU Architectures"
//! by Fuetterling et al.
//!
//! Specifically, the table-based traversal order approach they
//! propose is largely followed by this implementation.
#![allow(dead_code)]
use mem_arena::MemArena;
use algorithm::partition;
use bbox::BBox;
use bbox4::BBox4;
use boundable::Boundable;
use lerp::lerp_slice;
use ray::AccelRay;
use super::bvh_base::{BVHBase, BVHBaseNode, BVH_MAX_DEPTH};
// TRAVERSAL_TABLE
include!("bvh4_table.inc");
// Calculates the traversal code for a BVH4 node based on the splits and topology
// of its children.
//
// split_1 is the top split.
//
// split_2 is either the left or right split depending on topology, and is only
// relevant for topologies 0-2. For topology 3 it should be 0.
//
// split_3 is always the right split, and is only relevant for topology 0. For
// topologies 1-3 it should be 0.
//
// topology can be 0-3:
// 0: All three splits exist, representing 4 BVH4 children.
// 1: Two splits exist: top split and left split, representing 3 BVH4 children.
// 2: Two splits exist: top split and right split, representing 3 BVH4 children.
// 3: Only the top split exists, representing 2 BVH4 children.
fn calc_traversal_code(split_1: u8, split_2: u8, split_3: u8, topology: u8) -> u8 {
debug_assert!(!(topology > 0 && split_3 > 0));
debug_assert!(!(topology > 2 && split_2 > 0));
static T_TABLE: [u8; 4] = [0, 27, 27 + 9, 27 + 9 + 9];
split_1 + (split_2 * 3) + (split_3 * 9) + T_TABLE[topology as usize]
}
#[derive(Copy, Clone, Debug)]
pub struct BVH4<'a> {
@ -19,6 +53,12 @@ pub struct BVH4<'a> {
#[derive(Copy, Clone, Debug)]
enum BVH4Node<'a> {
// Internal {
// bounds: &'a [BBox4],
// children: [&'a BVH4Node<'a>; 4],
// children_count: u8,
// traversal_code: u8,
// },
Internal {
bounds: &'a [BBox],
children: (&'a BVH4Node<'a>, &'a BVH4Node<'a>),

35
src/accel/bvh4_table.inc Normal file
View File

@ -0,0 +1,35 @@
static TRAVERSAL_TABLE: [[u8; 48]; 8] = [
[228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
36, 36, 36, 36, 36, 36, 36, 36, 36,
36, 36, 36, 36, 36, 36, 36, 36, 36,
4, 4, 4],
[27, 177, 177, 75, 180, 180, 75, 180, 180, 30, 225, 225, 78, 228, 228, 78, 228, 228, 30, 225, 225, 78, 228, 228, 78, 228, 228,
6, 33, 33, 18, 36, 36, 18, 36, 36,
6, 24, 24, 9, 36, 36, 9, 36, 36,
1, 4, 4],
[228, 78, 228, 225, 30, 225, 228, 78, 228, 180, 75, 180, 177, 27, 177, 180, 75, 180, 228, 78, 228, 225, 30, 225, 228, 78, 228,
36, 18, 36, 33, 6, 33, 36, 18, 36,
36, 9, 36, 24, 6, 24, 36, 9, 36,
4, 1, 4],
[27, 27, 177, 27, 27, 177, 75, 75, 180, 27, 27, 177, 27, 27, 177, 75, 75, 180, 30, 30, 225, 30, 30, 225, 78, 78, 228,
6, 6, 33, 6, 6, 33, 18, 18, 36,
6, 6, 24, 6, 6, 24, 9, 9, 36,
1, 1, 4],
[228, 228, 78, 228, 228, 78, 225, 225, 30, 228, 228, 78, 228, 228, 78, 225, 225, 30, 180, 180, 75, 180, 180, 75, 177, 177, 27,
36, 36, 18, 36, 36, 18, 33, 33, 6,
36, 36, 9, 36, 36, 9, 24, 24, 6,
4, 4, 1],
[27, 177, 27, 75, 180, 75, 27, 177, 27, 30, 225, 30, 78, 228, 78, 30, 225, 30, 27, 177, 27, 75, 180, 75, 27, 177, 27,
6, 33, 6, 18, 36, 18, 6, 33, 6,
6, 24, 6, 9, 36, 9, 6, 24, 6,
1, 4, 1],
[228, 78, 78, 225, 30, 30, 225, 30, 30, 180, 75, 75, 177, 27, 27, 177, 27, 27, 180, 75, 75, 177, 27, 27, 177, 27, 27,
36, 18, 18, 33, 6, 6, 33, 6, 6,
36, 9, 9, 24, 6, 6, 24, 6, 6,
4, 1, 1],
[27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6,
1, 1, 1],
];

View File

@ -0,0 +1,58 @@
#!/usr/bin/env python
if __name__ == "__main__":
text = "static TRAVERSAL_TABLE: [[u8; 48]; 8] = [\n"
for raydir in range(0, 8):
ray = [raydir & 1, (raydir >> 1) & 1, (raydir >> 2) & 1]
text += " ["
for splits in [[s1, s2, s3] for s3 in range(0,3) for s2 in range(0,3) for s1 in range(0,3)]:
perm = [0, 1, 2, 3]
if ray[splits[1]] == 1:
perm = [perm[1], perm[0]] + perm[2:4]
if ray[splits[2]] == 1:
perm = perm[0:2] + [perm[3], perm[2]]
if ray[splits[0]] == 1:
perm = perm[2:4] + perm[0:2]
perm = perm[0] + (perm[1] << 2) + (perm[2] << 4) + (perm[3] << 6)
text += "%d, " % perm
text = text[:-1]
text += "\n "
for splits in [[s1, s2] for s2 in range(0,3) for s1 in range(0,3)]:
perm = [0, 1, 2]
if ray[splits[1]] == 1:
perm = [perm[1], perm[0], perm[2]]
if ray[splits[0]] == 1:
perm = [perm[2], perm[0], perm[1]]
perm = perm[0] + (perm[1] << 2) + (perm[2] << 4)
text += "%d, " % perm
text = text[:-1]
text += "\n "
for splits in [[s1, s2] for s2 in range(0,3) for s1 in range(0,3)]:
perm = [0, 1, 2]
if ray[splits[1]] == 1:
perm = [perm[0], perm[2], perm[1]]
if ray[splits[0]] == 1:
perm = [perm[1], perm[2], perm[0]]
perm = perm[0] + (perm[1] << 2) + (perm[2] << 4)
text += "%d, " % perm
text = text[:-1]
text += "\n "
for split in [s1 for s1 in range(0,3)]:
perm = [0, 1]
if ray[split] == 1:
perm = [perm[1], perm[0]]
perm = perm[0] + (perm[1] << 2)
text += "%d, " % perm
text = text[:-1]
text = text[:-1] + "],\n"
text += "];\n"
print text