From 353fa96af6603581d2ddd54465dd29c71d73a14f Mon Sep 17 00:00:00 2001 From: Gray Olson Date: Tue, 24 Nov 2020 02:28:58 -0700 Subject: [PATCH] Rename pow to powf, remove saturate from MathExt, and update to latest glam (#248) * remove saturate from spirv_std MathExt and rename pow to powf * update to latest glam * update glam again and add `std` feature to `spirv-std` to support cpu runner * re-remove spirv-tools-sys submodule * fixup! Merge branch 'main' into powf-saturate * Use libm instead of MathExt * Fix lint for unused import when compiling with std Co-authored-by: khyperia --- Cargo.lock | 13 +++- crates/spirv-std/Cargo.toml | 7 +- crates/spirv-std/src/lib.rs | 4 +- crates/spirv-std/src/math_ext.rs | 95 -------------------------- examples/runners/cpu/Cargo.toml | 2 +- examples/runners/cpu/src/main.rs | 11 ++- examples/shaders/shared/src/lib.rs | 40 ++++------- examples/shaders/sky-shader/src/lib.rs | 43 +++++++++--- setup.bat | 3 - setup.sh | 3 - 10 files changed, 71 insertions(+), 150 deletions(-) delete mode 100644 crates/spirv-std/src/math_ext.rs diff --git a/Cargo.lock b/Cargo.lock index 1c8b69e6dc..10eb8e6d90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -983,9 +983,10 @@ dependencies = [ [[package]] name = "glam" -version = "0.10.0" -source = "git+https://github.com/EmbarkStudios/glam-rs?rev=c9561e4dfd55fa5a9d6838cae3c9e90c8edafaf9#c9561e4dfd55fa5a9d6838cae3c9e90c8edafaf9" +version = "0.10.2" +source = "git+https://github.com/EmbarkStudios/glam-rs?rev=ea8fe2766ca27f481656d3507cc129537e262182#ea8fe2766ca27f481656d3507cc129537e262182" dependencies = [ + "num-traits", "version_check", ] @@ -1124,6 +1125,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "libm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" + [[package]] name = "lock_api" version = "0.4.2" @@ -1424,6 +1431,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg 1.0.1", + "libm", ] [[package]] @@ -2182,6 +2190,7 @@ name = "spirv-std" version = "0.1.0" dependencies = [ "glam", + "num-traits", ] [[package]] diff --git a/crates/spirv-std/Cargo.toml b/crates/spirv-std/Cargo.toml index b7d2572dd1..e10798e956 100644 --- a/crates/spirv-std/Cargo.toml +++ b/crates/spirv-std/Cargo.toml @@ -8,4 +8,9 @@ repository = "https://github.com/EmbarkStudios/rust-gpu" [dependencies] # https://github.com/bitshifter/glam-rs/pull/85 -glam = { git = "https://github.com/EmbarkStudios/glam-rs", rev = "c9561e4dfd55fa5a9d6838cae3c9e90c8edafaf9" } +glam = { git = "https://github.com/EmbarkStudios/glam-rs", rev = "ea8fe2766ca27f481656d3507cc129537e262182", default-features = false, features = ["libm"] } +num-traits = { version = "0.2.14", default-features = false } + +[features] +default = [] +std = ["glam/std"] diff --git a/crates/spirv-std/src/lib.rs b/crates/spirv-std/src/lib.rs index d70e3a64ad..7c9c6b7858 100644 --- a/crates/spirv-std/src/lib.rs +++ b/crates/spirv-std/src/lib.rs @@ -37,10 +37,8 @@ nonstandard_style )] -mod math_ext; -pub use math_ext::MathExt; - pub use glam; +pub use num_traits; macro_rules! pointer_addrspace_write { (false) => {}; diff --git a/crates/spirv-std/src/math_ext.rs b/crates/spirv-std/src/math_ext.rs deleted file mode 100644 index c5b5495d9d..0000000000 --- a/crates/spirv-std/src/math_ext.rs +++ /dev/null @@ -1,95 +0,0 @@ -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 trunc(self) -> Self; - fn fract(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 trunc(self) -> f32 { - unsafe { core::intrinsics::truncf32(self) } - } - - fn fract(self) -> f32 { - self - self.trunc() - } - - 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) } - } -} diff --git a/examples/runners/cpu/Cargo.toml b/examples/runners/cpu/Cargo.toml index a04982c604..948e85a98f 100644 --- a/examples/runners/cpu/Cargo.toml +++ b/examples/runners/cpu/Cargo.toml @@ -11,7 +11,7 @@ minifb = "0.19.1" # bring in the shader as natively compiled code shared = { path = "../../shaders/shared" } sky-shader = { path = "../../shaders/sky-shader" } -spirv-std = { path = "../../../crates/spirv-std" } +spirv-std = { path = "../../../crates/spirv-std", features = ["std"] } # for parallelism, not really needed though rayon = "1.5" diff --git a/examples/runners/cpu/src/main.rs b/examples/runners/cpu/src/main.rs index b613eacd53..99e37c9117 100644 --- a/examples/runners/cpu/src/main.rs +++ b/examples/runners/cpu/src/main.rs @@ -18,10 +18,10 @@ fn srgb_oetf(x: f32) -> f32 { fn color_u32_from_vec4(v: Vec4) -> u32 { let convert = |f: f32| -> u32 { (f.min(1.0).max(0.0) * 255.0).round() as u32 }; - convert(srgb_oetf(v.z())) - | convert(srgb_oetf(v.y())) << 8 - | convert(srgb_oetf(v.x())) << 16 - | convert(v.w()) << 24 + convert(srgb_oetf(v.z)) + | convert(srgb_oetf(v.y)) << 8 + | convert(srgb_oetf(v.x)) << 16 + | convert(v.w) << 24 } fn main() { @@ -55,8 +55,7 @@ fn main() { -((i / WIDTH) as f32 / HEIGHT as f32 * 2.0 - 1.0), ); - let frag_coord = (vec2(screen_pos.x(), -screen_pos.y()) + Vec2::one()) - / Vec2::splat(2.0) + let frag_coord = (vec2(screen_pos.x, -screen_pos.y) + Vec2::one()) / Vec2::splat(2.0) * vec2(WIDTH as f32, HEIGHT as f32); // evaluate the fragment shader for the specific pixel diff --git a/examples/shaders/shared/src/lib.rs b/examples/shaders/shared/src/lib.rs index 7496bd27f4..b1d7df1f69 100644 --- a/examples/shaders/shared/src/lib.rs +++ b/examples/shaders/shared/src/lib.rs @@ -6,8 +6,12 @@ #![register_attr(spirv)] use core::f32::consts::PI; -use spirv_std::glam::{Vec2, Vec3}; -use spirv_std::MathExt; +use spirv_std::glam::Vec3; + +// Note: This cfg is incorrect on its surface, it really should be "are we compiling with std", but +// we tie #[no_std] above to the same condition, so it's fine. +#[cfg(target_arch = "spirv")] +use spirv_std::num_traits::Float; #[derive(Copy, Clone)] pub struct ShaderConstants { @@ -16,14 +20,16 @@ pub struct ShaderConstants { pub time: f32, } -// TODO: add this to glam? Rust std has it on f32/f64 -pub fn pow(v: Vec3, power: f32) -> Vec3 { - Vec3::new(v.x().pow(power), v.y().pow(power), v.z().pow(power)) +pub fn saturate(x: f32) -> f32 { + x.max(0.0).min(1.0) +} + +pub fn pow(v: Vec3, power: f32) -> Vec3 { + Vec3::new(v.x.powf(power), v.y.powf(power), v.z.powf(power)) } -// TODO: add this to glam? Rust std has it on f32/f64 pub fn exp(v: Vec3) -> Vec3 { - Vec3::new(v.x().exp(), v.y().exp(), v.z().exp()) + Vec3::new(v.x.exp(), v.y.exp(), v.z.exp()) } /// Based on: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/ @@ -41,25 +47,7 @@ pub fn acos_approx(v: f32) -> f32 { pub fn smoothstep(edge0: f32, edge1: f32, x: f32) -> f32 { // Scale, bias and saturate x to 0..1 range - let x = ((x - edge0) / (edge1 - edge0)).saturate(); + let x = saturate((x - edge0) / (edge1 - edge0)); // Evaluate polynomial x * x * (3.0 - 2.0 * x) } - -pub fn tonemap(col: Vec3) -> Vec3 { - // see https://www.desmos.com/calculator/0eo9pzo1at - const A: f32 = 2.35; - const B: f32 = 2.8826666; - const C: f32 = 789.7459; - const D: f32 = 0.935; - - let z = pow(col, A); - z / (pow(z, D) * B + Vec3::splat(C)) -} - -pub fn get_ray_dir(uv: Vec2, pos: Vec3, look_at_pos: Vec3) -> Vec3 { - let forward = (look_at_pos - pos).normalize(); - let right = Vec3::new(0.0, 1.0, 0.0).cross(forward).normalize(); - let up = forward.cross(right); - (forward + uv.x() * right + uv.y() * up).normalize() -} diff --git a/examples/shaders/sky-shader/src/lib.rs b/examples/shaders/sky-shader/src/lib.rs index 42875466bb..331196ebaa 100644 --- a/examples/shaders/sky-shader/src/lib.rs +++ b/examples/shaders/sky-shader/src/lib.rs @@ -8,7 +8,12 @@ use core::f32::consts::PI; use shared::*; use spirv_std::glam::{const_vec3, Vec2, Vec3, Vec4}; -use spirv_std::{Input, MathExt, Output, PushConstant}; +use spirv_std::{Input, Output, PushConstant}; + +// Note: This cfg is incorrect on its surface, it really should be "are we compiling with std", but +// we tie #[no_std] above to the same condition, so it's fine. +#[cfg(target_arch = "spirv")] +use spirv_std::num_traits::Float; const DEPOLARIZATION_FACTOR: f32 = 0.035; const MIE_COEFFICIENT: f32 = 0.005; @@ -26,9 +31,20 @@ const SUN_INTENSITY_FACTOR: f32 = 1000.0; const SUN_INTENSITY_FALLOFF_STEEPNESS: f32 = 1.5; const TURBIDITY: f32 = 2.0; +pub fn tonemap(col: Vec3) -> Vec3 { + // see https://www.desmos.com/calculator/0eo9pzo1at + const A: f32 = 2.35; + const B: f32 = 2.8826666; + const C: f32 = 789.7459; + const D: f32 = 0.935; + + let z = pow(col, A); + z / (pow(z, D) * B + Vec3::splat(C)) +} + fn total_rayleigh(lambda: Vec3) -> Vec3 { - (8.0 * PI.pow(3.0) - * (REFRACTIVE_INDEX.pow(2.0) - 1.0).pow(2.0) + (8.0 * PI.powf(3.0) + * (REFRACTIVE_INDEX.powf(2.0) - 1.0).powf(2.0) * (6.0 + 3.0 * DEPOLARIZATION_FACTOR)) / (3.0 * NUM_MOLECULES * pow(lambda, 4.0) * (6.0 - 7.0 * DEPOLARIZATION_FACTOR)) } @@ -39,11 +55,11 @@ fn total_mie(lambda: Vec3, k: Vec3, t: f32) -> Vec3 { } fn rayleigh_phase(cos_theta: f32) -> f32 { - (3.0 / (16.0 * PI)) * (1.0 + cos_theta.pow(2.0)) + (3.0 / (16.0 * PI)) * (1.0 + cos_theta.powf(2.0)) } fn henyey_greenstein_phase(cos_theta: f32, g: f32) -> f32 { - (1.0 / (4.0 * PI)) * ((1.0 - g.pow(2.0)) / (1.0 - 2.0 * g * cos_theta + g.pow(2.0)).pow(1.5)) + (1.0 / (4.0 * PI)) * ((1.0 - g.powf(2.0)) / (1.0 - 2.0 * g * cos_theta + g.powf(2.0)).powf(1.5)) } fn sun_intensity(zenith_angle_cos: f32) -> f32 { @@ -58,7 +74,7 @@ fn sun_intensity(zenith_angle_cos: f32) -> f32 { 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.y() / 450000.0).exp()).saturate(); + let sunfade = 1.0 - (1.0 - saturate(sun_position.y / 450000.0).exp()); let rayleigh_coefficient = RAYLEIGH - (1.0 * (1.0 - sunfade)); let beta_r = total_rayleigh(PRIMARIES) * rayleigh_coefficient; @@ -67,7 +83,7 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { // Optical length, cutoff angle at 90 to avoid singularity let zenith_angle = acos_approx(up.dot(dir).max(0.0)); - let denom = (zenith_angle).cos() + 0.15 * (93.885 - ((zenith_angle * 180.0) / PI)).pow(-1.253); + let denom = (zenith_angle).cos() + 0.15 * (93.885 - ((zenith_angle * 180.0) / PI)).powf(-1.253); let s_r = RAYLEIGH_ZENITH_LENGTH / denom; let s_m = MIE_ZENITH_LENGTH / denom; @@ -92,7 +108,7 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { 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(), + saturate((1.0 - up.dot(sun_direction)).powf(5.0)), ); // Composition + solar disc @@ -108,10 +124,17 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { lin + l0 } +fn get_ray_dir(uv: Vec2, pos: Vec3, look_at_pos: Vec3) -> Vec3 { + let forward = (look_at_pos - pos).normalize(); + let right = Vec3::new(0.0, 1.0, 0.0).cross(forward).normalize(); + let up = forward.cross(right); + (forward + uv.x * right + uv.y * up).normalize() +} + pub fn fs(constants: &ShaderConstants, frag_coord: Vec2) -> Vec4 { let mut uv = (frag_coord - 0.5 * Vec2::new(constants.width as f32, constants.height as f32)) / constants.height as f32; - uv.set_y(-uv.y()); + uv.y = -uv.y; // hard-code information because we can't bind buffers at the moment let eye_pos = Vec3::new(0.0, 0.0997, 0.2); @@ -136,7 +159,7 @@ pub fn main_fs( ) { let constants = constants.load(); - let frag_coord = Vec2::new(in_frag_coord.load().x(), in_frag_coord.load().y()); + let frag_coord = Vec2::new(in_frag_coord.load().x, in_frag_coord.load().y); let color = fs(&constants, frag_coord); output.store(color); } diff --git a/setup.bat b/setup.bat index e7e66ca6be..2345dce20e 100644 --- a/setup.bat +++ b/setup.bat @@ -1,6 +1,3 @@ setlocal rustup toolchain install nightly-2020-11-15 --component rust-src rustc-dev llvm-tools-preview - -git submodule init -git submodule update diff --git a/setup.sh b/setup.sh index ec5fd3602d..ba62358ef0 100755 --- a/setup.sh +++ b/setup.sh @@ -1,6 +1,3 @@ #!/usr/bin/env bash rustup toolchain install nightly-2020-11-15 --component rust-src rustc-dev llvm-tools-preview - -git submodule init -git submodule update