1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use std::collections::HashSet; use std::fs::{read_dir,create_dir_all,read_to_string,write,DirEntry}; use std::path::{Path,PathBuf}; use shaderc::ShaderKind; pub fn build() { let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("Failed to get CARGO_MANIFEST_DIR environment variable."); let shaders_dir = Path::new(&manifest_dir).join("resources/shaders"); let output_directory = Path::new(&manifest_dir).join("out"); let mut shaderc_compiler = shaderc::Compiler::new().expect("Failed to create shaderc compiler."); let mut made_directories: HashSet<PathBuf> = HashSet::new(); let mut entries: Vec<DirEntry> = read_dir(&shaders_dir) .expect("Failed to read GLSL input directory.") .map(|x| x.expect("Failed to get item in GLSL input directory.")) .into_iter() .collect(); loop { let entry = match entries.pop() { Some(entry) => entry, None => break }; let shader_path_buf = entry.path(); println!("cargo:rerun-if-changed={}", shader_path_buf.as_os_str().to_str().unwrap()); let metadata = entry.metadata().expect("Failed to get metadata of item in GLSL input directory."); if metadata.is_dir() { entries.extend( read_dir(&shader_path_buf) .expect("Failed to read subdirectory item in GLSL input directory.") .map(|x| x.expect("Failed to get subdirectory item in GLSL input directory.")) .into_iter() ); } else if metadata.is_file() { let shader_source = read_to_string(&shader_path_buf).expect("Failed to read shader file."); let shader_file_name = &shader_path_buf.file_name().expect("Failed to get shader file name.") .to_str().expect("Failed to get shader file name as string."); let shader_file_stem = &shader_path_buf.file_stem().expect("Failed to get shader file stem.") .to_str().expect("Failed to get shader file stem as string."); let shader_file_stem_prefix: String = shader_file_stem.chars().take_while(|x| x != &'_').collect(); let shader_kind = match shader_file_stem_prefix.as_str() { "vertex" => ShaderKind::DefaultVertex, "fragment" => ShaderKind::DefaultFragment, "compute" => ShaderKind::DefaultCompute, "geometry" => ShaderKind::DefaultGeometry, "tessctrl" => ShaderKind::DefaultTessControl, "tesseval" => ShaderKind::DefaultTessEvaluation, "raygen" => ShaderKind::DefaultRayGeneration, "anyhit" => ShaderKind::DefaultAnyHit, "closesthit" => ShaderKind::DefaultClosestHit, "miss" => ShaderKind::DefaultMiss, "intersection" => ShaderKind::Intersection, "callable" => ShaderKind::DefaultCallable, "task" => ShaderKind::DefaultTask, "mesh" => ShaderKind::DefaultMesh, _ => ShaderKind::InferFromSource, }; let shader_artifact = shaderc_compiler.compile_into_spirv( shader_source.as_str(), shader_kind, &shader_file_name, "main", None ).expect("Failed to compile shader."); let shader_binary = shader_artifact.as_binary_u8(); let relative_path = &shader_path_buf.strip_prefix(&manifest_dir).expect("Failed to get shader's relative path."); let relative_path = relative_path.with_extension("spv"); let adjusted_path = Path::new(&output_directory).join(relative_path); let adjusted_path_directory = adjusted_path.parent().expect("Failed to get directory of SPIR-V output path."); if made_directories.get(adjusted_path_directory).is_none() { create_dir_all(adjusted_path_directory).expect("Failed to create directory of SPIR-V output."); made_directories.insert(adjusted_path_directory.clone().to_path_buf()); } write(&adjusted_path, shader_binary).expect("Failed to write shader."); println!("cargo:rerun-if-changed={}", &adjusted_path.as_os_str().to_str().unwrap()); println!("cargo:rerun-if-changed={}", &adjusted_path_directory.as_os_str().to_str().unwrap()); } } println!("cargo:rerun-if-changed={}", &output_directory.as_os_str().to_str().unwrap()); }