Update naga to 323999f, report pretty errors in shader validation (#2141)

This commit is contained in:
Dzmitry Malyshau 2021-11-01 16:57:33 -04:00 committed by GitHub
parent 8a76920349
commit ca7ca749cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 87 additions and 49 deletions

6
Cargo.lock generated
View File

@ -983,9 +983,8 @@ dependencies = [
[[package]]
name = "naga"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "032288733590c094012e5f1dec15848be90015bb9b3fd16743d84ea582c4154a"
version = "0.7.1"
source = "git+https://github.com/gfx-rs/naga?rev=323999f#323999fcb9eb8e8c525d75d2878fe1e2e5a99aad"
dependencies = [
"bit-set",
"bitflags",
@ -1831,6 +1830,7 @@ dependencies = [
"arrayvec",
"bitflags",
"cfg_aliases",
"codespan-reporting",
"copyless",
"fxhash",
"log",

View File

@ -23,6 +23,7 @@ serial-pass = ["serde", "wgt/serde", "arrayvec/serde"]
[dependencies]
arrayvec = "0.7"
bitflags = "1.0"
codespan-reporting = "0.11"
copyless = "0.1"
fxhash = "0.2"
log = "0.4"
@ -35,10 +36,10 @@ smallvec = "1"
thiserror = "1"
[dependencies.naga]
#git = "https://github.com/gfx-rs/naga"
#rev = "9d2b357"
version = "0.7"
features = ["validate", "wgsl-in"]
git = "https://github.com/gfx-rs/naga"
rev = "323999f"
#version = "0.7"
features = ["span", "validate", "wgsl-in"]
[dependencies.wgt]
path = "../wgpu-types"

View File

@ -967,25 +967,19 @@ impl<A: HalApi> Device<A> {
desc: &pipeline::ShaderModuleDescriptor<'a>,
source: pipeline::ShaderModuleSource<'a>,
) -> Result<pipeline::ShaderModule<A>, pipeline::CreateShaderModuleError> {
let module = match source {
let (module, source) = match source {
pipeline::ShaderModuleSource::Wgsl(code) => {
profiling::scope!("naga::wgsl::parse_str");
// TODO: refactor the corresponding Naga error to be owned, and then
// display it instead of unwrapping
match naga::front::wgsl::parse_str(&code) {
Ok(module) => module,
Err(err) => {
log::error!("Failed to parse WGSL code for {:?}: {}", desc.label, err);
return Err(pipeline::CreateShaderModuleError::Parsing(
pipeline::NagaParseError {
shader_source: code.to_string(),
error: err,
},
));
}
}
let module = naga::front::wgsl::parse_str(&code).map_err(|inner| {
pipeline::CreateShaderModuleError::Parsing(pipeline::ShaderError {
source: code.to_string(),
label: desc.label.as_ref().map(|l| l.to_string()),
inner,
})
})?;
(module, code.into_owned())
}
pipeline::ShaderModuleSource::Naga(module) => module,
pipeline::ShaderModuleSource::Naga(module) => (module, String::new()),
};
use naga::valid::Capabilities as Caps;
@ -1006,7 +1000,14 @@ impl<A: HalApi> Device<A> {
.contains(wgt::Features::SHADER_PRIMITIVE_INDEX),
);
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
.validate(&module)?;
.validate(&module)
.map_err(|inner| {
pipeline::CreateShaderModuleError::Validation(pipeline::ShaderError {
source,
label: desc.label.as_ref().map(|l| l.to_string()),
inner,
})
})?;
let interface = validation::Interface::new(&module, &info, self.features);
let hal_shader = hal::ShaderInput::Naga(hal::NagaShader { module, info });

View File

@ -5,9 +5,10 @@ use crate::{
id::{DeviceId, PipelineLayoutId, ShaderModuleId},
validation, Label, LifeGuard, Stored,
};
use std::borrow::Cow;
use std::{borrow::Cow, fmt};
use thiserror::Error;
#[allow(clippy::large_enum_variant)]
pub enum ShaderModuleSource<'a> {
Wgsl(Cow<'a, str>),
Naga(naga::Module),
@ -46,30 +47,62 @@ impl<A: hal::Api> Resource for ShaderModule<A> {
}
#[derive(Clone, Debug, Error)]
pub struct NagaParseError {
pub shader_source: String,
pub error: naga::front::wgsl::ParseError,
pub struct ShaderError<E> {
pub source: String,
pub label: Option<String>,
#[source]
pub inner: E,
}
impl std::fmt::Display for NagaParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for ShaderError<naga::front::wgsl::ParseError> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let label = self.label.as_deref().unwrap_or_default();
let string = self.inner.emit_to_string(&self.source);
write!(f, "\nShader '{}' parsing {}", label, string)
}
}
impl fmt::Display for ShaderError<naga::WithSpan<naga::valid::ValidationError>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use codespan_reporting::{
diagnostic::{Diagnostic, Label},
files::SimpleFile,
term,
};
let label = self.label.as_deref().unwrap_or_default();
let files = SimpleFile::new(label, &self.source);
let config = term::Config::default();
let mut writer = term::termcolor::Ansi::new(Vec::new());
let diagnostic = Diagnostic::error().with_labels(
self.inner
.spans()
.map(|&(span, ref desc)| {
Label::primary((), span.to_range().unwrap()).with_message(desc.to_owned())
})
.collect(),
);
term::emit(&mut writer, &config, &files, &diagnostic).expect("cannot write error");
write!(
f,
"\nShader error:\n{}",
self.error.emit_to_string(&self.shader_source)
"\nShader validation {}",
String::from_utf8_lossy(&writer.into_inner())
)
}
}
#[derive(Clone, Debug, Error)]
//Note: `Clone` would require `WithSpan: Clone`.
#[derive(Debug, Error)]
pub enum CreateShaderModuleError {
#[error("Failed to parse a shader")]
Parsing(#[from] NagaParseError),
#[error(transparent)]
Parsing(#[from] ShaderError<naga::front::wgsl::ParseError>),
#[error("Failed to generate the backend-specific code")]
Generation,
#[error(transparent)]
Device(#[from] DeviceError),
#[error(transparent)]
Validation(#[from] naga::valid::ValidationError),
Validation(#[from] ShaderError<naga::WithSpan<naga::valid::ValidationError>>),
#[error(transparent)]
MissingFeatures(#[from] MissingFeatures),
}

View File

@ -74,14 +74,14 @@ web-sys = { version = "0.3", features = ["Window", "HtmlCanvasElement", "WebGl2R
js-sys = { version = "0.3" }
[dependencies.naga]
#git = "https://github.com/gfx-rs/naga"
#rev = "9d2b357"
version = "0.7"
git = "https://github.com/gfx-rs/naga"
rev = "323999f"
#version = "0.7"
[dev-dependencies.naga]
#git = "https://github.com/gfx-rs/naga"
#rev = "9d2b357"
version = "0.7"
git = "https://github.com/gfx-rs/naga"
rev = "323999f"
#version = "0.7"
features = ["wgsl-in"]
[dev-dependencies]

View File

@ -917,6 +917,7 @@ impl fmt::Debug for NagaShader {
}
/// Shader input.
#[allow(clippy::large_enum_variant)]
pub enum ShaderInput<'a> {
Naga(NagaShader),
SpirV(&'a [u32]),

View File

@ -134,20 +134,22 @@ pollster = "0.2"
env_logger = "0.8"
[dependencies.naga]
#git = "https://github.com/gfx-rs/naga"
#rev = "9d2b357"
version = "0.7"
git = "https://github.com/gfx-rs/naga"
rev = "323999f"
#version = "0.7"
optional = true
# used to test all the example shaders
[dev-dependencies.naga]
#git = "https://github.com/gfx-rs/naga"
#rev = "9d2b357"
version = "0.7"
git = "https://github.com/gfx-rs/naga"
rev = "323999f"
#version = "0.7"
features = ["wgsl-in"]
[target.'cfg(target_arch = "wasm32")'.dependencies.naga]
version = "0.7"
git = "https://github.com/gfx-rs/naga"
rev = "323999f"
#version = "0.7"
features = ["wgsl-out"]
[target.'cfg(target_arch = "wasm32")'.dependencies]