@@ -316,6 +316,11 @@ pub enum ProcessShaderError {
316
316
expected : String ,
317
317
value : String ,
318
318
} ,
319
+ #[ error( "Invalid shader def definition for '{shader_def_name}': {value}" ) ]
320
+ InvalidShaderDefDefinitionValue {
321
+ shader_def_name : String ,
322
+ value : String ,
323
+ } ,
319
324
}
320
325
321
326
pub struct ShaderImportProcessor {
@@ -388,6 +393,7 @@ pub struct ShaderProcessor {
388
393
else_ifdef_regex : Regex ,
389
394
else_regex : Regex ,
390
395
endif_regex : Regex ,
396
+ define_regex : Regex ,
391
397
def_regex : Regex ,
392
398
def_regex_delimited : Regex ,
393
399
}
@@ -397,10 +403,11 @@ impl Default for ShaderProcessor {
397
403
Self {
398
404
ifdef_regex : Regex :: new ( r"^\s*#\s*ifdef\s*([\w|\d|_]+)" ) . unwrap ( ) ,
399
405
ifndef_regex : Regex :: new ( r"^\s*#\s*ifndef\s*([\w|\d|_]+)" ) . unwrap ( ) ,
400
- ifop_regex : Regex :: new ( r"^\s*#\s*if\s*([\w|\d|_]+)\s*([^\s]*)\s*([\w|\d]+)" ) . unwrap ( ) ,
406
+ ifop_regex : Regex :: new ( r"^\s*#\s*if\s*([\w|\d|_]+)\s*([^\s]*)\s*([- \w|\d]+)" ) . unwrap ( ) ,
401
407
else_ifdef_regex : Regex :: new ( r"^\s*#\s*else\s+ifdef\s*([\w|\d|_]+)" ) . unwrap ( ) ,
402
408
else_regex : Regex :: new ( r"^\s*#\s*else" ) . unwrap ( ) ,
403
409
endif_regex : Regex :: new ( r"^\s*#\s*endif" ) . unwrap ( ) ,
410
+ define_regex : Regex :: new ( r"^\s*#\s*define\s*([\w|\d|_]+)\s*([-\w|\d]+)?" ) . unwrap ( ) ,
404
411
def_regex : Regex :: new ( r"#\s*([\w|\d|_]+)" ) . unwrap ( ) ,
405
412
def_regex_delimited : Regex :: new ( r"#\s*\{([\w|\d|_]+)\}" ) . unwrap ( ) ,
406
413
}
@@ -449,24 +456,34 @@ impl ShaderProcessor {
449
456
shader_defs : & [ ShaderDefVal ] ,
450
457
shaders : & HashMap < Handle < Shader > , Shader > ,
451
458
import_handles : & HashMap < ShaderImport , Handle < Shader > > ,
459
+ ) -> Result < ProcessedShader , ProcessShaderError > {
460
+ let mut shader_defs_unique =
461
+ HashMap :: < String , ShaderDefVal > :: from_iter ( shader_defs. iter ( ) . map ( |v| match v {
462
+ ShaderDefVal :: Bool ( k, _) | ShaderDefVal :: Int ( k, _) | ShaderDefVal :: UInt ( k, _) => {
463
+ ( k. clone ( ) , v. clone ( ) )
464
+ }
465
+ } ) ) ;
466
+ self . process_inner ( shader, & mut shader_defs_unique, shaders, import_handles)
467
+ }
468
+
469
+ fn process_inner (
470
+ & self ,
471
+ shader : & Shader ,
472
+ shader_defs_unique : & mut HashMap < String , ShaderDefVal > ,
473
+ shaders : & HashMap < Handle < Shader > , Shader > ,
474
+ import_handles : & HashMap < ShaderImport , Handle < Shader > > ,
452
475
) -> Result < ProcessedShader , ProcessShaderError > {
453
476
let shader_str = match & shader. source {
454
477
Source :: Wgsl ( source) => source. deref ( ) ,
455
478
Source :: Glsl ( source, _stage) => source. deref ( ) ,
456
479
Source :: SpirV ( source) => {
457
- if shader_defs . is_empty ( ) {
480
+ if shader_defs_unique . is_empty ( ) {
458
481
return Ok ( ProcessedShader :: SpirV ( source. clone ( ) ) ) ;
459
482
}
460
483
return Err ( ProcessShaderError :: ShaderFormatDoesNotSupportShaderDefs ) ;
461
484
}
462
485
} ;
463
486
464
- let shader_defs_unique =
465
- HashMap :: < String , ShaderDefVal > :: from_iter ( shader_defs. iter ( ) . map ( |v| match v {
466
- ShaderDefVal :: Bool ( k, _) | ShaderDefVal :: Int ( k, _) | ShaderDefVal :: UInt ( k, _) => {
467
- ( k. clone ( ) , v. clone ( ) )
468
- }
469
- } ) ) ;
470
487
let mut scopes = vec ! [ Scope :: new( true ) ] ;
471
488
let mut final_string = String :: new ( ) ;
472
489
for line in shader_str. lines ( ) {
@@ -544,6 +561,26 @@ impl ShaderProcessor {
544
561
let current_valid = scopes. last ( ) . unwrap ( ) . is_accepting_lines ( ) ;
545
562
546
563
scopes. push ( Scope :: new ( current_valid && new_scope) ) ;
564
+ } else if let Some ( cap) = self . define_regex . captures ( line) {
565
+ let def = cap. get ( 1 ) . unwrap ( ) ;
566
+ let name = def. as_str ( ) . to_string ( ) ;
567
+
568
+ if let Some ( val) = cap. get ( 2 ) {
569
+ if let Ok ( val) = val. as_str ( ) . parse :: < u32 > ( ) {
570
+ shader_defs_unique. insert ( name. clone ( ) , ShaderDefVal :: UInt ( name, val) ) ;
571
+ } else if let Ok ( val) = val. as_str ( ) . parse :: < i32 > ( ) {
572
+ shader_defs_unique. insert ( name. clone ( ) , ShaderDefVal :: Int ( name, val) ) ;
573
+ } else if let Ok ( val) = val. as_str ( ) . parse :: < bool > ( ) {
574
+ shader_defs_unique. insert ( name. clone ( ) , ShaderDefVal :: Bool ( name, val) ) ;
575
+ } else {
576
+ return Err ( ProcessShaderError :: InvalidShaderDefDefinitionValue {
577
+ shader_def_name : name,
578
+ value : val. as_str ( ) . to_string ( ) ,
579
+ } ) ;
580
+ }
581
+ } else {
582
+ shader_defs_unique. insert ( name. clone ( ) , ShaderDefVal :: Bool ( name, true ) ) ;
583
+ }
547
584
} else if let Some ( cap) = self . else_ifdef_regex . captures ( line) {
548
585
// When should we accept the code in an
549
586
//
@@ -627,7 +664,7 @@ impl ShaderProcessor {
627
664
shaders,
628
665
& import,
629
666
shader,
630
- shader_defs ,
667
+ shader_defs_unique ,
631
668
& mut final_string,
632
669
) ?;
633
670
} else if let Some ( cap) = SHADER_IMPORT_PROCESSOR
@@ -640,7 +677,7 @@ impl ShaderProcessor {
640
677
shaders,
641
678
& import,
642
679
shader,
643
- shader_defs ,
680
+ shader_defs_unique ,
644
681
& mut final_string,
645
682
) ?;
646
683
} else if SHADER_IMPORT_PROCESSOR
@@ -695,15 +732,15 @@ impl ShaderProcessor {
695
732
shaders : & HashMap < Handle < Shader > , Shader > ,
696
733
import : & ShaderImport ,
697
734
shader : & Shader ,
698
- shader_defs : & [ ShaderDefVal ] ,
735
+ shader_defs_unique : & mut HashMap < String , ShaderDefVal > ,
699
736
final_string : & mut String ,
700
737
) -> Result < ( ) , ProcessShaderError > {
701
738
let imported_shader = import_handles
702
739
. get ( import)
703
740
. and_then ( |handle| shaders. get ( handle) )
704
741
. ok_or_else ( || ProcessShaderError :: UnresolvedImport ( import. clone ( ) ) ) ?;
705
742
let imported_processed =
706
- self . process ( imported_shader, shader_defs , shaders, import_handles) ?;
743
+ self . process_inner ( imported_shader, shader_defs_unique , shaders, import_handles) ?;
707
744
708
745
match & shader. source {
709
746
Source :: Wgsl ( _) => {
@@ -2441,4 +2478,114 @@ fn vertex(
2441
2478
. unwrap ( ) ;
2442
2479
assert_eq ! ( result. get_wgsl_source( ) . unwrap( ) , EXPECTED_REPLACED ) ;
2443
2480
}
2481
+
2482
+ #[ test]
2483
+ fn process_shader_define_in_shader ( ) {
2484
+ #[ rustfmt:: skip]
2485
+ const WGSL : & str = r"
2486
+ #ifdef NOW_DEFINED
2487
+ defined at start
2488
+ #endif
2489
+ #define NOW_DEFINED
2490
+ #ifdef NOW_DEFINED
2491
+ defined at end
2492
+ #endif
2493
+ " ;
2494
+
2495
+ #[ rustfmt:: skip]
2496
+ const EXPECTED : & str = r"
2497
+ defined at end
2498
+ " ;
2499
+ let processor = ShaderProcessor :: default ( ) ;
2500
+ let result = processor
2501
+ . process (
2502
+ & Shader :: from_wgsl ( WGSL ) ,
2503
+ & [ ] ,
2504
+ & HashMap :: default ( ) ,
2505
+ & HashMap :: default ( ) ,
2506
+ )
2507
+ . unwrap ( ) ;
2508
+ assert_eq ! ( result. get_wgsl_source( ) . unwrap( ) , EXPECTED ) ;
2509
+ }
2510
+
2511
+ #[ test]
2512
+ fn process_shader_define_in_shader_with_value ( ) {
2513
+ #[ rustfmt:: skip]
2514
+ const WGSL : & str = r"
2515
+ #define DEFUINT 1
2516
+ #define DEFINT -1
2517
+ #define DEFBOOL false
2518
+ #if DEFUINT == 1
2519
+ uint: #DEFUINT
2520
+ #endif
2521
+ #if DEFINT == -1
2522
+ int: #DEFINT
2523
+ #endif
2524
+ #if DEFBOOL == false
2525
+ bool: #DEFBOOL
2526
+ #endif
2527
+ " ;
2528
+
2529
+ #[ rustfmt:: skip]
2530
+ const EXPECTED : & str = r"
2531
+ uint: 1
2532
+ int: -1
2533
+ bool: false
2534
+ " ;
2535
+ let processor = ShaderProcessor :: default ( ) ;
2536
+ let result = processor
2537
+ . process (
2538
+ & Shader :: from_wgsl ( WGSL ) ,
2539
+ & [ ] ,
2540
+ & HashMap :: default ( ) ,
2541
+ & HashMap :: default ( ) ,
2542
+ )
2543
+ . unwrap ( ) ;
2544
+ assert_eq ! ( result. get_wgsl_source( ) . unwrap( ) , EXPECTED ) ;
2545
+ }
2546
+
2547
+ #[ test]
2548
+ fn process_shader_define_across_imports ( ) {
2549
+ #[ rustfmt:: skip]
2550
+ const FOO : & str = r"
2551
+ #define IMPORTED
2552
+ " ;
2553
+ const BAR : & str = r"
2554
+ #IMPORTED
2555
+ " ;
2556
+ #[ rustfmt:: skip]
2557
+ const INPUT : & str = r"
2558
+ #import FOO
2559
+ #import BAR
2560
+ " ;
2561
+ #[ rustfmt:: skip]
2562
+ const EXPECTED : & str = r"
2563
+
2564
+
2565
+ true
2566
+ " ;
2567
+ let processor = ShaderProcessor :: default ( ) ;
2568
+ let mut shaders = HashMap :: default ( ) ;
2569
+ let mut import_handles = HashMap :: default ( ) ;
2570
+ {
2571
+ let foo_handle = HandleUntyped :: weak_from_u64 ( Shader :: TYPE_UUID , 0 ) . typed ( ) ;
2572
+ shaders. insert ( foo_handle. clone_weak ( ) , Shader :: from_wgsl ( FOO ) ) ;
2573
+ import_handles. insert (
2574
+ ShaderImport :: Custom ( "FOO" . to_string ( ) ) ,
2575
+ foo_handle. clone_weak ( ) ,
2576
+ ) ;
2577
+ }
2578
+ {
2579
+ let bar_handle = HandleUntyped :: weak_from_u64 ( Shader :: TYPE_UUID , 1 ) . typed ( ) ;
2580
+ shaders. insert ( bar_handle. clone_weak ( ) , Shader :: from_wgsl ( BAR ) ) ;
2581
+ import_handles. insert (
2582
+ ShaderImport :: Custom ( "BAR" . to_string ( ) ) ,
2583
+ bar_handle. clone_weak ( ) ,
2584
+ ) ;
2585
+ }
2586
+ let result = processor
2587
+ . process ( & Shader :: from_wgsl ( INPUT ) , & [ ] , & shaders, & import_handles)
2588
+ . unwrap ( ) ;
2589
+ assert_eq ! ( result. get_wgsl_source( ) . unwrap( ) , EXPECTED ) ;
2590
+ }
2444
2591
}
0 commit comments