// Copyright 2023 the Vello Authors // SPDX-License-Identifier: Apache-2.0 OR MIT // These modules are also included in the main crate, where the items are reachable #[allow(unreachable_pub, unused)] #[path = "src/compile/mod.rs"] mod compile; #[allow(unreachable_pub, unused)] #[path = "src/types.rs"] mod types; use std::env; use std::fmt::Write; use std::path::Path; use compile::ShaderInfo; fn main() { let out_dir = env::var_os("OUT_DIR").unwrap(); let dest_path = Path::new(&out_dir).join("shaders.rs"); println!("cargo:rerun-if-changed={}", compile::shader_dir().display()); let mut shaders = match compile::ShaderInfo::from_default() { Ok(s) => s, Err(err) => { eprintln!("{err}"); return; } }; // 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)); let mut buf = String::default(); write_types(&mut buf, &shaders).unwrap(); write_shaders(&mut buf, &shaders).unwrap(); std::fs::write(dest_path, &buf).unwrap(); } fn write_types(buf: &mut String, shaders: &[(String, ShaderInfo)]) -> Result<(), std::fmt::Error> { writeln!(buf, "pub struct Shaders<'a> {{")?; for (name, _) in shaders { writeln!(buf, " pub {name}: ComputeShader<'a>,")?; } writeln!(buf, "}}")?; Ok(()) } fn write_shaders( buf: &mut String, shaders: &[(String, ShaderInfo)], ) -> Result<(), std::fmt::Error> { writeln!(buf, "mod generated {{")?; writeln!(buf, " use super::*;")?; writeln!(buf, " use BindType::*;")?; writeln!(buf, " pub const SHADERS: Shaders<'static> = Shaders {{")?; for (name, info) in shaders { let bind_tys = info .bindings .iter() .map(|binding| binding.ty) .collect::>(); let wg_bufs = &info.workgroup_buffers; writeln!(buf, " {name}: ComputeShader {{")?; writeln!(buf, " name: Cow::Borrowed({:?}),", name)?; writeln!( buf, " workgroup_size: {:?},", info.workgroup_size )?; writeln!(buf, " bindings: Cow::Borrowed(&{:?}),", bind_tys)?; writeln!( buf, " workgroup_buffers: Cow::Borrowed(&{:?}),", wg_bufs )?; if cfg!(feature = "wgsl") { let indices = info .bindings .iter() .map(|binding| binding.location.1) .collect::>(); writeln!(buf, " wgsl: WgslSource {{")?; writeln!( buf, " code: Cow::Borrowed({:?}),", info.source )?; writeln!( buf, " binding_indices : Cow::Borrowed(&{:?}),", indices )?; writeln!(buf, " }},")?; } if cfg!(feature = "msl") { write_msl(buf, info)?; } writeln!(buf, " }},")?; } writeln!(buf, " }};")?; writeln!(buf, "}}")?; Ok(()) } #[cfg(not(feature = "msl"))] fn write_msl(_: &mut String, _: &ShaderInfo) -> Result<(), std::fmt::Error> { Ok(()) } #[cfg(feature = "msl")] fn write_msl(buf: &mut String, info: &ShaderInfo) -> Result<(), std::fmt::Error> { let mut index_iter = compile::msl::BindingIndexIterator::default(); let indices = info .bindings .iter() .map(|binding| index_iter.next(binding.ty)) .collect::>(); writeln!(buf, " msl: MslSource {{")?; writeln!( buf, " code: Cow::Borrowed({:?}),", compile::msl::translate(info).unwrap() )?; writeln!( buf, " binding_indices : Cow::Borrowed(&{:?}),", indices )?; writeln!(buf, " }},")?; Ok(()) }