Skip to content

Commit

Permalink
prettier messages for shader processing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobhellermann committed Dec 21, 2021
1 parent c4e10fb commit d183a8c
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 8 deletions.
1 change: 1 addition & 0 deletions crates/bevy_render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ image = { version = "0.23.12", default-features = false }

# misc
wgpu = { version = "0.12.0", features = ["spirv"] }
codespan-reporting = "0.11.0"
naga = { version = "0.8.0", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] }
serde = { version = "1", features = ["derive"] }
bitflags = "1.2.1"
Expand Down
73 changes: 65 additions & 8 deletions crates/bevy_render/src/render_resource/pipeline_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ use crate::{
render_resource::{
AsModuleDescriptorError, BindGroupLayout, BindGroupLayoutId, ProcessShaderError,
RawFragmentState, RawRenderPipelineDescriptor, RawVertexState, RenderPipeline,
RenderPipelineDescriptor, Shader, ShaderImport, ShaderProcessor,
RenderPipelineDescriptor, Shader, ShaderImport, ShaderProcessor, ShaderReflectError,
},
renderer::RenderDevice,
RenderWorld,
};
use bevy_app::EventReader;
use bevy_asset::{AssetEvent, Assets, Handle};
use bevy_ecs::system::{Res, ResMut};
use bevy_utils::{HashMap, HashSet};
use bevy_utils::{tracing::error, HashMap, HashSet};
use std::{collections::hash_map::Entry, hash::Hash, ops::Deref, sync::Arc};
use thiserror::Error;
use wgpu::{PipelineLayoutDescriptor, ShaderModule, VertexBufferLayout};

use super::ProcessedShader;

#[derive(Default)]
pub struct ShaderData {
pipelines: HashSet<CachedPipelineId>,
Expand Down Expand Up @@ -68,7 +70,12 @@ impl ShaderCache {
&self.shaders,
&self.import_path_shaders,
)?;
let module_descriptor = processed.get_module_descriptor()?;
let module_descriptor = match processed.get_module_descriptor() {
Ok(module_descriptor) => module_descriptor,
Err(err) => {
return Err(RenderPipelineError::AsModuleDescriptorError(err, processed));
}
};
entry.insert(Arc::new(
render_device.create_shader_module(&module_descriptor),
))
Expand Down Expand Up @@ -206,8 +213,8 @@ pub enum RenderPipelineError {
ShaderNotLoaded(Handle<Shader>),
#[error(transparent)]
ProcessShaderError(#[from] ProcessShaderError),
#[error(transparent)]
AsModuleDescriptorError(#[from] AsModuleDescriptorError),
#[error("{0}")]
AsModuleDescriptorError(AsModuleDescriptorError, ProcessedShader),
#[error("Shader import not yet available.")]
ShaderImportNotYetAvailable,
}
Expand Down Expand Up @@ -274,9 +281,13 @@ impl RenderPipelineCache {
match err {
RenderPipelineError::ShaderNotLoaded(_)
| RenderPipelineError::ShaderImportNotYetAvailable => { /* retry */ }
RenderPipelineError::ProcessShaderError(_)
| RenderPipelineError::AsModuleDescriptorError(_) => {
// shader could not be processed ... retrying won't help
// shader could not be processed ... retrying won't help
RenderPipelineError::ProcessShaderError(err) => {
error!("failed to process shader: {}", err);
continue;
}
RenderPipelineError::AsModuleDescriptorError(err, source) => {
log_shader_error(source, err);
continue;
}
}
Expand Down Expand Up @@ -386,3 +397,49 @@ impl RenderPipelineCache {
}
}
}

fn log_shader_error(source: &ProcessedShader, err: &AsModuleDescriptorError) {
use codespan_reporting::{
diagnostic::{Diagnostic, Label},
files::SimpleFile,
term,
};

match source {
ProcessedShader::Wgsl(source) => match err {
AsModuleDescriptorError::ShaderReflectError(err) => match err {
ShaderReflectError::WgslParse(parse) => {
let msg = parse.emit_to_string(source);
error!("failed to process shader:\n{}", msg);
}
ShaderReflectError::Validation(error) => {
let files = SimpleFile::new("wgsl", &source);
let config = term::Config::default();
let mut writer = term::termcolor::Ansi::new(Vec::new());

let diagnostic = Diagnostic::error().with_labels(
error
.spans()
.map(|(span, desc)| {
Label::primary((), span.to_range().unwrap())
.with_message(desc.to_owned())
})
.collect(),
);

term::emit(&mut writer, &config, &files, &diagnostic)
.expect("cannot write error");

let msg = writer.into_inner();
let msg = String::from_utf8_lossy(&msg);

error!("failed to process shader: \n{}", msg);
}
ShaderReflectError::GlslParse(_) => {}
ShaderReflectError::SpirVParse(_) => {}
},
_ => (),
},
_ => error!("failed to process shader: {}", err),
}
}
59 changes: 59 additions & 0 deletions pipelined/bevy_render2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[package]
name = "bevy_render2"
version = "0.5.0"
edition = "2021"
authors = [
"Bevy Contributors <[email protected]>",
"Carter Anderson <[email protected]>",
]
description = "Provides rendering functionality for Bevy Engine"
homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT"
keywords = ["bevy"]

[dependencies]
# bevy
bevy_app = { path = "../../crates/bevy_app", version = "0.5.0" }
bevy_asset = { path = "../../crates/bevy_asset", version = "0.5.0" }
bevy_core = { path = "../../crates/bevy_core", version = "0.5.0" }
bevy_derive = { path = "../../crates/bevy_derive", version = "0.5.0" }
bevy_ecs = { path = "../../crates/bevy_ecs", version = "0.5.0" }
bevy_math = { path = "../../crates/bevy_math", version = "0.5.0" }
bevy_reflect = { path = "../../crates/bevy_reflect", version = "0.5.0", features = ["bevy"] }
bevy_transform = { path = "../../crates/bevy_transform", version = "0.5.0" }
bevy_window = { path = "../../crates/bevy_window", version = "0.5.0" }
bevy_utils = { path = "../../crates/bevy_utils", version = "0.5.0" }

# rendering
image = { version = "0.23.12", default-features = false }

# misc
wgpu = { version = "0.11.0", features = ["spirv"] }
wgpu-core = { version = "0.11.0" }
naga = { version = "0.7.0", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] }
serde = { version = "1", features = ["derive"] }
bitflags = "1.2.1"
smallvec = { version = "1.6", features = ["union", "const_generics"] }
once_cell = "1.4.1" # TODO: replace once_cell with std equivalent if/when this lands: https://github.com/rust-lang/rfcs/pull/2788
downcast-rs = "1.2.0"
thiserror = "1.0"
futures-lite = "1.4.0"
anyhow = "1.0"
hex = "0.4.2"
hexasphere = "6.0.0"
parking_lot = "0.11.0"
regex = "1.5"
crevice = { path = "../../crates/crevice", version = "0.8.0", features = ["glam"] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
wgpu = { version = "0.11.0", features = ["spirv", "webgl"] }

[features]
png = ["image/png"]
hdr = ["image/hdr"]
dds = ["image/dds"]
tga = ["image/tga"]
jpeg = ["image/jpeg"]
bmp = ["image/bmp"]
trace = []

0 comments on commit d183a8c

Please sign in to comment.