From 030b924e2a973508abe66a6074fb135c3572c03b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Mon, 11 Apr 2022 22:01:51 +0100 Subject: [PATCH] glsl-in: Add tests for constants NaN handling --- src/front/glsl/constants.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/front/glsl/constants.rs b/src/front/glsl/constants.rs index e537370858..0c7c4ed6ae 100644 --- a/src/front/glsl/constants.rs +++ b/src/front/glsl/constants.rs @@ -234,9 +234,7 @@ impl<'a> ConstantSolver<'a> { ScalarValue::Float(a), ScalarValue::Float(b), ScalarValue::Float(c), - ) => { - ScalarValue::Float(glsl_float_min(glsl_float_max(a, b), c)) - } + ) => ScalarValue::Float(glsl_float_clamp(a, b, c)), _ => return Err(ConstantSolvingError::InvalidMathArg), }, width, @@ -599,6 +597,15 @@ fn glsl_float_min(x: f64, y: f64) -> f64 { } } +/// Helper function to implement the GLSL `clamp` function for floats. +/// +/// While Rust does provide a `f64::clamp` method, it requires a version of rust +/// above our MSRV and it also panics if either `min` or `max` are `NaN`s which +/// is not the behavior specified by the glsl specification. +fn glsl_float_clamp(value: f64, min: f64, max: f64) -> f64 { + glsl_float_min(glsl_float_max(value, min), max) +} + #[cfg(test)] mod tests { use std::vec; @@ -610,6 +617,19 @@ mod tests { use super::ConstantSolver; + #[test] + fn nan_handling() { + assert!(super::glsl_float_max(f64::NAN, 2.0).is_nan()); + assert!(!super::glsl_float_max(2.0, f64::NAN).is_nan()); + + assert!(super::glsl_float_min(f64::NAN, 2.0).is_nan()); + assert!(!super::glsl_float_min(2.0, f64::NAN).is_nan()); + + assert!(super::glsl_float_clamp(f64::NAN, 1.0, 2.0).is_nan()); + assert!(!super::glsl_float_clamp(1.0, f64::NAN, 2.0).is_nan()); + assert!(!super::glsl_float_clamp(1.0, 2.0, f64::NAN).is_nan()); + } + #[test] fn unary_op() { let mut types = UniqueArena::new();