@@ -126,7 +126,10 @@ use indexmap::IndexMap;
126
126
///
127
127
/// codespan reporting for errors is available using the error `emit_to_string` method. this requires validation to be enabled, which is true by default. `Composer::non_validating()` produces a non-validating composer that is not able to give accurate error reporting.
128
128
///
129
- use naga:: EntryPoint ;
129
+ use naga:: {
130
+ valid:: { Capabilities , ShaderStages } ,
131
+ EntryPoint ,
132
+ } ;
130
133
use regex:: Regex ;
131
134
use std:: collections:: { hash_map:: Entry , BTreeMap , HashMap , HashSet } ;
132
135
use tracing:: { debug, trace} ;
@@ -318,6 +321,11 @@ pub struct Composer {
318
321
pub module_sets : HashMap < String , ComposableModuleDefinition > ,
319
322
pub module_index : HashMap < usize , String > ,
320
323
pub capabilities : naga:: valid:: Capabilities ,
324
+ /// The shader stages that the subgroup operations are valid for.
325
+ /// Used when creating a validator for the module.
326
+ /// See https://github.com/gfx-rs/wgpu/blob/d9c054c645af0ea9ef81617c3e762fbf0f3fecda/wgpu-core/src/device/mod.rs#L515
327
+ /// for how to set this for proper subgroup ops support.
328
+ pub subgroup_stages : ShaderStages ,
321
329
preprocessor : Preprocessor ,
322
330
check_decoration_regex : Regex ,
323
331
undecorate_regex : Regex ,
@@ -339,6 +347,7 @@ impl Default for Composer {
339
347
Self {
340
348
validate : true ,
341
349
capabilities : Default :: default ( ) ,
350
+ subgroup_stages : ShaderStages :: empty ( ) ,
342
351
module_sets : Default :: default ( ) ,
343
352
module_index : Default :: default ( ) ,
344
353
preprocessor : Preprocessor :: default ( ) ,
@@ -417,6 +426,21 @@ impl Composer {
417
426
String :: from_utf8 ( data_encoding:: BASE32_NOPAD . decode ( from. as_bytes ( ) ) . unwrap ( ) ) . unwrap ( )
418
427
}
419
428
429
+ /// This creates a validator that properly detects subgroup support.
430
+ fn create_validator ( & self ) -> naga:: valid:: Validator {
431
+ let subgroup_operations = if self . capabilities . contains ( Capabilities :: SUBGROUP ) {
432
+ use naga:: valid:: SubgroupOperationSet as S ;
433
+ S :: BASIC | S :: VOTE | S :: ARITHMETIC | S :: BALLOT | S :: SHUFFLE | S :: SHUFFLE_RELATIVE
434
+ } else {
435
+ naga:: valid:: SubgroupOperationSet :: empty ( )
436
+ } ;
437
+ let mut validator =
438
+ naga:: valid:: Validator :: new ( naga:: valid:: ValidationFlags :: all ( ) , self . capabilities ) ;
439
+ validator. subgroup_stages ( self . subgroup_stages ) ;
440
+ validator. subgroup_operations ( subgroup_operations) ;
441
+ validator
442
+ }
443
+
420
444
fn undecorate ( & self , string : & str ) -> String {
421
445
let undecor = self
422
446
. undecorate_regex
@@ -476,10 +500,10 @@ impl Composer {
476
500
#[ allow( unused) ] header_for : & str , // Only used when GLSL is enabled
477
501
) -> Result < String , ComposerErrorInner > {
478
502
// TODO: cache headers again
479
- let info =
480
- naga :: valid :: Validator :: new ( naga :: valid :: ValidationFlags :: all ( ) , self . capabilities )
481
- . validate ( naga_module)
482
- . map_err ( ComposerErrorInner :: HeaderValidationError ) ?;
503
+ let info = self
504
+ . create_validator ( )
505
+ . validate ( naga_module)
506
+ . map_err ( ComposerErrorInner :: HeaderValidationError ) ?;
483
507
484
508
match language {
485
509
ShaderLanguage :: Wgsl => naga:: back:: wgsl:: write_string (
@@ -526,12 +550,10 @@ impl Composer {
526
550
527
551
naga_module. entry_points . push ( ep) ;
528
552
529
- let info = naga:: valid:: Validator :: new (
530
- naga:: valid:: ValidationFlags :: all ( ) ,
531
- self . capabilities ,
532
- )
533
- . validate ( naga_module)
534
- . map_err ( ComposerErrorInner :: HeaderValidationError ) ?;
553
+ let info = self
554
+ . create_validator ( )
555
+ . validate ( naga_module)
556
+ . map_err ( ComposerErrorInner :: HeaderValidationError ) ?;
535
557
536
558
let mut string = String :: new ( ) ;
537
559
let options = naga:: back:: glsl:: Options {
@@ -1002,6 +1024,17 @@ impl Composer {
1002
1024
}
1003
1025
}
1004
1026
1027
+ // These are naga/wgpu's pipeline override constants, not naga_oil's overrides
1028
+ let mut owned_pipeline_overrides = IndexMap :: new ( ) ;
1029
+ for ( h, po) in source_ir. overrides . iter_mut ( ) {
1030
+ if let Some ( name) = po. name . as_mut ( ) {
1031
+ if !name. contains ( DECORATION_PRE ) {
1032
+ * name = format ! ( "{name}{module_decoration}" ) ;
1033
+ owned_pipeline_overrides. insert ( name. clone ( ) , h) ;
1034
+ }
1035
+ }
1036
+ }
1037
+
1005
1038
let mut owned_vars = IndexMap :: new ( ) ;
1006
1039
for ( h, gv) in source_ir. global_variables . iter_mut ( ) {
1007
1040
if let Some ( name) = gv. name . as_mut ( ) {
@@ -1101,6 +1134,11 @@ impl Composer {
1101
1134
module_builder. import_const ( h) ;
1102
1135
}
1103
1136
1137
+ for h in owned_pipeline_overrides. values ( ) {
1138
+ header_builder. import_pipeline_override ( h) ;
1139
+ module_builder. import_pipeline_override ( h) ;
1140
+ }
1141
+
1104
1142
for h in owned_vars. values ( ) {
1105
1143
header_builder. import_global ( h) ;
1106
1144
module_builder. import_global ( h) ;
@@ -1226,6 +1264,16 @@ impl Composer {
1226
1264
}
1227
1265
}
1228
1266
1267
+ for ( h, po) in source_ir. overrides . iter ( ) {
1268
+ if let Some ( name) = & po. name {
1269
+ if composable. owned_functions . contains ( name)
1270
+ && items. map_or ( true , |items| items. contains ( name) )
1271
+ {
1272
+ derived. import_pipeline_override ( & h) ;
1273
+ }
1274
+ }
1275
+ }
1276
+
1229
1277
for ( h, v) in source_ir. global_variables . iter ( ) {
1230
1278
if let Some ( name) = & v. name {
1231
1279
if composable. owned_vars . contains ( name)
@@ -1385,10 +1433,17 @@ impl Composer {
1385
1433
1386
1434
/// specify capabilities to be used for naga module generation.
1387
1435
/// purges any existing modules
1388
- pub fn with_capabilities ( self , capabilities : naga:: valid:: Capabilities ) -> Self {
1436
+ /// See https://github.com/gfx-rs/wgpu/blob/d9c054c645af0ea9ef81617c3e762fbf0f3fecda/wgpu-core/src/device/mod.rs#L515
1437
+ /// for how to set the subgroup_stages value.
1438
+ pub fn with_capabilities (
1439
+ self ,
1440
+ capabilities : naga:: valid:: Capabilities ,
1441
+ subgroup_stages : naga:: valid:: ShaderStages ,
1442
+ ) -> Self {
1389
1443
Self {
1390
1444
capabilities,
1391
1445
validate : self . validate ,
1446
+ subgroup_stages,
1392
1447
..Default :: default ( )
1393
1448
}
1394
1449
}
@@ -1748,9 +1803,7 @@ impl Composer {
1748
1803
1749
1804
// validation
1750
1805
if self . validate {
1751
- let info =
1752
- naga:: valid:: Validator :: new ( naga:: valid:: ValidationFlags :: all ( ) , self . capabilities )
1753
- . validate ( & naga_module) ;
1806
+ let info = self . create_validator ( ) . validate ( & naga_module) ;
1754
1807
match info {
1755
1808
Ok ( _) => Ok ( naga_module) ,
1756
1809
Err ( e) => {
0 commit comments