1use std::collections::BTreeMap;
2use vyre_foundation::ir::Program;
3
4#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
5pub struct WgslDump {
6 pub text: String,
7 pub variable_lines: BTreeMap<String, usize>,
8}
9
10pub fn dump_wgsl(program: &Program) -> Result<WgslDump, String> {
11 let lowered = vyre_lower::lower_for_emit(program).map_err(|e| format!("{:?}", e))?;
12 let module = vyre_emit_naga::emit(&lowered.descriptor).map_err(|e| format!("{:?}", e))?;
13 let info = naga::valid::Validator::new(
14 naga::valid::ValidationFlags::all(),
15 naga::valid::Capabilities::all(),
16 )
17 .validate(&module)
18 .map_err(|e| format!("Naga validation failed: {:?}", e))?;
19
20 let mut text = String::new();
21 let mut writer =
22 naga::back::wgsl::Writer::new(&mut text, naga::back::wgsl::WriterFlags::empty());
23 writer
24 .write(&module, &info)
25 .map_err(|e| format!("WGSL emission failed: {:?}", e))?;
26
27 let mut variable_lines = BTreeMap::new();
29 for (i, line) in text.lines().enumerate() {
30 if line.contains("var ") || line.contains("let ") {
31 let parts: Vec<&str> = line.split_whitespace().collect();
32 if parts.len() > 1 {
33 let name = parts[1].trim_end_matches(':').to_string();
34 if !variable_lines.contains_key(&name) {
35 variable_lines.insert(name, i + 1);
36 }
37 }
38 }
39 }
40
41 Ok(WgslDump {
42 text,
43 variable_lines,
44 })
45}
46
47pub fn dump_wgsl_with_lines(program: &Program) -> Result<WgslDump, String> {
48 let dump = dump_wgsl(program)?;
49 let mut numbered_text = String::new();
50 for (i, line) in dump.text.lines().enumerate() {
51 if !line.trim().is_empty() {
52 numbered_text.push_str(&format!("{:5} | {}\n", i + 1, line));
53 } else {
54 numbered_text.push('\n');
55 }
56 }
57
58 Ok(WgslDump {
59 text: numbered_text,
60 variable_lines: dump.variable_lines,
61 })
62}