mirror of
https://github.com/sotrh/learn-wgpu.git
synced 2024-11-08 07:10:33 +00:00
95 lines
2.8 KiB
Rust
95 lines
2.8 KiB
Rust
use anyhow::*;
|
|
use fs_extra::copy_items;
|
|
use fs_extra::dir::CopyOptions;
|
|
use glob::glob;
|
|
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<Self> {
|
|
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<()> {
|
|
// Collect all shaders recursively within /src/
|
|
let mut shader_paths = [
|
|
glob("./src/**/*.vert")?,
|
|
glob("./src/**/*.frag")?,
|
|
glob("./src/**/*.comp")?,
|
|
];
|
|
|
|
// This could be parallelized
|
|
let shaders = shader_paths
|
|
.iter_mut()
|
|
.flatten()
|
|
.map(|glob_result| ShaderData::load(glob_result?))
|
|
.collect::<Vec<Result<_>>>()
|
|
.into_iter()
|
|
.collect::<Result<Vec<_>>>()?;
|
|
|
|
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 {
|
|
// This tells cargo to rerun this script if something in /src/ changes.
|
|
println!("cargo:rerun-if-changed={:?}", shader.src_path);
|
|
|
|
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/");
|
|
match copy_items(&paths_to_copy, out_dir, ©_options) {
|
|
Ok(_) => {}
|
|
Err(e) => eprintln!("{}", e),
|
|
}
|
|
|
|
Ok(())
|
|
}
|