1use super::{HandleMap, HandleSet, ModuleMap};
2use crate::arena::{Arena, Handle};
3
4pub struct ExpressionTracer<'tracer> {
5 pub constants: &'tracer Arena<crate::Constant>,
6 pub overrides: &'tracer Arena<crate::Override>,
7
8 pub expressions: &'tracer Arena<crate::Expression>,
10
11 pub types_used: &'tracer mut HandleSet<crate::Type>,
13
14 pub global_variables_used: &'tracer mut HandleSet<crate::GlobalVariable>,
16
17 pub constants_used: &'tracer mut HandleSet<crate::Constant>,
19
20 pub overrides_used: &'tracer mut HandleSet<crate::Override>,
22
23 pub expressions_used: &'tracer mut HandleSet<crate::Expression>,
29
30 pub global_expressions_used: Option<&'tracer mut HandleSet<crate::Expression>>,
35}
36
37impl ExpressionTracer<'_> {
38 pub fn trace_expressions(&mut self) {
51 log::trace!(
52 "entering trace_expression of {}",
53 if self.global_expressions_used.is_some() {
54 "function expressions"
55 } else {
56 "const expressions"
57 }
58 );
59
60 for (handle, expr) in self.expressions.iter().rev() {
66 if !self.expressions_used.contains(handle) {
68 continue;
69 }
70
71 log::trace!("tracing new expression {expr:?}");
72 self.trace_expression(expr);
73 }
74 }
75
76 pub fn trace_expression(&mut self, expr: &crate::Expression) {
77 use crate::Expression as Ex;
78 match *expr {
79 Ex::Literal(_)
81 | Ex::FunctionArgument(_)
82 | Ex::LocalVariable(_)
83 | Ex::SubgroupBallotResult
84 | Ex::RayQueryProceedResult => {}
85
86 Ex::Constant(handle) => {
97 self.constants_used.insert(handle);
98 let constant = &self.constants[handle];
99 self.types_used.insert(constant.ty);
100 match self.global_expressions_used {
101 Some(ref mut used) => used.insert(constant.init),
102 None => self.expressions_used.insert(constant.init),
103 };
104 }
105 Ex::Override(handle) => {
106 self.overrides_used.insert(handle);
107 let r#override = &self.overrides[handle];
108 self.types_used.insert(r#override.ty);
109 if let Some(init) = r#override.init {
110 match self.global_expressions_used {
111 Some(ref mut used) => used.insert(init),
112 None => self.expressions_used.insert(init),
113 };
114 }
115 }
116 Ex::ZeroValue(ty) => {
117 self.types_used.insert(ty);
118 }
119 Ex::Compose { ty, ref components } => {
120 self.types_used.insert(ty);
121 self.expressions_used
122 .insert_iter(components.iter().cloned());
123 }
124 Ex::Access { base, index } => self.expressions_used.insert_iter([base, index]),
125 Ex::AccessIndex { base, index: _ } => {
126 self.expressions_used.insert(base);
127 }
128 Ex::Splat { size: _, value } => {
129 self.expressions_used.insert(value);
130 }
131 Ex::Swizzle {
132 size: _,
133 vector,
134 pattern: _,
135 } => {
136 self.expressions_used.insert(vector);
137 }
138 Ex::GlobalVariable(handle) => {
139 self.global_variables_used.insert(handle);
140 }
141 Ex::Load { pointer } => {
142 self.expressions_used.insert(pointer);
143 }
144 Ex::ImageSample {
145 image,
146 sampler,
147 gather: _,
148 coordinate,
149 array_index,
150 offset,
151 ref level,
152 depth_ref,
153 clamp_to_edge: _,
154 } => {
155 self.expressions_used
156 .insert_iter([image, sampler, coordinate]);
157 self.expressions_used.insert_iter(array_index);
158 self.expressions_used.insert_iter(offset);
159 use crate::SampleLevel as Sl;
160 match *level {
161 Sl::Auto | Sl::Zero => {}
162 Sl::Exact(expr) | Sl::Bias(expr) => {
163 self.expressions_used.insert(expr);
164 }
165 Sl::Gradient { x, y } => self.expressions_used.insert_iter([x, y]),
166 }
167 self.expressions_used.insert_iter(depth_ref);
168 }
169 Ex::ImageLoad {
170 image,
171 coordinate,
172 array_index,
173 sample,
174 level,
175 } => {
176 self.expressions_used.insert(image);
177 self.expressions_used.insert(coordinate);
178 self.expressions_used.insert_iter(array_index);
179 self.expressions_used.insert_iter(sample);
180 self.expressions_used.insert_iter(level);
181 }
182 Ex::ImageQuery { image, ref query } => {
183 self.expressions_used.insert(image);
184 use crate::ImageQuery as Iq;
185 match *query {
186 Iq::Size { level } => self.expressions_used.insert_iter(level),
187 Iq::NumLevels | Iq::NumLayers | Iq::NumSamples => {}
188 }
189 }
190 Ex::RayQueryVertexPositions {
191 query,
192 committed: _,
193 } => {
194 self.expressions_used.insert(query);
195 }
196 Ex::Unary { op: _, expr } => {
197 self.expressions_used.insert(expr);
198 }
199 Ex::Binary { op: _, left, right } => {
200 self.expressions_used.insert_iter([left, right]);
201 }
202 Ex::Select {
203 condition,
204 accept,
205 reject,
206 } => self
207 .expressions_used
208 .insert_iter([condition, accept, reject]),
209 Ex::Derivative {
210 axis: _,
211 ctrl: _,
212 expr,
213 } => {
214 self.expressions_used.insert(expr);
215 }
216 Ex::Relational { fun: _, argument } => {
217 self.expressions_used.insert(argument);
218 }
219 Ex::Math {
220 fun: _,
221 arg,
222 arg1,
223 arg2,
224 arg3,
225 } => {
226 self.expressions_used.insert(arg);
227 self.expressions_used.insert_iter(arg1);
228 self.expressions_used.insert_iter(arg2);
229 self.expressions_used.insert_iter(arg3);
230 }
231 Ex::As {
232 expr,
233 kind: _,
234 convert: _,
235 } => {
236 self.expressions_used.insert(expr);
237 }
238 Ex::ArrayLength(expr) => {
239 self.expressions_used.insert(expr);
240 }
241 Ex::CallResult(_) => {}
245 Ex::AtomicResult { ty, comparison: _ }
246 | Ex::WorkGroupUniformLoadResult { ty }
247 | Ex::SubgroupOperationResult { ty } => {
248 self.types_used.insert(ty);
249 }
250 Ex::RayQueryGetIntersection {
251 query,
252 committed: _,
253 } => {
254 self.expressions_used.insert(query);
255 }
256 Ex::CooperativeLoad { ref data, .. } => {
257 self.expressions_used.insert(data.pointer);
258 self.expressions_used.insert(data.stride);
259 }
260 Ex::CooperativeMultiplyAdd { a, b, c } => {
261 self.expressions_used.insert(a);
262 self.expressions_used.insert(b);
263 self.expressions_used.insert(c);
264 }
265 }
266 }
267}
268
269impl ModuleMap {
270 pub fn adjust_expression(
275 &self,
276 expr: &mut crate::Expression,
277 operand_map: &HandleMap<crate::Expression>,
278 ) {
279 let adjust = |expr: &mut Handle<crate::Expression>| {
280 operand_map.adjust(expr);
281 };
282
283 use crate::Expression as Ex;
284 match *expr {
285 Ex::Literal(_)
287 | Ex::FunctionArgument(_)
288 | Ex::LocalVariable(_)
289 | Ex::SubgroupBallotResult
290 | Ex::RayQueryProceedResult => {}
291
292 Ex::Constant(ref mut constant) => self.constants.adjust(constant),
294 Ex::Override(ref mut r#override) => self.overrides.adjust(r#override),
295 Ex::ZeroValue(ref mut ty) => self.types.adjust(ty),
296 Ex::Compose {
297 ref mut ty,
298 ref mut components,
299 } => {
300 self.types.adjust(ty);
301 for component in components {
302 adjust(component);
303 }
304 }
305 Ex::Access {
306 ref mut base,
307 ref mut index,
308 } => {
309 adjust(base);
310 adjust(index);
311 }
312 Ex::AccessIndex {
313 ref mut base,
314 index: _,
315 } => adjust(base),
316 Ex::Splat {
317 size: _,
318 ref mut value,
319 } => adjust(value),
320 Ex::Swizzle {
321 size: _,
322 ref mut vector,
323 pattern: _,
324 } => adjust(vector),
325 Ex::GlobalVariable(ref mut handle) => self.globals.adjust(handle),
326 Ex::Load { ref mut pointer } => adjust(pointer),
327 Ex::ImageSample {
328 ref mut image,
329 ref mut sampler,
330 gather: _,
331 ref mut coordinate,
332 ref mut array_index,
333 ref mut offset,
334 ref mut level,
335 ref mut depth_ref,
336 clamp_to_edge: _,
337 } => {
338 adjust(image);
339 adjust(sampler);
340 adjust(coordinate);
341 operand_map.adjust_option(array_index);
342 operand_map.adjust_option(offset);
343 self.adjust_sample_level(level, operand_map);
344 operand_map.adjust_option(depth_ref);
345 }
346 Ex::ImageLoad {
347 ref mut image,
348 ref mut coordinate,
349 ref mut array_index,
350 ref mut sample,
351 ref mut level,
352 } => {
353 adjust(image);
354 adjust(coordinate);
355 operand_map.adjust_option(array_index);
356 operand_map.adjust_option(sample);
357 operand_map.adjust_option(level);
358 }
359 Ex::ImageQuery {
360 ref mut image,
361 ref mut query,
362 } => {
363 adjust(image);
364 self.adjust_image_query(query, operand_map);
365 }
366 Ex::Unary {
367 op: _,
368 ref mut expr,
369 } => adjust(expr),
370 Ex::Binary {
371 op: _,
372 ref mut left,
373 ref mut right,
374 } => {
375 adjust(left);
376 adjust(right);
377 }
378 Ex::Select {
379 ref mut condition,
380 ref mut accept,
381 ref mut reject,
382 } => {
383 adjust(condition);
384 adjust(accept);
385 adjust(reject);
386 }
387 Ex::Derivative {
388 axis: _,
389 ctrl: _,
390 ref mut expr,
391 } => adjust(expr),
392 Ex::Relational {
393 fun: _,
394 ref mut argument,
395 } => adjust(argument),
396 Ex::Math {
397 fun: _,
398 ref mut arg,
399 ref mut arg1,
400 ref mut arg2,
401 ref mut arg3,
402 } => {
403 adjust(arg);
404 operand_map.adjust_option(arg1);
405 operand_map.adjust_option(arg2);
406 operand_map.adjust_option(arg3);
407 }
408 Ex::As {
409 ref mut expr,
410 kind: _,
411 convert: _,
412 } => adjust(expr),
413 Ex::CallResult(ref mut function) => {
414 self.functions.adjust(function);
415 }
416 Ex::AtomicResult {
417 ref mut ty,
418 comparison: _,
419 } => self.types.adjust(ty),
420 Ex::WorkGroupUniformLoadResult { ref mut ty } => self.types.adjust(ty),
421 Ex::SubgroupOperationResult { ref mut ty } => self.types.adjust(ty),
422 Ex::ArrayLength(ref mut expr) => adjust(expr),
423 Ex::RayQueryGetIntersection {
424 ref mut query,
425 committed: _,
426 } => adjust(query),
427 Ex::RayQueryVertexPositions {
428 ref mut query,
429 committed: _,
430 } => adjust(query),
431 Ex::CooperativeLoad { ref mut data, .. } => {
432 adjust(&mut data.pointer);
433 adjust(&mut data.stride);
434 }
435 Ex::CooperativeMultiplyAdd {
436 ref mut a,
437 ref mut b,
438 ref mut c,
439 } => {
440 adjust(a);
441 adjust(b);
442 adjust(c);
443 }
444 }
445 }
446
447 fn adjust_sample_level(
448 &self,
449 level: &mut crate::SampleLevel,
450 operand_map: &HandleMap<crate::Expression>,
451 ) {
452 let adjust = |expr: &mut Handle<crate::Expression>| operand_map.adjust(expr);
453
454 use crate::SampleLevel as Sl;
455 match *level {
456 Sl::Auto | Sl::Zero => {}
457 Sl::Exact(ref mut expr) => adjust(expr),
458 Sl::Bias(ref mut expr) => adjust(expr),
459 Sl::Gradient {
460 ref mut x,
461 ref mut y,
462 } => {
463 adjust(x);
464 adjust(y);
465 }
466 }
467 }
468
469 fn adjust_image_query(
470 &self,
471 query: &mut crate::ImageQuery,
472 operand_map: &HandleMap<crate::Expression>,
473 ) {
474 use crate::ImageQuery as Iq;
475
476 match *query {
477 Iq::Size { ref mut level } => operand_map.adjust_option(level),
478 Iq::NumLevels | Iq::NumLayers | Iq::NumSamples => {}
479 }
480 }
481}