1 #[cfg(feature = "validate")] 2 use super::{compose::validate_compose, FunctionInfo, ShaderStages, TypeFlags}; 3 #[cfg(feature = "validate")] 4 use crate::arena::UniqueArena; 5 6 use crate::{ 7 arena::Handle, 8 proc::{ProcError, ResolveError}, 9 }; 10 11 #[derive(Clone, Debug, thiserror::Error)] 12 #[cfg_attr(test, derive(PartialEq))] 13 pub enum ExpressionError { 14 #[error("Doesn't exist")] 15 DoesntExist, 16 #[error("Used by a statement before it was introduced into the scope by any of the dominating blocks")] 17 NotInScope, 18 #[error("Depends on {0:?}, which has not been processed yet")] 19 ForwardDependency(Handle<crate::Expression>), 20 #[error("Base type {0:?} is not compatible with this expression")] 21 InvalidBaseType(Handle<crate::Expression>), 22 #[error("Accessing with index {0:?} can't be done")] 23 InvalidIndexType(Handle<crate::Expression>), 24 #[error("Accessing index {1:?} is out of {0:?} bounds")] 25 IndexOutOfBounds(Handle<crate::Expression>, crate::ScalarValue), 26 #[error("The expression {0:?} may only be indexed by a constant")] 27 IndexMustBeConstant(Handle<crate::Expression>), 28 #[error("Function argument {0:?} doesn't exist")] 29 FunctionArgumentDoesntExist(u32), 30 #[error("Constant {0:?} doesn't exist")] 31 ConstantDoesntExist(Handle<crate::Constant>), 32 #[error("Global variable {0:?} doesn't exist")] 33 GlobalVarDoesntExist(Handle<crate::GlobalVariable>), 34 #[error("Local variable {0:?} doesn't exist")] 35 LocalVarDoesntExist(Handle<crate::LocalVariable>), 36 #[error("Loading of {0:?} can't be done")] 37 InvalidPointerType(Handle<crate::Expression>), 38 #[error("Array length of {0:?} can't be done")] 39 InvalidArrayType(Handle<crate::Expression>), 40 #[error("Splatting {0:?} can't be done")] 41 InvalidSplatType(Handle<crate::Expression>), 42 #[error("Swizzling {0:?} can't be done")] 43 InvalidVectorType(Handle<crate::Expression>), 44 #[error("Swizzle component {0:?} is outside of vector size {1:?}")] 45 InvalidSwizzleComponent(crate::SwizzleComponent, crate::VectorSize), 46 #[error(transparent)] 47 Compose(#[from] super::ComposeError), 48 #[error(transparent)] 49 Proc(#[from] ProcError), 50 #[error("Operation {0:?} can't work with {1:?}")] 51 InvalidUnaryOperandType(crate::UnaryOperator, Handle<crate::Expression>), 52 #[error("Operation {0:?} can't work with {1:?} and {2:?}")] 53 InvalidBinaryOperandTypes( 54 crate::BinaryOperator, 55 Handle<crate::Expression>, 56 Handle<crate::Expression>, 57 ), 58 #[error("Selecting is not possible")] 59 InvalidSelectTypes, 60 #[error("Relational argument {0:?} is not a boolean vector")] 61 InvalidBooleanVector(Handle<crate::Expression>), 62 #[error("Relational argument {0:?} is not a float")] 63 InvalidFloatArgument(Handle<crate::Expression>), 64 #[error("Type resolution failed")] 65 Type(#[from] ResolveError), 66 #[error("Not a global variable")] 67 ExpectedGlobalVariable, 68 #[error("Not a global variable or a function argument")] 69 ExpectedGlobalOrArgument, 70 #[error("Calling an undeclared function {0:?}")] 71 CallToUndeclaredFunction(Handle<crate::Function>), 72 #[error("Needs to be an image instead of {0:?}")] 73 ExpectedImageType(Handle<crate::Type>), 74 #[error("Needs to be an image instead of {0:?}")] 75 ExpectedSamplerType(Handle<crate::Type>), 76 #[error("Unable to operate on image class {0:?}")] 77 InvalidImageClass(crate::ImageClass), 78 #[error("Derivatives can only be taken from scalar and vector floats")] 79 InvalidDerivative, 80 #[error("Image array index parameter is misplaced")] 81 InvalidImageArrayIndex, 82 #[error("Image other index parameter is misplaced")] 83 InvalidImageOtherIndex, 84 #[error("Image array index type of {0:?} is not an integer scalar")] 85 InvalidImageArrayIndexType(Handle<crate::Expression>), 86 #[error("Image other index type of {0:?} is not an integer scalar")] 87 InvalidImageOtherIndexType(Handle<crate::Expression>), 88 #[error("Image coordinate type of {1:?} does not match dimension {0:?}")] 89 InvalidImageCoordinateType(crate::ImageDimension, Handle<crate::Expression>), 90 #[error("Comparison sampling mismatch: image has class {image:?}, but the sampler is comparison={sampler}, and the reference was provided={has_ref}")] 91 ComparisonSamplingMismatch { 92 image: crate::ImageClass, 93 sampler: bool, 94 has_ref: bool, 95 }, 96 #[error("Sample offset constant {1:?} doesn't match the image dimension {0:?}")] 97 InvalidSampleOffset(crate::ImageDimension, Handle<crate::Constant>), 98 #[error("Depth reference {0:?} is not a scalar float")] 99 InvalidDepthReference(Handle<crate::Expression>), 100 #[error("Depth sample level can only be Auto or Zero")] 101 InvalidDepthSampleLevel, 102 #[error("Gather level can only be Zero")] 103 InvalidGatherLevel, 104 #[error("Gather component {0:?} doesn't exist in the image")] 105 InvalidGatherComponent(crate::SwizzleComponent), 106 #[error("Gather can't be done for image dimension {0:?}")] 107 InvalidGatherDimension(crate::ImageDimension), 108 #[error("Sample level (exact) type {0:?} is not a scalar float")] 109 InvalidSampleLevelExactType(Handle<crate::Expression>), 110 #[error("Sample level (bias) type {0:?} is not a scalar float")] 111 InvalidSampleLevelBiasType(Handle<crate::Expression>), 112 #[error("Sample level (gradient) of {1:?} doesn't match the image dimension {0:?}")] 113 InvalidSampleLevelGradientType(crate::ImageDimension, Handle<crate::Expression>), 114 #[error("Unable to cast")] 115 InvalidCastArgument, 116 #[error("Invalid argument count for {0:?}")] 117 WrongArgumentCount(crate::MathFunction), 118 #[error("Argument [{1}] to {0:?} as expression {2:?} has an invalid type.")] 119 InvalidArgumentType(crate::MathFunction, u32, Handle<crate::Expression>), 120 #[error("Atomic result type can't be {0:?} of {1} bytes")] 121 InvalidAtomicResultType(crate::ScalarKind, crate::Bytes), 122 } 123 124 #[cfg(feature = "validate")] 125 struct ExpressionTypeResolver<'a> { 126 root: Handle<crate::Expression>, 127 types: &'a UniqueArena<crate::Type>, 128 info: &'a FunctionInfo, 129 } 130 131 #[cfg(feature = "validate")] 132 impl<'a> ExpressionTypeResolver<'a> { resolve( &self, handle: Handle<crate::Expression>, ) -> Result<&'a crate::TypeInner, ExpressionError>133 fn resolve( 134 &self, 135 handle: Handle<crate::Expression>, 136 ) -> Result<&'a crate::TypeInner, ExpressionError> { 137 if handle < self.root { 138 Ok(self.info[handle].ty.inner_with(self.types)) 139 } else { 140 Err(ExpressionError::ForwardDependency(handle)) 141 } 142 } 143 } 144 145 #[cfg(feature = "validate")] 146 impl super::Validator { validate_expression( &self, root: Handle<crate::Expression>, expression: &crate::Expression, function: &crate::Function, module: &crate::Module, info: &FunctionInfo, other_infos: &[FunctionInfo], ) -> Result<ShaderStages, ExpressionError>147 pub(super) fn validate_expression( 148 &self, 149 root: Handle<crate::Expression>, 150 expression: &crate::Expression, 151 function: &crate::Function, 152 module: &crate::Module, 153 info: &FunctionInfo, 154 other_infos: &[FunctionInfo], 155 ) -> Result<ShaderStages, ExpressionError> { 156 use crate::{Expression as E, ScalarKind as Sk, TypeInner as Ti}; 157 158 let resolver = ExpressionTypeResolver { 159 root, 160 types: &module.types, 161 info, 162 }; 163 164 let stages = match *expression { 165 E::Access { base, index } => { 166 let base_type = resolver.resolve(base)?; 167 // See the documentation for `Expression::Access`. 168 let dynamic_indexing_restricted = match *base_type { 169 Ti::Vector { .. } => false, 170 Ti::Matrix { .. } | Ti::Array { .. } => true, 171 Ti::Pointer { .. } | Ti::ValuePointer { size: Some(_), .. } => false, 172 ref other => { 173 log::error!("Indexing of {:?}", other); 174 return Err(ExpressionError::InvalidBaseType(base)); 175 } 176 }; 177 match *resolver.resolve(index)? { 178 //TODO: only allow one of these 179 Ti::Scalar { 180 kind: Sk::Sint, 181 width: _, 182 } 183 | Ti::Scalar { 184 kind: Sk::Uint, 185 width: _, 186 } => {} 187 ref other => { 188 log::error!("Indexing by {:?}", other); 189 return Err(ExpressionError::InvalidIndexType(index)); 190 } 191 } 192 if dynamic_indexing_restricted 193 && function.expressions[index].is_dynamic_index(module) 194 { 195 return Err(ExpressionError::IndexMustBeConstant(base)); 196 } 197 198 // If we know both the length and the index, we can do the 199 // bounds check now. 200 if let crate::proc::IndexableLength::Known(known_length) = 201 base_type.indexable_length(module)? 202 { 203 if let E::Constant(k) = function.expressions[index] { 204 if let crate::Constant { 205 // We must treat specializable constants as unknown. 206 specialization: None, 207 // Non-scalar indices should have been caught above. 208 inner: crate::ConstantInner::Scalar { value, .. }, 209 .. 210 } = module.constants[k] 211 { 212 match value { 213 crate::ScalarValue::Uint(u) if u >= known_length as u64 => { 214 return Err(ExpressionError::IndexOutOfBounds(base, value)); 215 } 216 crate::ScalarValue::Sint(s) 217 if s < 0 || s >= known_length as i64 => 218 { 219 return Err(ExpressionError::IndexOutOfBounds(base, value)); 220 } 221 _ => (), 222 } 223 } 224 } 225 } 226 227 ShaderStages::all() 228 } 229 E::AccessIndex { base, index } => { 230 fn resolve_index_limit( 231 module: &crate::Module, 232 top: Handle<crate::Expression>, 233 ty: &crate::TypeInner, 234 top_level: bool, 235 ) -> Result<u32, ExpressionError> { 236 let limit = match *ty { 237 Ti::Vector { size, .. } 238 | Ti::ValuePointer { 239 size: Some(size), .. 240 } => size as u32, 241 Ti::Matrix { columns, .. } => columns as u32, 242 Ti::Array { 243 size: crate::ArraySize::Constant(handle), 244 .. 245 } => module.constants[handle].to_array_length().unwrap(), 246 Ti::Array { .. } => !0, // can't statically know, but need run-time checks 247 Ti::Pointer { base, .. } if top_level => { 248 resolve_index_limit(module, top, &module.types[base].inner, false)? 249 } 250 Ti::Struct { ref members, .. } => members.len() as u32, 251 ref other => { 252 log::error!("Indexing of {:?}", other); 253 return Err(ExpressionError::InvalidBaseType(top)); 254 } 255 }; 256 Ok(limit) 257 } 258 259 let limit = resolve_index_limit(module, base, resolver.resolve(base)?, true)?; 260 if index >= limit { 261 return Err(ExpressionError::IndexOutOfBounds( 262 base, 263 crate::ScalarValue::Uint(limit as _), 264 )); 265 } 266 ShaderStages::all() 267 } 268 E::Constant(handle) => { 269 let _ = module 270 .constants 271 .try_get(handle) 272 .ok_or(ExpressionError::ConstantDoesntExist(handle))?; 273 ShaderStages::all() 274 } 275 E::Splat { size: _, value } => match *resolver.resolve(value)? { 276 Ti::Scalar { .. } => ShaderStages::all(), 277 ref other => { 278 log::error!("Splat scalar type {:?}", other); 279 return Err(ExpressionError::InvalidSplatType(value)); 280 } 281 }, 282 E::Swizzle { 283 size, 284 vector, 285 pattern, 286 } => { 287 let vec_size = match *resolver.resolve(vector)? { 288 Ti::Vector { size: vec_size, .. } => vec_size, 289 ref other => { 290 log::error!("Swizzle vector type {:?}", other); 291 return Err(ExpressionError::InvalidVectorType(vector)); 292 } 293 }; 294 for &sc in pattern[..size as usize].iter() { 295 if sc as u8 >= vec_size as u8 { 296 return Err(ExpressionError::InvalidSwizzleComponent(sc, vec_size)); 297 } 298 } 299 ShaderStages::all() 300 } 301 E::Compose { ref components, ty } => { 302 for &handle in components { 303 if handle >= root { 304 return Err(ExpressionError::ForwardDependency(handle)); 305 } 306 } 307 validate_compose( 308 ty, 309 &module.constants, 310 &module.types, 311 components.iter().map(|&handle| info[handle].ty.clone()), 312 )?; 313 ShaderStages::all() 314 } 315 E::FunctionArgument(index) => { 316 if index >= function.arguments.len() as u32 { 317 return Err(ExpressionError::FunctionArgumentDoesntExist(index)); 318 } 319 ShaderStages::all() 320 } 321 E::GlobalVariable(handle) => { 322 let _ = module 323 .global_variables 324 .try_get(handle) 325 .ok_or(ExpressionError::GlobalVarDoesntExist(handle))?; 326 ShaderStages::all() 327 } 328 E::LocalVariable(handle) => { 329 let _ = function 330 .local_variables 331 .try_get(handle) 332 .ok_or(ExpressionError::LocalVarDoesntExist(handle))?; 333 ShaderStages::all() 334 } 335 E::Load { pointer } => { 336 match *resolver.resolve(pointer)? { 337 Ti::Pointer { base, .. } 338 if self.types[base.index()] 339 .flags 340 .contains(TypeFlags::SIZED | TypeFlags::DATA) => {} 341 Ti::ValuePointer { .. } => {} 342 ref other => { 343 log::error!("Loading {:?}", other); 344 return Err(ExpressionError::InvalidPointerType(pointer)); 345 } 346 } 347 ShaderStages::all() 348 } 349 E::ImageSample { 350 image, 351 sampler, 352 gather, 353 coordinate, 354 array_index, 355 offset, 356 level, 357 depth_ref, 358 } => { 359 // check the validity of expressions 360 let image_ty = match function.expressions[image] { 361 crate::Expression::GlobalVariable(var_handle) => { 362 module.global_variables[var_handle].ty 363 } 364 crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty, 365 _ => return Err(ExpressionError::ExpectedGlobalVariable), 366 }; 367 let sampler_ty = match function.expressions[sampler] { 368 crate::Expression::GlobalVariable(var_handle) => { 369 module.global_variables[var_handle].ty 370 } 371 crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty, 372 _ => return Err(ExpressionError::ExpectedGlobalVariable), 373 }; 374 let comparison = match module.types[sampler_ty].inner { 375 Ti::Sampler { comparison } => comparison, 376 _ => return Err(ExpressionError::ExpectedSamplerType(sampler_ty)), 377 }; 378 379 let (class, dim) = match module.types[image_ty].inner { 380 Ti::Image { 381 class, 382 arrayed, 383 dim, 384 } => { 385 // check the array property 386 if arrayed != array_index.is_some() { 387 return Err(ExpressionError::InvalidImageArrayIndex); 388 } 389 if let Some(expr) = array_index { 390 match *resolver.resolve(expr)? { 391 Ti::Scalar { 392 kind: Sk::Sint, 393 width: _, 394 } => {} 395 _ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)), 396 } 397 } 398 (class, dim) 399 } 400 _ => return Err(ExpressionError::ExpectedImageType(image_ty)), 401 }; 402 403 // check sampling and comparison properties 404 let image_depth = match class { 405 crate::ImageClass::Sampled { 406 kind: crate::ScalarKind::Float, 407 multi: false, 408 } => false, 409 crate::ImageClass::Depth { multi: false } => true, 410 _ => return Err(ExpressionError::InvalidImageClass(class)), 411 }; 412 if comparison != depth_ref.is_some() || (comparison && !image_depth) { 413 return Err(ExpressionError::ComparisonSamplingMismatch { 414 image: class, 415 sampler: comparison, 416 has_ref: depth_ref.is_some(), 417 }); 418 } 419 420 // check texture coordinates type 421 let num_components = match dim { 422 crate::ImageDimension::D1 => 1, 423 crate::ImageDimension::D2 => 2, 424 crate::ImageDimension::D3 | crate::ImageDimension::Cube => 3, 425 }; 426 match *resolver.resolve(coordinate)? { 427 Ti::Scalar { 428 kind: Sk::Float, .. 429 } if num_components == 1 => {} 430 Ti::Vector { 431 size, 432 kind: Sk::Float, 433 .. 434 } if size as u32 == num_components => {} 435 _ => return Err(ExpressionError::InvalidImageCoordinateType(dim, coordinate)), 436 } 437 438 // check constant offset 439 if let Some(const_handle) = offset { 440 let good = match module.constants[const_handle].inner { 441 crate::ConstantInner::Scalar { 442 width: _, 443 value: crate::ScalarValue::Sint(_), 444 } => num_components == 1, 445 crate::ConstantInner::Scalar { .. } => false, 446 crate::ConstantInner::Composite { ty, .. } => { 447 match module.types[ty].inner { 448 Ti::Vector { 449 size, 450 kind: Sk::Sint, 451 .. 452 } => size as u32 == num_components, 453 _ => false, 454 } 455 } 456 }; 457 if !good { 458 return Err(ExpressionError::InvalidSampleOffset(dim, const_handle)); 459 } 460 } 461 462 // check depth reference type 463 if let Some(expr) = depth_ref { 464 match *resolver.resolve(expr)? { 465 Ti::Scalar { 466 kind: Sk::Float, .. 467 } => {} 468 _ => return Err(ExpressionError::InvalidDepthReference(expr)), 469 } 470 match level { 471 crate::SampleLevel::Auto | crate::SampleLevel::Zero => {} 472 _ => return Err(ExpressionError::InvalidDepthSampleLevel), 473 } 474 } 475 476 if let Some(component) = gather { 477 match dim { 478 crate::ImageDimension::D2 | crate::ImageDimension::Cube => {} 479 crate::ImageDimension::D1 | crate::ImageDimension::D3 => { 480 return Err(ExpressionError::InvalidGatherDimension(dim)) 481 } 482 }; 483 let max_component = match class { 484 crate::ImageClass::Depth { .. } => crate::SwizzleComponent::X, 485 _ => crate::SwizzleComponent::W, 486 }; 487 if component > max_component { 488 return Err(ExpressionError::InvalidGatherComponent(component)); 489 } 490 match level { 491 crate::SampleLevel::Zero => {} 492 _ => return Err(ExpressionError::InvalidGatherLevel), 493 } 494 } 495 496 // check level properties 497 match level { 498 crate::SampleLevel::Auto => ShaderStages::FRAGMENT, 499 crate::SampleLevel::Zero => ShaderStages::all(), 500 crate::SampleLevel::Exact(expr) => { 501 match *resolver.resolve(expr)? { 502 Ti::Scalar { 503 kind: Sk::Float, .. 504 } => {} 505 _ => return Err(ExpressionError::InvalidSampleLevelExactType(expr)), 506 } 507 ShaderStages::all() 508 } 509 crate::SampleLevel::Bias(expr) => { 510 match *resolver.resolve(expr)? { 511 Ti::Scalar { 512 kind: Sk::Float, .. 513 } => {} 514 _ => return Err(ExpressionError::InvalidSampleLevelBiasType(expr)), 515 } 516 ShaderStages::all() 517 } 518 crate::SampleLevel::Gradient { x, y } => { 519 match *resolver.resolve(x)? { 520 Ti::Scalar { 521 kind: Sk::Float, .. 522 } if num_components == 1 => {} 523 Ti::Vector { 524 size, 525 kind: Sk::Float, 526 .. 527 } if size as u32 == num_components => {} 528 _ => { 529 return Err(ExpressionError::InvalidSampleLevelGradientType(dim, x)) 530 } 531 } 532 match *resolver.resolve(y)? { 533 Ti::Scalar { 534 kind: Sk::Float, .. 535 } if num_components == 1 => {} 536 Ti::Vector { 537 size, 538 kind: Sk::Float, 539 .. 540 } if size as u32 == num_components => {} 541 _ => { 542 return Err(ExpressionError::InvalidSampleLevelGradientType(dim, y)) 543 } 544 } 545 ShaderStages::all() 546 } 547 } 548 } 549 E::ImageLoad { 550 image, 551 coordinate, 552 array_index, 553 index, 554 } => { 555 let ty = match function.expressions[image] { 556 crate::Expression::GlobalVariable(var_handle) => { 557 module.global_variables[var_handle].ty 558 } 559 crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty, 560 _ => return Err(ExpressionError::ExpectedGlobalVariable), 561 }; 562 match module.types[ty].inner { 563 Ti::Image { 564 class, 565 arrayed, 566 dim, 567 } => { 568 match resolver.resolve(coordinate)?.image_storage_coordinates() { 569 Some(coord_dim) if coord_dim == dim => {} 570 _ => { 571 return Err(ExpressionError::InvalidImageCoordinateType( 572 dim, coordinate, 573 )) 574 } 575 }; 576 let needs_index = match class { 577 crate::ImageClass::Storage { .. } => false, 578 _ => true, 579 }; 580 if arrayed != array_index.is_some() { 581 return Err(ExpressionError::InvalidImageArrayIndex); 582 } 583 if needs_index != index.is_some() { 584 return Err(ExpressionError::InvalidImageOtherIndex); 585 } 586 if let Some(expr) = array_index { 587 match *resolver.resolve(expr)? { 588 Ti::Scalar { 589 kind: Sk::Sint, 590 width: _, 591 } => {} 592 _ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)), 593 } 594 } 595 if let Some(expr) = index { 596 match *resolver.resolve(expr)? { 597 Ti::Scalar { 598 kind: Sk::Sint, 599 width: _, 600 } => {} 601 _ => return Err(ExpressionError::InvalidImageOtherIndexType(expr)), 602 } 603 } 604 } 605 _ => return Err(ExpressionError::ExpectedImageType(ty)), 606 } 607 ShaderStages::all() 608 } 609 E::ImageQuery { image, query } => { 610 let ty = match function.expressions[image] { 611 crate::Expression::GlobalVariable(var_handle) => { 612 module.global_variables[var_handle].ty 613 } 614 crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty, 615 _ => return Err(ExpressionError::ExpectedGlobalVariable), 616 }; 617 match module.types[ty].inner { 618 Ti::Image { class, arrayed, .. } => { 619 let can_level = match class { 620 crate::ImageClass::Sampled { multi, .. } => !multi, 621 crate::ImageClass::Depth { multi } => !multi, 622 crate::ImageClass::Storage { .. } => false, 623 }; 624 let good = match query { 625 crate::ImageQuery::NumLayers => arrayed, 626 crate::ImageQuery::Size { level: None } => true, 627 crate::ImageQuery::Size { level: Some(_) } 628 | crate::ImageQuery::NumLevels => can_level, 629 //TODO: forbid on storage images 630 crate::ImageQuery::NumSamples => !can_level, 631 }; 632 if !good { 633 return Err(ExpressionError::InvalidImageClass(class)); 634 } 635 } 636 _ => return Err(ExpressionError::ExpectedImageType(ty)), 637 } 638 ShaderStages::all() 639 } 640 E::Unary { op, expr } => { 641 use crate::UnaryOperator as Uo; 642 let inner = resolver.resolve(expr)?; 643 match (op, inner.scalar_kind()) { 644 (_, Some(Sk::Sint)) 645 | (_, Some(Sk::Bool)) 646 //TODO: restrict Negate for bools? 647 | (Uo::Negate, Some(Sk::Float)) 648 | (Uo::Not, Some(Sk::Uint)) => {} 649 other => { 650 log::error!("Op {:?} kind {:?}", op, other); 651 return Err(ExpressionError::InvalidUnaryOperandType(op, expr)); 652 } 653 } 654 ShaderStages::all() 655 } 656 E::Binary { op, left, right } => { 657 use crate::BinaryOperator as Bo; 658 let left_inner = resolver.resolve(left)?; 659 let right_inner = resolver.resolve(right)?; 660 let good = match op { 661 Bo::Add | Bo::Subtract => match *left_inner { 662 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind { 663 Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, 664 Sk::Bool => false, 665 }, 666 Ti::Matrix { .. } => left_inner == right_inner, 667 _ => false, 668 }, 669 Bo::Divide | Bo::Modulo => match *left_inner { 670 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind { 671 Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, 672 Sk::Bool => false, 673 }, 674 _ => false, 675 }, 676 Bo::Multiply => { 677 let kind_match = match left_inner.scalar_kind() { 678 Some(Sk::Uint) | Some(Sk::Sint) | Some(Sk::Float) => true, 679 Some(Sk::Bool) | None => false, 680 }; 681 //TODO: should we be more restrictive here? I.e. expect scalar only to the left. 682 let types_match = match (left_inner, right_inner) { 683 (&Ti::Scalar { kind: kind1, .. }, &Ti::Scalar { kind: kind2, .. }) 684 | (&Ti::Vector { kind: kind1, .. }, &Ti::Scalar { kind: kind2, .. }) 685 | (&Ti::Scalar { kind: kind1, .. }, &Ti::Vector { kind: kind2, .. }) => { 686 kind1 == kind2 687 } 688 ( 689 &Ti::Scalar { 690 kind: Sk::Float, .. 691 }, 692 &Ti::Matrix { .. }, 693 ) 694 | ( 695 &Ti::Matrix { .. }, 696 &Ti::Scalar { 697 kind: Sk::Float, .. 698 }, 699 ) => true, 700 ( 701 &Ti::Vector { 702 kind: kind1, 703 size: size1, 704 .. 705 }, 706 &Ti::Vector { 707 kind: kind2, 708 size: size2, 709 .. 710 }, 711 ) => kind1 == kind2 && size1 == size2, 712 ( 713 &Ti::Matrix { columns, .. }, 714 &Ti::Vector { 715 kind: Sk::Float, 716 size, 717 .. 718 }, 719 ) => columns == size, 720 ( 721 &Ti::Vector { 722 kind: Sk::Float, 723 size, 724 .. 725 }, 726 &Ti::Matrix { rows, .. }, 727 ) => size == rows, 728 (&Ti::Matrix { columns, .. }, &Ti::Matrix { rows, .. }) => { 729 columns == rows 730 } 731 _ => false, 732 }; 733 let left_width = match *left_inner { 734 Ti::Scalar { width, .. } 735 | Ti::Vector { width, .. } 736 | Ti::Matrix { width, .. } => width, 737 _ => 0, 738 }; 739 let right_width = match *right_inner { 740 Ti::Scalar { width, .. } 741 | Ti::Vector { width, .. } 742 | Ti::Matrix { width, .. } => width, 743 _ => 0, 744 }; 745 kind_match && types_match && left_width == right_width 746 } 747 Bo::Equal | Bo::NotEqual => left_inner.is_sized() && left_inner == right_inner, 748 Bo::Less | Bo::LessEqual | Bo::Greater | Bo::GreaterEqual => { 749 match *left_inner { 750 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind { 751 Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, 752 Sk::Bool => false, 753 }, 754 ref other => { 755 log::error!("Op {:?} left type {:?}", op, other); 756 false 757 } 758 } 759 } 760 Bo::LogicalAnd | Bo::LogicalOr => match *left_inner { 761 Ti::Scalar { kind: Sk::Bool, .. } | Ti::Vector { kind: Sk::Bool, .. } => { 762 left_inner == right_inner 763 } 764 ref other => { 765 log::error!("Op {:?} left type {:?}", op, other); 766 false 767 } 768 }, 769 Bo::And | Bo::InclusiveOr => match *left_inner { 770 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind { 771 Sk::Bool | Sk::Sint | Sk::Uint => left_inner == right_inner, 772 Sk::Float => false, 773 }, 774 ref other => { 775 log::error!("Op {:?} left type {:?}", op, other); 776 false 777 } 778 }, 779 Bo::ExclusiveOr => match *left_inner { 780 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind { 781 Sk::Sint | Sk::Uint => left_inner == right_inner, 782 Sk::Bool | Sk::Float => false, 783 }, 784 ref other => { 785 log::error!("Op {:?} left type {:?}", op, other); 786 false 787 } 788 }, 789 Bo::ShiftLeft | Bo::ShiftRight => { 790 let (base_size, base_kind) = match *left_inner { 791 Ti::Scalar { kind, .. } => (Ok(None), kind), 792 Ti::Vector { size, kind, .. } => (Ok(Some(size)), kind), 793 ref other => { 794 log::error!("Op {:?} base type {:?}", op, other); 795 (Err(()), Sk::Bool) 796 } 797 }; 798 let shift_size = match *right_inner { 799 Ti::Scalar { kind: Sk::Uint, .. } => Ok(None), 800 Ti::Vector { 801 size, 802 kind: Sk::Uint, 803 .. 804 } => Ok(Some(size)), 805 ref other => { 806 log::error!("Op {:?} shift type {:?}", op, other); 807 Err(()) 808 } 809 }; 810 match base_kind { 811 Sk::Sint | Sk::Uint => base_size.is_ok() && base_size == shift_size, 812 Sk::Float | Sk::Bool => false, 813 } 814 } 815 }; 816 if !good { 817 log::error!( 818 "Left: {:?} of type {:?}", 819 function.expressions[left], 820 left_inner 821 ); 822 log::error!( 823 "Right: {:?} of type {:?}", 824 function.expressions[right], 825 right_inner 826 ); 827 return Err(ExpressionError::InvalidBinaryOperandTypes(op, left, right)); 828 } 829 ShaderStages::all() 830 } 831 E::Select { 832 condition, 833 accept, 834 reject, 835 } => { 836 let accept_inner = resolver.resolve(accept)?; 837 let reject_inner = resolver.resolve(reject)?; 838 let condition_good = match *resolver.resolve(condition)? { 839 Ti::Scalar { 840 kind: Sk::Bool, 841 width: _, 842 } => { 843 // When `condition` is a single boolean, `accept` and 844 // `reject` can be vectors or scalars. 845 match *accept_inner { 846 Ti::Scalar { .. } | Ti::Vector { .. } => true, 847 _ => false, 848 } 849 } 850 Ti::Vector { 851 size, 852 kind: Sk::Bool, 853 width: _, 854 } => match *accept_inner { 855 Ti::Vector { 856 size: other_size, .. 857 } => size == other_size, 858 _ => false, 859 }, 860 _ => false, 861 }; 862 if !condition_good || accept_inner != reject_inner { 863 return Err(ExpressionError::InvalidSelectTypes); 864 } 865 ShaderStages::all() 866 } 867 E::Derivative { axis: _, expr } => { 868 match *resolver.resolve(expr)? { 869 Ti::Scalar { 870 kind: Sk::Float, .. 871 } 872 | Ti::Vector { 873 kind: Sk::Float, .. 874 } => {} 875 _ => return Err(ExpressionError::InvalidDerivative), 876 } 877 ShaderStages::FRAGMENT 878 } 879 E::Relational { fun, argument } => { 880 use crate::RelationalFunction as Rf; 881 let argument_inner = resolver.resolve(argument)?; 882 match fun { 883 Rf::All | Rf::Any => match *argument_inner { 884 Ti::Vector { kind: Sk::Bool, .. } => {} 885 ref other => { 886 log::error!("All/Any of type {:?}", other); 887 return Err(ExpressionError::InvalidBooleanVector(argument)); 888 } 889 }, 890 Rf::IsNan | Rf::IsInf | Rf::IsFinite | Rf::IsNormal => match *argument_inner { 891 Ti::Scalar { 892 kind: Sk::Float, .. 893 } 894 | Ti::Vector { 895 kind: Sk::Float, .. 896 } => {} 897 ref other => { 898 log::error!("Float test of type {:?}", other); 899 return Err(ExpressionError::InvalidFloatArgument(argument)); 900 } 901 }, 902 } 903 ShaderStages::all() 904 } 905 E::Math { 906 fun, 907 arg, 908 arg1, 909 arg2, 910 arg3, 911 } => { 912 use crate::MathFunction as Mf; 913 914 let arg_ty = resolver.resolve(arg)?; 915 let arg1_ty = arg1.map(|expr| resolver.resolve(expr)).transpose()?; 916 let arg2_ty = arg2.map(|expr| resolver.resolve(expr)).transpose()?; 917 let arg3_ty = arg3.map(|expr| resolver.resolve(expr)).transpose()?; 918 match fun { 919 Mf::Abs => { 920 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 921 return Err(ExpressionError::WrongArgumentCount(fun)); 922 } 923 let good = match *arg_ty { 924 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool, 925 _ => false, 926 }; 927 if !good { 928 return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)); 929 } 930 } 931 Mf::Min | Mf::Max => { 932 let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) { 933 (Some(ty1), None, None) => ty1, 934 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 935 }; 936 let good = match *arg_ty { 937 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool, 938 _ => false, 939 }; 940 if !good { 941 return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)); 942 } 943 if arg1_ty != arg_ty { 944 return Err(ExpressionError::InvalidArgumentType( 945 fun, 946 1, 947 arg1.unwrap(), 948 )); 949 } 950 } 951 Mf::Clamp => { 952 let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) { 953 (Some(ty1), Some(ty2), None) => (ty1, ty2), 954 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 955 }; 956 let good = match *arg_ty { 957 Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool, 958 _ => false, 959 }; 960 if !good { 961 return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)); 962 } 963 if arg1_ty != arg_ty { 964 return Err(ExpressionError::InvalidArgumentType( 965 fun, 966 1, 967 arg1.unwrap(), 968 )); 969 } 970 if arg2_ty != arg_ty { 971 return Err(ExpressionError::InvalidArgumentType( 972 fun, 973 2, 974 arg2.unwrap(), 975 )); 976 } 977 } 978 Mf::Cos 979 | Mf::Cosh 980 | Mf::Sin 981 | Mf::Sinh 982 | Mf::Tan 983 | Mf::Tanh 984 | Mf::Acos 985 | Mf::Asin 986 | Mf::Atan 987 | Mf::Asinh 988 | Mf::Acosh 989 | Mf::Atanh 990 | Mf::Radians 991 | Mf::Degrees 992 | Mf::Ceil 993 | Mf::Floor 994 | Mf::Round 995 | Mf::Fract 996 | Mf::Trunc 997 | Mf::Exp 998 | Mf::Exp2 999 | Mf::Log 1000 | Mf::Log2 1001 | Mf::Length 1002 | Mf::Sign 1003 | Mf::Sqrt 1004 | Mf::InverseSqrt => { 1005 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1006 return Err(ExpressionError::WrongArgumentCount(fun)); 1007 } 1008 match *arg_ty { 1009 Ti::Scalar { 1010 kind: Sk::Float, .. 1011 } 1012 | Ti::Vector { 1013 kind: Sk::Float, .. 1014 } => {} 1015 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1016 } 1017 } 1018 Mf::Atan2 | Mf::Pow | Mf::Distance | Mf::Step => { 1019 let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) { 1020 (Some(ty1), None, None) => ty1, 1021 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1022 }; 1023 match *arg_ty { 1024 Ti::Scalar { 1025 kind: Sk::Float, .. 1026 } 1027 | Ti::Vector { 1028 kind: Sk::Float, .. 1029 } => {} 1030 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1031 } 1032 if arg1_ty != arg_ty { 1033 return Err(ExpressionError::InvalidArgumentType( 1034 fun, 1035 1, 1036 arg1.unwrap(), 1037 )); 1038 } 1039 } 1040 Mf::Modf | Mf::Frexp | Mf::Ldexp => { 1041 let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) { 1042 (Some(ty1), None, None) => ty1, 1043 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1044 }; 1045 let (size0, width0) = match *arg_ty { 1046 Ti::Scalar { 1047 kind: Sk::Float, 1048 width, 1049 } => (None, width), 1050 Ti::Vector { 1051 kind: Sk::Float, 1052 size, 1053 width, 1054 } => (Some(size), width), 1055 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1056 }; 1057 let good = match *arg1_ty { 1058 Ti::Pointer { base, class: _ } => module.types[base].inner == *arg_ty, 1059 Ti::ValuePointer { 1060 size, 1061 kind: Sk::Float, 1062 width, 1063 class: _, 1064 } => size == size0 && width == width0, 1065 _ => false, 1066 }; 1067 if !good { 1068 return Err(ExpressionError::InvalidArgumentType( 1069 fun, 1070 1, 1071 arg1.unwrap(), 1072 )); 1073 } 1074 } 1075 Mf::Dot | Mf::Outer | Mf::Cross | Mf::Reflect => { 1076 let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) { 1077 (Some(ty1), None, None) => ty1, 1078 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1079 }; 1080 match *arg_ty { 1081 Ti::Vector { 1082 kind: Sk::Float, .. 1083 } => {} 1084 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1085 } 1086 if arg1_ty != arg_ty { 1087 return Err(ExpressionError::InvalidArgumentType( 1088 fun, 1089 1, 1090 arg1.unwrap(), 1091 )); 1092 } 1093 } 1094 Mf::Refract => { 1095 let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) { 1096 (Some(ty1), Some(ty2), None) => (ty1, ty2), 1097 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1098 }; 1099 1100 match *arg_ty { 1101 Ti::Vector { 1102 kind: Sk::Float, .. 1103 } => {} 1104 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1105 } 1106 1107 if arg1_ty != arg_ty { 1108 return Err(ExpressionError::InvalidArgumentType( 1109 fun, 1110 1, 1111 arg1.unwrap(), 1112 )); 1113 } 1114 1115 match (arg_ty, arg2_ty) { 1116 ( 1117 &Ti::Vector { 1118 width: vector_width, 1119 .. 1120 }, 1121 &Ti::Scalar { 1122 width: scalar_width, 1123 kind: Sk::Float, 1124 }, 1125 ) if vector_width == scalar_width => {} 1126 _ => { 1127 return Err(ExpressionError::InvalidArgumentType( 1128 fun, 1129 2, 1130 arg2.unwrap(), 1131 )) 1132 } 1133 } 1134 } 1135 Mf::Normalize => { 1136 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1137 return Err(ExpressionError::WrongArgumentCount(fun)); 1138 } 1139 match *arg_ty { 1140 Ti::Vector { 1141 kind: Sk::Float, .. 1142 } => {} 1143 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1144 } 1145 } 1146 Mf::FaceForward | Mf::Fma | Mf::SmoothStep => { 1147 let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) { 1148 (Some(ty1), Some(ty2), None) => (ty1, ty2), 1149 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1150 }; 1151 match *arg_ty { 1152 Ti::Scalar { 1153 kind: Sk::Float, .. 1154 } 1155 | Ti::Vector { 1156 kind: Sk::Float, .. 1157 } => {} 1158 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1159 } 1160 if arg1_ty != arg_ty { 1161 return Err(ExpressionError::InvalidArgumentType( 1162 fun, 1163 1, 1164 arg1.unwrap(), 1165 )); 1166 } 1167 if arg2_ty != arg_ty { 1168 return Err(ExpressionError::InvalidArgumentType( 1169 fun, 1170 2, 1171 arg2.unwrap(), 1172 )); 1173 } 1174 } 1175 Mf::Mix => { 1176 let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) { 1177 (Some(ty1), Some(ty2), None) => (ty1, ty2), 1178 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1179 }; 1180 let arg_width = match *arg_ty { 1181 Ti::Scalar { 1182 kind: Sk::Float, 1183 width, 1184 } 1185 | Ti::Vector { 1186 kind: Sk::Float, 1187 width, 1188 .. 1189 } => width, 1190 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1191 }; 1192 if arg1_ty != arg_ty { 1193 return Err(ExpressionError::InvalidArgumentType( 1194 fun, 1195 1, 1196 arg1.unwrap(), 1197 )); 1198 } 1199 // the last argument can always be a scalar 1200 match *arg2_ty { 1201 Ti::Scalar { 1202 kind: Sk::Float, 1203 width, 1204 } if width == arg_width => {} 1205 _ if arg2_ty == arg_ty => {} 1206 _ => { 1207 return Err(ExpressionError::InvalidArgumentType( 1208 fun, 1209 2, 1210 arg2.unwrap(), 1211 )); 1212 } 1213 } 1214 } 1215 Mf::Inverse | Mf::Determinant => { 1216 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1217 return Err(ExpressionError::WrongArgumentCount(fun)); 1218 } 1219 let good = match *arg_ty { 1220 Ti::Matrix { columns, rows, .. } => columns == rows, 1221 _ => false, 1222 }; 1223 if !good { 1224 return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)); 1225 } 1226 } 1227 Mf::Transpose => { 1228 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1229 return Err(ExpressionError::WrongArgumentCount(fun)); 1230 } 1231 match *arg_ty { 1232 Ti::Matrix { .. } => {} 1233 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1234 } 1235 } 1236 Mf::CountOneBits | Mf::ReverseBits | Mf::FindLsb | Mf::FindMsb => { 1237 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1238 return Err(ExpressionError::WrongArgumentCount(fun)); 1239 } 1240 match *arg_ty { 1241 Ti::Scalar { kind: Sk::Sint, .. } 1242 | Ti::Scalar { kind: Sk::Uint, .. } 1243 | Ti::Vector { kind: Sk::Sint, .. } 1244 | Ti::Vector { kind: Sk::Uint, .. } => {} 1245 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1246 } 1247 } 1248 Mf::InsertBits => { 1249 let (arg1_ty, arg2_ty, arg3_ty) = match (arg1_ty, arg2_ty, arg3_ty) { 1250 (Some(ty1), Some(ty2), Some(ty3)) => (ty1, ty2, ty3), 1251 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1252 }; 1253 match *arg_ty { 1254 Ti::Scalar { kind: Sk::Sint, .. } 1255 | Ti::Scalar { kind: Sk::Uint, .. } 1256 | Ti::Vector { kind: Sk::Sint, .. } 1257 | Ti::Vector { kind: Sk::Uint, .. } => {} 1258 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1259 } 1260 if arg1_ty != arg_ty { 1261 return Err(ExpressionError::InvalidArgumentType( 1262 fun, 1263 1, 1264 arg1.unwrap(), 1265 )); 1266 } 1267 match *arg2_ty { 1268 Ti::Scalar { kind: Sk::Uint, .. } => {} 1269 _ => { 1270 return Err(ExpressionError::InvalidArgumentType( 1271 fun, 1272 2, 1273 arg2.unwrap(), 1274 )) 1275 } 1276 } 1277 match *arg3_ty { 1278 Ti::Scalar { kind: Sk::Uint, .. } => {} 1279 _ => { 1280 return Err(ExpressionError::InvalidArgumentType( 1281 fun, 1282 2, 1283 arg3.unwrap(), 1284 )) 1285 } 1286 } 1287 } 1288 Mf::ExtractBits => { 1289 let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) { 1290 (Some(ty1), Some(ty2), None) => (ty1, ty2), 1291 _ => return Err(ExpressionError::WrongArgumentCount(fun)), 1292 }; 1293 match *arg_ty { 1294 Ti::Scalar { kind: Sk::Sint, .. } 1295 | Ti::Scalar { kind: Sk::Uint, .. } 1296 | Ti::Vector { kind: Sk::Sint, .. } 1297 | Ti::Vector { kind: Sk::Uint, .. } => {} 1298 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1299 } 1300 match *arg1_ty { 1301 Ti::Scalar { kind: Sk::Uint, .. } => {} 1302 _ => { 1303 return Err(ExpressionError::InvalidArgumentType( 1304 fun, 1305 2, 1306 arg1.unwrap(), 1307 )) 1308 } 1309 } 1310 match *arg2_ty { 1311 Ti::Scalar { kind: Sk::Uint, .. } => {} 1312 _ => { 1313 return Err(ExpressionError::InvalidArgumentType( 1314 fun, 1315 2, 1316 arg2.unwrap(), 1317 )) 1318 } 1319 } 1320 } 1321 Mf::Pack2x16unorm | Mf::Pack2x16snorm | Mf::Pack2x16float => { 1322 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1323 return Err(ExpressionError::WrongArgumentCount(fun)); 1324 } 1325 match *arg_ty { 1326 Ti::Vector { 1327 size: crate::VectorSize::Bi, 1328 kind: Sk::Float, 1329 .. 1330 } => {} 1331 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1332 } 1333 } 1334 Mf::Pack4x8snorm | Mf::Pack4x8unorm => { 1335 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1336 return Err(ExpressionError::WrongArgumentCount(fun)); 1337 } 1338 match *arg_ty { 1339 Ti::Vector { 1340 size: crate::VectorSize::Quad, 1341 kind: Sk::Float, 1342 .. 1343 } => {} 1344 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1345 } 1346 } 1347 Mf::Unpack2x16float 1348 | Mf::Unpack2x16snorm 1349 | Mf::Unpack2x16unorm 1350 | Mf::Unpack4x8snorm 1351 | Mf::Unpack4x8unorm => { 1352 if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { 1353 return Err(ExpressionError::WrongArgumentCount(fun)); 1354 } 1355 match *arg_ty { 1356 Ti::Scalar { kind: Sk::Uint, .. } => {} 1357 _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), 1358 } 1359 } 1360 } 1361 ShaderStages::all() 1362 } 1363 E::As { 1364 expr, 1365 kind, 1366 convert, 1367 } => { 1368 let base_width = match *resolver.resolve(expr)? { 1369 crate::TypeInner::Scalar { width, .. } 1370 | crate::TypeInner::Vector { width, .. } 1371 | crate::TypeInner::Matrix { width, .. } => width, 1372 _ => return Err(ExpressionError::InvalidCastArgument), 1373 }; 1374 let width = convert.unwrap_or(base_width); 1375 if !self.check_width(kind, width) { 1376 return Err(ExpressionError::InvalidCastArgument); 1377 } 1378 ShaderStages::all() 1379 } 1380 E::CallResult(function) => other_infos[function.index()].available_stages, 1381 E::AtomicResult { 1382 kind, 1383 width, 1384 comparison: _, 1385 } => { 1386 let good = match kind { 1387 crate::ScalarKind::Uint | crate::ScalarKind::Sint => { 1388 self.check_width(kind, width) 1389 } 1390 _ => false, 1391 }; 1392 if !good { 1393 return Err(ExpressionError::InvalidAtomicResultType(kind, width)); 1394 } 1395 ShaderStages::all() 1396 } 1397 E::ArrayLength(expr) => match *resolver.resolve(expr)? { 1398 Ti::Pointer { base, .. } => { 1399 if let Some(&Ti::Array { 1400 size: crate::ArraySize::Dynamic, 1401 .. 1402 }) = resolver.types.get_handle(base).map(|ty| &ty.inner) 1403 { 1404 ShaderStages::all() 1405 } else { 1406 return Err(ExpressionError::InvalidArrayType(expr)); 1407 } 1408 } 1409 ref other => { 1410 log::error!("Array length of {:?}", other); 1411 return Err(ExpressionError::InvalidArrayType(expr)); 1412 } 1413 }, 1414 }; 1415 Ok(stages) 1416 } 1417 } 1418