Skip to content

Commit 09178f2

Browse files
[naga] Track globals used directly by a named expression (gfx-rs#7540)
1 parent ffc920b commit 09178f2

4 files changed

Lines changed: 128 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ Bottom level categories:
4444

4545
#### Naga
4646

47+
### Bux Fixes
48+
49+
#### Naga
50+
51+
Naga now infers the correct binding layout when a resource appears only in an assignment to `_`. By @andyleiserson in [#7540](https://github.com/gfx-rs/wgpu/pull/7540).
52+
4753
- Add polyfills for `dot4U8Packed` and `dot4I8Packed` for all backends. By @robamler in [#7494](https://github.com/gfx-rs/wgpu/pull/7494).
4854

4955
### Changes

naga/src/front/wgsl/lower/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,6 +1988,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
19881988
return Ok(());
19891989
}
19901990
ast::StatementKind::Phony(expr) => {
1991+
// Remembered the RHS of the phony assignment as a named expression. This
1992+
// is important (1) to preserve the RHS for validation, (2) to track any
1993+
// referenced globals.
19911994
let mut emitter = Emitter::default();
19921995
emitter.start(&ctx.function.expressions);
19931996

naga/src/valid/analyzer.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,11 @@ pub struct ExpressionInfo {
158158
/// originates. Otherwise, this is `None`.
159159
pub uniformity: Uniformity,
160160

161-
/// The number of statements and other expressions using this
162-
/// expression's value.
161+
/// The number of direct references to this expression in statements and
162+
/// other expressions.
163+
///
164+
/// This is a _local_ reference count only, it may be non-zero for
165+
/// expressions that are ultimately unused.
163166
pub ref_count: usize,
164167

165168
/// The global variable into which this expression produces a pointer.
@@ -362,7 +365,7 @@ impl FunctionInfo {
362365
) -> NonUniformResult {
363366
let info = &mut self.expressions[expr.index()];
364367
info.ref_count += 1;
365-
// mark the used global as read
368+
// Record usage if this expression may access a global
366369
if let Some(global) = info.assignable_global {
367370
self.global_uses[global.index()] |= global_use;
368371
}
@@ -1220,6 +1223,19 @@ impl ModuleInfo {
12201223
info.uniformity = uniformity.result;
12211224
info.may_kill = uniformity.exit.contains(ExitFlags::MAY_KILL);
12221225

1226+
// If there are any globals referenced directly by a named expression,
1227+
// ensure they are marked as used even if they are not referenced
1228+
// anywhere else. An important case where this matters is phony
1229+
// assignments used to include a global in the shader's resource
1230+
// interface. https://www.w3.org/TR/WGSL/#phony-assignment-section
1231+
for &handle in fun.named_expressions.keys() {
1232+
if let Some(global) = info[handle].assignable_global {
1233+
if info.global_uses[global.index()].is_empty() {
1234+
info.global_uses[global.index()] = GlobalUse::QUERY;
1235+
}
1236+
}
1237+
}
1238+
12231239
Ok(info)
12241240
}
12251241

naga/tests/naga/validation.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,3 +823,103 @@ fn arity_check() {
823823
assert!(validate(Mf::Pow, &[1]).is_ok());
824824
assert!(validate(Mf::Pow, &[3]).is_err());
825825
}
826+
827+
#[cfg(feature = "wgsl-in")]
828+
#[test]
829+
fn global_use_scalar() {
830+
let source = "
831+
@group(0) @binding(0)
832+
var<storage, read_write> global: u32;
833+
834+
@compute @workgroup_size(64)
835+
fn main() {
836+
let used = &global;
837+
}
838+
";
839+
840+
let module = naga::front::wgsl::parse_str(source).expect("module should parse");
841+
let info = valid::Validator::new(Default::default(), valid::Capabilities::all())
842+
.validate(&module)
843+
.unwrap();
844+
845+
let global = module.global_variables.iter().next().unwrap().0;
846+
assert_eq!(
847+
info.get_entry_point(0)[global],
848+
naga::valid::GlobalUse::QUERY
849+
);
850+
}
851+
852+
#[cfg(feature = "wgsl-in")]
853+
#[test]
854+
fn global_use_array() {
855+
let source = "
856+
@group(0) @binding(0)
857+
var<storage, read_write> global: array<f32>;
858+
859+
@compute @workgroup_size(64)
860+
fn main() {
861+
let used = &global;
862+
}
863+
";
864+
865+
let module = naga::front::wgsl::parse_str(source).expect("module should parse");
866+
let info = valid::Validator::new(Default::default(), valid::Capabilities::all())
867+
.validate(&module)
868+
.unwrap();
869+
870+
let global = module.global_variables.iter().next().unwrap().0;
871+
assert_eq!(
872+
info.get_entry_point(0)[global],
873+
naga::valid::GlobalUse::QUERY
874+
);
875+
}
876+
877+
#[cfg(feature = "wgsl-in")]
878+
#[test]
879+
fn global_use_array_index() {
880+
let source = "
881+
@group(0) @binding(0)
882+
var<storage, read_write> global: array<f32>;
883+
884+
@compute @workgroup_size(64)
885+
fn main() {
886+
let used = &global[0];
887+
}
888+
";
889+
890+
let module = naga::front::wgsl::parse_str(source).expect("module should parse");
891+
let info = valid::Validator::new(Default::default(), valid::Capabilities::all())
892+
.validate(&module)
893+
.unwrap();
894+
895+
let global = module.global_variables.iter().next().unwrap().0;
896+
assert_eq!(
897+
info.get_entry_point(0)[global],
898+
naga::valid::GlobalUse::QUERY
899+
);
900+
}
901+
902+
#[cfg(feature = "wgsl-in")]
903+
#[test]
904+
fn global_use_phony() {
905+
let source = "
906+
@group(0) @binding(0)
907+
var<storage, read_write> global: u32;
908+
909+
@compute @workgroup_size(64)
910+
fn main() {
911+
_ = &global;
912+
}
913+
";
914+
915+
let module = naga::front::wgsl::parse_str(source).expect("module should parse");
916+
let info = valid::Validator::new(Default::default(), valid::Capabilities::all())
917+
.validate(&module)
918+
.unwrap();
919+
920+
let global = module.global_variables.iter().next().unwrap().0;
921+
assert_eq!(
922+
info.get_entry_point(0)[global],
923+
naga::valid::GlobalUse::QUERY
924+
);
925+
}

0 commit comments

Comments
 (0)