Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wgsl-in] Remove unused expressions from Module::const_expressions. #4648

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ For naga changelogs at or before v0.14.0. See [naga's changelog](naga/CHANGELOG.

- Fix issue where local variables were sometimes using variable names from previous functions.

### Changes
#### Naga

- [wgsl-in] Omit unused constant expressions from the Module's `const_expressions` arena, in preparation for supporting abstract types. By @jimblandy in [#4648](https://github.com/gfx-rs/wgpu/pull/4648).

## v0.18.0 (2023-10-25)

### Desktop OpenGL 3.3+ Support on Windows
Expand Down
2 changes: 1 addition & 1 deletion naga/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ impl<T> Arena<T> {
Ok(())
}

#[cfg(feature = "compact")]
#[cfg(any(feature = "compact", feature = "wgsl-in"))]
pub(crate) fn retain_mut<P>(&mut self, mut predicate: P)
where
P: FnMut(Handle<T>, &mut T) -> bool,
Expand Down
160 changes: 160 additions & 0 deletions naga/src/front/wgsl/lower/compact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
use crate::Handle;
use bit_set::BitSet;

/// Remove all unused expressions from `module.const_expressions`.
///
/// Abstract values make extensive use of 64-bit literals, which the
/// validator should never see.
pub fn compact(module: &mut crate::Module) {
// Trace which expressions in `module.const_expressions` are actually used.
let used = trace(module);

// Assuming unused expressions are squeezed out of the arena,
// compute a map from pre-squeeze indices to post-squeeze
// expression handles.
let mut next = 0;
let compacted: Vec<Option<Handle<crate::Expression>>> = module
.const_expressions
.iter()
.map(|(handle, _)| {
if used.contains(handle.index()) {
let index = next;
next += 1;
std::num::NonZeroU32::new(index + 1).map(Handle::new)
} else {
None
}
})
.collect();

adjust(module, &compacted);
}

fn trace(module: &crate::Module) -> BitSet {
let mut used = BitSet::new();

// Note uses by global constants.
for (_, constant) in module.constants.iter() {
used.insert(constant.init.index());
}

// Note uses by global variable initializers.
for (_, global) in module.global_variables.iter() {
if let Some(init) = global.init {
used.insert(init.index());
}
}

// Note uses by functions' expressions.
for (_, fun) in module.functions.iter() {
trace_function(fun, &mut used);
}

// Note uses by entry points' expressions.
for entry_point in &module.entry_points {
trace_function(&entry_point.function, &mut used);
}

// Note transitive uses by other used constant expressions.
//
// Since we know that expressions only refer to other expressions
// appearing before them in the arena, we can do this without a
// stack by making a single pass from back to front.
for (handle, expr) in module.const_expressions.iter().rev() {
if used.contains(handle.index()) {
match *expr {
crate::Expression::Compose { ref components, .. } => {
for component in components {
used.insert(component.index());
}
}
crate::Expression::Splat { value, .. } => {
used.insert(value.index());
}
_ => {}
}
}
}

used
}

fn trace_function(function: &crate::Function, used: &mut BitSet) {
for (_, expr) in function.expressions.iter() {
match *expr {
crate::Expression::ImageSample {
offset: Some(offset),
..
} => {
used.insert(offset.index());
}
_ => {}
}
}
}

fn adjust(module: &mut crate::Module, compacted: &[Option<Handle<crate::Expression>>]) {
// Remove unused expressions from the constant arena,
// and adjust the handles in retained expressions.
module.const_expressions.retain_mut(|handle, expr| {
match compacted[handle.index()] {
Some(_) => {
// This expression is used, and thus its handles are worth adjusting.
match *expr {
crate::Expression::Compose {
ref mut components, ..
} => {
for component in components {
*component = compacted[component.index()].unwrap();
}
}
crate::Expression::Splat { ref mut value, .. } => {
*value = compacted[value.index()].unwrap();
}
_ => {}
}
true
}
None => false,
}
});

// Adjust uses by global constants.
for (_, constant) in module.constants.iter_mut() {
constant.init = compacted[constant.init.index()].unwrap();
}

// Adjust uses by global variable initializers.
for (_, global) in module.global_variables.iter_mut() {
if let Some(ref mut init) = global.init {
*init = compacted[init.index()].unwrap();
}
}

// Adjust uses by functions' expressions.
for (_, fun) in module.functions.iter_mut() {
adjust_function(fun, compacted);
}

// Adjust uses by entry points' expressions.
for entry_point in &mut module.entry_points {
adjust_function(&mut entry_point.function, compacted);
}
}

fn adjust_function(
function: &mut crate::Function,
compacted: &[Option<Handle<crate::Expression>>],
) {
for (_, expr) in function.expressions.iter_mut() {
match *expr {
crate::Expression::ImageSample {
offset: Some(ref mut offset),
..
} => {
*offset = compacted[offset.index()].unwrap();
}
_ => {}
}
}
}
3 changes: 3 additions & 0 deletions naga/src/front/wgsl/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::proc::{
};
use crate::{Arena, FastHashMap, FastIndexMap, Handle, Span};

mod compact;
mod construction;

/// Resolves the inner type of a given expression.
Expand Down Expand Up @@ -971,6 +972,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
}
}

compact::compact(&mut module);

Ok(module)
}

Expand Down
26 changes: 0 additions & 26 deletions naga/tests/out/ir/access.ron
Original file line number Diff line number Diff line change
Expand Up @@ -412,32 +412,6 @@
6,
],
),
Literal(I32(8)),
Literal(I32(2)),
Literal(I32(10)),
Literal(I32(2)),
Literal(I32(0)),
Literal(I32(0)),
Literal(I32(0)),
Literal(I32(1)),
Literal(I32(0)),
Literal(I32(2)),
Literal(I32(2)),
Literal(I32(0)),
Literal(I32(3)),
Literal(I32(2)),
Literal(I32(2)),
Literal(I32(10)),
Literal(I32(5)),
Literal(I32(5)),
Literal(I32(10)),
Literal(I32(5)),
Literal(I32(0)),
Literal(I32(2)),
Literal(I32(2)),
Literal(I32(2)),
Literal(I32(2)),
Literal(I32(1)),
],
functions: [
(
Expand Down
6 changes: 1 addition & 5 deletions naga/tests/out/ir/collatz.ron
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,7 @@
init: None,
),
],
const_expressions: [
Literal(I32(0)),
Literal(I32(0)),
Literal(I32(1)),
],
const_expressions: [],
functions: [
(
name: Some("collatz_iterations"),
Expand Down
Loading