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
use crate::error::CompileError;
use shaderc::{IncludeType, ResolvedInclude};
use shaderc::{ShaderKind, CompileOptions};
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
pub fn compile<T>(path: T, shader_kind: ShaderKind) -> Result<Vec<u32>, CompileError>
where
T: AsRef<Path>,
{
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler)?;
compile_with_options(path, shader_kind, options)
}
pub fn compile_with_options<T>(path: T, shader_kind: ShaderKind, mut options: CompileOptions) -> Result<Vec<u32>, CompileError>
where
T: AsRef<Path>,
{
let mut compiler = shaderc::Compiler::new().ok_or(CompileError::CreateCompiler)?;
let mut f = File::open(&path).map_err(CompileError::Open)?;
let mut src = String::new();
f.read_to_string(&mut src).map_err(CompileError::Open)?;
options.set_include_callback(|path, include_type, folder_path, depth| {
get_include(path, include_type, folder_path, depth)
});
let result = compiler
.compile_into_spirv(
src.as_str(),
shader_kind,
path.as_ref().to_str().ok_or(CompileError::InvalidPath)?,
"main",
Some(&options),
)
.map_err(CompileError::Compile)?;
let data = result.as_binary();
Ok(data.to_owned())
}
fn get_include(
path: &str,
include_type: IncludeType,
folder_path: &str,
_depth: usize,
) -> Result<ResolvedInclude, String> {
match include_type {
IncludeType::Relative => {
let p = Path::new(path);
let mut folder = PathBuf::from(folder_path);
folder.pop();
folder.push(p);
let p = folder;
if !p.is_file() {
return Err("Include doesn't point to file".to_string());
}
let resolved_name = p
.to_str()
.ok_or("Path has invalid characters".to_string())?
.to_owned();
let p = p.canonicalize().map_err(|_|"Failed to parse include path".to_string())?;
let mut content = String::new();
File::open(p)
.map_err(|_|"Couldn't open include directory".to_string())?
.read_to_string(&mut content)
.map_err(|_|"Failed to read included shader".to_string())?;
Ok(ResolvedInclude {
resolved_name,
content,
})
}
IncludeType::Standard => Err("Standard includes are unimplemented".to_string()),
}
}