Changed the BBox4 data layout to give a small speed boost.

This commit is contained in:
Nathan Vegdahl 2017-04-16 15:54:02 -07:00
parent 2c4f103db5
commit f93dde1810

View File

@ -14,20 +14,18 @@ const BBOX_MAXT_ADJUST: f32 = 1.00000024;
/// A SIMD set of 4 3D axis-aligned bounding boxes. /// A SIMD set of 4 3D axis-aligned bounding boxes.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct BBox4 { pub struct BBox4 {
pub min: (Float4, Float4, Float4), // xs, ys, zs pub x: (Float4, Float4), // (min, max)
pub max: (Float4, Float4, Float4), // xs, ys, zs pub y: (Float4, Float4), // (min, max)
pub z: (Float4, Float4), // (min, max)
} }
impl BBox4 { impl BBox4 {
/// Creates a degenerate BBox with +infinity min and -infinity max. /// Creates a degenerate BBox with +infinity min and -infinity max.
pub fn new() -> BBox4 { pub fn new() -> BBox4 {
BBox4 { BBox4 {
min: (Float4::splat(std::f32::INFINITY), x: (Float4::splat(std::f32::INFINITY), Float4::splat(std::f32::NEG_INFINITY)),
Float4::splat(std::f32::INFINITY), y: (Float4::splat(std::f32::INFINITY), Float4::splat(std::f32::NEG_INFINITY)),
Float4::splat(std::f32::INFINITY)), z: (Float4::splat(std::f32::INFINITY), Float4::splat(std::f32::NEG_INFINITY)),
max: (Float4::splat(std::f32::NEG_INFINITY),
Float4::splat(std::f32::NEG_INFINITY),
Float4::splat(std::f32::NEG_INFINITY)),
} }
} }
@ -35,17 +33,21 @@ impl BBox4 {
/// extent. /// extent.
pub fn from_bboxes(b1: BBox, b2: BBox, b3: BBox, b4: BBox) -> BBox4 { pub fn from_bboxes(b1: BBox, b2: BBox, b3: BBox, b4: BBox) -> BBox4 {
BBox4 { BBox4 {
min: (Float4::new(b1.min.x(), b2.min.x(), b3.min.x(), b4.min.x()), x: (Float4::new(b1.min.x(), b2.min.x(), b3.min.x(), b4.min.x()),
Float4::new(b1.min.y(), b2.min.y(), b3.min.y(), b4.min.y()), Float4::new(b1.max.x(), b2.max.x(), b3.max.x(), b4.max.x())),
Float4::new(b1.min.z(), b2.min.z(), b3.min.z(), b4.min.z())), y: (Float4::new(b1.min.y(), b2.min.y(), b3.min.y(), b4.min.y()),
max: (Float4::new(b1.max.x(), b2.max.x(), b3.max.x(), b4.max.x()), Float4::new(b1.max.y(), b2.max.y(), b3.max.y(), b4.max.y())),
Float4::new(b1.max.y(), b2.max.y(), b3.max.y(), b4.max.y()), z: (Float4::new(b1.min.z(), b2.min.z(), b3.min.z(), b4.min.z()),
Float4::new(b1.max.z(), b2.max.z(), b3.max.z(), b4.max.z())), Float4::new(b1.max.z(), b2.max.z(), b3.max.z(), b4.max.z())),
} }
} }
// Returns whether the given ray intersects with the bboxes. // Returns whether the given ray intersects with the bboxes.
pub fn intersect_accel_ray(&self, ray: &AccelRay) -> Bool4 { pub fn intersect_accel_ray(&self, ray: &AccelRay) -> Bool4 {
// Precalculate ray direction sign booleans.
// Doing it up here slightly speeds things up lower down.
let ray_pos = (ray.dir_inv.x() >= 0.0, ray.dir_inv.y() >= 0.0, ray.dir_inv.z() >= 0.0);
// Convert ray to SIMD form // Convert ray to SIMD form
let ray4_o = let ray4_o =
(Float4::splat(ray.orig.x()), Float4::splat(ray.orig.y()), Float4::splat(ray.orig.z())); (Float4::splat(ray.orig.x()), Float4::splat(ray.orig.y()), Float4::splat(ray.orig.z()));
@ -54,22 +56,20 @@ impl BBox4 {
Float4::splat(ray.dir_inv.z())); Float4::splat(ray.dir_inv.z()));
// Calculate the plane intersections // Calculate the plane intersections
let (xlos, xhis) = if ray.dir_inv.x() >= 0.0 { let (xlos, xhis) = if ray_pos.0 {
((self.min.0 - ray4_o.0) * ray4_dinv.0, (self.max.0 - ray4_o.0) * ray4_dinv.0) ((self.x.0 - ray4_o.0) * ray4_dinv.0, (self.x.1 - ray4_o.0) * ray4_dinv.0)
} else { } else {
((self.max.0 - ray4_o.0) * ray4_dinv.0, (self.min.0 - ray4_o.0) * ray4_dinv.0) ((self.x.1 - ray4_o.0) * ray4_dinv.0, (self.x.0 - ray4_o.0) * ray4_dinv.0)
}; };
let (ylos, yhis) = if ray_pos.1 {
let (ylos, yhis) = if ray.dir_inv.y() >= 0.0 { ((self.y.0 - ray4_o.1) * ray4_dinv.1, (self.y.1 - ray4_o.1) * ray4_dinv.1)
((self.min.1 - ray4_o.1) * ray4_dinv.1, (self.max.1 - ray4_o.1) * ray4_dinv.1)
} else { } else {
((self.max.1 - ray4_o.1) * ray4_dinv.1, (self.min.1 - ray4_o.1) * ray4_dinv.1) ((self.y.1 - ray4_o.1) * ray4_dinv.1, (self.y.0 - ray4_o.1) * ray4_dinv.1)
}; };
let (zlos, zhis) = if ray_pos.2 {
let (zlos, zhis) = if ray.dir_inv.z() >= 0.0 { ((self.z.0 - ray4_o.2) * ray4_dinv.2, (self.z.1 - ray4_o.2) * ray4_dinv.2)
((self.min.2 - ray4_o.2) * ray4_dinv.2, (self.max.2 - ray4_o.2) * ray4_dinv.2)
} else { } else {
((self.max.2 - ray4_o.2) * ray4_dinv.2, (self.min.2 - ray4_o.2) * ray4_dinv.2) ((self.z.1 - ray4_o.2) * ray4_dinv.2, (self.z.0 - ray4_o.2) * ray4_dinv.2)
}; };
// Get the minimum and maximum hits // Get the minimum and maximum hits
@ -91,12 +91,9 @@ impl BitOr for BBox4 {
fn bitor(self, rhs: BBox4) -> BBox4 { fn bitor(self, rhs: BBox4) -> BBox4 {
BBox4 { BBox4 {
min: (self.min.0.v_min(rhs.min.0), x: (self.x.0.v_min(rhs.x.0), self.x.1.v_max(rhs.x.1)),
self.min.1.v_min(rhs.min.1), y: (self.y.0.v_min(rhs.y.0), self.y.1.v_max(rhs.y.1)),
self.min.2.v_min(rhs.min.2)), z: (self.z.0.v_min(rhs.z.0), self.z.1.v_max(rhs.z.1)),
max: (self.max.0.v_max(rhs.max.0),
self.max.1.v_max(rhs.max.1),
self.max.2.v_max(rhs.max.2)),
} }
} }
} }
@ -110,12 +107,9 @@ impl BitOrAssign for BBox4 {
impl Lerp for BBox4 { impl Lerp for BBox4 {
fn lerp(self, other: BBox4, alpha: f32) -> BBox4 { fn lerp(self, other: BBox4, alpha: f32) -> BBox4 {
BBox4 { BBox4 {
min: (lerp(self.min.0, other.min.0, alpha), x: (lerp(self.x.0, other.x.0, alpha), lerp(self.x.1, other.x.1, alpha)),
lerp(self.min.1, other.min.1, alpha), y: (lerp(self.y.0, other.y.0, alpha), lerp(self.y.1, other.y.1, alpha)),
lerp(self.min.2, other.min.2, alpha)), z: (lerp(self.z.0, other.z.0, alpha), lerp(self.z.1, other.z.1, alpha)),
max: (lerp(self.max.0, other.max.0, alpha),
lerp(self.max.1, other.max.1, alpha),
lerp(self.max.2, other.max.2, alpha)),
} }
} }
} }