Skip to content

Commit 93c1a64

Browse files
Elabajabarobtfm
andauthored
Naga 0.20 (#87)
Pipeline override constants will be fully implemented in a followup PR. They're theoretically working, but they need tests and also need a function to map the unmangled names to the mangled names. Otherwise this appears to work. I've tested it with bevy and everything seemed to work. --------- Co-authored-by: robtfm <[email protected]>
1 parent 37a472c commit 93c1a64

File tree

9 files changed

+266
-176
lines changed

9 files changed

+266
-176
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ prune = []
1717
allow_deprecated = []
1818

1919
[dependencies]
20-
naga = { version = "0.19.0", features = ["wgsl-in", "wgsl-out", "clone"] }
20+
naga = { version = "0.20", features = ["wgsl-in", "wgsl-out"] }
2121
tracing = "0.1"
2222
regex = "1.8"
2323
regex-syntax = "0.8"
@@ -31,6 +31,6 @@ once_cell = "1.17.0"
3131
indexmap = "2"
3232

3333
[dev-dependencies]
34-
wgpu = { version = "0.19.0", features = ["naga-ir"] }
34+
wgpu = { version = "0.20", features = ["naga-ir"] }
3535
futures-lite = "1"
3636
tracing-subscriber = { version = "0.3", features = ["std", "fmt"] }

examples/pbr_compose_test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ fn test_compose_full() -> Result<naga::Module, ComposerError> {
9696
}) {
9797
Ok(module) => {
9898
// println!("shader: {:#?}", module);
99-
// let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), naga::valid::Capabilities::default()).validate(&module).unwrap();
99+
// let info = composer.create_validator().validate(&module).unwrap();
100100
// let _wgsl = naga::back::wgsl::write_string(&module, &info, naga::back::wgsl::WriterFlags::EXPLICIT_TYPES).unwrap();
101101
// println!("wgsl: \n\n{}", wgsl);
102102
Ok(module)
@@ -120,7 +120,7 @@ fn test_compose_final_module(n: usize, composer: &mut Composer) {
120120
}) {
121121
Ok(module) => {
122122
// println!("shader: {:#?}", module);
123-
// let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), naga::valid::Capabilities::default()).validate(&module).unwrap();
123+
// let info = composer.create_validator().validate(&module).unwrap();
124124
// let _wgsl = naga::back::wgsl::write_string(&module, &info, naga::back::wgsl::WriterFlags::EXPLICIT_TYPES).unwrap();
125125
// println!("wgsl: \n\n{}", wgsl);
126126
Ok(module)

src/compose/error.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub enum ComposerErrorInner {
7878
WgslParseError(naga::front::wgsl::ParseError),
7979
#[cfg(feature = "glsl")]
8080
#[error("{0:?}")]
81-
GlslParseError(Vec<naga::front::glsl::Error>),
81+
GlslParseError(naga::front::glsl::ParseError),
8282
#[error("naga_oil bug, please file a report: failed to convert imported module IR back into WGSL for use with WGSL shaders: {0}")]
8383
WgslBackError(naga::back::wgsl::Error),
8484
#[cfg(feature = "glsl")]
@@ -226,7 +226,8 @@ impl ComposerError {
226226
),
227227
#[cfg(feature = "glsl")]
228228
ComposerErrorInner::GlslParseError(e) => (
229-
e.iter()
229+
e.errors
230+
.iter()
230231
.map(|naga::front::glsl::Error { kind, meta }| {
231232
Label::primary((), map_span(meta.to_range().unwrap_or(0..0)))
232233
.with_message(kind.to_string())

src/compose/mod.rs

+68-15
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ use indexmap::IndexMap;
126126
///
127127
/// 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.
128128
///
129-
use naga::EntryPoint;
129+
use naga::{
130+
valid::{Capabilities, ShaderStages},
131+
EntryPoint,
132+
};
130133
use regex::Regex;
131134
use std::collections::{hash_map::Entry, BTreeMap, HashMap, HashSet};
132135
use tracing::{debug, trace};
@@ -318,6 +321,11 @@ pub struct Composer {
318321
pub module_sets: HashMap<String, ComposableModuleDefinition>,
319322
pub module_index: HashMap<usize, String>,
320323
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,
321329
preprocessor: Preprocessor,
322330
check_decoration_regex: Regex,
323331
undecorate_regex: Regex,
@@ -339,6 +347,7 @@ impl Default for Composer {
339347
Self {
340348
validate: true,
341349
capabilities: Default::default(),
350+
subgroup_stages: ShaderStages::empty(),
342351
module_sets: Default::default(),
343352
module_index: Default::default(),
344353
preprocessor: Preprocessor::default(),
@@ -417,6 +426,21 @@ impl Composer {
417426
String::from_utf8(data_encoding::BASE32_NOPAD.decode(from.as_bytes()).unwrap()).unwrap()
418427
}
419428

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+
420444
fn undecorate(&self, string: &str) -> String {
421445
let undecor = self
422446
.undecorate_regex
@@ -476,10 +500,10 @@ impl Composer {
476500
#[allow(unused)] header_for: &str, // Only used when GLSL is enabled
477501
) -> Result<String, ComposerErrorInner> {
478502
// 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)?;
483507

484508
match language {
485509
ShaderLanguage::Wgsl => naga::back::wgsl::write_string(
@@ -526,12 +550,10 @@ impl Composer {
526550

527551
naga_module.entry_points.push(ep);
528552

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)?;
535557

536558
let mut string = String::new();
537559
let options = naga::back::glsl::Options {
@@ -1002,6 +1024,17 @@ impl Composer {
10021024
}
10031025
}
10041026

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+
10051038
let mut owned_vars = IndexMap::new();
10061039
for (h, gv) in source_ir.global_variables.iter_mut() {
10071040
if let Some(name) = gv.name.as_mut() {
@@ -1101,6 +1134,11 @@ impl Composer {
11011134
module_builder.import_const(h);
11021135
}
11031136

1137+
for h in owned_pipeline_overrides.values() {
1138+
header_builder.import_pipeline_override(h);
1139+
module_builder.import_pipeline_override(h);
1140+
}
1141+
11041142
for h in owned_vars.values() {
11051143
header_builder.import_global(h);
11061144
module_builder.import_global(h);
@@ -1226,6 +1264,16 @@ impl Composer {
12261264
}
12271265
}
12281266

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+
12291277
for (h, v) in source_ir.global_variables.iter() {
12301278
if let Some(name) = &v.name {
12311279
if composable.owned_vars.contains(name)
@@ -1385,10 +1433,17 @@ impl Composer {
13851433

13861434
/// specify capabilities to be used for naga module generation.
13871435
/// 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 {
13891443
Self {
13901444
capabilities,
13911445
validate: self.validate,
1446+
subgroup_stages,
13921447
..Default::default()
13931448
}
13941449
}
@@ -1748,9 +1803,7 @@ impl Composer {
17481803

17491804
// validation
17501805
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);
17541807
match info {
17551808
Ok(_) => Ok(naga_module),
17561809
Err(e) => {

0 commit comments

Comments
 (0)