From ab7023712696b5067ce46d439c074d1eaaca20cb Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Mon, 24 Feb 2025 16:43:46 -0800 Subject: [PATCH] [naga] Introduce `TypeInner::is_abstract` utility function. Define `TypeInner::is_abstract`, and let it take a type arena so that it can properly handle abstract arrays. Use this in compaction and in the WGSL front end's conversion code to recognize abstract types. --- naga/src/compact/mod.rs | 24 +++++++----------------- naga/src/front/wgsl/lower/conversion.rs | 9 +-------- naga/src/proc/type_methods.rs | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/naga/src/compact/mod.rs b/naga/src/compact/mod.rs index 25835984eb..f889a8e1b9 100644 --- a/naga/src/compact/mod.rs +++ b/naga/src/compact/mod.rs @@ -114,24 +114,14 @@ pub fn compact(module: &mut crate::Module) { // abstract type as we do not want those reaching the validator. log::trace!("tracing named constants"); for (handle, constant) in module.constants.iter() { - if constant.name.is_some() { - log::trace!("tracing constant {:?}", constant.name.as_ref().unwrap()); - // If the type is an array (of an array, etc) then we must check whether the - // type of the innermost array's base type is abstract. - let mut ty = constant.ty; - while let crate::TypeInner::Array { base, .. } = module.types[ty].inner { - ty = base; - } - if !module.types[ty] - .inner - .scalar() - .is_some_and(|s| s.is_abstract()) - { - module_tracer.constants_used.insert(handle); - module_tracer.types_used.insert(constant.ty); - module_tracer.global_expressions_used.insert(constant.init); - } + if constant.name.is_none() || module.types[constant.ty].inner.is_abstract(&module.types) { + continue; } + + log::trace!("tracing constant {:?}", constant.name.as_ref().unwrap()); + module_tracer.constants_used.insert(handle); + module_tracer.types_used.insert(constant.ty); + module_tracer.global_expressions_used.insert(constant.init); } // We treat all named overrides as used by definition. diff --git a/naga/src/front/wgsl/lower/conversion.rs b/naga/src/front/wgsl/lower/conversion.rs index f7e767bfb8..f78bb3da27 100644 --- a/naga/src/front/wgsl/lower/conversion.rs +++ b/naga/src/front/wgsl/lower/conversion.rs @@ -37,14 +37,7 @@ impl<'source> super::ExpressionContext<'source, '_, '_> { // rather than them being misreported as type conversion errors. // If the type is an array (of an array, etc) then we must check whether the // type of the innermost array's base type is abstract. - let mut base_inner = expr_inner; - while let crate::TypeInner::Array { base, .. } = *base_inner { - base_inner = &types[base].inner; - } - if !base_inner - .scalar() - .is_some_and(|scalar| scalar.is_abstract()) - { + if !expr_inner.is_abstract(types) { return Ok(expr); } diff --git a/naga/src/proc/type_methods.rs b/naga/src/proc/type_methods.rs index 351f4c5368..d73b6df10f 100644 --- a/naga/src/proc/type_methods.rs +++ b/naga/src/proc/type_methods.rs @@ -281,4 +281,26 @@ impl crate::TypeInner { | crate::TypeInner::BindingArray { .. } => None, } } + + /// Return true if `self` is an abstract type. + /// + /// Use `types` to look up type handles. This is necessary to + /// recognize abstract arrays. + pub fn is_abstract(&self, types: &crate::UniqueArena) -> bool { + match *self { + crate::TypeInner::Scalar(scalar) + | crate::TypeInner::Vector { scalar, .. } + | crate::TypeInner::Matrix { scalar, .. } + | crate::TypeInner::Atomic(scalar) => scalar.is_abstract(), + crate::TypeInner::Array { base, .. } => types[base].inner.is_abstract(types), + crate::TypeInner::ValuePointer { .. } + | crate::TypeInner::Pointer { .. } + | crate::TypeInner::Struct { .. } + | crate::TypeInner::Image { .. } + | crate::TypeInner::Sampler { .. } + | crate::TypeInner::AccelerationStructure + | crate::TypeInner::RayQuery + | crate::TypeInner::BindingArray { .. } => false, + } + } }