Skip to content

Commit

Permalink
Naga 0.20 (#87)
Browse files Browse the repository at this point in the history
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 <50659922+robtfm@users.noreply.github.com>
  • Loading branch information
Elabajaba and robtfm committed May 28, 2024
1 parent 37a472c commit 93c1a64
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 176 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ prune = []
allow_deprecated = []

[dependencies]
naga = { version = "0.19.0", features = ["wgsl-in", "wgsl-out", "clone"] }
naga = { version = "0.20", features = ["wgsl-in", "wgsl-out"] }
tracing = "0.1"
regex = "1.8"
regex-syntax = "0.8"
Expand All @@ -31,6 +31,6 @@ once_cell = "1.17.0"
indexmap = "2"

[dev-dependencies]
wgpu = { version = "0.19.0", features = ["naga-ir"] }
wgpu = { version = "0.20", features = ["naga-ir"] }
futures-lite = "1"
tracing-subscriber = { version = "0.3", features = ["std", "fmt"] }
4 changes: 2 additions & 2 deletions examples/pbr_compose_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ fn test_compose_full() -> Result<naga::Module, ComposerError> {
}) {
Ok(module) => {
// println!("shader: {:#?}", module);
// let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), naga::valid::Capabilities::default()).validate(&module).unwrap();
// let info = composer.create_validator().validate(&module).unwrap();
// let _wgsl = naga::back::wgsl::write_string(&module, &info, naga::back::wgsl::WriterFlags::EXPLICIT_TYPES).unwrap();
// println!("wgsl: \n\n{}", wgsl);
Ok(module)
Expand All @@ -120,7 +120,7 @@ fn test_compose_final_module(n: usize, composer: &mut Composer) {
}) {
Ok(module) => {
// println!("shader: {:#?}", module);
// let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), naga::valid::Capabilities::default()).validate(&module).unwrap();
// let info = composer.create_validator().validate(&module).unwrap();
// let _wgsl = naga::back::wgsl::write_string(&module, &info, naga::back::wgsl::WriterFlags::EXPLICIT_TYPES).unwrap();
// println!("wgsl: \n\n{}", wgsl);
Ok(module)
Expand Down
5 changes: 3 additions & 2 deletions src/compose/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub enum ComposerErrorInner {
WgslParseError(naga::front::wgsl::ParseError),
#[cfg(feature = "glsl")]
#[error("{0:?}")]
GlslParseError(Vec<naga::front::glsl::Error>),
GlslParseError(naga::front::glsl::ParseError),
#[error("naga_oil bug, please file a report: failed to convert imported module IR back into WGSL for use with WGSL shaders: {0}")]
WgslBackError(naga::back::wgsl::Error),
#[cfg(feature = "glsl")]
Expand Down Expand Up @@ -226,7 +226,8 @@ impl ComposerError {
),
#[cfg(feature = "glsl")]
ComposerErrorInner::GlslParseError(e) => (
e.iter()
e.errors
.iter()
.map(|naga::front::glsl::Error { kind, meta }| {
Label::primary((), map_span(meta.to_range().unwrap_or(0..0)))
.with_message(kind.to_string())
Expand Down
83 changes: 68 additions & 15 deletions src/compose/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ use indexmap::IndexMap;
///
/// 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.
///
use naga::EntryPoint;
use naga::{
valid::{Capabilities, ShaderStages},
EntryPoint,
};
use regex::Regex;
use std::collections::{hash_map::Entry, BTreeMap, HashMap, HashSet};
use tracing::{debug, trace};
Expand Down Expand Up @@ -318,6 +321,11 @@ pub struct Composer {
pub module_sets: HashMap<String, ComposableModuleDefinition>,
pub module_index: HashMap<usize, String>,
pub capabilities: naga::valid::Capabilities,
/// The shader stages that the subgroup operations are valid for.
/// Used when creating a validator for the module.
/// See https://github.com/gfx-rs/wgpu/blob/d9c054c645af0ea9ef81617c3e762fbf0f3fecda/wgpu-core/src/device/mod.rs#L515
/// for how to set this for proper subgroup ops support.
pub subgroup_stages: ShaderStages,
preprocessor: Preprocessor,
check_decoration_regex: Regex,
undecorate_regex: Regex,
Expand All @@ -339,6 +347,7 @@ impl Default for Composer {
Self {
validate: true,
capabilities: Default::default(),
subgroup_stages: ShaderStages::empty(),
module_sets: Default::default(),
module_index: Default::default(),
preprocessor: Preprocessor::default(),
Expand Down Expand Up @@ -417,6 +426,21 @@ impl Composer {
String::from_utf8(data_encoding::BASE32_NOPAD.decode(from.as_bytes()).unwrap()).unwrap()
}

/// This creates a validator that properly detects subgroup support.
fn create_validator(&self) -> naga::valid::Validator {
let subgroup_operations = if self.capabilities.contains(Capabilities::SUBGROUP) {
use naga::valid::SubgroupOperationSet as S;
S::BASIC | S::VOTE | S::ARITHMETIC | S::BALLOT | S::SHUFFLE | S::SHUFFLE_RELATIVE
} else {
naga::valid::SubgroupOperationSet::empty()
};
let mut validator =
naga::valid::Validator::new(naga::valid::ValidationFlags::all(), self.capabilities);
validator.subgroup_stages(self.subgroup_stages);
validator.subgroup_operations(subgroup_operations);
validator
}

fn undecorate(&self, string: &str) -> String {
let undecor = self
.undecorate_regex
Expand Down Expand Up @@ -476,10 +500,10 @@ impl Composer {
#[allow(unused)] header_for: &str, // Only used when GLSL is enabled
) -> Result<String, ComposerErrorInner> {
// TODO: cache headers again
let info =
naga::valid::Validator::new(naga::valid::ValidationFlags::all(), self.capabilities)
.validate(naga_module)
.map_err(ComposerErrorInner::HeaderValidationError)?;
let info = self
.create_validator()
.validate(naga_module)
.map_err(ComposerErrorInner::HeaderValidationError)?;

match language {
ShaderLanguage::Wgsl => naga::back::wgsl::write_string(
Expand Down Expand Up @@ -526,12 +550,10 @@ impl Composer {

naga_module.entry_points.push(ep);

let info = naga::valid::Validator::new(
naga::valid::ValidationFlags::all(),
self.capabilities,
)
.validate(naga_module)
.map_err(ComposerErrorInner::HeaderValidationError)?;
let info = self
.create_validator()
.validate(naga_module)
.map_err(ComposerErrorInner::HeaderValidationError)?;

let mut string = String::new();
let options = naga::back::glsl::Options {
Expand Down Expand Up @@ -1002,6 +1024,17 @@ impl Composer {
}
}

// These are naga/wgpu's pipeline override constants, not naga_oil's overrides
let mut owned_pipeline_overrides = IndexMap::new();
for (h, po) in source_ir.overrides.iter_mut() {
if let Some(name) = po.name.as_mut() {
if !name.contains(DECORATION_PRE) {
*name = format!("{name}{module_decoration}");
owned_pipeline_overrides.insert(name.clone(), h);
}
}
}

let mut owned_vars = IndexMap::new();
for (h, gv) in source_ir.global_variables.iter_mut() {
if let Some(name) = gv.name.as_mut() {
Expand Down Expand Up @@ -1101,6 +1134,11 @@ impl Composer {
module_builder.import_const(h);
}

for h in owned_pipeline_overrides.values() {
header_builder.import_pipeline_override(h);
module_builder.import_pipeline_override(h);
}

for h in owned_vars.values() {
header_builder.import_global(h);
module_builder.import_global(h);
Expand Down Expand Up @@ -1226,6 +1264,16 @@ impl Composer {
}
}

for (h, po) in source_ir.overrides.iter() {
if let Some(name) = &po.name {
if composable.owned_functions.contains(name)
&& items.map_or(true, |items| items.contains(name))
{
derived.import_pipeline_override(&h);
}
}
}

for (h, v) in source_ir.global_variables.iter() {
if let Some(name) = &v.name {
if composable.owned_vars.contains(name)
Expand Down Expand Up @@ -1385,10 +1433,17 @@ impl Composer {

/// specify capabilities to be used for naga module generation.
/// purges any existing modules
pub fn with_capabilities(self, capabilities: naga::valid::Capabilities) -> Self {
/// See https://github.com/gfx-rs/wgpu/blob/d9c054c645af0ea9ef81617c3e762fbf0f3fecda/wgpu-core/src/device/mod.rs#L515
/// for how to set the subgroup_stages value.
pub fn with_capabilities(
self,
capabilities: naga::valid::Capabilities,
subgroup_stages: naga::valid::ShaderStages,
) -> Self {
Self {
capabilities,
validate: self.validate,
subgroup_stages,
..Default::default()
}
}
Expand Down Expand Up @@ -1748,9 +1803,7 @@ impl Composer {

// validation
if self.validate {
let info =
naga::valid::Validator::new(naga::valid::ValidationFlags::all(), self.capabilities)
.validate(&naga_module);
let info = self.create_validator().validate(&naga_module);
match info {
Ok(_) => Ok(naga_module),
Err(e) => {
Expand Down
Loading

0 comments on commit 93c1a64

Please sign in to comment.