/// The arena in which we are currently tracing expressions. pub expressions: &'tracer Arena<crate::Expression>,
/// The used map for `types`. pub types_used: &'tracer mut HandleSet<crate::Type>,
/// The used map for `constants`. pub constants_used: &'tracer mut HandleSet<crate::Constant>,
/// The used set for `arena`. /// /// This points to whatever arena holds the expressions we are /// currently tracing: either a function's expression arena, or /// the module's constant expression arena. pub expressions_used: &'tracer mut HandleSet<crate::Expression>,
/// The used set for the module's `global_expressions` arena. /// /// If `None`, we are already tracing the constant expressions, /// and `expressions_used` already refers to their handle set. pub global_expressions_used: Option<&'tracer mut HandleSet<crate::Expression>>,
}
impl ExpressionTracer<'_> { /// Propagate usage through `self.expressions`, starting with `self.expressions_used`. /// /// Treat `self.expressions_used` as the initial set of "known /// live" expressions, and follow through to identify all /// transitively used expressions. /// /// Mark types, constants, and constant expressions used directly /// by `self.expressions` as used. Items used indirectly are not /// marked. /// /// [fe]: crate::Function::expressions /// [ce]: crate::Module::global_expressions pubfn trace_expressions(&mutself) {
log::trace!( "entering trace_expression of {}", ifself.global_expressions_used.is_some() { "function expressions"
} else { "const expressions"
}
);
// We don't need recursion or a work list. Because an // expression may only refer to other expressions that precede // it in the arena, it suffices to make a single pass over the // arena from back to front, marking the referents of used // expressions as used themselves. for (handle, expr) inself.expressions.iter().rev() { // If this expression isn't used, it doesn't matter what it uses. if !self.expressions_used.contains(handle) { continue;
}
log::trace!("tracing new expression {:?}", expr);
usecrate::Expression as Ex; match *expr { // Expressions that do not contain handles that need to be traced.
Ex::Literal(_)
| Ex::FunctionArgument(_)
| Ex::GlobalVariable(_)
| Ex::LocalVariable(_)
| Ex::CallResult(_)
| Ex::SubgroupBallotResult
| Ex::RayQueryProceedResult => {}
Ex::Constant(handle) => { self.constants_used.insert(handle); // Constants and expressions are mutually recursive, which // complicates our nice one-pass algorithm. However, since // constants don't refer to each other, we can get around // this by looking *through* each constant and marking its // initializer as used. Since `expr` refers to the constant, // and the constant refers to the initializer, it must // precede `expr` in the arena. let init = self.constants[handle].init; matchself.global_expressions_used {
Some(refmut used) => used.insert(init),
None => self.expressions_used.insert(init),
};
}
Ex::Override(_) => { // All overrides are considered used by definition. We mark // their types and initialization expressions as used in // `compact::compact`, so we have no more work to do here.
}
Ex::ZeroValue(ty) => { self.types_used.insert(ty);
}
Ex::Compose { ty, ref components } => { self.types_used.insert(ty); self.expressions_used
.insert_iter(components.iter().cloned());
}
Ex::Access { base, index } => self.expressions_used.insert_iter([base, index]),
Ex::AccessIndex { base, index: _ } => { self.expressions_used.insert(base);
}
Ex::Splat { size: _, value } => { self.expressions_used.insert(value);
}
Ex::Swizzle {
size: _,
vector,
pattern: _,
} => { self.expressions_used.insert(vector);
}
Ex::Load { pointer } => { self.expressions_used.insert(pointer);
}
Ex::ImageSample {
image,
sampler,
gather: _,
coordinate,
array_index,
offset, ref level,
depth_ref,
} => { self.expressions_used
.insert_iter([image, sampler, coordinate]); self.expressions_used.insert_iter(array_index); matchself.global_expressions_used {
Some(refmut used) => used.insert_iter(offset),
None => self.expressions_used.insert_iter(offset),
} usecrate::SampleLevel as Sl; match *level {
Sl::Auto | Sl::Zero => {}
Sl::Exact(expr) | Sl::Bias(expr) => { self.expressions_used.insert(expr);
}
Sl::Gradient { x, y } => self.expressions_used.insert_iter([x, y]),
} self.expressions_used.insert_iter(depth_ref);
}
Ex::ImageLoad {
image,
coordinate,
array_index,
sample,
level,
} => { self.expressions_used.insert(image); self.expressions_used.insert(coordinate); self.expressions_used.insert_iter(array_index); self.expressions_used.insert_iter(sample); self.expressions_used.insert_iter(level);
}
Ex::ImageQuery { image, ref query } => { self.expressions_used.insert(image); usecrate::ImageQuery as Iq; match *query {
Iq::Size { level } => self.expressions_used.insert_iter(level),
Iq::NumLevels | Iq::NumLayers | Iq::NumSamples => {}
}
}
Ex::Unary { op: _, expr } => { self.expressions_used.insert(expr);
}
Ex::Binary { op: _, left, right } => { self.expressions_used.insert_iter([left, right]);
}
Ex::Select {
condition,
accept,
reject,
} => self
.expressions_used
.insert_iter([condition, accept, reject]),
Ex::Derivative {
axis: _,
ctrl: _,
expr,
} => { self.expressions_used.insert(expr);
}
Ex::Relational { fun: _, argument } => { self.expressions_used.insert(argument);
}
Ex::Math {
fun: _,
arg,
arg1,
arg2,
arg3,
} => { self.expressions_used.insert(arg); self.expressions_used.insert_iter(arg1); self.expressions_used.insert_iter(arg2); self.expressions_used.insert_iter(arg3);
}
Ex::As {
expr,
kind: _,
convert: _,
} => { self.expressions_used.insert(expr);
}
Ex::ArrayLength(expr) => { self.expressions_used.insert(expr);
}
Ex::AtomicResult { ty, comparison: _ }
| Ex::WorkGroupUniformLoadResult { ty }
| Ex::SubgroupOperationResult { ty } => { self.types_used.insert(ty);
}
Ex::RayQueryGetIntersection {
query,
committed: _,
} => { self.expressions_used.insert(query);
}
}
}
}
}
impl ModuleMap { /// Fix up all handles in `expr`. /// /// Use the expression handle remappings in `operand_map`, and all /// other mappings from `self`. pubfn adjust_expression(
&self,
expr: &mutcrate::Expression,
operand_map: &HandleMap<crate::Expression>,
) { let adjust = |expr: &mut Handle<crate::Expression>| {
operand_map.adjust(expr);
};
usecrate::Expression as Ex; match *expr { // Expressions that do not contain handles that need to be adjusted.
Ex::Literal(_)
| Ex::FunctionArgument(_)
| Ex::GlobalVariable(_)
| Ex::LocalVariable(_)
| Ex::CallResult(_)
| Ex::SubgroupBallotResult
| Ex::RayQueryProceedResult => {}
// All overrides are retained, so their handles never change.
Ex::Override(_) => {}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.