mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Add stderr and termcolor features to Naga (#7482)
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com> Co-authored-by: Erich Gubler <erichdongubler@gmail.com>
This commit is contained in:
parent
6666d528b2
commit
bf8cc43a15
@ -351,6 +351,7 @@ By @cwfitzgerald in [#6811](https://github.com/gfx-rs/wgpu/pull/6811), [#6815](h
|
|||||||
- Refactored `use` statements to simplify future `no_std` support. By @bushrat011899 in [#7256](https://github.com/gfx-rs/wgpu/pull/7256)
|
- Refactored `use` statements to simplify future `no_std` support. By @bushrat011899 in [#7256](https://github.com/gfx-rs/wgpu/pull/7256)
|
||||||
- Naga's WGSL frontend no longer allows using the `&` operator to take the address of a component of a vector,
|
- Naga's WGSL frontend no longer allows using the `&` operator to take the address of a component of a vector,
|
||||||
which is not permitted by the WGSL specification. By @andyleiserson in [#7284](https://github.com/gfx-rs/wgpu/pull/7284)
|
which is not permitted by the WGSL specification. By @andyleiserson in [#7284](https://github.com/gfx-rs/wgpu/pull/7284)
|
||||||
|
- Naga's use of `termcolor` and `stderr` are now optional behind features of the same names. By @bushrat011899 in [#7482](https://github.com/gfx-rs/wgpu/pull/7482)
|
||||||
|
|
||||||
#### Vulkan
|
#### Vulkan
|
||||||
|
|
||||||
|
|||||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2407,6 +2407,7 @@ dependencies = [
|
|||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bit-set 0.8.0",
|
"bit-set 0.8.0",
|
||||||
"bitflags 2.9.0",
|
"bitflags 2.9.0",
|
||||||
|
"cfg-if",
|
||||||
"cfg_aliases 0.2.1",
|
"cfg_aliases 0.2.1",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
"diff",
|
"diff",
|
||||||
|
|||||||
@ -37,6 +37,8 @@ naga = { workspace = true, features = [
|
|||||||
"dot-out",
|
"dot-out",
|
||||||
"serialize",
|
"serialize",
|
||||||
"deserialize",
|
"deserialize",
|
||||||
|
"termcolor",
|
||||||
|
"stderr",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
bincode.workspace = true
|
bincode.workspace = true
|
||||||
|
|||||||
@ -80,15 +80,19 @@ hlsl-out-if-target-windows = []
|
|||||||
|
|
||||||
compact = []
|
compact = []
|
||||||
|
|
||||||
|
## Enables colored output through codespan-reporting and termcolor.
|
||||||
|
termcolor = ["codespan-reporting/termcolor"]
|
||||||
|
|
||||||
|
## Enables writing output to stderr.
|
||||||
|
stderr = ["codespan-reporting/std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arbitrary = { version = "1.4", features = ["derive"], optional = true }
|
arbitrary = { version = "1.4", features = ["derive"], optional = true }
|
||||||
arrayvec.workspace = true
|
arrayvec.workspace = true
|
||||||
bitflags.workspace = true
|
bitflags.workspace = true
|
||||||
bit-set.workspace = true
|
bit-set.workspace = true
|
||||||
codespan-reporting = { workspace = true, default-features = false, features = [
|
cfg-if.workspace = true
|
||||||
"std",
|
codespan-reporting = { workspace = true, default-features = false }
|
||||||
"termcolor",
|
|
||||||
] }
|
|
||||||
hashbrown.workspace = true
|
hashbrown.workspace = true
|
||||||
half = { workspace = true, default-features = false, features = ["num-traits"] }
|
half = { workspace = true, default-features = false, features = ["num-traits"] }
|
||||||
rustc-hash.workspace = true
|
rustc-hash.workspace = true
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
use alloc::{boxed::Box, string::String};
|
||||||
use core::{error::Error, fmt};
|
use core::{error::Error, fmt};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -43,14 +43,88 @@ impl fmt::Display for ShaderError<crate::WithSpan<crate::valid::ValidationError>
|
|||||||
let label = self.label.as_deref().unwrap_or_default();
|
let label = self.label.as_deref().unwrap_or_default();
|
||||||
let files = SimpleFile::new(label, &self.source);
|
let files = SimpleFile::new(label, &self.source);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
let mut writer = term::termcolor::NoColor::new(Vec::new());
|
|
||||||
term::emit(&mut writer, &config, &files, &self.inner.diagnostic())
|
let writer = {
|
||||||
.expect("cannot write error");
|
let mut writer = DiagnosticBuffer::new();
|
||||||
write!(
|
term::emit(
|
||||||
f,
|
writer.inner_mut(),
|
||||||
"\nShader validation {}",
|
&config,
|
||||||
String::from_utf8_lossy(&writer.into_inner())
|
&files,
|
||||||
|
&self.inner.diagnostic(),
|
||||||
)
|
)
|
||||||
|
.expect("cannot write error");
|
||||||
|
writer.into_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(f, "\nShader validation {}", writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(feature = "termcolor")] {
|
||||||
|
type DiagnosticBufferInner = codespan_reporting::term::termcolor::NoColor<alloc::vec::Vec<u8>>;
|
||||||
|
pub(crate) use codespan_reporting::term::termcolor::WriteColor as _ErrorWrite;
|
||||||
|
} else if #[cfg(feature = "stderr")] {
|
||||||
|
type DiagnosticBufferInner = alloc::vec::Vec<u8>;
|
||||||
|
pub(crate) use std::io::Write as _ErrorWrite;
|
||||||
|
} else {
|
||||||
|
type DiagnosticBufferInner = String;
|
||||||
|
pub(crate) use core::fmt::Write as _ErrorWrite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using this indirect export to avoid duplicating the expect(...) for all three cases above.
|
||||||
|
#[cfg_attr(
|
||||||
|
not(any(feature = "spv-in", feature = "glsl-in")),
|
||||||
|
expect(
|
||||||
|
unused_imports,
|
||||||
|
reason = "only need `ErrorWrite` with an appropriate front-end."
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
pub(crate) use _ErrorWrite as ErrorWrite;
|
||||||
|
|
||||||
|
pub(crate) struct DiagnosticBuffer {
|
||||||
|
inner: DiagnosticBufferInner,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DiagnosticBuffer {
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "termcolor"),
|
||||||
|
expect(
|
||||||
|
clippy::missing_const_for_fn,
|
||||||
|
reason = "`NoColor::new` isn't `const`, but other `inner`s are."
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(feature = "termcolor")] {
|
||||||
|
let inner = codespan_reporting::term::termcolor::NoColor::new(alloc::vec::Vec::new());
|
||||||
|
} else if #[cfg(feature = "stderr")] {
|
||||||
|
let inner = alloc::vec::Vec::new();
|
||||||
|
} else {
|
||||||
|
let inner = String::new();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Self { inner }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inner_mut(&mut self) -> &mut DiagnosticBufferInner {
|
||||||
|
&mut self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_string(self) -> String {
|
||||||
|
let Self { inner } = self;
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(feature = "termcolor")] {
|
||||||
|
String::from_utf8(inner.into_inner()).unwrap()
|
||||||
|
} else if #[cfg(feature = "stderr")] {
|
||||||
|
String::from_utf8(inner).unwrap()
|
||||||
|
} else {
|
||||||
|
inner
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,13 +8,12 @@ use alloc::{
|
|||||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||||
use codespan_reporting::files::SimpleFile;
|
use codespan_reporting::files::SimpleFile;
|
||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use codespan_reporting::term::termcolor::{NoColor, WriteColor};
|
|
||||||
use pp_rs::token::PreprocessorError;
|
use pp_rs::token::PreprocessorError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use super::token::TokenValue;
|
use super::token::TokenValue;
|
||||||
use crate::SourceLocation;
|
use crate::SourceLocation;
|
||||||
use crate::{proc::ConstantEvaluatorError, Span};
|
use crate::{error::ErrorWrite, proc::ConstantEvaluatorError, Span};
|
||||||
|
|
||||||
fn join_with_comma(list: &[ExpectedToken]) -> String {
|
fn join_with_comma(list: &[ExpectedToken]) -> String {
|
||||||
let mut string = "".to_string();
|
let mut string = "".to_string();
|
||||||
@ -166,11 +165,11 @@ pub struct ParseErrors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ParseErrors {
|
impl ParseErrors {
|
||||||
pub fn emit_to_writer(&self, writer: &mut impl WriteColor, source: &str) {
|
pub fn emit_to_writer(&self, writer: &mut impl ErrorWrite, source: &str) {
|
||||||
self.emit_to_writer_with_path(writer, source, "glsl");
|
self.emit_to_writer_with_path(writer, source, "glsl");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_to_writer_with_path(&self, writer: &mut impl WriteColor, source: &str, path: &str) {
|
pub fn emit_to_writer_with_path(&self, writer: &mut impl ErrorWrite, source: &str, path: &str) {
|
||||||
let path = path.to_string();
|
let path = path.to_string();
|
||||||
let files = SimpleFile::new(path, source);
|
let files = SimpleFile::new(path, source);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
@ -187,9 +186,9 @@ impl ParseErrors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_to_string(&self, source: &str) -> String {
|
pub fn emit_to_string(&self, source: &str) -> String {
|
||||||
let mut writer = NoColor::new(Vec::new());
|
let mut writer = crate::error::DiagnosticBuffer::new();
|
||||||
self.emit_to_writer(&mut writer, source);
|
self.emit_to_writer(writer.inner_mut(), source);
|
||||||
String::from_utf8(writer.into_inner()).unwrap()
|
writer.into_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
use alloc::{
|
use alloc::{
|
||||||
format,
|
format,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use codespan_reporting::diagnostic::Diagnostic;
|
use codespan_reporting::diagnostic::Diagnostic;
|
||||||
use codespan_reporting::files::SimpleFile;
|
use codespan_reporting::files::SimpleFile;
|
||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use codespan_reporting::term::termcolor::{NoColor, WriteColor};
|
|
||||||
|
|
||||||
use super::ModuleState;
|
use super::ModuleState;
|
||||||
use crate::{arena::Handle, front::atomic_upgrade};
|
use crate::{arena::Handle, error::ErrorWrite, front::atomic_upgrade};
|
||||||
|
|
||||||
#[derive(Clone, Debug, thiserror::Error)]
|
#[derive(Clone, Debug, thiserror::Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -153,11 +151,11 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn emit_to_writer(&self, writer: &mut impl WriteColor, source: &str) {
|
pub fn emit_to_writer(&self, writer: &mut impl ErrorWrite, source: &str) {
|
||||||
self.emit_to_writer_with_path(writer, source, "glsl");
|
self.emit_to_writer_with_path(writer, source, "glsl");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_to_writer_with_path(&self, writer: &mut impl WriteColor, source: &str, path: &str) {
|
pub fn emit_to_writer_with_path(&self, writer: &mut impl ErrorWrite, source: &str, path: &str) {
|
||||||
let path = path.to_string();
|
let path = path.to_string();
|
||||||
let files = SimpleFile::new(path, source);
|
let files = SimpleFile::new(path, source);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
@ -167,9 +165,9 @@ impl Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_to_string(&self, source: &str) -> String {
|
pub fn emit_to_string(&self, source: &str) -> String {
|
||||||
let mut writer = NoColor::new(Vec::new());
|
let mut writer = crate::error::DiagnosticBuffer::new();
|
||||||
self.emit_to_writer(&mut writer, source);
|
self.emit_to_writer(writer.inner_mut(), source);
|
||||||
String::from_utf8(writer.into_inner()).unwrap()
|
writer.into_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,6 @@ use super::parse::lexer::Token;
|
|||||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||||
use codespan_reporting::files::SimpleFile;
|
use codespan_reporting::files::SimpleFile;
|
||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use codespan_reporting::term::termcolor::{ColorChoice, NoColor, StandardStream};
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
@ -68,11 +67,13 @@ impl ParseError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to standard error stream.
|
/// Emits a summary of the error to standard error stream.
|
||||||
|
#[cfg(feature = "stderr")]
|
||||||
pub fn emit_to_stderr(&self, source: &str) {
|
pub fn emit_to_stderr(&self, source: &str) {
|
||||||
self.emit_to_stderr_with_path(source, "wgsl")
|
self.emit_to_stderr_with_path(source, "wgsl")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to standard error stream.
|
/// Emits a summary of the error to standard error stream.
|
||||||
|
#[cfg(feature = "stderr")]
|
||||||
pub fn emit_to_stderr_with_path<P>(&self, source: &str, path: P)
|
pub fn emit_to_stderr_with_path<P>(&self, source: &str, path: P)
|
||||||
where
|
where
|
||||||
P: AsRef<std::path::Path>,
|
P: AsRef<std::path::Path>,
|
||||||
@ -80,7 +81,15 @@ impl ParseError {
|
|||||||
let path = path.as_ref().display().to_string();
|
let path = path.as_ref().display().to_string();
|
||||||
let files = SimpleFile::new(path, source);
|
let files = SimpleFile::new(path, source);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
let writer = StandardStream::stderr(ColorChoice::Auto);
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(feature = "termcolor")] {
|
||||||
|
let writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Auto);
|
||||||
|
} else {
|
||||||
|
let writer = std::io::stderr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
|
term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
|
||||||
.expect("cannot write error");
|
.expect("cannot write error");
|
||||||
}
|
}
|
||||||
@ -98,9 +107,11 @@ impl ParseError {
|
|||||||
let path = path.as_ref().display().to_string();
|
let path = path.as_ref().display().to_string();
|
||||||
let files = SimpleFile::new(path, source);
|
let files = SimpleFile::new(path, source);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
let mut writer = NoColor::new(Vec::new());
|
|
||||||
term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
|
let mut writer = crate::error::DiagnosticBuffer::new();
|
||||||
String::from_utf8(writer.into_inner()).unwrap()
|
term::emit(writer.inner_mut(), &config, &files, &self.diagnostic())
|
||||||
|
.expect("cannot write error");
|
||||||
|
writer.into_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a [`SourceLocation`] for the first label in the error message.
|
/// Returns a [`SourceLocation`] for the first label in the error message.
|
||||||
|
|||||||
@ -110,7 +110,9 @@ void main() {
|
|||||||
wgsl_out,
|
wgsl_out,
|
||||||
|
|
||||||
feature = "spv-in",
|
feature = "spv-in",
|
||||||
feature = "wgsl-in"
|
feature = "wgsl-in",
|
||||||
|
|
||||||
|
feature = "stderr",
|
||||||
))]
|
))]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
|
|||||||
@ -273,6 +273,7 @@ impl<E> WithSpan<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to standard error stream.
|
/// Emits a summary of the error to standard error stream.
|
||||||
|
#[cfg(feature = "stderr")]
|
||||||
pub fn emit_to_stderr(&self, source: &str)
|
pub fn emit_to_stderr(&self, source: &str)
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@ -281,16 +282,24 @@ impl<E> WithSpan<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to standard error stream.
|
/// Emits a summary of the error to standard error stream.
|
||||||
|
#[cfg(feature = "stderr")]
|
||||||
pub fn emit_to_stderr_with_path(&self, source: &str, path: &str)
|
pub fn emit_to_stderr_with_path(&self, source: &str, path: &str)
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
|
||||||
use codespan_reporting::{files, term};
|
use codespan_reporting::{files, term};
|
||||||
|
|
||||||
let files = files::SimpleFile::new(path, source);
|
let files = files::SimpleFile::new(path, source);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
let writer = StandardStream::stderr(ColorChoice::Auto);
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(feature = "termcolor")] {
|
||||||
|
let writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Auto);
|
||||||
|
} else {
|
||||||
|
let writer = std::io::stderr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
|
term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
|
||||||
.expect("cannot write error");
|
.expect("cannot write error");
|
||||||
}
|
}
|
||||||
@ -308,14 +317,15 @@ impl<E> WithSpan<E> {
|
|||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
use codespan_reporting::term::termcolor::NoColor;
|
|
||||||
use codespan_reporting::{files, term};
|
use codespan_reporting::{files, term};
|
||||||
|
|
||||||
let files = files::SimpleFile::new(path, source);
|
let files = files::SimpleFile::new(path, source);
|
||||||
let config = term::Config::default();
|
let config = term::Config::default();
|
||||||
let mut writer = NoColor::new(Vec::new());
|
|
||||||
term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
|
let mut writer = crate::error::DiagnosticBuffer::new();
|
||||||
String::from_utf8(writer.into_inner()).unwrap()
|
term::emit(writer.inner_mut(), &config, &files, &self.diagnostic())
|
||||||
|
.expect("cannot write error");
|
||||||
|
writer.into_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -325,7 +325,7 @@ cfg_aliases.workspace = true
|
|||||||
cfg-if.workspace = true
|
cfg-if.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
glam.workspace = true # for ray-traced-triangle example
|
glam.workspace = true # for ray-traced-triangle example
|
||||||
naga = { workspace = true, features = ["wgsl-in"] }
|
naga = { workspace = true, features = ["wgsl-in", "termcolor"] }
|
||||||
winit.workspace = true # for "halmark" example
|
winit.workspace = true # for "halmark" example
|
||||||
|
|
||||||
### Platform: Windows + MacOS + Linux for "raw-gles" example ###
|
### Platform: Windows + MacOS + Linux for "raw-gles" example ###
|
||||||
|
|||||||
@ -153,7 +153,7 @@ fragile-send-sync-non-atomic-wasm = [
|
|||||||
#########################
|
#########################
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
naga = { workspace = true, optional = true }
|
naga = { workspace = true, optional = true, features = ["termcolor"] }
|
||||||
wgpu-core = { workspace = true, optional = true }
|
wgpu-core = { workspace = true, optional = true }
|
||||||
wgpu-types.workspace = true
|
wgpu-types.workspace = true
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user