mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 08:17:40 +03:00
83 lines
2.4 KiB
Rust
83 lines
2.4 KiB
Rust
use anyhow::*;
|
|
use glob::glob;
|
|
use std::fs::{read_to_string, write};
|
|
use std::path::PathBuf;
|
|
use rayon::prelude::*;
|
|
|
|
// Adapted from https://github.com/sotrh/learn-wgpu
|
|
// by Benjamin Hansen, licensed under the MIT license
|
|
|
|
|
|
// Rename this file to build.rs and uncomment the build-dependencies in Cargo.toml to compile
|
|
// the shaders into .spv files
|
|
|
|
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 = Vec::new();
|
|
shader_paths.extend(glob("./src/**/*.vert")?);
|
|
shader_paths.extend(glob("./src/**/*.frag")?);
|
|
shader_paths.extend(glob("./src/**/*.comp")?);
|
|
|
|
|
|
let shaders = shader_paths.into_par_iter()
|
|
.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 {
|
|
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())?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|