diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 9b30e7c1abcdb0..7ff840b52d814b 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -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" diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index c904ff74715d82..77f892b9aa9024 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -2,7 +2,7 @@ use crate::{ render_resource::{ AsModuleDescriptorError, BindGroupLayout, BindGroupLayoutId, ProcessShaderError, RawFragmentState, RawRenderPipelineDescriptor, RawVertexState, RenderPipeline, - RenderPipelineDescriptor, Shader, ShaderImport, ShaderProcessor, + RenderPipelineDescriptor, Shader, ShaderImport, ShaderProcessor, ShaderReflectError, }, renderer::RenderDevice, RenderWorld, @@ -10,11 +10,13 @@ use crate::{ 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, @@ -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), )) @@ -206,8 +213,8 @@ pub enum RenderPipelineError { ShaderNotLoaded(Handle), #[error(transparent)] ProcessShaderError(#[from] ProcessShaderError), - #[error(transparent)] - AsModuleDescriptorError(#[from] AsModuleDescriptorError), + #[error("{0}")] + AsModuleDescriptorError(AsModuleDescriptorError, ProcessedShader), #[error("Shader import not yet available.")] ShaderImportNotYetAvailable, } @@ -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; } } @@ -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), + } +} diff --git a/pipelined/bevy_render2/Cargo.toml b/pipelined/bevy_render2/Cargo.toml new file mode 100644 index 00000000000000..c66599cc88087d --- /dev/null +++ b/pipelined/bevy_render2/Cargo.toml @@ -0,0 +1,59 @@ +[package] +name = "bevy_render2" +version = "0.5.0" +edition = "2021" +authors = [ + "Bevy Contributors ", + "Carter Anderson ", +] +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 = []