Created a BitStack128 type and added it to Ray.

This will be used for BVH4 traversal.
This commit is contained in:
Nathan Vegdahl 2017-04-11 11:13:23 -07:00
parent f5ba119562
commit c05bae2636
3 changed files with 78 additions and 0 deletions

73
src/bitstack.rs Normal file
View File

@ -0,0 +1,73 @@
#![allow(dead_code)]
use std::mem::size_of;
#[derive(Copy, Clone, Debug)]
pub struct BitStack128 {
data: (u64, u64),
}
impl BitStack128 {
pub fn new() -> BitStack128 {
BitStack128 { data: (0, 0) }
}
/// Push a bit onto the top of the stack.
pub fn push(&mut self, value: bool) {
debug_assert!((self.data.1 >> (size_of::<u64>() - 1)) == 0); // Verify no stack overflow
self.data.1 = (self.data.1 << 1) | (self.data.0 >> (size_of::<u64>() - 1));
self.data.0 <<= 1;
self.data.0 |= value as u64;
}
/// Push 3 bits onto the top of the stack. The input
/// bits are passed as an integer, with the bit that
/// will be on top in the least significant digit, and
/// the rest following in order from there.
///
/// Note that unless you are running a debug build, no
/// effort is made to verify that only the first three
/// bits of the passed value are used. So if other
/// bits are non-zero this will produce incorrect results.
pub fn push_3(&mut self, value: u8) {
debug_assert!((self.data.1 >> (size_of::<u64>() - 3)) == 0); // Verify no stack overflow
debug_assert!(value & (!((1 << 3) - 1)) == 0); // Verify no bits outside of the 3-bit range
self.data.1 = (self.data.1 << 3) | (self.data.0 >> (size_of::<u64>() - 3));
self.data.0 <<= 3;
self.data.0 |= value as u64;
}
/// Pop the top bit off the stack.
pub fn pop(&mut self) -> bool {
let b = (self.data.0 & 1) != 0;
self.data.0 = (self.data.0 >> 1) | (self.data.1 << (size_of::<u64>() - 1));
self.data.1 >>= 1;
return b;
}
/// Pop the top n bits off the stack. The bits are returned as
/// an integer, with the top bit in the least significant digit,
/// and the rest following in order from there.
pub fn pop_n(&mut self, n: usize) -> u64 {
debug_assert!(n < size_of::<BitStack128>()); // Can't pop more than we have
debug_assert!(n < size_of::<u64>()); // Can't pop more than the return type can hold
let b = self.data.0 & ((1 << n) - 1);
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.
pub fn peek(&self) -> bool {
(self.data.0 & 1) != 0
}
/// Read the top n bits of the stack without popping them. The bits
/// are returned as an integer, with the top bit in the least
/// significant digit, and the rest following in order from there.
pub fn peek_n(&self, n: usize) -> u64 {
debug_assert!(n < size_of::<BitStack128>()); // Can't return more than we have
debug_assert!(n < size_of::<u64>()); // Can't return more than the return type can hold
self.data.0 & ((1 << n) - 1)
}
}

View File

@ -21,6 +21,7 @@ extern crate simd;
mod accel;
mod algorithm;
mod bbox;
mod bitstack;
mod boundable;
mod camera;
mod color;

View File

@ -2,6 +2,7 @@
use std;
use bitstack::BitStack128;
use float4::Float4;
use math::{Vector, Point, Matrix4x4};
@ -16,6 +17,7 @@ pub struct Ray {
pub max_t: f32,
pub time: f32,
pub flags: u32,
pub trav_stack: BitStack128,
}
impl Ray {
@ -27,6 +29,7 @@ impl Ray {
max_t: std::f32::INFINITY,
time: time,
flags: 0,
trav_stack: BitStack128::new(),
}
} else {
Ray {
@ -35,6 +38,7 @@ impl Ray {
max_t: 1.0,
time: time,
flags: OCCLUSION_FLAG,
trav_stack: BitStack128::new(),
}
}
}