@@ -4,8 +4,8 @@ use arrayvec::ArrayVec;
4
4
5
5
use crate :: {
6
6
arena:: { Arena , Handle , HandleVec , UniqueArena } ,
7
- ArraySize , BinaryOperator , Constant , Expression , Literal , Override , ScalarKind , Span , Type ,
8
- TypeInner , UnaryOperator ,
7
+ ArraySize , BinaryOperator , Constant , Expression , Literal , Override , RelationalFunction ,
8
+ ScalarKind , Span , Type , TypeInner , UnaryOperator ,
9
9
} ;
10
10
11
11
/// A macro that allows dollar signs (`$`) to be emitted by other macros. Useful for generating
@@ -547,6 +547,8 @@ pub enum ConstantEvaluatorError {
547
547
InvalidMathArg ,
548
548
#[ error( "{0:?} built-in function expects {1:?} arguments but {2:?} were supplied" ) ]
549
549
InvalidMathArgCount ( crate :: MathFunction , usize , usize ) ,
550
+ #[ error( "Cannot apply relational function to type" ) ]
551
+ InvalidRelationalArg ( RelationalFunction ) ,
550
552
#[ error( "value of `low` is greater than `high` for clamp built-in function" ) ]
551
553
InvalidClamp ,
552
554
#[ error( "Splat is defined only on scalar values" ) ]
@@ -931,9 +933,10 @@ impl<'a> ConstantEvaluator<'a> {
931
933
Expression :: Select { .. } => Err ( ConstantEvaluatorError :: NotImplemented (
932
934
"select built-in function" . into ( ) ,
933
935
) ) ,
934
- Expression :: Relational { fun, .. } => Err ( ConstantEvaluatorError :: NotImplemented (
935
- format ! ( "{fun:?} built-in function" ) ,
936
- ) ) ,
936
+ Expression :: Relational { fun, argument } => {
937
+ let argument = self . check_and_get ( argument) ?;
938
+ self . relational ( fun, argument, span)
939
+ }
937
940
Expression :: ArrayLength ( expr) => match self . behavior {
938
941
Behavior :: Wgsl ( _) => Err ( ConstantEvaluatorError :: ArrayLength ) ,
939
942
Behavior :: Glsl ( _) => {
@@ -2103,6 +2106,41 @@ impl<'a> ConstantEvaluator<'a> {
2103
2106
Ok ( Expression :: Compose { ty, components } )
2104
2107
}
2105
2108
2109
+ fn relational (
2110
+ & mut self ,
2111
+ fun : RelationalFunction ,
2112
+ arg : Handle < Expression > ,
2113
+ span : Span ,
2114
+ ) -> Result < Handle < Expression > , ConstantEvaluatorError > {
2115
+ let arg = self . eval_zero_value_and_splat ( arg, span) ?;
2116
+ match fun {
2117
+ RelationalFunction :: All | RelationalFunction :: Any => match self . expressions [ arg] {
2118
+ Expression :: Literal ( Literal :: Bool ( _) ) => Ok ( arg) ,
2119
+ Expression :: Compose { ty, ref components }
2120
+ if matches ! ( self . types[ ty] . inner, TypeInner :: Vector { .. } ) =>
2121
+ {
2122
+ let components =
2123
+ crate :: proc:: flatten_compose ( ty, components, self . expressions , self . types )
2124
+ . map ( |component| match self . expressions [ component] {
2125
+ Expression :: Literal ( Literal :: Bool ( val) ) => Ok ( val) ,
2126
+ _ => Err ( ConstantEvaluatorError :: InvalidRelationalArg ( fun) ) ,
2127
+ } )
2128
+ . collect :: < Result < ArrayVec < bool , { crate :: VectorSize :: MAX } > , _ > > ( ) ?;
2129
+ let result = match fun {
2130
+ RelationalFunction :: All => components. iter ( ) . all ( |c| * c) ,
2131
+ RelationalFunction :: Any => components. iter ( ) . any ( |c| * c) ,
2132
+ _ => unreachable ! ( ) ,
2133
+ } ;
2134
+ self . register_evaluated_expr ( Expression :: Literal ( Literal :: Bool ( result) ) , span)
2135
+ }
2136
+ _ => Err ( ConstantEvaluatorError :: InvalidRelationalArg ( fun) ) ,
2137
+ } ,
2138
+ _ => Err ( ConstantEvaluatorError :: NotImplemented ( format ! (
2139
+ "{fun:?} built-in function"
2140
+ ) ) ) ,
2141
+ }
2142
+ }
2143
+
2106
2144
/// Deep copy `expr` from `expressions` into `self.expressions`.
2107
2145
///
2108
2146
/// Return the root of the new copy.
0 commit comments