diff --git a/src/accel/bvh4.rs b/src/accel/bvh4.rs index 15eab8e..9a5fa40 100644 --- a/src/accel/bvh4.rs +++ b/src/accel/bvh4.rs @@ -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>), diff --git a/src/accel/bvh4_table.inc b/src/accel/bvh4_table.inc new file mode 100644 index 0000000..fef7769 --- /dev/null +++ b/src/accel/bvh4_table.inc @@ -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], +]; + diff --git a/src/accel/create_bvh4_table.py b/src/accel/create_bvh4_table.py new file mode 100644 index 0000000..d9b9410 --- /dev/null +++ b/src/accel/create_bvh4_table.py @@ -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 +