@@ -303,4 +303,109 @@ impl crate::TypeInner {
303
303
| crate :: TypeInner :: BindingArray { .. } => false ,
304
304
}
305
305
}
306
+
307
+ /// Determine whether `self` automatically converts to `goal`.
308
+ ///
309
+ /// If Naga IR's automatic conversions will convert `self` to
310
+ /// `goal`, then return a pair `(from, to)`, where `from` and `to`
311
+ /// are the scalar types of the leaf values of `self` and `goal`.
312
+ ///
313
+ /// If `self` and `goal` are the same type, this will simply return
314
+ /// a pair `(S, S)`.
315
+ ///
316
+ /// If the automatic conversions cannot convert `self` to `goal`,
317
+ /// return `None`.
318
+ ///
319
+ /// Naga IR's automatic conversions will convert:
320
+ ///
321
+ /// - [`AbstractInt`] scalars to [`AbstractFloat`] or any numeric scalar type
322
+ ///
323
+ /// - [`AbstractFloat`] scalars to any floating-point scalar type
324
+ ///
325
+ /// - A [`Vector`] `{ size, scalar: S }` to `{ size, scalar: T }`
326
+ /// if they would convert `S` to `T`
327
+ ///
328
+ /// - An [`Array`] `{ base: S, size, stride }` to `{ base: T, size, stride }`
329
+ /// if they would convert `S` to `T`
330
+ ///
331
+ /// [`AbstractInt`]: crate::ScalarKind::AbstractInt
332
+ /// [`AbstractFloat`]: crate::ScalarKind::AbstractFloat
333
+ /// [`Vector`]: crate::TypeInner::Vector
334
+ /// [`Array`]: crate::TypeInner::Array
335
+ pub fn automatically_converts_to (
336
+ & self ,
337
+ goal : & Self ,
338
+ types : & crate :: UniqueArena < crate :: Type > ,
339
+ ) -> Option < ( crate :: Scalar , crate :: Scalar ) > {
340
+ use crate :: ScalarKind as Sk ;
341
+ use crate :: TypeInner as Ti ;
342
+
343
+ // Automatic conversions only change the scalar type of a value's leaves
344
+ // (e.g., `vec4<AbstractFloat>` to `vec4<f32>`), never the type
345
+ // constructors applied to those scalar types (e.g., never scalar to
346
+ // `vec4`, or `vec2` to `vec3`). So first we check that the type
347
+ // constructors match, extracting the leaf scalar types in the process.
348
+ let expr_scalar;
349
+ let goal_scalar;
350
+ match ( self , goal) {
351
+ ( & Ti :: Scalar ( expr) , & Ti :: Scalar ( goal) ) => {
352
+ expr_scalar = expr;
353
+ goal_scalar = goal;
354
+ }
355
+ (
356
+ & Ti :: Vector {
357
+ size : expr_size,
358
+ scalar : expr,
359
+ } ,
360
+ & Ti :: Vector {
361
+ size : goal_size,
362
+ scalar : goal,
363
+ } ,
364
+ ) if expr_size == goal_size => {
365
+ expr_scalar = expr;
366
+ goal_scalar = goal;
367
+ }
368
+ (
369
+ & Ti :: Matrix {
370
+ rows : expr_rows,
371
+ columns : expr_columns,
372
+ scalar : expr,
373
+ } ,
374
+ & Ti :: Matrix {
375
+ rows : goal_rows,
376
+ columns : goal_columns,
377
+ scalar : goal,
378
+ } ,
379
+ ) if expr_rows == goal_rows && expr_columns == goal_columns => {
380
+ expr_scalar = expr;
381
+ goal_scalar = goal;
382
+ }
383
+ (
384
+ & Ti :: Array {
385
+ base : expr_base,
386
+ size : expr_size,
387
+ stride : _,
388
+ } ,
389
+ & Ti :: Array {
390
+ base : goal_base,
391
+ size : goal_size,
392
+ stride : _,
393
+ } ,
394
+ ) if expr_size == goal_size => {
395
+ return types[ expr_base]
396
+ . inner
397
+ . automatically_converts_to ( & types[ goal_base] . inner , types) ;
398
+ }
399
+ _ => return None ,
400
+ }
401
+
402
+ match ( expr_scalar. kind , goal_scalar. kind ) {
403
+ ( Sk :: AbstractFloat , Sk :: Float ) => { }
404
+ ( Sk :: AbstractInt , Sk :: Sint | Sk :: Uint | Sk :: AbstractFloat | Sk :: Float ) => { }
405
+ _ => return None ,
406
+ }
407
+
408
+ log:: trace!( " okay: expr {expr_scalar:?}, goal {goal_scalar:?}" ) ;
409
+ Some ( ( expr_scalar, goal_scalar) )
410
+ }
306
411
}
0 commit comments