diff --git a/.github/workflows/clippy.sh b/.github/workflows/clippy.sh index bb23186c66..49716d5ecb 100755 --- a/.github/workflows/clippy.sh +++ b/.github/workflows/clippy.sh @@ -34,7 +34,10 @@ clippy rustc_codegen_spirv clippy spirv-builder # Examples -clippy examples/example-runner + +# disabled due to https://github.com/EmbarkStudios/rust-gpu/issues/186 +#clippy examples/example-runner + clippy examples/wgpu-example-runner clippy_no_features examples/example-runner-cpu diff --git a/Cargo.lock b/Cargo.lock index 448dee46b2..c00bf65a32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -605,15 +605,16 @@ name = "example-runner-cpu" version = "0.1.0" dependencies = [ "example-shader", + "glam", "minifb", "rayon", - "spirv-std", ] [[package]] name = "example-shader" version = "0.1.0" dependencies = [ + "glam", "spirv-std", ] @@ -933,6 +934,11 @@ dependencies = [ "slab", ] +[[package]] +name = "glam" +version = "0.9.5" +source = "git+https://github.com/EmbarkStudios/glam-rs?rev=262e4e1b86e54dbd7772a9c1f342abd30a438282#262e4e1b86e54dbd7772a9c1f342abd30a438282" + [[package]] name = "heck" version = "0.3.1" @@ -2930,6 +2936,7 @@ dependencies = [ name = "wgpu-example-shader" version = "0.1.0" dependencies = [ + "glam", "spirv-std", ] diff --git a/Cargo.toml b/Cargo.toml index 6303afed05..c79635774a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,7 @@ members = [ "spirv-tools", "spirv-tools-sys", ] + +[patch.crates-io] +# https://github.com/bitshifter/glam-rs/pull/85 +glam = { git = "https://github.com/EmbarkStudios/glam-rs", rev = "262e4e1b86e54dbd7772a9c1f342abd30a438282" } diff --git a/examples/example-runner-cpu/Cargo.toml b/examples/example-runner-cpu/Cargo.toml index 347108adfa..07385444b9 100644 --- a/examples/example-runner-cpu/Cargo.toml +++ b/examples/example-runner-cpu/Cargo.toml @@ -9,8 +9,7 @@ license = "MIT OR Apache-2.0" minifb = "0.19.1" # bring in the shader as natively compiled code example-shader = { path = "../example-shader" } -# for math types, likely get from glam directly later instead -spirv-std = { path = "../../spirv-std" } +glam = { version = "0.9", default_features = false } # for parallelism, not really needed though rayon = "1.5" diff --git a/examples/example-runner-cpu/src/main.rs b/examples/example-runner-cpu/src/main.rs index 16e112837f..acbaeaec28 100644 --- a/examples/example-runner-cpu/src/main.rs +++ b/examples/example-runner-cpu/src/main.rs @@ -1,6 +1,6 @@ +use glam::{vec2, Vec4}; use minifb::{Key, Window, WindowOptions}; use rayon::prelude::*; -use spirv_std::{vec2, Vec4}; use std::time::Instant; fn color_u32_from_vec4(v: Vec4) -> u32 { diff --git a/examples/example-shader/Cargo.toml b/examples/example-shader/Cargo.toml index 1a723f2a98..46c8a796f9 100644 --- a/examples/example-shader/Cargo.toml +++ b/examples/example-shader/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["dylib"] [dependencies] spirv-std = { path = "../../spirv-std" } +glam = { version = "0.9", default_features = false } \ No newline at end of file diff --git a/examples/example-shader/src/lib.rs b/examples/example-shader/src/lib.rs index a74b0e8102..35968a5dd4 100644 --- a/examples/example-shader/src/lib.rs +++ b/examples/example-shader/src/lib.rs @@ -6,26 +6,39 @@ #![register_attr(spirv)] use core::f32::consts::PI; -use spirv_std::{Input, Mat4, MathExt, Output, Vec2, Vec3, Vec4}; +use glam::{const_vec3, Mat4, Vec2, Vec3, Vec4}; +use spirv_std::{Input, MathExt, Output}; const DEPOLARIZATION_FACTOR: f32 = 0.035; const LUMINANCE: f32 = 1.0; const MIE_COEFFICIENT: f32 = 0.005; const MIE_DIRECTIONAL_G: f32 = 0.8; -const MIE_K_COEFFICIENT: Vec3 = Vec3::new(0.686, 0.678, 0.666); +const MIE_K_COEFFICIENT: Vec3 = const_vec3!([0.686, 0.678, 0.666]); const MIE_V: f32 = 4.0; const MIE_ZENITH_LENGTH: f32 = 1.25e3; const NUM_MOLECULES: f32 = 2.542e25f32; -const PRIMARIES: Vec3 = Vec3::new(6.8e-7f32, 5.5e-7f32, 4.5e-7f32); +const PRIMARIES: Vec3 = const_vec3!([6.8e-7f32, 5.5e-7f32, 4.5e-7f32]); const RAYLEIGH: f32 = 1.0; const RAYLEIGH_ZENITH_LENGTH: f32 = 8.4e3; const REFRACTIVE_INDEX: f32 = 1.0003; const SUN_ANGULAR_DIAMETER_DEGREES: f32 = 0.0093333; const SUN_INTENSITY_FACTOR: f32 = 1000.0; const SUN_INTENSITY_FALLOFF_STEEPNESS: f32 = 1.5; -const TONEMAP_WEIGHTING: Vec3 = Vec3::splat(9.50); +const TONEMAP_WEIGHTING: Vec3 = const_vec3!([9.50; 3]); const TURBIDITY: f32 = 2.0; +// TODO: add this to glam? Rust std has it on f32/f64 +fn pow(v: Vec3, power: f32) -> Vec3 { + let v: [f32; 3] = v.into(); + Vec3::new(v[0].pow(power), v[1].pow(power), v[2].pow(power)) +} + +// TODO: add this to glam? Rust std has it on f32/f64 +fn exp(v: Vec3) -> Vec3 { + let v: [f32; 3] = v.into(); + Vec3::new(v[0].exp(), v[1].exp(), v[2].exp()) +} + /// Based on: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/ fn acos_approx(v: f32) -> f32 { let x = v.abs(); @@ -51,12 +64,12 @@ fn total_rayleigh(lambda: Vec3) -> Vec3 { (8.0 * PI.pow(3.0) * (REFRACTIVE_INDEX.pow(2.0) - 1.0).pow(2.0) * (6.0 + 3.0 * DEPOLARIZATION_FACTOR)) - / (3.0 * NUM_MOLECULES * lambda.pow(4.0) * (6.0 - 7.0 * DEPOLARIZATION_FACTOR)) + / (3.0 * NUM_MOLECULES * pow(lambda, 4.0) * (6.0 - 7.0 * DEPOLARIZATION_FACTOR)) } fn total_mie(lambda: Vec3, k: Vec3, t: f32) -> Vec3 { let c = 0.2 * t * 10e-18; - 0.434 * c * PI * ((2.0 * PI) / lambda).pow(MIE_V - 2.0) * k + 0.434 * c * PI * pow((2.0 * PI) / lambda, MIE_V - 2.0) * k } fn rayleigh_phase(cos_theta: f32) -> f32 { @@ -78,19 +91,19 @@ fn sun_intensity(zenith_angle_cos: f32) -> f32 { } fn uncharted2_tonemap(w: Vec3) -> Vec3 { - const A: Vec3 = Vec3::splat(0.15); // Shoulder strength - const B: Vec3 = Vec3::splat(0.50); // Linear strength - const C: Vec3 = Vec3::splat(0.10); // Linear angle - const D: Vec3 = Vec3::splat(0.20); // Toe strength - const E: Vec3 = Vec3::splat(0.02); // Toe numerator - const F: Vec3 = Vec3::splat(0.30); // Toe denominator + const A: Vec3 = const_vec3!([0.15; 3]); // Shoulder strength + const B: Vec3 = const_vec3!([0.50; 3]); // Linear strength + const C: Vec3 = const_vec3!([0.10; 3]); // Linear angle + const D: Vec3 = const_vec3!([0.20; 3]); // Toe strength + const E: Vec3 = const_vec3!([0.02; 3]); // Toe numerator + const F: Vec3 = const_vec3!([0.30; 3]); // Toe denominator ((w * (A * w + C * B) + D * E) / (w * (A * w + B) + D * F)) - E / F } fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { let up = Vec3::new(0.0, 1.0, 0.0); - let sunfade = 1.0 - (1.0 - (sun_position.1 / 450000.0).exp()).saturate(); + let sunfade = 1.0 - (1.0 - (sun_position.y() / 450000.0).exp()).saturate(); let rayleigh_coefficient = RAYLEIGH - (1.0 * (1.0 - sunfade)); let beta_r = total_rayleigh(PRIMARIES) * rayleigh_coefficient; @@ -105,7 +118,7 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { let s_m = MIE_ZENITH_LENGTH / denom; // Combined extinction factor - let fex = (-(beta_r * s_r + beta_m * s_m)).exp(); + let fex = exp(-(beta_r * s_r + beta_m * s_m)); // In-scattering let sun_direction = sun_position.normalize(); @@ -114,11 +127,16 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { let beta_m_theta = beta_m * henyey_greenstein_phase(cos_theta, MIE_DIRECTIONAL_G); let sun_e = sun_intensity(sun_direction.dot(up)); - let mut lin = - (sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * (Vec3::splat(1.0) - fex)) - .pow(1.5); + let mut lin = pow( + sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * (Vec3::splat(1.0) - fex), + 1.5, + ); + lin *= Vec3::splat(1.0).lerp( - (sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * fex).pow(0.5), + pow( + sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * fex, + 0.5, + ), ((1.0 - up.dot(sun_direction)).pow(5.0)).saturate(), ); @@ -140,50 +158,24 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { let curr = uncharted2_tonemap(((2.0 / LUMINANCE.pow(4.0)).log2()) * tex_color); let color = curr * white_scale; - color.pow(1.0 / (1.2 + (1.2 * sunfade))) -} - -pub fn main_fs_test(screen_pos: Vec2) -> Vec4 { - // hard-code information because we can't bind buffers at the moment - let eye_pos = Vec3(0.0, 0.0997, 0.2); - let sun_pos = Vec3::new(0.0, 75.0, -1000.0); - let clip_to_world = Mat4 { - x_axis: Vec4(-0.5522849, 0.0, 0.0, 0.0), - y_axis: Vec4(0.0, 0.4096309, -0.061444636, 0.0), - z_axis: Vec4(0.0, 99.99999, 199.99998, 999.99994), - w_axis: Vec4(0.0, -0.14834046, -0.98893654, 0.0), - }; - - let cs_pos = Vec4(screen_pos.0, -screen_pos.1, 1.0, 1.0); - let ws_pos = { - let p = clip_to_world.mul_vec4(cs_pos); - p.truncate() / p.3 - }; - let dir = (ws_pos - eye_pos).normalize(); - - // evaluate Preetham sky model - let color = sky(dir, sun_pos); - - // let color = dir; - - color.extend(1.0) + pow(color, 1.0 / (1.2 + (1.2 * sunfade))) } pub fn fs(screen_pos: Vec2) -> Vec4 { // hard-code information because we can't bind buffers at the moment - let eye_pos = Vec3(0.0, 0.0997, 0.2); + let eye_pos = Vec3::new(0.0, 0.0997, 0.2); let sun_pos = Vec3::new(0.0, 75.0, -1000.0); - let clip_to_world = Mat4 { - x_axis: Vec4(-0.5522849, 0.0, 0.0, 0.0), - y_axis: Vec4(0.0, 0.4096309, -0.061444636, 0.0), - z_axis: Vec4(0.0, 99.99999, 199.99998, 999.99994), - w_axis: Vec4(0.0, -0.14834046, -0.98893654, 0.0), - }; + let clip_to_world = Mat4::from_cols( + Vec4::new(-0.5522849, 0.0, 0.0, 0.0), + Vec4::new(0.0, 0.4096309, -0.061444636, 0.0), + Vec4::new(0.0, 99.99999, 199.99998, 999.99994), + Vec4::new(0.0, -0.14834046, -0.98893654, 0.0), + ); - let cs_pos = Vec4(screen_pos.0, -screen_pos.1, 1.0, 1.0); + let cs_pos = Vec4::new(screen_pos.x(), -screen_pos.y(), 1.0, 1.0); let ws_pos = { let p = clip_to_world.mul_vec4(cs_pos); - p.truncate() / p.3 + p.truncate() / p.w() }; let dir = (ws_pos - eye_pos).normalize(); @@ -197,7 +189,7 @@ pub fn fs(screen_pos: Vec2) -> Vec4 { #[spirv(fragment)] pub fn main_fs(input: Input, mut output: Output) { let v = input.load(); - let color = fs(Vec2::new(v.0, v.1)); + let color = fs(Vec2::new(v.x(), v.y())); output.store(color) } diff --git a/examples/wgpu-example-shader/Cargo.toml b/examples/wgpu-example-shader/Cargo.toml index c07da10088..83f22f96a6 100644 --- a/examples/wgpu-example-shader/Cargo.toml +++ b/examples/wgpu-example-shader/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["dylib"] [dependencies] spirv-std = { path = "../../spirv-std" } +glam = { version = "0.9", default_features = false } \ No newline at end of file diff --git a/examples/wgpu-example-shader/src/lib.rs b/examples/wgpu-example-shader/src/lib.rs index 5b80b99b35..db2cf97cfe 100644 --- a/examples/wgpu-example-shader/src/lib.rs +++ b/examples/wgpu-example-shader/src/lib.rs @@ -3,7 +3,8 @@ #![feature(register_attr)] #![register_attr(spirv)] -use spirv_std::{Input, Output, Vec4}; +use glam::Vec4; +use spirv_std::{Input, Output}; #[allow(unused_attributes)] #[spirv(fragment)] diff --git a/rustc_codegen_spirv/src/codegen_cx/constant.rs b/rustc_codegen_spirv/src/codegen_cx/constant.rs index b8d730d33f..06d682e9e4 100644 --- a/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -11,7 +11,6 @@ use rustc_middle::ty::layout::TyAndLayout; use rustc_mir::interpret::Scalar; use rustc_span::symbol::Symbol; use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Primitive, Size}; -use std::ops::Range; impl<'tcx> CodegenCx<'tcx> { pub fn constant_u8(&self, val: u8) -> SpirvValue { @@ -405,7 +404,6 @@ impl<'tcx> CodegenCx<'tcx> { "create_const_alloc must consume all bytes of an Allocation after an unsized struct" ); } - Self::assert_uninit(alloc, base, *offset, occupied_spaces); self.constant_composite(ty, values) } SpirvType::Opaque { name } => self.tcx.sess.fatal(&format!( @@ -508,21 +506,4 @@ impl<'tcx> CodegenCx<'tcx> { *offset += Size::from_bytes(len); Pointer::new_with_tag(alloc_id, Size::from_bytes(inner_offset), ()) } - - fn assert_uninit( - alloc: &Allocation, - start: Size, - end: Size, - occupied_ranges: Vec>, - ) { - // Range doesn't impl Iterator, so manually do it. - let mut index = start; - while index < end { - assert_eq!( - occupied_ranges.iter().any(|range| range.contains(&index)), - alloc.init_mask().get(index) - ); - index += Size::from_bytes(1); - } - } } diff --git a/spirv-std/src/lib.rs b/spirv-std/src/lib.rs index 3dac209fec..1d11d35892 100644 --- a/spirv-std/src/lib.rs +++ b/spirv-std/src/lib.rs @@ -11,7 +11,6 @@ clippy::enum_glob_use, clippy::pub_enum_variant_names, clippy::mem_forget, - clippy::use_self, clippy::filter_map_next, clippy::needless_continue, clippy::needless_borrow, @@ -37,9 +36,8 @@ nonstandard_style )] -pub mod math; -pub use crate::math::MathExt; -pub use crate::math::*; +mod math_ext; +pub use math_ext::MathExt; macro_rules! pointer_addrspace_write { (false) => {}; diff --git a/spirv-std/src/math/mat2.rs b/spirv-std/src/math/mat2.rs deleted file mode 100644 index f2aa7913b3..0000000000 --- a/spirv-std/src/math/mat2.rs +++ /dev/null @@ -1,242 +0,0 @@ -use super::{Vec2, Vec4}; -use core::ops::{Add, Mul, Sub}; - -/// Creates a `Mat2` from two column vectors. -#[inline] -pub fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 { - Mat2::from_cols(x_axis, y_axis) -} - -/// A 2x2 column major matrix. -#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] -pub struct Mat2(pub Vec4); - -impl Default for Mat2 { - #[inline] - fn default() -> Self { - Self::identity() - } -} - -impl Mat2 { - /// Creates a 2x2 matrix with all elements set to `0.0`. - #[inline] - pub const fn zero() -> Self { - Self(Vec4::zero()) - } - - /// Creates a 2x2 identity matrix. - #[inline] - pub const fn identity() -> Self { - Self(Vec4::new(1.0, 0.0, 0.0, 1.0)) - } - - /// Creates a 2x2 matrix from two column vectors. - #[inline] - pub fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self { - Self(Vec4::new(x_axis.x(), x_axis.y(), y_axis.x(), y_axis.y())) - } - - /// Creates a 2x2 matrix from a `[f32; 4]` stored in column major order. If - /// your data is stored in row major you will need to `transpose` the - /// returned matrix. - #[inline] - pub fn from_cols_array(m: &[f32; 4]) -> Self { - Self(Vec4::new(m[0], m[1], m[2], m[3])) - } - - /// Creates a `[f32; 4]` storing data in column major order. - /// If you require data in row major order `transpose` the matrix first. - #[inline] - pub fn to_cols_array(&self) -> [f32; 4] { - self.0.into() - } - - /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` stored in column major - /// order. If your data is in row major order you will need to `transpose` - /// the returned matrix. - #[inline] - pub fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self { - Self(Vec4::new(m[0][0], m[0][1], m[1][0], m[1][1])) - } - - /// Creates a `[[f32; 2]; 2]` storing data in column major order. - /// If you require data in row major order `transpose` the matrix first. - #[inline] - pub fn to_cols_array_2d(&self) -> [[f32; 2]; 2] { - let (x0, y0, x1, y1) = self.0.into(); - [[x0, y0], [x1, y1]] - } - - /// Creates a 2x2 matrix containing the given non-uniform `scale`. - #[inline] - pub fn from_scale(scale: Vec2) -> Self { - let (x, y) = scale.into(); - Self(Vec4::new(x, 0.0, 0.0, y)) - } - - /// Sets the first column, the `x` axis. - #[inline] - pub fn set_x_axis(&mut self, x: Vec2) { - (self.0).0 = x.x(); - (self.0).1 = x.y(); - } - - /// Sets the second column, the `y` axis. - #[inline] - pub fn set_y_axis(&mut self, y: Vec2) { - (self.0).2 = y.x(); - (self.0).3 = y.y(); - } - - /// Returns the first column, the `x` axis. - #[inline] - pub fn x_axis(&self) -> Vec2 { - let (x, y, _, _) = self.0.into(); - Vec2::new(x, y) - } - - /// Returns the second column, the `y` axis. - #[inline] - pub fn y_axis(&self) -> Vec2 { - let (_, _, x, y) = self.0.into(); - Vec2::new(x, y) - } - - // #[inline] - // pub(crate) fn col(&self, index: usize) -> Vec2 { - // match index { - // 0 => self.x_axis(), - // 1 => self.y_axis(), - // _ => panic!( - // "index out of bounds: the len is 2 but the index is {}", - // index - // ), - // } - // } - - // #[inline] - // pub(crate) fn col_mut(&mut self, index: usize) -> &mut Vec2 { - // match index { - // 0 => unsafe { &mut *(self.0.as_mut().as_mut_ptr() as *mut Vec2) }, - // 1 => unsafe { &mut *(self.0.as_mut()[2..].as_mut_ptr() as *mut Vec2) }, - // _ => panic!( - // "index out of bounds: the len is 2 but the index is {}", - // index - // ), - // } - // } - - /// Returns the transpose of `self`. - #[inline] - pub fn transpose(&self) -> Self { - let (m00, m01, m10, m11) = self.0.into(); - Self(Vec4::new(m00, m10, m01, m11)) - } - - /// Returns the determinant of `self`. - #[inline] - pub fn determinant(&self) -> f32 { - let (a, b, c, d) = self.0.into(); - a * d - b * c - } - - /// Returns the inverse of `self`. - /// - /// If the matrix is not invertible the returned matrix will be invalid. - #[inline] - pub fn inverse(&self) -> Self { - let (a, b, c, d) = self.0.into(); - let det = a * d - b * c; - let tmp = Vec4::new(1.0, -1.0, -1.0, 1.0) / det; - Self(Vec4::new(d, b, c, a) * tmp) - } - - /// Transforms a `Vec2`. - #[inline] - pub fn mul_vec2(&self, other: Vec2) -> Vec2 { - // TODO: SSE2 - let other = Vec4::new(other.x(), other.x(), other.y(), other.y()); - let tmp = self.0 * other; - let (x0, y0, x1, y1) = tmp.into(); - Vec2::new(x0 + x1, y0 + y1) - } - - /// Multiplies two 2x2 matrices. - #[inline] - pub fn mul_mat2(&self, other: &Self) -> Self { - // TODO: SSE2 - let (x0, y0, x1, y1) = other.0.into(); - Self::from_cols( - self.mul_vec2(Vec2::new(x0, y0)), - self.mul_vec2(Vec2::new(x1, y1)), - ) - } - - /// Adds two 2x2 matrices. - #[inline] - pub fn add_mat2(&self, other: &Self) -> Self { - Self(self.0 + other.0) - } - - /// Subtracts two 2x2 matrices. - #[inline] - pub fn sub_mat2(&self, other: &Self) -> Self { - Self(self.0 - other.0) - } - - /// Multiplies a 2x2 matrix by a scalar. - #[inline] - pub fn mul_scalar(&self, other: f32) -> Self { - let s = Vec4::splat(other); - Self(self.0 * s) - } -} - -impl Add for Mat2 { - type Output = Self; - #[inline] - fn add(self, other: Self) -> Self { - self.add_mat2(&other) - } -} - -impl Sub for Mat2 { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - self.sub_mat2(&other) - } -} - -impl Mul for Mat2 { - type Output = Self; - #[inline] - fn mul(self, other: Self) -> Self { - self.mul_mat2(&other) - } -} - -impl Mul for Mat2 { - type Output = Vec2; - #[inline] - fn mul(self, other: Vec2) -> Vec2 { - self.mul_vec2(other) - } -} - -impl Mul for f32 { - type Output = Mat2; - #[inline] - fn mul(self, other: Mat2) -> Mat2 { - other.mul_scalar(self) - } -} - -impl Mul for Mat2 { - type Output = Self; - #[inline] - fn mul(self, other: f32) -> Self { - self.mul_scalar(other) - } -} diff --git a/spirv-std/src/math/mat3.rs b/spirv-std/src/math/mat3.rs deleted file mode 100644 index 3af4e8bc08..0000000000 --- a/spirv-std/src/math/mat3.rs +++ /dev/null @@ -1,320 +0,0 @@ -use super::Vec3; -use core::ops::{Add, Mul, Sub}; - -/// Creates a `Mat3` from three column vectors. -#[inline] -pub fn mat3(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Mat3 { - Mat3 { - x_axis, - y_axis, - z_axis, - } -} - -/// A 3x3 column major matrix. -#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] -pub struct Mat3 { - pub x_axis: Vec3, - pub y_axis: Vec3, - pub z_axis: Vec3, -} - -impl Default for Mat3 { - #[inline] - fn default() -> Self { - Self::identity() - } -} - -impl Mat3 { - /// Creates a 3x3 matrix with all elements set to `0.0`. - #[inline] - pub const fn zero() -> Self { - Self { - x_axis: Vec3::zero(), - y_axis: Vec3::zero(), - z_axis: Vec3::zero(), - } - } - - /// Creates a 3x3 identity matrix. - #[inline] - pub const fn identity() -> Self { - Self { - x_axis: Vec3::new(1.0, 0.0, 0.0), - y_axis: Vec3::new(0.0, 1.0, 0.0), - z_axis: Vec3::new(0.0, 0.0, 1.0), - } - } - - /// Creates a 3x3 matrix from three column vectors. - #[inline] - pub fn from_cols(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self { - Self { - x_axis, - y_axis, - z_axis, - } - } - - /// Creates a 3x3 matrix from a `[f32; 9]` stored in column major order. - /// If your data is stored in row major you will need to `transpose` the - /// returned matrix. - #[inline] - pub fn from_cols_array(m: &[f32; 9]) -> Self { - Self { - x_axis: Vec3::new(m[0], m[1], m[2]), - y_axis: Vec3::new(m[3], m[4], m[5]), - z_axis: Vec3::new(m[6], m[7], m[8]), - } - } - - /// Creates a `[f32; 9]` storing data in column major order. - /// If you require data in row major order `transpose` the matrix first. - #[inline] - pub fn to_cols_array(&self) -> [f32; 9] { - let (m00, m01, m02) = self.x_axis.into(); - let (m10, m11, m12) = self.y_axis.into(); - let (m20, m21, m22) = self.z_axis.into(); - [m00, m01, m02, m10, m11, m12, m20, m21, m22] - } - - /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` stored in column major order. - /// If your data is in row major order you will need to `transpose` the - /// returned matrix. - #[inline] - pub fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self { - Self { - x_axis: m[0].into(), - y_axis: m[1].into(), - z_axis: m[2].into(), - } - } - - /// Creates a `[[f32; 3]; 3]` storing data in column major order. - /// If you require data in row major order `transpose` the matrix first. - #[inline] - pub fn to_cols_array_2d(&self) -> [[f32; 3]; 3] { - [self.x_axis.into(), self.y_axis.into(), self.z_axis.into()] - } - - /// Creates a 3x3 non-uniform scale matrix. - #[inline] - pub fn from_scale(scale: Vec3) -> Self { - // TODO: should have a affine 2D scale and a 3d scale? - // Do not panic as long as any component is non-zero - let (x, y, z) = scale.into(); - Self { - x_axis: Vec3::new(x, 0.0, 0.0), - y_axis: Vec3::new(0.0, y, 0.0), - z_axis: Vec3::new(0.0, 0.0, z), - } - } - - /// Sets the first column, the `x` axis. - #[inline] - pub fn set_x_axis(&mut self, x: Vec3) { - self.x_axis = x; - } - - /// Sets the second column, the `y` axis. - #[inline] - pub fn set_y_axis(&mut self, y: Vec3) { - self.y_axis = y; - } - - /// Sets the third column, the `z` axis. - #[inline] - pub fn set_z_axis(&mut self, z: Vec3) { - self.z_axis = z; - } - - /// Returns the first column, the `x` axis. - #[inline] - pub fn x_axis(&self) -> Vec3 { - self.x_axis - } - - /// Returns the second column, the `y` axis. - #[inline] - pub fn y_axis(&self) -> Vec3 { - self.y_axis - } - - /// Returns the third column, the `z` axis. - #[inline] - pub fn z_axis(&self) -> Vec3 { - self.z_axis - } - - /// Returns a mutable reference to the first column, the `x` axis. - #[inline] - pub fn x_axis_mut(&mut self) -> &mut Vec3 { - &mut self.x_axis - } - - /// Returns a mutable reference to the second column, the `y` axis. - #[inline] - pub fn y_axis_mut(&mut self) -> &mut Vec3 { - &mut self.y_axis - } - - /// Returns a mutable reference to the third column, the `z` axis. - #[inline] - pub fn z_axis_mut(&mut self) -> &mut Vec3 { - &mut self.z_axis - } - - // #[inline] - // pub(crate) fn col(&self, index: usize) -> Vec3 { - // match index { - // 0 => self.x_axis, - // 1 => self.y_axis, - // 2 => self.z_axis, - // _ => panic!( - // "index out of bounds: the len is 3 but the index is {}", - // index - // ), - // } - // } - - // #[inline] - // pub(crate) fn col_mut(&mut self, index: usize) -> &mut Vec3 { - // match index { - // 0 => &mut self.x_axis, - // 1 => &mut self.y_axis, - // 2 => &mut self.z_axis, - // _ => panic!( - // "index out of bounds: the len is 3 but the index is {}", - // index - // ), - // } - // } - - /// Returns the transpose of `self`. - #[inline] - pub fn transpose(&self) -> Self { - Self { - x_axis: Vec3::new(self.x_axis.0, self.y_axis.0, self.z_axis.0), - y_axis: Vec3::new(self.x_axis.1, self.y_axis.1, self.z_axis.1), - z_axis: Vec3::new(self.x_axis.2, self.y_axis.2, self.z_axis.2), - } - } - - /// Returns the determinant of `self`. - #[inline] - pub fn determinant(&self) -> f32 { - self.z_axis.dot(self.x_axis.cross(self.y_axis)) - } - - /// Returns the inverse of `self`. - /// - /// If the matrix is not invertible the returned matrix will be invalid. - pub fn inverse(&self) -> Self { - let tmp0 = self.y_axis.cross(self.z_axis); - let tmp1 = self.z_axis.cross(self.x_axis); - let tmp2 = self.x_axis.cross(self.y_axis); - let det = self.z_axis.dot_as_vec3(tmp2); - let inv_det = det.recip(); - // TODO: Work out if it's possible to get rid of the transpose - Self::from_cols(tmp0 * inv_det, tmp1 * inv_det, tmp2 * inv_det).transpose() - } - - /// Multiplies two 3x3 matrices. - #[inline] - pub fn mul_mat3(&self, other: &Self) -> Self { - Self { - x_axis: self.mul_vec3(other.x_axis), - y_axis: self.mul_vec3(other.y_axis), - z_axis: self.mul_vec3(other.z_axis), - } - } - - /// Adds two 3x3 matrices. - #[inline] - pub fn add_mat3(&self, other: &Self) -> Self { - Self { - x_axis: self.x_axis + other.x_axis, - y_axis: self.y_axis + other.y_axis, - z_axis: self.z_axis + other.z_axis, - } - } - - /// Subtracts two 3x3 matrices. - #[inline] - pub fn sub_mat3(&self, other: &Self) -> Self { - Self { - x_axis: self.x_axis - other.x_axis, - y_axis: self.y_axis - other.y_axis, - z_axis: self.z_axis - other.z_axis, - } - } - - /// Transforms a `Vec3`. - #[inline] - pub fn mul_vec3(&self, other: Vec3) -> Vec3 { - let mut res = self.x_axis * Vec3::splat(other.x()); - res = self.y_axis.mul_add(Vec3::splat(other.y()), res); - res = self.z_axis.mul_add(Vec3::splat(other.z()), res); - res - } - - #[inline] - /// Multiplies a 3x3 matrix by a scalar. - pub fn mul_scalar(&self, other: f32) -> Self { - let s = Vec3::splat(other); - Self { - x_axis: self.x_axis * s, - y_axis: self.y_axis * s, - z_axis: self.z_axis * s, - } - } -} - -impl Add for Mat3 { - type Output = Self; - #[inline] - fn add(self, other: Self) -> Self { - self.add_mat3(&other) - } -} - -impl Sub for Mat3 { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - self.sub_mat3(&other) - } -} - -impl Mul for Mat3 { - type Output = Self; - #[inline] - fn mul(self, other: Self) -> Self { - self.mul_mat3(&other) - } -} - -impl Mul for Mat3 { - type Output = Vec3; - #[inline] - fn mul(self, other: Vec3) -> Vec3 { - self.mul_vec3(other) - } -} - -impl Mul for f32 { - type Output = Mat3; - #[inline] - fn mul(self, other: Mat3) -> Mat3 { - other.mul_scalar(self) - } -} - -impl Mul for Mat3 { - type Output = Self; - #[inline] - fn mul(self, other: f32) -> Self { - self.mul_scalar(other) - } -} diff --git a/spirv-std/src/math/mat4.rs b/spirv-std/src/math/mat4.rs deleted file mode 100644 index e3412c604a..0000000000 --- a/spirv-std/src/math/mat4.rs +++ /dev/null @@ -1,464 +0,0 @@ -use super::{Vec3, Vec4}; -use core::ops::{Add, Mul, Sub}; - -/// Creates a `Mat4` from four column vectors. -#[inline] -pub fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 { - Mat4 { - x_axis, - y_axis, - z_axis, - w_axis, - } -} - -/// A 4x4 column major matrix. -/// -/// This type is 16 byte aligned. -#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)] -pub struct Mat4 { - pub x_axis: Vec4, - pub y_axis: Vec4, - pub z_axis: Vec4, - pub w_axis: Vec4, -} - -impl Default for Mat4 { - #[inline] - fn default() -> Self { - Self::identity() - } -} - -impl Mat4 { - /// Creates a 4x4 matrix with all elements set to `0.0`. - #[inline] - pub const fn zero() -> Self { - Self { - x_axis: Vec4::zero(), - y_axis: Vec4::zero(), - z_axis: Vec4::zero(), - w_axis: Vec4::zero(), - } - } - - /// Creates a 4x4 identity matrix. - #[inline] - pub const fn identity() -> Self { - Self { - x_axis: Vec4::new(1.0, 0.0, 0.0, 0.0), - y_axis: Vec4::new(0.0, 1.0, 0.0, 0.0), - z_axis: Vec4::new(0.0, 0.0, 1.0, 0.0), - w_axis: Vec4::new(0.0, 0.0, 0.0, 1.0), - } - } - - /// Creates a 4x4 matrix from four column vectors. - #[inline] - pub fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self { - Self { - x_axis, - y_axis, - z_axis, - w_axis, - } - } - - /// Creates a 4x4 matrix from a `[f32; 16]` stored in column major order. - /// If your data is stored in row major you will need to `transpose` the - /// returned matrix. - #[inline] - pub fn from_cols_array(m: &[f32; 16]) -> Self { - Self { - x_axis: Vec4::new(m[0], m[1], m[2], m[3]), - y_axis: Vec4::new(m[4], m[5], m[6], m[7]), - z_axis: Vec4::new(m[8], m[9], m[10], m[11]), - w_axis: Vec4::new(m[12], m[13], m[14], m[15]), - } - } - - /// Creates a `[f32; 16]` storing data in column major order. - /// If you require data in row major order `transpose` the matrix first. - #[inline] - pub fn to_cols_array(&self) -> [f32; 16] { - *self.as_ref() - } - - /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` stored in column major - /// order. If your data is in row major order you will need to `transpose` - /// the returned matrix. - #[inline] - pub fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self { - Self { - x_axis: m[0].into(), - y_axis: m[1].into(), - z_axis: m[2].into(), - w_axis: m[3].into(), - } - } - - /// Creates a `[[f32; 4]; 4]` storing data in column major order. - /// If you require data in row major order `transpose` the matrix first. - #[inline] - pub fn to_cols_array_2d(&self) -> [[f32; 4]; 4] { - [ - self.x_axis.into(), - self.y_axis.into(), - self.z_axis.into(), - self.w_axis.into(), - ] - } - - /// Creates a 4x4 homogeneous transformation matrix from the given `translation`. - #[inline] - pub fn from_translation(translation: Vec3) -> Self { - Self { - x_axis: Vec4::unit_x(), - y_axis: Vec4::unit_y(), - z_axis: Vec4::unit_z(), - w_axis: translation.extend(1.0), - } - } - - /// Creates a 4x4 homogeneous transformation matrix containing the given - /// non-uniform `scale`. - #[inline] - pub fn from_scale(scale: Vec3) -> Self { - // Do not panic as long as any component is non-zero - let (x, y, z) = scale.into(); - Self { - x_axis: Vec4::new(x, 0.0, 0.0, 0.0), - y_axis: Vec4::new(0.0, y, 0.0, 0.0), - z_axis: Vec4::new(0.0, 0.0, z, 0.0), - w_axis: Vec4::unit_w(), - } - } - - /// Sets the first column, the `x` axis. - #[inline] - pub fn set_x_axis(&mut self, x: Vec4) { - self.x_axis = x; - } - - /// Sets the second column, the `y` axis. - #[inline] - pub fn set_y_axis(&mut self, y: Vec4) { - self.y_axis = y; - } - - /// Sets the third column, the `z` axis. - #[inline] - pub fn set_z_axis(&mut self, z: Vec4) { - self.z_axis = z; - } - - /// Sets the fourth column, the `w` axis. - #[inline] - pub fn set_w_axis(&mut self, w: Vec4) { - self.w_axis = w; - } - - /// Returns the first column, the `x` axis. - #[inline] - pub fn x_axis(&self) -> Vec4 { - self.x_axis - } - - /// Returns the second column, the `y` axis. - #[inline] - pub fn y_axis(&self) -> Vec4 { - self.y_axis - } - - /// Returns the third column, the `z` axis. - #[inline] - pub fn z_axis(&self) -> Vec4 { - self.z_axis - } - - /// Returns the fourth column, the `w` axis. - #[inline] - pub fn w_axis(&self) -> Vec4 { - self.w_axis - } - - /// Returns a mutable reference to the first column, the `x` axis. - #[inline] - pub fn x_axis_mut(&mut self) -> &mut Vec4 { - &mut self.x_axis - } - - /// Returns a mutable reference to the second column, the `y` axis. - #[inline] - pub fn y_axis_mut(&mut self) -> &mut Vec4 { - &mut self.y_axis - } - - /// Returns a mutable reference to the third column, the `z` axis. - #[inline] - pub fn z_axis_mut(&mut self) -> &mut Vec4 { - &mut self.z_axis - } - - /// Returns a mutable reference to the fourth column, the `w` axis. - #[inline] - pub fn w_axis_mut(&mut self) -> &mut Vec4 { - &mut self.w_axis - } - - // #[inline] - // pub(crate) fn col(&self, index: usize) -> Vec4 { - // match index { - // 0 => self.x_axis, - // 1 => self.y_axis, - // 2 => self.z_axis, - // 3 => self.w_axis, - // _ => panic!( - // "index out of bounds: the len is 4 but the index is {}", - // index - // ), - // } - // } - - // #[inline] - // pub(crate) fn col_mut(&mut self, index: usize) -> &mut Vec4 { - // match index { - // 0 => &mut self.x_axis, - // 1 => &mut self.y_axis, - // 2 => &mut self.z_axis, - // 3 => &mut self.w_axis, - // _ => panic!( - // "index out of bounds: the len is 4 but the index is {}", - // index - // ), - // } - // } - - /// Returns the transpose of `self`. - #[inline] - pub fn transpose(&self) -> Self { - let (m00, m01, m02, m03) = self.x_axis.into(); - let (m10, m11, m12, m13) = self.y_axis.into(); - let (m20, m21, m22, m23) = self.z_axis.into(); - let (m30, m31, m32, m33) = self.w_axis.into(); - - Self { - x_axis: Vec4::new(m00, m10, m20, m30), - y_axis: Vec4::new(m01, m11, m21, m31), - z_axis: Vec4::new(m02, m12, m22, m32), - w_axis: Vec4::new(m03, m13, m23, m33), - } - } - - /// Returns the determinant of `self`. - #[inline] - pub fn determinant(&self) -> f32 { - let (m00, m01, m02, m03) = self.x_axis.into(); - let (m10, m11, m12, m13) = self.y_axis.into(); - let (m20, m21, m22, m23) = self.z_axis.into(); - let (m30, m31, m32, m33) = self.w_axis.into(); - - let a2323 = m22 * m33 - m23 * m32; - let a1323 = m21 * m33 - m23 * m31; - let a1223 = m21 * m32 - m22 * m31; - let a0323 = m20 * m33 - m23 * m30; - let a0223 = m20 * m32 - m22 * m30; - let a0123 = m20 * m31 - m21 * m30; - - m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223) - - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223) - + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123) - - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123) - } - - /// Returns the inverse of `self`. - /// - /// If the matrix is not invertible the returned matrix will be invalid. - pub fn inverse(&self) -> Self { - let (m00, m01, m02, m03) = self.x_axis.into(); - let (m10, m11, m12, m13) = self.y_axis.into(); - let (m20, m21, m22, m23) = self.z_axis.into(); - let (m30, m31, m32, m33) = self.w_axis.into(); - - let coef00 = m22 * m33 - m32 * m23; - let coef02 = m12 * m33 - m32 * m13; - let coef03 = m12 * m23 - m22 * m13; - - let coef04 = m21 * m33 - m31 * m23; - let coef06 = m11 * m33 - m31 * m13; - let coef07 = m11 * m23 - m21 * m13; - - let coef08 = m21 * m32 - m31 * m22; - let coef10 = m11 * m32 - m31 * m12; - let coef11 = m11 * m22 - m21 * m12; - - let coef12 = m20 * m33 - m30 * m23; - let coef14 = m10 * m33 - m30 * m13; - let coef15 = m10 * m23 - m20 * m13; - - let coef16 = m20 * m32 - m30 * m22; - let coef18 = m10 * m32 - m30 * m12; - let coef19 = m10 * m22 - m20 * m12; - - let coef20 = m20 * m31 - m30 * m21; - let coef22 = m10 * m31 - m30 * m11; - let coef23 = m10 * m21 - m20 * m11; - - let fac0 = Vec4::new(coef00, coef00, coef02, coef03); - let fac1 = Vec4::new(coef04, coef04, coef06, coef07); - let fac2 = Vec4::new(coef08, coef08, coef10, coef11); - let fac3 = Vec4::new(coef12, coef12, coef14, coef15); - let fac4 = Vec4::new(coef16, coef16, coef18, coef19); - let fac5 = Vec4::new(coef20, coef20, coef22, coef23); - - let vec0 = Vec4::new(m10, m00, m00, m00); - let vec1 = Vec4::new(m11, m01, m01, m01); - let vec2 = Vec4::new(m12, m02, m02, m02); - let vec3 = Vec4::new(m13, m03, m03, m03); - - let inv0 = vec1 * fac0 - vec2 * fac1 + vec3 * fac2; - let inv1 = vec0 * fac0 - vec2 * fac3 + vec3 * fac4; - let inv2 = vec0 * fac1 - vec1 * fac3 + vec3 * fac5; - let inv3 = vec0 * fac2 - vec1 * fac4 + vec2 * fac5; - - let sign_a = Vec4::new(1.0, -1.0, 1.0, -1.0); - let sign_b = Vec4::new(-1.0, 1.0, -1.0, 1.0); - - let inverse = Self { - x_axis: inv0 * sign_a, - y_axis: inv1 * sign_b, - z_axis: inv2 * sign_a, - w_axis: inv3 * sign_b, - }; - - let col0 = Vec4::new( - inverse.x_axis.x(), - inverse.y_axis.x(), - inverse.z_axis.x(), - inverse.w_axis.x(), - ); - - let dot0 = self.x_axis * col0; - let dot1 = dot0.x() + dot0.y() + dot0.z() + dot0.w(); - - let rcp_det = 1.0 / dot1; - inverse * rcp_det - } - - /// Transforms a 4D vector. - #[inline] - pub fn mul_vec4(&self, other: Vec4) -> Vec4 { - let mut res = self.x_axis * other.dup_x(); - res = self.y_axis.mul_add(other.dup_y(), res); - res = self.z_axis.mul_add(other.dup_z(), res); - res = self.w_axis.mul_add(other.dup_w(), res); - res - } - - /// Multiplies two 4x4 matrices. - #[inline] - pub fn mul_mat4(&self, other: &Self) -> Self { - Self { - x_axis: self.mul_vec4(other.x_axis), - y_axis: self.mul_vec4(other.y_axis), - z_axis: self.mul_vec4(other.z_axis), - w_axis: self.mul_vec4(other.w_axis), - } - } - - /// Adds two 4x4 matrices. - #[inline] - pub fn add_mat4(&self, other: &Self) -> Self { - Self { - x_axis: self.x_axis + other.x_axis, - y_axis: self.y_axis + other.y_axis, - z_axis: self.z_axis + other.z_axis, - w_axis: self.w_axis + other.w_axis, - } - } - - /// Subtracts two 4x4 matrices. - #[inline] - pub fn sub_mat4(&self, other: &Self) -> Self { - Self { - x_axis: self.x_axis - other.x_axis, - y_axis: self.y_axis - other.y_axis, - z_axis: self.z_axis - other.z_axis, - w_axis: self.w_axis - other.w_axis, - } - } - - /// Multiplies this matrix by a scalar value. - #[inline] - pub fn mul_scalar(&self, other: f32) -> Self { - let s = Vec4::splat(other); - Self { - x_axis: self.x_axis * s, - y_axis: self.y_axis * s, - z_axis: self.z_axis * s, - w_axis: self.w_axis * s, - } - } -} - -impl AsRef<[f32; 16]> for Mat4 { - #[inline] - fn as_ref(&self) -> &[f32; 16] { - unsafe { &*(self as *const Self as *const [f32; 16]) } - } -} - -impl AsMut<[f32; 16]> for Mat4 { - #[inline] - fn as_mut(&mut self) -> &mut [f32; 16] { - unsafe { &mut *(self as *mut Self as *mut [f32; 16]) } - } -} - -impl Add for Mat4 { - type Output = Self; - #[inline] - fn add(self, other: Self) -> Self { - self.add_mat4(&other) - } -} - -impl Sub for Mat4 { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - self.sub_mat4(&other) - } -} - -impl Mul for Mat4 { - type Output = Self; - #[inline] - fn mul(self, other: Self) -> Self { - self.mul_mat4(&other) - } -} - -impl Mul for Mat4 { - type Output = Vec4; - #[inline] - fn mul(self, other: Vec4) -> Vec4 { - self.mul_vec4(other) - } -} - -impl Mul for f32 { - type Output = Mat4; - #[inline] - fn mul(self, other: Mat4) -> Mat4 { - other.mul_scalar(self) - } -} - -impl Mul for Mat4 { - type Output = Self; - #[inline] - fn mul(self, other: f32) -> Self { - self.mul_scalar(other) - } -} diff --git a/spirv-std/src/math/mod.rs b/spirv-std/src/math/mod.rs deleted file mode 100644 index 766fb72f62..0000000000 --- a/spirv-std/src/math/mod.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! This math library is heavily borrowed from [glam](https://github.com/bitshifter/glam-rs) -//! In the future we hope to be able to use it directly! - -pub mod mat2; -pub mod mat3; -pub mod mat4; -pub mod vec2; -pub mod vec3; -pub mod vec4; -pub use mat2::*; -pub use mat3::*; -pub use mat4::*; -pub use vec2::*; -pub use vec3::*; -pub use vec4::*; - -pub trait MathExt { - fn pow(self, factor: Self) -> Self; - fn sqrt(self) -> Self; - fn log2(self) -> Self; - fn abs(self) -> Self; - fn cos(self) -> Self; - fn round(self) -> Self; - fn floor(self) -> Self; - fn ceil(self) -> Self; - fn exp(self) -> Self; - fn saturate(self) -> Self; -} - -#[allow(clippy::use_self)] -impl MathExt for f32 { - fn pow(self, factor: Self) -> Self { - unsafe { core::intrinsics::powf32(self, factor) } - } - - fn sqrt(self) -> Self { - unsafe { core::intrinsics::sqrtf32(self) } - } - - fn log2(self) -> Self { - unsafe { core::intrinsics::log2f32(self) } - } - - fn abs(self) -> Self { - unsafe { core::intrinsics::fabsf32(self) } - } - - fn cos(self) -> Self { - unsafe { core::intrinsics::cosf32(self) } - } - - fn round(self) -> Self { - unsafe { core::intrinsics::roundf32(self) } - } - - fn floor(self) -> Self { - unsafe { core::intrinsics::floorf32(self) } - } - - fn ceil(self) -> Self { - unsafe { core::intrinsics::ceilf32(self) } - } - - fn exp(self) -> Self { - unsafe { core::intrinsics::expf32(self) } - } - - fn saturate(self) -> Self { - self.max(0.0).min(1.0) - } -} diff --git a/spirv-std/src/math/vec2.rs b/spirv-std/src/math/vec2.rs deleted file mode 100644 index 7217726ac0..0000000000 --- a/spirv-std/src/math/vec2.rs +++ /dev/null @@ -1,409 +0,0 @@ -use super::Vec3; -use crate::math::MathExt; -use core::{f32, ops::*}; - -/// A 2-dimensional vector. -#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default)] -#[repr(simd)] -pub struct Vec2(pub f32, pub f32); - -/// Creates a `Vec2`. -#[inline] -pub fn vec2(x: f32, y: f32) -> Vec2 { - Vec2(x, y) -} - -impl Vec2 { - #[deprecated(since = "0.9.5", note = "please use `Vec2::recip` instead")] - #[inline(always)] - pub fn reciprocal(self) -> Self { - self.recip() - } - - /// Returns a `Vec2` containing the reciprocal `1.0/n` of each element of `self`. - #[inline] - pub fn recip(self) -> Self { - Self(self.0.recip(), self.1.recip()) - } - - /// Performs a linear interpolation between `self` and `other` based on - /// the value `s`. - /// - /// When `s` is `0.0`, the result will be equal to `self`. When `s` - /// is `1.0`, the result will be equal to `other`. - #[inline] - pub fn lerp(self, other: Self, s: f32) -> Self { - self + ((other - self) * s) - } - - /// Creates a new `Vec2`. - #[inline] - pub fn new(x: f32, y: f32) -> Self { - Self(x, y) - } - - /// Creates a `Vec2` with all elements set to `0.0`. - #[inline] - pub fn zero() -> Self { - Self::splat(0.0) - } - - /// Creates a `Vec2` with all elements set to `1.0`. - #[inline] - pub fn one() -> Self { - Self::splat(1.0) - } - - /// Creates a `Vec2` with values `[x: 1.0, y: 0.0]`. - #[inline] - pub fn unit_x() -> Self { - Self::new(1.0, 0.0) - } - - /// Creates a `Vec2` with values `[x: 0.0, y: 1.0]`. - #[inline] - pub fn unit_y() -> Self { - Self::new(0.0, 1.0) - } - - /// Creates a `Vec2` with all elements set to `v`. - #[inline] - pub fn splat(v: f32) -> Self { - Self(v, v) - } - - /// Creates a `Vec3` from `self` and the given `z` value. - #[inline] - pub fn extend(self, z: f32) -> Vec3 { - Vec3::new(self.0, self.1, z) - } - - /// Returns element `x`. - #[inline] - pub fn x(self) -> f32 { - self.0 - } - - /// Returns element `y`. - #[inline] - pub fn y(self) -> f32 { - self.1 - } - - /// Returns a mutable reference to element `x`. - #[inline] - pub fn x_mut(&mut self) -> &mut f32 { - &mut self.0 - } - - /// Returns a mutable reference to element `y`. - #[inline] - pub fn y_mut(&mut self) -> &mut f32 { - &mut self.1 - } - - /// Sets element `x`. - #[inline] - pub fn set_x(&mut self, x: f32) { - self.0 = x; - } - - /// Sets element `y`. - #[inline] - pub fn set_y(&mut self, y: f32) { - self.1 = y; - } - - /// Computes the dot product of `self` and `other`. - #[inline] - pub fn dot(self, other: Self) -> f32 { - (self.0 * other.0) + (self.1 * other.1) - } - - /// Computes the length of `self`. - #[inline] - pub fn length(self) -> f32 { - self.dot(self).sqrt() - } - - /// Computes the squared length of `self`. - /// - /// This is generally faster than `Vec2::length()` as it avoids a square - /// root operation. - #[inline] - pub fn length_squared(self) -> f32 { - self.dot(self) - } - - #[deprecated(since = "0.9.5", note = "please use `Vec2::length_recip` instead")] - #[inline(always)] - pub fn length_reciprocal(self) -> f32 { - self.length_recip() - } - - /// Computes `1.0 / Vec2::length()`. - /// - /// For valid results, `self` must _not_ be of length zero. - #[inline] - pub fn length_recip(self) -> f32 { - self.length().recip() - } - - /// Returns `self` normalized to length 1.0. - /// - /// For valid results, `self` must _not_ be of length zero. - #[inline] - pub fn normalize(self) -> Self { - self * self.length_recip() - } - - /// Returns the vertical minimum of `self` and `other`. - /// - /// In other words, this computes - /// `[x: min(x1, x2), y: min(y1, y2)]`, - /// taking the minimum of each element individually. - #[inline] - pub fn min(self, other: Self) -> Self { - Self(self.0.min(other.0), self.1.min(other.1)) - } - - /// Returns the vertical maximum of `self` and `other`. - /// - /// In other words, this computes - /// `[x: max(x1, x2), y: max(y1, y2)]`, - /// taking the maximum of each element individually. - #[inline] - pub fn max(self, other: Self) -> Self { - Self(self.0.max(other.0), self.1.max(other.1)) - } - - /// Returns the horizontal minimum of `self`'s elements. - /// - /// In other words, this computes `min(x, y)`. - #[inline] - pub fn min_element(self) -> f32 { - self.0.min(self.1) - } - - /// Returns the horizontal maximum of `self`'s elements. - /// - /// In other words, this computes `max(x, y)`. - #[inline] - pub fn max_element(self) -> f32 { - self.0.max(self.1) - } - - /// Creates a `Vec2` from the first two values in `slice`. - /// - /// # Panics - /// - /// Panics if `slice` is less than two elements long. - #[inline] - pub fn from_slice_unaligned(slice: &[f32]) -> Self { - Self(slice[0], slice[1]) - } - - /// Writes the elements of `self` to the first two elements in `slice`. - /// - /// # Panics - /// - /// Panics if `slice` is less than two elements long. - #[inline] - pub fn write_to_slice_unaligned(self, slice: &mut [f32]) { - slice[0] = self.0; - slice[1] = self.1; - } - - /// Returns a `Vec2` containing the absolute value of each element of `self`. - #[inline] - pub fn abs(self) -> Self { - Self(self.0.abs(), self.1.abs()) - } - - /// Returns a `Vec2` containing the nearest integer to a number for each element of `self`. - /// Round half-way cases away from 0.0. - #[inline] - pub fn round(self) -> Self { - Self(self.0.round(), self.1.round()) - } - - /// Returns a `Vec2` containing the largest integer less than or equal to a number for each - /// element of `self`. - #[inline] - pub fn floor(self) -> Self { - Self(self.0.floor(), self.1.floor()) - } - - /// Returns a `Vec2` containing this vector raised to the power of `power` - #[inline] - pub fn pow(self, power: f32) -> Self { - Self(self.0.pow(power), self.1.pow(power)) - } - - /// Returns a `Vec2` containing this vector exp'd - #[inline] - pub fn exp(self) -> Self { - Self(self.0.exp(), self.1.exp()) - } - - /// Returns a `Vec2` containing the smallest integer greater than or equal to a number for each - /// element of `self`. - #[inline] - pub fn ceil(self) -> Self { - Self(self.0.ceil(), self.1.ceil()) - } - - /// The perpendicular dot product of the vector and `other`. - #[inline] - pub fn perp_dot(self, other: Self) -> f32 { - (self.0 * other.1) - (self.1 * other.0) - } -} - -impl Div for Vec2 { - type Output = Self; - #[inline] - fn div(self, other: Self) -> Self { - Self(self.0 / other.0, self.1 / other.1) - } -} - -impl DivAssign for Vec2 { - #[inline] - fn div_assign(&mut self, other: Self) { - self.0 /= other.0; - self.1 /= other.1; - } -} - -impl Div for Vec2 { - type Output = Self; - #[inline] - fn div(self, other: f32) -> Self { - Self(self.0 / other, self.1 / other) - } -} - -impl DivAssign for Vec2 { - #[inline] - fn div_assign(&mut self, other: f32) { - self.0 /= other; - self.1 /= other; - } -} - -impl Div for f32 { - type Output = Vec2; - #[inline] - fn div(self, other: Vec2) -> Vec2 { - Vec2(self / other.0, self / other.1) - } -} - -impl Mul for Vec2 { - type Output = Self; - #[inline] - fn mul(self, other: Self) -> Self { - Self(self.0 * other.0, self.1 * other.1) - } -} - -impl MulAssign for Vec2 { - #[inline] - fn mul_assign(&mut self, other: Self) { - self.0 *= other.0; - self.1 *= other.1; - } -} - -impl Mul for Vec2 { - type Output = Self; - #[inline] - fn mul(self, other: f32) -> Self { - Self(self.0 * other, self.1 * other) - } -} - -impl MulAssign for Vec2 { - #[inline] - fn mul_assign(&mut self, other: f32) { - self.0 *= other; - self.1 *= other; - } -} - -impl Mul for f32 { - type Output = Vec2; - #[inline] - fn mul(self, other: Vec2) -> Vec2 { - Vec2(self * other.0, self * other.1) - } -} - -impl Add for Vec2 { - type Output = Self; - #[inline] - fn add(self, other: Self) -> Self { - Self(self.0 + other.0, self.1 + other.1) - } -} - -impl AddAssign for Vec2 { - #[inline] - fn add_assign(&mut self, other: Self) { - self.0 += other.0; - self.1 += other.1; - } -} - -impl Sub for Vec2 { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - Self(self.0 - other.0, self.1 - other.1) - } -} - -impl SubAssign for Vec2 { - #[inline] - fn sub_assign(&mut self, other: Self) { - self.0 -= other.0; - self.1 -= other.1; - } -} - -impl Neg for Vec2 { - type Output = Self; - #[inline] - fn neg(self) -> Self { - Self(-self.0, -self.1) - } -} - -impl From<(f32, f32)> for Vec2 { - #[inline] - fn from(t: (f32, f32)) -> Self { - Self(t.0, t.1) - } -} - -impl From for (f32, f32) { - #[inline] - fn from(v: Vec2) -> Self { - (v.0, v.1) - } -} - -impl From<[f32; 2]> for Vec2 { - #[inline] - fn from(a: [f32; 2]) -> Self { - Self(a[0], a[1]) - } -} - -impl From for [f32; 2] { - #[inline] - fn from(v: Vec2) -> Self { - [v.0, v.1] - } -} diff --git a/spirv-std/src/math/vec3.rs b/spirv-std/src/math/vec3.rs deleted file mode 100644 index 4f3fe24571..0000000000 --- a/spirv-std/src/math/vec3.rs +++ /dev/null @@ -1,510 +0,0 @@ -use super::{Vec2, Vec4}; -use crate::math::MathExt; -use core::ops::*; - -/// A 3-dimensional vector without SIMD support. -#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default)] -#[repr(simd)] -pub struct Vec3(pub f32, pub f32, pub f32); - -/// Creates a `Vec3`. -#[inline] -pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 { - Vec3::new(x, y, z) -} - -impl Vec3 { - /// Creates a new `Vec3`. - #[inline] - pub const fn new(x: f32, y: f32, z: f32) -> Self { - Self(x, y, z) - } - - /// Creates a `Vec3` with all elements set to `0.0`. - #[inline] - pub const fn zero() -> Self { - Self::splat(0.0) - } - - /// Creates a `Vec3` with all elements set to `1.0`. - #[inline] - pub const fn one() -> Self { - Self::splat(1.0) - } - - /// Creates a `Vec3` with values `[x: 1.0, y: 0.0, z: 0.0]`. - #[inline] - pub const fn unit_x() -> Self { - Self::new(1.0, 0.0, 0.0) - } - - /// Creates a `Vec3` with values `[x: 0.0, y: 1.0, z: 0.0]`. - #[inline] - pub const fn unit_y() -> Self { - Self::new(0.0, 1.0, 0.0) - } - - /// Creates a `Vec3` with values `[x: 0.0, y: 0.0, z: 1.0]`. - #[inline] - pub const fn unit_z() -> Self { - Self::new(0.0, 0.0, 1.0) - } - - /// Creates a `Vec3` with all elements set to `v`. - #[inline] - pub const fn splat(v: f32) -> Self { - Self(v, v, v) - } - - /// Creates a `Vec4` from `self` and the given `w` value. - #[inline] - pub fn extend(self, w: f32) -> Vec4 { - Vec4::new(self.0, self.1, self.2, w) - } - - /// Creates a `Vec2` from the first three elements of `self`, - /// removing `z`. - #[inline] - pub fn truncate(self) -> Vec2 { - Vec2::new(self.0, self.1) - } - - /// Returns element `x`. - #[inline] - pub fn x(self) -> f32 { - self.0 - } - - /// Returns element `y`. - #[inline] - pub fn y(self) -> f32 { - self.1 - } - - /// Returns element `z`. - #[inline] - pub fn z(self) -> f32 { - self.2 - } - - /// Returns a mutable reference to element `x`. - #[inline] - pub fn x_mut(&mut self) -> &mut f32 { - &mut self.0 - } - - /// Returns a mutable reference to element `y`. - #[inline] - pub fn y_mut(&mut self) -> &mut f32 { - &mut self.1 - } - - /// Returns a mutable reference to element `z`. - #[inline] - pub fn z_mut(&mut self) -> &mut f32 { - &mut self.2 - } - - /// Sets element `x`. - #[inline] - pub fn set_x(&mut self, x: f32) { - self.0 = x; - } - - /// Sets element `y`. - #[inline] - pub fn set_y(&mut self, y: f32) { - self.1 = y; - } - - /// Sets element `z`. - #[inline] - pub fn set_z(&mut self, z: f32) { - self.2 = z; - } - - /// Returns a `Vec3` with all elements set to the value of element `x`. - #[inline] - #[allow(dead_code)] - pub(crate) fn dup_x(self) -> Self { - Self(self.0, self.0, self.0) - } - - /// Returns a `Vec3` with all elements set to the value of element `y`. - #[inline] - #[allow(dead_code)] - pub(crate) fn dup_y(self) -> Self { - Self(self.1, self.1, self.1) - } - - /// Returns a `Vec3` with all elements set to the value of element `z`. - #[inline] - #[allow(dead_code)] - pub(crate) fn dup_z(self) -> Self { - Self(self.2, self.2, self.2) - } - - /// Computes the dot product of `self` and `other`. - #[inline] - pub fn dot(self, other: Self) -> f32 { - (self.0 * other.0) + (self.1 * other.1) + (self.2 * other.2) - } - - /// Returns Vec3 dot in all lanes of Vec3 - #[inline] - #[allow(dead_code)] - pub(crate) fn dot_as_vec3(self, other: Self) -> Self { - let dot = self.dot(other); - Self::new(dot, dot, dot) - } - - /// Computes the cross product of `self` and `other`. - #[inline] - pub fn cross(self, other: Self) -> Self { - Self( - self.1 * other.2 - other.1 * self.2, - self.2 * other.0 - other.2 * self.0, - self.0 * other.1 - other.0 * self.1, - ) - } - - /// Computes the length of `self`. - #[inline] - pub fn length(self) -> f32 { - self.dot(self).sqrt() - } - - /// Computes the squared length of `self`. - /// - /// This is generally faster than `Vec3::length()` as it avoids a square - /// root operation. - #[inline] - pub fn length_squared(self) -> f32 { - self.dot(self) - } - - #[deprecated(since = "0.9.5", note = "please use `Vec3::length_recip` instead")] - #[inline(always)] - pub fn length_reciprocal(self) -> f32 { - self.length_recip() - } - - /// Computes `1.0 / Vec3::length()`. - /// - /// For valid results, `self` must _not_ be of length zero. - #[inline] - pub fn length_recip(self) -> f32 { - self.length().recip() - } - - /// Returns `self` normalized to length 1.0. - /// - /// For valid results, `self` must _not_ be of length zero. - #[inline] - pub fn normalize(self) -> Self { - self * self.length_recip() - } - - /// Returns the vertical minimum of `self` and `other`. - /// - /// In other words, this computes - /// `[x: min(x1, x2), y: min(y1, y2), z: min(z1, z2)]`, - /// taking the minimum of each element individually. - #[inline] - pub fn min(self, other: Self) -> Self { - Self( - self.0.min(other.0), - self.1.min(other.1), - self.2.min(other.2), - ) - } - - /// Returns the vertical maximum of `self` and `other`. - /// - /// In other words, this computes - /// `[x: max(x1, x2), y: max(y1, y2), z: max(z1, z2)]`, - /// taking the maximum of each element individually. - #[inline] - pub fn max(self, other: Self) -> Self { - Self( - self.0.max(other.0), - self.1.max(other.1), - self.2.max(other.2), - ) - } - - /// Returns the horizontal minimum of `self`'s elements. - /// - /// In other words, this computes `min(x, y, z)`. - #[inline] - pub fn min_element(self) -> f32 { - self.0.min(self.1.min(self.2)) - } - - /// Returns the horizontal maximum of `self`'s elements. - /// - /// In other words, this computes `max(x, y, z)`. - #[inline] - pub fn max_element(self) -> f32 { - self.0.max(self.1.max(self.2)) - } - - /// Creates a `Vec3` from the first three values in `slice`. - /// - /// # Panics - /// - /// Panics if `slice` is less than three elements long. - #[inline] - pub fn from_slice_unaligned(slice: &[f32]) -> Self { - Self::new(slice[0], slice[1], slice[2]) - } - - /// Writes the elements of `self` to the first three elements in `slice`. - /// - /// # Panics - /// - /// Panics if `slice` is less than three elements long. - #[inline] - pub fn write_to_slice_unaligned(self, slice: &mut [f32]) { - slice[0] = self.0; - slice[1] = self.1; - slice[2] = self.2; - } - - /// Per element multiplication/addition of the three inputs: b + (self * a) - #[inline] - #[allow(dead_code)] - pub(crate) fn mul_add(self, a: Self, b: Self) -> Self { - Self( - (self.0 * a.0) + b.0, - (self.1 * a.1) + b.1, - (self.2 * a.2) + b.2, - ) - } - - /// Returns a `Vec3` containing the absolute value of each element of `self`. - #[inline] - pub fn abs(self) -> Self { - Self(self.0.abs(), self.1.abs(), self.2.abs()) - } - - /// Returns a `Vec3` containing the nearest integer to a number for each element of `self`. - /// Round half-way cases away from 0.0. - #[inline] - pub fn round(self) -> Self { - Self(self.0.round(), self.1.round(), self.2.round()) - } - - /// Returns a `Vec3` containing the largest integer less than or equal to a number for each - /// element of `self`. - #[inline] - pub fn floor(self) -> Self { - Self(self.0.floor(), self.1.floor(), self.2.floor()) - } - - /// Returns a `Vec3` containing this vector raised to the power of `power` - #[inline] - pub fn pow(self, power: f32) -> Self { - Self(self.0.pow(power), self.1.pow(power), self.2.pow(power)) - } - - /// Returns a `Vec3` containing this vector exp'd - #[inline] - pub fn exp(self) -> Self { - Self(self.0.exp(), self.1.exp(), self.2.exp()) - } - - /// Returns a `Vec3` containing the smallest integer greater than or equal to a number for each - /// element of `self`. - #[inline] - pub fn ceil(self) -> Self { - Self(self.0.ceil(), self.1.ceil(), self.2.ceil()) - } - - #[deprecated(since = "0.9.5", note = "please use `Vec3::recip` instead")] - #[inline(always)] - pub fn reciprocal(self) -> Self { - self.recip() - } - - /// Returns a `Vec3` containing the reciprocal `1.0/n` of each element of `self`. - #[inline] - pub fn recip(self) -> Self { - Self(self.0.recip(), self.1.recip(), self.2.recip()) - } - - /// Performs a linear interpolation between `self` and `other` based on - /// the value `s`. - /// - /// When `s` is `0.0`, the result will be equal to `self`. When `s` - /// is `1.0`, the result will be equal to `other`. - #[inline] - pub fn lerp(self, other: Self, s: f32) -> Self { - self + ((other - self) * s) - } -} - -impl Div for Vec3 { - type Output = Self; - #[inline] - fn div(self, other: Self) -> Self { - Self(self.0 / other.0, self.1 / other.1, self.2 / other.2) - } -} - -impl DivAssign for Vec3 { - #[inline] - fn div_assign(&mut self, other: Self) { - self.0 /= other.0; - self.1 /= other.1; - self.2 /= other.2; - } -} - -impl Div for Vec3 { - type Output = Self; - #[inline] - fn div(self, other: f32) -> Self { - Self(self.0 / other, self.1 / other, self.2 / other) - } -} - -impl DivAssign for Vec3 { - #[inline] - fn div_assign(&mut self, other: f32) { - self.0 /= other; - self.1 /= other; - self.2 /= other; - } -} - -impl Div for f32 { - type Output = Vec3; - #[inline] - fn div(self, other: Vec3) -> Vec3 { - Vec3(self / other.0, self / other.1, self / other.2) - } -} - -impl Mul for Vec3 { - type Output = Self; - #[inline] - fn mul(self, other: Self) -> Self { - Self(self.0 * other.0, self.1 * other.1, self.2 * other.2) - } -} - -impl MulAssign for Vec3 { - #[inline] - fn mul_assign(&mut self, other: Self) { - self.0 *= other.0; - self.1 *= other.1; - self.2 *= other.2; - } -} - -impl Mul for Vec3 { - type Output = Self; - #[inline] - fn mul(self, other: f32) -> Self { - Self(self.0 * other, self.1 * other, self.2 * other) - } -} - -impl MulAssign for Vec3 { - #[inline] - fn mul_assign(&mut self, other: f32) { - self.0 *= other; - self.1 *= other; - self.2 *= other; - } -} - -impl Mul for f32 { - type Output = Vec3; - #[inline] - fn mul(self, other: Vec3) -> Vec3 { - Vec3(self * other.0, self * other.1, self * other.2) - } -} - -impl Add for Vec3 { - type Output = Self; - #[inline] - fn add(self, other: Self) -> Self { - Self(self.0 + other.0, self.1 + other.1, self.2 + other.2) - } -} - -impl AddAssign for Vec3 { - #[inline] - fn add_assign(&mut self, other: Self) { - self.0 += other.0; - self.1 += other.1; - self.2 += other.2; - } -} - -impl Sub for Vec3 { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - Self(self.0 - other.0, self.1 - other.1, self.2 - other.2) - } -} - -impl SubAssign for Vec3 { - #[inline] - fn sub_assign(&mut self, other: Self) { - self.0 -= other.0; - self.1 -= other.1; - self.2 -= other.2; - } -} - -impl Neg for Vec3 { - type Output = Self; - #[inline] - fn neg(self) -> Self { - Self(-self.0, -self.1, -self.2) - } -} - -impl From<(f32, f32, f32)> for Vec3 { - #[inline] - fn from(t: (f32, f32, f32)) -> Self { - Self::new(t.0, t.1, t.2) - } -} - -impl From for (f32, f32, f32) { - #[inline] - fn from(v: Vec3) -> Self { - (v.0, v.1, v.2) - } -} - -impl From<[f32; 3]> for Vec3 { - #[inline] - fn from(a: [f32; 3]) -> Self { - Self::new(a[0], a[1], a[2]) - } -} - -impl From for [f32; 3] { - #[inline] - fn from(v: Vec3) -> Self { - [v.0, v.1, v.2] - } -} - -#[test] -fn test_vec3_private() { - assert_eq!( - vec3(1.0, 1.0, 1.0).mul_add(vec3(0.5, 2.0, -4.0), vec3(-1.0, -1.0, -1.0)), - vec3(-0.5, 1.0, -5.0) - ); - assert_eq!(vec3(1.0, 2.0, 3.0).dup_x(), vec3(1.0, 1.0, 1.0)); - assert_eq!(vec3(1.0, 2.0, 3.0).dup_y(), vec3(2.0, 2.0, 2.0)); - assert_eq!(vec3(1.0, 2.0, 3.0).dup_z(), vec3(3.0, 3.0, 3.0)); -} diff --git a/spirv-std/src/math/vec4.rs b/spirv-std/src/math/vec4.rs deleted file mode 100644 index 8d7c51e733..0000000000 --- a/spirv-std/src/math/vec4.rs +++ /dev/null @@ -1,619 +0,0 @@ -use crate::math::{MathExt, Vec3}; -use core::{f32, ops::*}; - -/// A 4-dimensional vector. -/// -/// A 4-dimensional vector. -/// -/// This type is 16 byte aligned unless the `scalar-math` feature is enabed. -#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Default)] -// if compiling with simd enabled assume alignment needs to match the simd type -#[repr(simd)] -pub struct Vec4(pub f32, pub f32, pub f32, pub f32); - -/// Creates a `Vec4`. -#[inline] -pub fn vec4(x: f32, y: f32, z: f32, w: f32) -> Vec4 { - Vec4::new(x, y, z, w) -} - -impl Vec4 { - /// Creates a new `Vec4`. - #[inline] - pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self { - Self(x, y, z, w) - } - - /// Creates a `Vec4` with all elements set to `0.0`. - #[inline] - pub const fn zero() -> Self { - Self::splat(0.0) - } - - /// Creates a `Vec4` with all elements set to `1.0`. - #[inline] - pub const fn one() -> Self { - Self::splat(1.0) - } - - /// Creates a `Vec4` with values `[x: 1.0, y: 0.0, z: 0.0, w: 0.0]`. - #[inline] - pub const fn unit_x() -> Self { - Self::new(1.0, 0.0, 0.0, 0.0) - } - - /// Creates a `Vec4` with values `[x: 0.0, y: 1.0, z: 0.0, w: 0.0]`. - #[inline] - pub const fn unit_y() -> Self { - Self::new(0.0, 1.0, 0.0, 0.0) - } - - /// Creates a `Vec4` with values `[x: 0.0, y: 0.0, z: 1.0, w: 0.0]`. - #[inline] - pub const fn unit_z() -> Self { - Self::new(0.0, 0.0, 1.0, 0.0) - } - - /// Creates a `Vec4` with values `[x: 0.0, y: 0.0, z: 0.0, w: 1.0]`. - #[inline] - pub const fn unit_w() -> Self { - Self::new(0.0, 0.0, 0.0, 1.0) - } - - /// Creates a `Vec4` with all elements set to `v`. - #[inline] - pub const fn splat(v: f32) -> Self { - Self(v, v, v, v) - } - - /// Creates a `Vec3` from the first three elements of `self`, - /// removing `w`. - #[inline] - pub fn truncate(self) -> Vec3 { - Vec3::new(self.0, self.1, self.2) - } - - /// Returns element `x`. - #[inline] - pub fn x(self) -> f32 { - self.0 - } - - /// Returns element `y`. - #[inline] - pub fn y(self) -> f32 { - self.1 - } - - /// Returns element `z`. - #[inline] - pub fn z(self) -> f32 { - self.2 - } - - /// Returns element `w`. - #[inline] - pub fn w(self) -> f32 { - self.3 - } - - /// Returns a mutable reference to element `x`. - #[inline] - pub fn x_mut(&mut self) -> &mut f32 { - &mut self.0 - } - - /// Returns a mutable reference to element `y`. - #[inline] - pub fn y_mut(&mut self) -> &mut f32 { - &mut self.1 - } - - /// Returns a mutable reference to element `z`. - #[inline] - pub fn z_mut(&mut self) -> &mut f32 { - &mut self.2 - } - - /// Returns a mutable reference to element `w`. - #[inline] - pub fn w_mut(&mut self) -> &mut f32 { - &mut self.3 - } - - /// Sets element `x`. - #[inline] - pub fn set_x(&mut self, x: f32) { - self.0 = x; - } - - /// Sets element `y`. - #[inline] - pub fn set_y(&mut self, y: f32) { - self.1 = y; - } - - /// Sets element `z`. - #[inline] - pub fn set_z(&mut self, z: f32) { - self.2 = z; - } - - /// Sets element `w`. - #[inline] - pub fn set_w(&mut self, w: f32) { - self.3 = w; - } - - /// Returns a `Vec4` with all elements set to the value of element `x`. - #[inline] - pub fn dup_x(self) -> Self { - Self(self.0, self.0, self.0, self.0) - } - - /// Returns a `Vec4` with all elements set to the value of element `y`. - #[inline] - pub fn dup_y(self) -> Self { - Self(self.1, self.1, self.1, self.1) - } - - /// Returns a `Vec4` with all elements set to the value of element `z`. - #[inline] - pub fn dup_z(self) -> Self { - Self(self.2, self.2, self.2, self.2) - } - - /// Returns a `Vec4` with all elements set to the value of element `w`. - #[inline] - pub fn dup_w(self) -> Self { - Self(self.3, self.3, self.3, self.3) - } - - /// Computes the 4D dot product of `self` and `other`. - #[inline] - pub fn dot(self, other: Self) -> f32 { - (self.0 * other.0) + (self.1 * other.1) + (self.2 * other.2) + (self.3 * other.3) - } - - /// Computes the 4D length of `self`. - #[inline] - pub fn length(self) -> f32 { - self.dot(self).sqrt() - } - - /// Computes the squared 4D length of `self`. - /// - /// This is generally faster than `Vec4::length()` as it avoids a square - /// root operation. - #[inline] - pub fn length_squared(self) -> f32 { - self.dot(self) - } - - #[deprecated(since = "0.9.5", note = "please use `Vec4::length_recip` instead")] - #[inline(always)] - pub fn length_reciprocal(self) -> f32 { - self.length_recip() - } - - /// Computes `1.0 / Vec4::length()`. - /// - /// For valid results, `self` must _not_ be of length zero. - #[inline] - pub fn length_recip(self) -> f32 { - self.length().recip() - } - - /// Returns `self` normalized to length 1.0. - /// - /// For valid results, `self` must _not_ be of length zero. - #[inline] - pub fn normalize(self) -> Self { - self * self.length_recip() - } - - /// Returns the vertical minimum of `self` and `other`. - /// - /// In other words, this computes - /// `[x: min(x1, x2), y: min(y1, y2), z: min(z1, z2), w: min(w1, w2)]`, - /// taking the minimum of each element individually. - #[inline] - pub fn min(self, other: Self) -> Self { - Self( - self.0.min(other.0), - self.1.min(other.1), - self.2.min(other.2), - self.3.min(other.3), - ) - } - - /// Returns the vertical maximum of `self` and `other`. - /// - /// In other words, this computes - /// `[x: max(x1, x2), y: max(y1, y2), z: max(z1, z2), w: max(w1, w2)]`, - /// taking the maximum of each element individually. - #[inline] - pub fn max(self, other: Self) -> Self { - Self( - self.0.max(other.0), - self.1.max(other.1), - self.2.max(other.2), - self.3.max(other.3), - ) - } - - /// Returns the horizontal minimum of `self`'s elements. - /// - /// In other words, this computes `min(x, y, z, w)`. - #[inline] - pub fn min_element(self) -> f32 { - self.0.min(self.1.min(self.2.min(self.3))) - } - - /// Returns the horizontal maximum of `self`'s elements. - /// - /// In other words, this computes `max(x, y, z, w)`. - #[inline] - pub fn max_element(self) -> f32 { - self.0.max(self.1.max(self.2.min(self.3))) - } - - /// Creates a `Vec4` from the first four values in `slice`. - /// - /// # Panics - /// - /// Panics if `slice` is less than four elements long. - #[inline] - pub fn from_slice_unaligned(slice: &[f32]) -> Self { - Self(slice[0], slice[1], slice[2], slice[3]) - } - - /// Writes the elements of `self` to the first four elements in `slice`. - /// - /// # Panics - /// - /// Panics if `slice` is less than four elements long. - #[inline] - pub fn write_to_slice_unaligned(self, slice: &mut [f32]) { - slice[0] = self.0; - slice[1] = self.1; - slice[2] = self.2; - slice[3] = self.3; - } - - /// Per element multiplication/addition of the three inputs: b + (self * a) - #[inline] - pub fn mul_add(self, a: Self, b: Self) -> Self { - Self( - (self.0 * a.0) + b.0, - (self.1 * a.1) + b.1, - (self.2 * a.2) + b.2, - (self.3 * a.3) + b.3, - ) - } - - /// Returns a `Vec4` containing the absolute value of each element of `self`. - #[inline] - pub fn abs(self) -> Self { - Self(self.0.abs(), self.1.abs(), self.2.abs(), self.3.abs()) - } - - /// Returns a `Vec4` containing the nearest integer to a number for each element of `self`. - /// Round half-way cases away from 0.0. - #[inline] - pub fn round(self) -> Self { - Self( - self.0.round(), - self.1.round(), - self.2.round(), - self.3.round(), - ) - } - - /// Returns a `Vec4` containing the largest integer less than or equal to a number for each - /// element of `self`. - #[inline] - pub fn floor(self) -> Self { - Self( - self.0.floor(), - self.1.floor(), - self.2.floor(), - self.3.floor(), - ) - } - - /// Returns a `Vec4` containing this vector raised to the power of `power` - #[inline] - pub fn pow(self, power: f32) -> Self { - Self( - self.0.pow(power), - self.1.pow(power), - self.2.pow(power), - self.3.pow(power), - ) - } - - /// Returns a `Vec4` containing this vector exp'd - #[inline] - pub fn exp(self) -> Self { - Self(self.0.exp(), self.1.exp(), self.2.exp(), self.3.exp()) - } - - /// Returns a `Vec4` containing the smallest integer greater than or equal to a number for each - /// element of `self`. - #[inline] - pub fn ceil(self) -> Self { - Self(self.0.ceil(), self.1.ceil(), self.2.ceil(), self.3.ceil()) - } - - #[deprecated(since = "0.9.5", note = "please use `Vec4::recip` instead")] - #[inline(always)] - pub fn reciprocal(self) -> Self { - self.recip() - } - - /// Returns a `Vec4` containing the reciprocal `1.0/n` of each element of `self`. - #[inline] - pub fn recip(self) -> Self { - // TODO: Optimize - Self::one() / self - } - - /// Performs a linear interpolation between `self` and `other` based on - /// the value `s`. - /// - /// When `s` is `0.0`, the result will be equal to `self`. When `s` - /// is `1.0`, the result will be equal to `other`. - #[inline] - pub fn lerp(self, other: Self, s: f32) -> Self { - self + ((other - self) * s) - } -} - -impl Div for Vec4 { - type Output = Self; - #[inline] - fn div(self, other: Self) -> Self { - { - Self( - self.0 / other.0, - self.1 / other.1, - self.2 / other.2, - self.3 / other.3, - ) - } - } -} - -impl DivAssign for Vec4 { - #[inline] - fn div_assign(&mut self, other: Self) { - { - self.0 /= other.0; - self.1 /= other.1; - self.2 /= other.2; - self.3 /= other.3; - } - } -} - -impl Div for Vec4 { - type Output = Self; - #[inline] - fn div(self, other: f32) -> Self { - { - Self( - self.0 / other, - self.1 / other, - self.2 / other, - self.3 / other, - ) - } - } -} - -impl DivAssign for Vec4 { - #[inline] - fn div_assign(&mut self, other: f32) { - { - self.0 /= other; - self.1 /= other; - self.2 /= other; - self.3 /= other; - } - } -} - -impl Div for f32 { - type Output = Vec4; - #[inline] - fn div(self, other: Vec4) -> Vec4 { - { - Vec4( - self / other.0, - self / other.1, - self / other.2, - self / other.3, - ) - } - } -} - -impl Mul for Vec4 { - type Output = Self; - #[inline] - fn mul(self, other: Self) -> Self { - { - Self( - self.0 * other.0, - self.1 * other.1, - self.2 * other.2, - self.3 * other.3, - ) - } - } -} - -impl MulAssign for Vec4 { - #[inline] - fn mul_assign(&mut self, other: Self) { - { - self.0 *= other.0; - self.1 *= other.1; - self.2 *= other.2; - self.3 *= other.3; - } - } -} - -impl Mul for Vec4 { - type Output = Self; - #[inline] - fn mul(self, other: f32) -> Self { - { - Self( - self.0 * other, - self.1 * other, - self.2 * other, - self.3 * other, - ) - } - } -} - -impl MulAssign for Vec4 { - #[inline] - fn mul_assign(&mut self, other: f32) { - { - self.0 *= other; - self.1 *= other; - self.2 *= other; - self.3 *= other; - } - } -} - -impl Mul for f32 { - type Output = Vec4; - #[inline] - fn mul(self, other: Vec4) -> Vec4 { - { - Vec4( - self * other.0, - self * other.1, - self * other.2, - self * other.3, - ) - } - } -} - -impl Add for Vec4 { - type Output = Self; - #[inline] - fn add(self, other: Self) -> Self { - { - Self( - self.0 + other.0, - self.1 + other.1, - self.2 + other.2, - self.3 + other.3, - ) - } - } -} - -impl AddAssign for Vec4 { - #[inline] - fn add_assign(&mut self, other: Self) { - { - self.0 += other.0; - self.1 += other.1; - self.2 += other.2; - self.3 += other.3; - } - } -} - -impl Sub for Vec4 { - type Output = Self; - #[inline] - fn sub(self, other: Self) -> Self { - { - Self( - self.0 - other.0, - self.1 - other.1, - self.2 - other.2, - self.3 - other.3, - ) - } - } -} - -impl SubAssign for Vec4 { - #[inline] - fn sub_assign(&mut self, other: Self) { - { - self.0 -= other.0; - self.1 -= other.1; - self.2 -= other.2; - self.3 -= other.3; - } - } -} - -impl Neg for Vec4 { - type Output = Self; - #[inline] - fn neg(self) -> Self { - { - Self(-self.0, -self.1, -self.2, -self.3) - } - } -} - -impl From<(f32, f32, f32, f32)> for Vec4 { - #[inline] - fn from(t: (f32, f32, f32, f32)) -> Self { - Self::new(t.0, t.1, t.2, t.3) - } -} - -impl From for (f32, f32, f32, f32) { - #[inline] - fn from(v: Vec4) -> Self { - { - (v.0, v.1, v.2, v.3) - } - } -} - -impl From<[f32; 4]> for Vec4 { - #[inline] - fn from(a: [f32; 4]) -> Self { - { - Self(a[0], a[1], a[2], a[3]) - } - } -} - -impl From for [f32; 4] { - #[inline] - fn from(v: Vec4) -> Self { - { - [v.0, v.1, v.2, v.3] - } - } -} - -#[test] -fn test_vec4_private() { - assert_eq!( - vec4(1.0, 1.0, 1.0, 1.0).mul_add(vec4(0.5, 2.0, -4.0, 0.0), vec4(-1.0, -1.0, -1.0, -1.0)), - vec4(-0.5, 1.0, -5.0, -1.0) - ); - assert_eq!(vec4(1.0, 2.0, 3.0, 4.0).dup_x(), vec4(1.0, 1.0, 1.0, 1.0)); - assert_eq!(vec4(1.0, 2.0, 3.0, 4.0).dup_y(), vec4(2.0, 2.0, 2.0, 2.0)); - assert_eq!(vec4(1.0, 2.0, 3.0, 4.0).dup_z(), vec4(3.0, 3.0, 3.0, 3.0)); - assert_eq!(vec4(1.0, 2.0, 4.0, 4.0).dup_w(), vec4(4.0, 4.0, 4.0, 4.0)); -} diff --git a/spirv-std/src/math_ext.rs b/spirv-std/src/math_ext.rs new file mode 100644 index 0000000000..f196cd086c --- /dev/null +++ b/spirv-std/src/math_ext.rs @@ -0,0 +1,85 @@ +pub trait MathExt { + fn pow(self, factor: Self) -> Self; + fn sqrt(self) -> Self; + fn log2(self) -> Self; + fn abs(self) -> Self; + fn cos(self) -> Self; + fn sin(self) -> Self; + fn sin_cos(self) -> (f32, f32); + fn round(self) -> Self; + fn floor(self) -> Self; + fn ceil(self) -> Self; + fn exp(self) -> Self; + fn saturate(self) -> Self; + + fn signum(self) -> Self; + fn copysign(self, sign: Self) -> Self; + + // TODO: implement but need new intrinsic in core? + //fn tan(self) -> Self; +} + +impl MathExt for f32 { + fn pow(self, factor: f32) -> f32 { + unsafe { core::intrinsics::powf32(self, factor) } + } + + fn sqrt(self) -> f32 { + unsafe { core::intrinsics::sqrtf32(self) } + } + + fn log2(self) -> f32 { + unsafe { core::intrinsics::log2f32(self) } + } + + fn abs(self) -> f32 { + unsafe { core::intrinsics::fabsf32(self) } + } + + fn cos(self) -> f32 { + unsafe { core::intrinsics::cosf32(self) } + } + + fn sin(self) -> f32 { + unsafe { core::intrinsics::sinf32(self) } + } + + // TODO: implement but need new intrinsic in core? + //fn tan(self) -> f32 { + + fn sin_cos(self) -> (f32, f32) { + (self.sin(), self.cos()) + } + + fn round(self) -> f32 { + unsafe { core::intrinsics::roundf32(self) } + } + + fn floor(self) -> f32 { + unsafe { core::intrinsics::floorf32(self) } + } + + fn ceil(self) -> f32 { + unsafe { core::intrinsics::ceilf32(self) } + } + + fn exp(self) -> f32 { + unsafe { core::intrinsics::expf32(self) } + } + + fn saturate(self) -> f32 { + self.max(0.0).min(1.0) + } + + fn signum(self) -> f32 { + if self.is_nan() { + Self::NAN + } else { + 1.0_f32.copysign(self) + } + } + + fn copysign(self, sign: f32) -> f32 { + unsafe { core::intrinsics::copysignf32(self, sign) } + } +}