damascene_ash/
naga_compile.rs1use naga::back::spv;
8use naga::front::wgsl;
9use naga::valid;
10
11#[derive(Debug)]
13pub enum CompileError {
14 Parse { name: String, message: String },
15 Validate { name: String, message: String },
16 SpirVWrite { name: String, message: String },
17}
18
19impl std::fmt::Display for CompileError {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 CompileError::Parse { name, message } => {
23 write!(f, "WGSL parse error in `{name}`: {message}")
24 }
25 CompileError::Validate { name, message } => {
26 write!(f, "WGSL validation error in `{name}`: {message}")
27 }
28 CompileError::SpirVWrite { name, message } => {
29 write!(f, "SPIR-V write error in `{name}`: {message}")
30 }
31 }
32 }
33}
34
35impl std::error::Error for CompileError {}
36
37pub fn wgsl_to_spirv(name: &str, source: &str) -> std::result::Result<Vec<u32>, CompileError> {
40 let module = wgsl::parse_str(source).map_err(|e| CompileError::Parse {
41 name: name.to_string(),
42 message: e.emit_to_string(source),
43 })?;
44
45 let info = valid::Validator::new(valid::ValidationFlags::all(), valid::Capabilities::all())
46 .validate(&module)
47 .map_err(|e| CompileError::Validate {
48 name: name.to_string(),
49 message: e.emit_to_string(source),
50 })?;
51
52 let options = spv::Options::default();
53 spv::write_vec(&module, &info, &options, None).map_err(|e| CompileError::SpirVWrite {
54 name: name.to_string(),
55 message: e.to_string(),
56 })
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use damascene_core::shader::stock_wgsl;
63
64 #[test]
65 fn rounded_rect_compiles() {
66 let words = wgsl_to_spirv("rounded_rect", stock_wgsl::ROUNDED_RECT)
67 .expect("rounded_rect WGSL should compile");
68 assert_eq!(words.first().copied(), Some(0x0723_0203));
69 }
70
71 #[test]
72 fn surface_compiles() {
73 let words =
74 wgsl_to_spirv("surface", stock_wgsl::SURFACE).expect("surface WGSL should compile");
75 assert_eq!(words.first().copied(), Some(0x0723_0203));
76 }
77
78 #[test]
79 fn parse_error_carries_name() {
80 let err =
81 wgsl_to_spirv("broken", "not valid wgsl @@@").expect_err("invalid WGSL must fail");
82 assert!(matches!(err, CompileError::Parse { .. }));
83 assert!(err.to_string().contains("broken"));
84 }
85}