diff --git a/crates/shaders/build.rs b/crates/shaders/build.rs index 8c948c1..614bacb 100644 --- a/crates/shaders/build.rs +++ b/crates/shaders/build.rs @@ -8,14 +8,26 @@ mod types; use std::env; use std::fmt::Write; -use std::path::Path; +use std::path::{Path, PathBuf}; use compile::ShaderInfo; fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); let dest_path = Path::new(&out_dir).join("shaders.rs"); - let mut shaders = compile::ShaderInfo::from_dir("../../shader"); + + // The shaders are defined under the workspace root and not in this crate so we need to locate + // them somehow. Cargo doesn't define an environment variable that points at the root workspace + // directory. In hermetic build environments that don't support relative paths (such as Bazel) + // we support supplying a `WORKSPACE_MANIFEST_FILE` that is expected to be an absolute path to + // the Cargo.toml file at the workspace root. If that's not present, we use a relative path. + let workspace_dir = env::var("WORKSPACE_MANIFEST_FILE") + .ok() + .and_then(|p| Path::new(&p).parent().map(|p| p.to_owned())) + .unwrap_or(PathBuf::from("../../")); + let shader_dir = Path::new(&workspace_dir).join("shader"); + let mut shaders = compile::ShaderInfo::from_dir(&shader_dir); + // Drop the HashMap and sort by name so that we get deterministic order. let mut shaders = shaders.drain().collect::>(); shaders.sort_by(|x, y| x.0.cmp(&y.0)); diff --git a/crates/shaders/src/compile/mod.rs b/crates/shaders/src/compile/mod.rs index 74cafda..98d116d 100644 --- a/crates/shaders/src/compile/mod.rs +++ b/crates/shaders/src/compile/mod.rs @@ -166,28 +166,29 @@ impl ShaderInfo { for entry in shader_dir .read_dir() .expect("Can read shader import directory") + .filter_map(move |e| { + e.ok() + .filter(|e| e.path().extension().map(|e| e == "wgsl").unwrap_or(false)) + }) { - let entry = entry.expect("Can continue reading shader import directory"); - if entry.file_type().unwrap().is_file() { - let file_name = entry.file_name(); - if let Some(name) = file_name.to_str() { - let suffix = ".wgsl"; - if let Some(shader_name) = name.strip_suffix(suffix) { - let contents = fs::read_to_string(shader_dir.join(&file_name)) - .expect("Could read shader {shader_name} contents"); - if let Some(permutations) = permutation_map.get(shader_name) { - for permutation in permutations { - let mut defines = defines.clone(); - defines.extend(permutation.defines.iter().cloned()); - let source = preprocess::preprocess(&contents, &defines, &imports); - let shader_info = Self::new(source.clone(), "main").unwrap(); - info.insert(permutation.name.clone(), shader_info); - } - } else { + let file_name = entry.file_name(); + if let Some(name) = file_name.to_str() { + let suffix = ".wgsl"; + if let Some(shader_name) = name.strip_suffix(suffix) { + let contents = fs::read_to_string(shader_dir.join(&file_name)) + .expect("Could read shader {shader_name} contents"); + if let Some(permutations) = permutation_map.get(shader_name) { + for permutation in permutations { + let mut defines = defines.clone(); + defines.extend(permutation.defines.iter().cloned()); let source = preprocess::preprocess(&contents, &defines, &imports); let shader_info = Self::new(source.clone(), "main").unwrap(); - info.insert(shader_name.to_string(), shader_info); + info.insert(permutation.name.clone(), shader_info); } + } else { + let source = preprocess::preprocess(&contents, &defines, &imports); + let shader_info = Self::new(source.clone(), "main").unwrap(); + info.insert(shader_name.to_string(), shader_info); } } } diff --git a/crates/shaders/src/compile/preprocess.rs b/crates/shaders/src/compile/preprocess.rs index 917f83f..199ea40 100644 --- a/crates/shaders/src/compile/preprocess.rs +++ b/crates/shaders/src/compile/preprocess.rs @@ -14,17 +14,18 @@ pub fn get_imports(shader_dir: &Path) -> HashMap { for entry in imports_dir .read_dir() .expect("Can read shader import directory") + .filter_map(move |e| { + e.ok() + .filter(|e| e.path().extension().map(|e| e == "wgsl").unwrap_or(false)) + }) { - let entry = entry.expect("Can continue reading shader import directory"); - if entry.file_type().unwrap().is_file() { - let file_name = entry.file_name(); - if let Some(name) = file_name.to_str() { - let suffix = ".wgsl"; - if let Some(import_name) = name.strip_suffix(suffix) { - let contents = fs::read_to_string(imports_dir.join(&file_name)) - .expect("Could read shader {import_name} contents"); - imports.insert(import_name.to_owned(), contents); - } + let file_name = entry.file_name(); + if let Some(name) = file_name.to_str() { + let suffix = ".wgsl"; + if let Some(import_name) = name.strip_suffix(suffix) { + let contents = fs::read_to_string(imports_dir.join(&file_name)) + .expect("Could read shader {import_name} contents"); + imports.insert(import_name.to_owned(), contents); } } }