@@ -5,11 +5,16 @@ use std::cmp::Ordering;
55use std:: fmt:: { Debug , Display , Formatter } ;
66use std:: ops:: { Deref , DerefMut } ;
77use std:: str:: FromStr ;
8+ use strum:: { Display , EnumString , IntoStaticStr } ;
89
910#[ derive( Clone , Eq , PartialEq ) ]
1011pub enum TargetError {
12+ /// If during parsing a target variant returns `UnknownTarget`, further variants will attempt to parse the string.
13+ /// Returning another error means that you have recognized the target but something else is invalid, and we should
14+ /// abort the parsing with your error.
1115 UnknownTarget ( String ) ,
1216 InvalidTargetVersion ( SpirvTarget ) ,
17+ InvalidNagaVariant ( String ) ,
1318}
1419
1520impl Display for TargetError {
@@ -21,6 +26,9 @@ impl Display for TargetError {
2126 TargetError :: InvalidTargetVersion ( target) => {
2227 write ! ( f, "Invalid version in target `{}`" , target. env( ) )
2328 }
29+ TargetError :: InvalidNagaVariant ( target) => {
30+ write ! ( f, "Unknown naga out variant `{target}`" )
31+ }
2432 }
2533 }
2634}
@@ -439,13 +447,71 @@ impl Display for OpenGLTarget {
439447 }
440448}
441449
450+ /// A naga target
451+ #[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
452+ pub struct NagaTarget {
453+ pub out : NagaOut ,
454+ }
455+
456+ #[ derive( Copy , Clone , Debug , Eq , PartialEq , IntoStaticStr , Display , EnumString ) ]
457+ #[ allow( clippy:: upper_case_acronyms) ]
458+ pub enum NagaOut {
459+ #[ strum( to_string = "wgsl" ) ]
460+ WGSL ,
461+ }
462+
463+ impl NagaTarget {
464+ pub const NAGA_WGSL : Self = NagaTarget :: new ( NagaOut :: WGSL ) ;
465+ pub const ALL_NAGA_TARGETS : & ' static [ Self ] = & [ Self :: NAGA_WGSL ] ;
466+ /// emit spirv like naga targets were this target
467+ pub const EMIT_SPIRV_LIKE : SpirvTarget = SpirvTarget :: VULKAN_1_3 ;
468+
469+ pub const fn new ( out : NagaOut ) -> Self {
470+ Self { out }
471+ }
472+ }
473+
474+ impl SpirvTargetVariant for NagaTarget {
475+ fn validate ( & self ) -> Result < ( ) , TargetError > {
476+ Ok ( ( ) )
477+ }
478+
479+ fn to_spirv_tools ( & self ) -> spirv_tools:: TargetEnv {
480+ Self :: EMIT_SPIRV_LIKE . to_spirv_tools ( )
481+ }
482+
483+ fn spirv_version ( & self ) -> SpirvVersion {
484+ Self :: EMIT_SPIRV_LIKE . spirv_version ( )
485+ }
486+ }
487+
488+ impl FromStr for NagaTarget {
489+ type Err = TargetError ;
490+
491+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
492+ let s = s
493+ . strip_prefix ( "naga-" )
494+ . ok_or_else ( || TargetError :: UnknownTarget ( s. to_owned ( ) ) ) ?;
495+ Ok ( Self :: new ( FromStr :: from_str ( s) . map_err ( |_e| {
496+ TargetError :: InvalidNagaVariant ( s. to_owned ( ) )
497+ } ) ?) )
498+ }
499+ }
500+
501+ impl Display for NagaTarget {
502+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
503+ write ! ( f, "naga-{}" , self . out)
504+ }
505+ }
506+
442507/// A rust-gpu target
443508#[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
444509#[ non_exhaustive]
445510pub enum SpirvTarget {
446511 Universal ( UniversalTarget ) ,
447512 Vulkan ( VulkanTarget ) ,
448513 OpenGL ( OpenGLTarget ) ,
514+ Naga ( NagaTarget ) ,
449515}
450516
451517impl SpirvTarget {
@@ -467,12 +533,15 @@ impl SpirvTarget {
467533 pub const OPENGL_4_2 : Self = Self :: OpenGL ( OpenGLTarget :: OPENGL_4_2 ) ;
468534 pub const OPENGL_4_3 : Self = Self :: OpenGL ( OpenGLTarget :: OPENGL_4_3 ) ;
469535 pub const OPENGL_4_5 : Self = Self :: OpenGL ( OpenGLTarget :: OPENGL_4_5 ) ;
536+ pub const NAGA_WGSL : Self = Self :: Naga ( NagaTarget :: NAGA_WGSL ) ;
470537
538+ #[ allow( clippy:: match_same_arms) ]
471539 pub const fn memory_model ( & self ) -> MemoryModel {
472540 match self {
473541 SpirvTarget :: Universal ( _) => MemoryModel :: Simple ,
474542 SpirvTarget :: Vulkan ( _) => MemoryModel :: Vulkan ,
475543 SpirvTarget :: OpenGL ( _) => MemoryModel :: GLSL450 ,
544+ SpirvTarget :: Naga ( _) => MemoryModel :: Vulkan ,
476545 }
477546 }
478547}
@@ -483,6 +552,7 @@ impl SpirvTargetVariant for SpirvTarget {
483552 SpirvTarget :: Universal ( t) => t. validate ( ) ,
484553 SpirvTarget :: Vulkan ( t) => t. validate ( ) ,
485554 SpirvTarget :: OpenGL ( t) => t. validate ( ) ,
555+ SpirvTarget :: Naga ( t) => t. validate ( ) ,
486556 }
487557 }
488558
@@ -491,6 +561,7 @@ impl SpirvTargetVariant for SpirvTarget {
491561 SpirvTarget :: Universal ( t) => t. to_spirv_tools ( ) ,
492562 SpirvTarget :: Vulkan ( t) => t. to_spirv_tools ( ) ,
493563 SpirvTarget :: OpenGL ( t) => t. to_spirv_tools ( ) ,
564+ SpirvTarget :: Naga ( t) => t. to_spirv_tools ( ) ,
494565 }
495566 }
496567
@@ -499,6 +570,7 @@ impl SpirvTargetVariant for SpirvTarget {
499570 SpirvTarget :: Universal ( t) => t. spirv_version ( ) ,
500571 SpirvTarget :: Vulkan ( t) => t. spirv_version ( ) ,
501572 SpirvTarget :: OpenGL ( t) => t. spirv_version ( ) ,
573+ SpirvTarget :: Naga ( t) => t. spirv_version ( ) ,
502574 }
503575 }
504576}
@@ -513,6 +585,9 @@ impl SpirvTarget {
513585 if matches ! ( result, Err ( TargetError :: UnknownTarget ( ..) ) ) {
514586 result = OpenGLTarget :: from_str ( s) . map ( Self :: OpenGL ) ;
515587 }
588+ if matches ! ( result, Err ( TargetError :: UnknownTarget ( ..) ) ) {
589+ result = NagaTarget :: from_str ( s) . map ( Self :: Naga ) ;
590+ }
516591 result
517592 }
518593
@@ -533,6 +608,7 @@ impl SpirvTarget {
533608 SpirvTarget :: Universal ( t) => t. to_string ( ) ,
534609 SpirvTarget :: Vulkan ( t) => t. to_string ( ) ,
535610 SpirvTarget :: OpenGL ( t) => t. to_string ( ) ,
611+ SpirvTarget :: Naga ( t) => t. to_string ( ) ,
536612 }
537613 }
538614
@@ -555,6 +631,7 @@ impl SpirvTarget {
555631 . iter ( )
556632 . map ( |t| Self :: OpenGL ( * t) ) ,
557633 )
634+ . chain ( NagaTarget :: ALL_NAGA_TARGETS . iter ( ) . map ( |t| Self :: Naga ( * t) ) )
558635 }
559636}
560637
0 commit comments