Added AVX2 enabled version of vec3 type, Updated readme
This commit is contained in:
parent
1610db3a06
commit
1e234756ef
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -174,6 +174,12 @@ version = "0.2.86"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memoffset"
|
name = "memoffset"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -243,6 +249,16 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packed_simd_2"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10",
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.16.8"
|
version = "0.16.8"
|
||||||
|
@ -332,6 +348,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"image",
|
"image",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"packed_simd_2",
|
||||||
"rand",
|
"rand",
|
||||||
"rayon",
|
"rayon",
|
||||||
"sdl2",
|
"sdl2",
|
||||||
|
|
|
@ -6,6 +6,7 @@ version = "0.1.0"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-traits = "*"
|
num-traits = "*"
|
||||||
rayon = "1.5.0"
|
rayon = "1.5.0"
|
||||||
|
packed_simd = { version = "0.3.4", package = "packed_simd_2" }
|
||||||
|
|
||||||
[dependencies.image]
|
[dependencies.image]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
|
|
||||||
This is my attempt at Ray Tracing the Next Week book by Peter Shirley.
|
This is my attempt at Ray Tracing the Next Week book by Peter Shirley.
|
||||||
|
|
||||||
|
|
||||||
|
On x86_64 target, It'll try to use AVX2. If you get build errors, Try commenting the simd_vec3 import in `src/types/mod.rs`.
|
||||||
|
I tried changing the cfg attribute to, `all(target_arch = "x86_64", target_feature = "avx2")` but it keeps reporting that `avx2` feature is disabled on my machine?
|
||||||
|
|
||||||
|
|
||||||
|
Without AVX2, The final scene takes ~33 seconds to render at a certain setting and with AVX2 the same scene takes ~23.5 seconds.
|
||||||
|
|
||||||
[_Ray Tracing: The Next Week_](https://raytracing.github.io/books/RayTracingTheNextWeek.html)
|
[_Ray Tracing: The Next Week_](https://raytracing.github.io/books/RayTracingTheNextWeek.html)
|
||||||
|
|
||||||
# Renders
|
# Renders
|
||||||
|
|
24
src/aabb.rs
24
src/aabb.rs
|
@ -11,23 +11,17 @@ impl Aabb {
|
||||||
Self { min, max }
|
Self { min, max }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hit(&self, ray: &Ray, mut t_min: f64, mut t_max: f64) -> bool {
|
pub fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> bool {
|
||||||
for i in 0..=2 {
|
let min = (self.min - ray.origin) / ray.direction;
|
||||||
let inverse_dir = 1.0 / ray.direction[i];
|
let max = (self.max - ray.origin) / ray.direction;
|
||||||
let mut t0 = (self.min[i] - ray.origin[i]) * inverse_dir;
|
|
||||||
let mut t1 = (self.max[i] - ray.origin[i]) * inverse_dir;
|
|
||||||
if inverse_dir < 0.0 {
|
|
||||||
std::mem::swap(&mut t0, &mut t1);
|
|
||||||
}
|
|
||||||
t_min = if t0 > t_min { t0 } else { t_min };
|
|
||||||
t_max = if t1 < t_max { t1 } else { t_max };
|
|
||||||
|
|
||||||
if t_max <= t_min {
|
let mins = min.min(max);
|
||||||
return false;
|
let maxs = min.max(max);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
let tmin = mins.max_element(t_min);
|
||||||
|
let tmax = maxs.min_element(t_max);
|
||||||
|
|
||||||
|
tmax > tmin
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surrounding_box(box0: Aabb, box1: Aabb) -> Self {
|
pub fn surrounding_box(box0: Aabb, box1: Aabb) -> Self {
|
||||||
|
|
|
@ -22,11 +22,11 @@ use std::time::Instant;
|
||||||
pub trait Asf64: num_traits::AsPrimitive<f64> {}
|
pub trait Asf64: num_traits::AsPrimitive<f64> {}
|
||||||
impl<T: num_traits::AsPrimitive<f64>> Asf64 for T {}
|
impl<T: num_traits::AsPrimitive<f64>> Asf64 for T {}
|
||||||
|
|
||||||
const NUM_SAMPLES: u16 = 10000;
|
const NUM_SAMPLES: u16 = 500;
|
||||||
const VERTICAL_PARTITION: usize = 12;
|
const VERTICAL_PARTITION: usize = 12;
|
||||||
const HORIZONTAL_PARTITION: usize = 12;
|
const HORIZONTAL_PARTITION: usize = 12;
|
||||||
const WIDTH: usize = 1500;
|
const WIDTH: usize = 500;
|
||||||
const HEIGHT: usize = 1500;
|
const HEIGHT: usize = 500;
|
||||||
|
|
||||||
fn main() -> Result<(), String> {
|
fn main() -> Result<(), String> {
|
||||||
run(WIDTH, HEIGHT)
|
run(WIDTH, HEIGHT)
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
mod color;
|
mod color;
|
||||||
mod dimension;
|
mod dimension;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod vec3;
|
|
||||||
|
|
||||||
pub use color::Color;
|
pub use color::Color;
|
||||||
pub use dimension::{Dimension, X, Y, Z};
|
pub use dimension::{Dimension, X, Y, Z};
|
||||||
pub use ray::Ray;
|
pub use ray::Ray;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "x86_64"))]
|
||||||
|
mod vec3;
|
||||||
|
#[cfg(not(target_arch = "x86_64"))]
|
||||||
pub use vec3::Vec3;
|
pub use vec3::Vec3;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
mod simd_vec3;
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub use simd_vec3::Vec3;
|
||||||
|
|
214
src/types/simd_vec3.rs
Normal file
214
src/types/simd_vec3.rs
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
use std::{
|
||||||
|
fmt::{Display, Formatter, Result as FmtResult},
|
||||||
|
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, RangeInclusive, Sub, SubAssign},
|
||||||
|
};
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use crate::{Asf64, Dimension, X, Y, Z};
|
||||||
|
|
||||||
|
use packed_simd::{f64x4, shuffle};
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Copy, Clone)]
|
||||||
|
pub struct Vec3(f64x4);
|
||||||
|
|
||||||
|
impl Vec3 {
|
||||||
|
#[inline]
|
||||||
|
pub fn new(a: impl Asf64, b: impl Asf64, c: impl Asf64) -> Vec3 {
|
||||||
|
Self(f64x4::new(a.as_(), b.as_(), c.as_(), 0.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn splat(xyz: impl Asf64) -> Self {
|
||||||
|
Self::new(xyz, xyz, xyz)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random<R: Rng + ?Sized>(rng: &mut R) -> Self {
|
||||||
|
Self(f64x4::from_slice_aligned(&rng.gen::<[f64; 4]>()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random_in_range<R: Rng + ?Sized>(rng: &mut R, range: RangeInclusive<f64>) -> Self {
|
||||||
|
Vec3::new(
|
||||||
|
rng.gen_range(range.clone()),
|
||||||
|
rng.gen_range(range.clone()),
|
||||||
|
rng.gen_range(range),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn x(&self) -> f64 {
|
||||||
|
self.get::<X>()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn y(&self) -> f64 {
|
||||||
|
self.get::<Y>()
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
pub fn z(&self) -> f64 {
|
||||||
|
self.get::<Z>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<D: Dimension>(&self) -> f64 {
|
||||||
|
unsafe { self.0.extract_unchecked(D::INDEX) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set<D: Dimension>(self, value: f64) -> Self {
|
||||||
|
Self(unsafe { self.0.replace_unchecked(D::INDEX, value) })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn length(&self) -> f64 {
|
||||||
|
self.sq_len().sqrt()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn sq_len(&self) -> f64 {
|
||||||
|
(self.0 * self.0).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn dot(&self, v: &Vec3) -> f64 {
|
||||||
|
(self.0 * v.0).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn cross(&self, v: &Vec3) -> Vec3 {
|
||||||
|
// https://web.archive.org/web/20210412192227/https://geometrian.com/programming/tutorials/cross-product/index.php
|
||||||
|
let tmp0: f64x4 = shuffle!(self.0, [1, 2, 0, 3]);
|
||||||
|
let tmp1: f64x4 = shuffle!(v.0, [2, 0, 1, 3]);
|
||||||
|
let tmp2: f64x4 = shuffle!(self.0, [2, 0, 1, 3]);
|
||||||
|
let tmp3: f64x4 = shuffle!(v.0, [1, 2, 0, 3]);
|
||||||
|
|
||||||
|
Vec3(tmp0 * tmp1 - tmp2 * tmp3)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn unit_vector(self) -> Vec3 {
|
||||||
|
self / self.length()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min(self, other: Self) -> Vec3 {
|
||||||
|
Self(self.0.min(other.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max(self, other: Self) -> Vec3 {
|
||||||
|
Self(self.0.max(other.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min_element(self, other: f64) -> f64 {
|
||||||
|
unsafe { self.0.replace_unchecked(3, other).min_element() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_element(self, other: f64) -> f64 {
|
||||||
|
unsafe { self.0.replace_unchecked(3, other).max_element() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn sqrt(self) -> Self {
|
||||||
|
Self(self.0.sqrt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn add(self, o: Vec3) -> Vec3 {
|
||||||
|
Vec3(self.0 + o.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign for Vec3 {
|
||||||
|
fn add_assign(&mut self, o: Vec3) {
|
||||||
|
self.0 += o.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn sub(self, o: Vec3) -> Vec3 {
|
||||||
|
Vec3(self.0 - o.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign for Vec3 {
|
||||||
|
fn sub_assign(&mut self, o: Vec3) {
|
||||||
|
self.0 -= o.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn neg(self) -> Vec3 {
|
||||||
|
Vec3(-self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MulAssign<Vec3> for Vec3 {
|
||||||
|
fn mul_assign(&mut self, o: Vec3) {
|
||||||
|
self.0 *= o.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MulAssign<f64> for Vec3 {
|
||||||
|
fn mul_assign(&mut self, o: f64) {
|
||||||
|
self.0 *= o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<f64> for Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
fn mul(self, o: f64) -> Vec3 {
|
||||||
|
Vec3(self.0 * o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mul<Vec3> for Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
fn mul(self, o: Vec3) -> Vec3 {
|
||||||
|
Vec3(self.0 * o.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Div<Vec3> for Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn div(self, o: Vec3) -> Vec3 {
|
||||||
|
Vec3(self.0 / o.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Div<f64> for Vec3 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn div(self, o: f64) -> Vec3 {
|
||||||
|
let o = 1.0 / o;
|
||||||
|
|
||||||
|
Vec3(self.0 * o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DivAssign<f64> for Vec3 {
|
||||||
|
fn div_assign(&mut self, o: f64) {
|
||||||
|
let o = 1.0 / o;
|
||||||
|
|
||||||
|
self.0 *= o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Vec3 {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> FmtResult {
|
||||||
|
f.write_fmt(format_args!(
|
||||||
|
"{} {} {}",
|
||||||
|
self.get::<X>(),
|
||||||
|
self.get::<Y>(),
|
||||||
|
self.get::<Z>()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Asf64, B: Asf64, C: Asf64> From<(A, B, C)> for Vec3 {
|
||||||
|
fn from((x, y, z): (A, B, C)) -> Self {
|
||||||
|
Self::new(x, y, z)
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ pub struct Vec3([f64; 3]);
|
||||||
impl Vec3 {
|
impl Vec3 {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(a: impl Asf64, b: impl Asf64, c: impl Asf64) -> Vec3 {
|
pub fn new(a: impl Asf64, b: impl Asf64, c: impl Asf64) -> Vec3 {
|
||||||
Vec3([a.as_(), b.as_(), c.as_()])
|
Self([a.as_(), b.as_(), c.as_()])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn splat(xyz: impl Asf64) -> Self {
|
pub fn splat(xyz: impl Asf64) -> Self {
|
||||||
|
@ -102,12 +102,12 @@ impl Vec3 {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min_element(self) -> f64 {
|
pub fn min_element(self, other: f64) -> f64 {
|
||||||
self.x().min(self.y()).min(self.z())
|
self.x().min(self.y()).min(self.z()).min(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_element(self) -> f64 {
|
pub fn max_element(self, other: f64) -> f64 {
|
||||||
self.x().max(self.y()).max(self.z())
|
self.x().max(self.y()).max(self.z()).max(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user