pub fn module(chunks: &[Chunk<'_>], kind: &[u8; 4]) -> Result<Option<Module>>Expand description
The module of a container’s program part of this kind (DXIL, or STAT for the reflection module), if it has one.
Examples found in repository?
examples/inspect_dxil.rs (line 7)
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4 let path = std::env::args().nth(1).ok_or("usage: inspect <shader.dxil>")?;
5 let container = std::fs::read(path)?;
6 let parts = dxil_reader::parts(&container)?;
7 let module = dxil_reader::module(&parts, b"DXIL")?.ok_or("no DXIL part")?;
8 println!("{} functions", module.functions.len());
9
10 // The records the file stores for its entry point:
11 let (inputs, outputs) = dxil_reader::reflection::elements(&module)?;
12 println!(
13 "{} input and {} output signature elements",
14 inputs.len(),
15 outputs.len()
16 );
17 for (range, name, _) in dxil_reader::reflection::ranges(&module)? {
18 println!("{name}: class {} register {}", range.class, range.lower);
19 }
20 Ok(())
21}More examples
examples/pairs_dxil.rs (line 85)
73fn main() -> Result<(), Box<dyn std::error::Error>> {
74 let mut paths = Vec::new();
75 for argument in std::env::args().skip(1) {
76 files(Path::new(&argument), &mut paths)?;
77 }
78 let (mut programs, mut skipped) = (0_usize, 0_usize);
79 for path in &paths {
80 let bytes = std::fs::read(path)?;
81 let Ok(chunks) = dxil_reader::parts(&bytes) else {
82 skipped += 1;
83 continue;
84 };
85 let module = match dxil_reader::module(&chunks, b"DXIL") {
86 Ok(Some(module)) => module,
87 Ok(None) => {
88 skipped += 1;
89 continue;
90 }
91 Err(e) => {
92 eprintln!("{}: {e}", path.display());
93 continue;
94 }
95 };
96 let kind = dxil_reader::part(&bytes)?.program_version >> 16;
97 let reads = match texture_reads(&module) {
98 Ok(reads) => reads,
99 Err(e) => {
100 eprintln!("{}: {e}", path.display());
101 continue;
102 }
103 };
104 let samplers: Vec<_> = dxil_reader::reflection::ranges(&module)?
105 .into_iter()
106 .filter(|(range, _, _)| range.class == 3)
107 .map(|(range, _, _)| range)
108 .collect();
109 programs += 1;
110 let hash = fnv1a64(&bytes);
111 // (texture, sampler, comparison, declared kind) -> call count and operation names
112 type Key = ((String, String), (String, String), bool, String);
113 let mut pairs: BTreeMap<Key, (usize, BTreeMap<String, usize>)> = BTreeMap::new();
114 for read in reads {
115 let sampler = if read.sampled {
116 columns(read.sampler)
117 } else {
118 ("-".to_owned(), "-".to_owned())
119 };
120 let declared = read
121 .sampler
122 .and_then(|h| {
123 let register = h.register?;
124 samplers.iter().find(|r| {
125 r.space == h.space
126 && register >= r.lower
127 && register
128 .checked_sub(r.lower)
129 .is_some_and(|offset| offset < r.count)
130 })
131 })
132 .map_or_else(|| "-".to_owned(), |r| r.extra.to_string());
133 let entry = pairs
134 .entry((columns(read.texture), sampler, read.comparison, declared))
135 .or_default();
136 entry.0 += 1;
137 *entry.1.entry(operation(read.opcode)).or_default() += 1;
138 }
139 for ((texture, sampler, comparison, declared), (count, names)) in pairs {
140 let names: Vec<String> = names.iter().map(|(n, c)| format!("{n}x{c}")).collect();
141 println!(
142 "{hash:016x}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{declared}\t{count}\t{}",
143 path.display(),
144 stage(kind),
145 texture.0,
146 texture.1,
147 sampler.0,
148 sampler.1,
149 u8::from(comparison),
150 names.join(",")
151 );
152 }
153 }
154 eprintln!("{programs} programs, {skipped} files skipped");
155 Ok(())
156}