use anyhow::*; // use fs_extra::copy_items; // use fs_extra::dir::CopyOptions; use glob::glob; use rayon::prelude::*; // use std::env; use std::fs::{read_to_string, write}; use std::path::PathBuf; struct ShaderData { src: String, src_path: PathBuf, spv_path: PathBuf, kind: shaderc::ShaderKind, } impl ShaderData { pub fn load(src_path: PathBuf) -> Result { let extension = src_path .extension() .context("File has no extension")? .to_str() .context("Extension cannot be converted to &str")?; let kind = match extension { "vert" => shaderc::ShaderKind::Vertex, "frag" => shaderc::ShaderKind::Fragment, "comp" => shaderc::ShaderKind::Compute, _ => bail!("Unsupported shader: {}", src_path.display()), }; let src = read_to_string(src_path.clone())?; let spv_path = src_path.with_extension(format!("{}.spv", extension)); Ok(Self { src, src_path, spv_path, kind, }) } } fn main() -> Result<()> { // This tells cargo to rerun this script if something in /src/ changes. println!("cargo:rerun-if-changed=src/*"); // Collect all shaders recursively within /src/ // UDPATED! let mut shader_paths = Vec::new(); shader_paths.extend(glob("./src/**/*.vert")?); shader_paths.extend(glob("./src/**/*.frag")?); shader_paths.extend(glob("./src/**/*.comp")?); // UPDATED! // This is parallelized let shaders = shader_paths .into_par_iter() .map(|glob_result| ShaderData::load(glob_result?)) .collect::>>() .into_iter() .collect::>>(); let mut compiler = shaderc::Compiler::new().context("Unable to create shader compiler")?; // This can't be parallelized. The [shaderc::Compiler] is not // thread safe. Also, it creates a lot of resources. You could // spawn multiple processes to handle this, but it would probably // be better just to only compile shaders that have been changed // recently. for shader in shaders? { let compiled = compiler.compile_into_spirv( &shader.src, shader.kind, &shader.src_path.to_str().unwrap(), "main", None, )?; write(shader.spv_path, compiled.as_binary_u8())?; } // This tells cargo to rerun this script if something in /res/ changes. // println!("cargo:rerun-if-changed=res/*"); // let out_dir = env::var("OUT_DIR")?; // let mut copy_options = CopyOptions::new(); // copy_options.overwrite = true; // let mut paths_to_copy = Vec::new(); // paths_to_copy.push("res/"); // copy_items(&paths_to_copy, out_dir, ©_options)?; Ok(()) }