1+ use crate :: common;
12use crate :: proc:: KeywordSet ;
23use crate :: racy_lock:: RacyLock ;
4+ use alloc:: vec:: Vec ;
5+ use alloc:: { boxed:: Box , format} ;
36
47// MSLS - Metal Shading Language Specification:
58// https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
@@ -346,7 +349,7 @@ pub const RESERVED: &[&str] = &[
346349 super :: writer:: MODF_FUNCTION ,
347350 super :: writer:: ABS_FUNCTION ,
348351 super :: writer:: DIV_FUNCTION ,
349- super :: writer :: DOT_FUNCTION ,
352+ // DOT_FUNCTION_PREFIX variants are added dynamically below
350353 super :: writer:: MOD_FUNCTION ,
351354 super :: writer:: NEG_FUNCTION ,
352355 super :: writer:: F2I32_FUNCTION ,
@@ -360,8 +363,65 @@ pub const RESERVED: &[&str] = &[
360363 super :: writer:: EXTERNAL_TEXTURE_WRAPPER_STRUCT ,
361364] ;
362365
366+ const CONCRETE_INTEGER_SCALARS : [ crate :: Scalar ; 4 ] = [
367+ crate :: Scalar :: I32 ,
368+ crate :: Scalar :: U32 ,
369+ crate :: Scalar :: I64 ,
370+ crate :: Scalar :: U64 ,
371+ ] ;
372+
373+ const CONCRETE_VECTOR_SIZES : [ crate :: VectorSize ; 3 ] = [
374+ crate :: VectorSize :: Bi ,
375+ crate :: VectorSize :: Tri ,
376+ crate :: VectorSize :: Quad ,
377+ ] ;
378+
363379/// The above set of reserved keywords, turned into a cached HashSet. This saves
364380/// significant time during [`Namer::reset`](crate::proc::Namer::reset).
365381///
366382/// See <https://github.com/gfx-rs/wgpu/pull/7338> for benchmarks.
367- pub static RESERVED_SET : RacyLock < KeywordSet > = RacyLock :: new ( || KeywordSet :: from_iter ( RESERVED ) ) ;
383+ pub static RESERVED_SET : RacyLock < KeywordSet > = RacyLock :: new ( || {
384+ let mut set = KeywordSet :: from_iter ( RESERVED ) ;
385+ // Add all concrete integer dot product function variants.
386+ // These are generated to match the names produced by
387+ // `Writer::get_dot_wrapper_function_helper_name`, ensuring they stay in sync.
388+ let mut dot_function_names: Vec < & ' static str > = Vec :: new ( ) ;
389+ for scalar in CONCRETE_INTEGER_SCALARS {
390+ // Map scalar to MSL type name (matching the logic in Scalar::to_msl_name)
391+ let type_name = match scalar {
392+ crate :: Scalar {
393+ kind : crate :: ScalarKind :: Sint ,
394+ width : 4 ,
395+ } => "int" ,
396+ crate :: Scalar {
397+ kind : crate :: ScalarKind :: Uint ,
398+ width : 4 ,
399+ } => "uint" ,
400+ crate :: Scalar {
401+ kind : crate :: ScalarKind :: Sint ,
402+ width : 8 ,
403+ } => "long" ,
404+ crate :: Scalar {
405+ kind : crate :: ScalarKind :: Uint ,
406+ width : 8 ,
407+ } => "ulong" ,
408+ _ => continue , // Skip non-integer or unsupported types
409+ } ;
410+
411+ for size in CONCRETE_VECTOR_SIZES {
412+ let size_suffix = common:: vector_size_str ( size) ;
413+ let fun_name = format ! (
414+ "{}_{}{}" ,
415+ super :: writer:: DOT_FUNCTION_PREFIX ,
416+ type_name,
417+ size_suffix
418+ ) ;
419+ // Convert to &'static str by leaking the String
420+ // (In theory) This is safe because these are generated once and cached
421+ let leaked = Box :: leak ( fun_name. into_boxed_str ( ) ) ;
422+ dot_function_names. push ( leaked) ;
423+ }
424+ }
425+ set. extend ( dot_function_names. into_iter ( ) ) ;
426+ set
427+ } ) ;
0 commit comments