1use naga::{Block, Module, Statement};
2use std::collections::HashMap;
3
4pub struct NagaDump {
5 pub text: String,
6 block_paths: HashMap<u32, Vec<String>>,
8}
9
10impl NagaDump {
11 pub fn find(&self, handle: u32) -> Option<&Vec<String>> {
12 self.block_paths.get(&handle)
13 }
14}
15
16pub fn dump_naga_module(module: &Module) -> NagaDump {
17 let mut out = String::new();
18 let mut block_paths = HashMap::new();
19
20 out.push_str("=== globals ===\n");
21 for (handle, global) in module.global_variables.iter() {
22 let name = global.name.as_deref().unwrap_or("");
23 out.push_str(&format!(
24 "[{}] {} : {:?}, space={:?}\n",
25 handle.index(),
26 name,
27 global.ty,
28 global.space
29 ));
30 }
31 out.push_str("\n");
32
33 if let Some(ep) = module.entry_points.first() {
36 let func = &ep.function;
37 out.push_str("=== local_variables ===\n");
38 for (handle, local) in func.local_variables.iter() {
39 let name = local.name.as_deref().unwrap_or("");
40 out.push_str(&format!(
41 "[{}] {:?} : {:?}\n",
42 handle.index(),
43 name,
44 local.ty
45 ));
46 }
47 out.push_str("\n");
48
49 out.push_str("=== expressions ===\n");
50 for (handle, expr) in func.expressions.iter() {
51 out.push_str(&format!("[{}] {:?}\n", handle.index(), expr));
53 }
54 out.push_str("\n");
55
56 out.push_str("=== body ===\n");
57 fn walk_block(
58 block: &Block,
59 path: &mut Vec<String>,
60 out: &mut String,
61 indent: usize,
62 block_paths: &mut HashMap<u32, Vec<String>>,
63 func: &naga::Function,
64 ) {
65 let ind = " ".repeat(indent);
66 out.push_str(&format!("{}{{\n", ind));
67 for stmt in block.iter() {
68 out.push_str(&format!("{} {:?}\n", ind, stmt));
69 match stmt {
70 Statement::Emit(range) => {
71 for h in range.clone() {
72 block_paths.insert(h.index() as u32, path.clone());
73 }
74 }
75 Statement::Block(b) => {
76 path.push("Block".to_string());
77 walk_block(b, path, out, indent + 1, block_paths, func);
78 path.pop();
79 }
80 Statement::If {
81 condition: _,
82 accept,
83 reject,
84 } => {
85 path.push("If.accept".to_string());
86 walk_block(accept, path, out, indent + 1, block_paths, func);
87 path.pop();
88 path.push("If.reject".to_string());
89 walk_block(reject, path, out, indent + 1, block_paths, func);
90 path.pop();
91 }
92 Statement::Loop {
93 body,
94 continuing,
95 break_if: _,
96 } => {
97 path.push("Loop.body".to_string());
98 walk_block(body, path, out, indent + 1, block_paths, func);
99 path.pop();
100 path.push("Loop.continuing".to_string());
101 walk_block(continuing, path, out, indent + 1, block_paths, func);
102 path.pop();
103 }
104 _ => {}
105 }
106 }
107 out.push_str(&format!("{}}}\n", ind));
108 }
109
110 let mut root_path = vec!["root".to_string()];
111 walk_block(
112 &func.body,
113 &mut root_path,
114 &mut out,
115 0,
116 &mut block_paths,
117 func,
118 );
119 }
120
121 NagaDump {
122 text: out,
123 block_paths,
124 }
125}