[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.
This commit is contained in:
Jim Blandy
2025-02-24 16:43:46 -08:00
committed by Jamie Nicol
parent 9f949459f7
commit ab70237126
3 changed files with 30 additions and 25 deletions

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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<crate::Type>) -> 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,
}
}
}