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
extern crate tempdir;
use std::fs::File;
use std::io::Write;
use std::process::Command;
pub type SpirvOutput = File;
pub fn compile(code: &str, ty: ShaderType) -> Result<SpirvOutput, String> {
compile_inner(Some((code, ty)))
}
fn compile_inner<'a, I>(shaders: I) -> Result<SpirvOutput, String>
where I: IntoIterator<Item = (&'a str, ShaderType)>
{
let temp_dir = tempdir::TempDir::new("glslang-compile").unwrap();
let output_file = temp_dir.path().join("compilation_output.spv");
let mut command = Command::new(concat!(env!("OUT_DIR"), "/glslang_validator"));
command.arg("-V");
command.arg("-l");
command.arg("-o").arg(&output_file);
for (num, (source, ty)) in shaders.into_iter().enumerate() {
let extension = match ty {
ShaderType::Vertex => ".vert",
ShaderType::Fragment => ".frag",
ShaderType::Geometry => ".geom",
ShaderType::TessellationControl => ".tesc",
ShaderType::TessellationEvaluation => ".tese",
ShaderType::Compute => ".comp",
};
let file_path = temp_dir.path().join(format!("{}{}", num, extension));
File::create(&file_path).unwrap().write_all(source.as_bytes()).unwrap();
command.arg(file_path);
}
let output = command.output().expect("Failed to execute glslangValidator");
if output.status.success() {
let spirv_output = File::open(output_file).expect("failed to open SPIR-V output file");
return Ok(spirv_output);
}
let error1 = String::from_utf8_lossy(&output.stdout);
let error2 = String::from_utf8_lossy(&output.stderr);
return Err(error1.into_owned() + &error2);
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ShaderType {
Vertex,
Fragment,
Geometry,
TessellationControl,
TessellationEvaluation,
Compute,
}