Introduce GlobalCtx

This commit is contained in:
teoxoy
2023-05-11 18:09:05 +02:00
committed by Jim Blandy
parent d763fb31e2
commit d842d6688d
20 changed files with 138 additions and 170 deletions

View File

@@ -40,11 +40,7 @@ impl crate::TypeInner {
}
}
pub(super) fn size_hlsl(
&self,
types: &crate::UniqueArena<crate::Type>,
constants: &crate::Arena<crate::Constant>,
) -> u32 {
pub(super) fn size_hlsl(&self, gctx: crate::proc::GlobalCtx) -> u32 {
match *self {
Self::Matrix {
columns,
@@ -58,26 +54,25 @@ impl crate::TypeInner {
Self::Array { base, size, stride } => {
let count = match size {
crate::ArraySize::Constant(handle) => {
constants[handle].to_array_length().unwrap_or(1)
gctx.constants[handle].to_array_length().unwrap_or(1)
}
// A dynamically-sized array has to have at least one element
crate::ArraySize::Dynamic => 1,
};
let last_el_size = types[base].inner.size_hlsl(types, constants);
let last_el_size = gctx.types[base].inner.size_hlsl(gctx);
((count - 1) * stride) + last_el_size
}
_ => self.size(constants),
_ => self.size(gctx),
}
}
/// Used to generate the name of the wrapped type constructor
pub(super) fn hlsl_type_id<'a>(
base: crate::Handle<crate::Type>,
types: &crate::UniqueArena<crate::Type>,
constants: &crate::Arena<crate::Constant>,
gctx: crate::proc::GlobalCtx,
names: &'a crate::FastHashMap<crate::proc::NameKey, String>,
) -> Result<Cow<'a, str>, Error> {
Ok(match types[base].inner {
Ok(match gctx.types[base].inner {
crate::TypeInner::Scalar { kind, width } => Cow::Borrowed(kind.to_hlsl_str(width)?),
crate::TypeInner::Vector { size, kind, width } => Cow::Owned(format!(
"{}{}",
@@ -100,8 +95,8 @@ impl crate::TypeInner {
..
} => Cow::Owned(format!(
"array{}_{}_",
constants[size].to_array_length().unwrap(),
Self::hlsl_type_id(base, types, constants, names)?
gctx.constants[size].to_array_length().unwrap(),
Self::hlsl_type_id(base, gctx, names)?
)),
crate::TypeInner::Struct { .. } => {
Cow::Borrowed(&names[&crate::proc::NameKey::Type(base)])

View File

@@ -347,12 +347,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
module: &crate::Module,
constructor: WrappedConstructor,
) -> BackendResult {
let name = crate::TypeInner::hlsl_type_id(
constructor.ty,
&module.types,
&module.constants,
&self.names,
)?;
let name = crate::TypeInner::hlsl_type_id(constructor.ty, module.to_ctx(), &self.names)?;
write!(self.out, "Construct{name}")?;
Ok(())
}

View File

@@ -218,7 +218,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
self.write_wrapped_constructor_function_name(module, constructor)?;
write!(self.out, "(")?;
let count = module.constants[const_handle].to_array_length().unwrap();
let stride = module.types[base].inner.size(&module.constants);
let stride = module.types[base].inner.size(module.to_ctx());
let iter = (0..count).map(|i| (TypeResolution::Handle(base), stride * i));
self.write_storage_load_sequence(module, var_handle, iter, func_ctx)?;
write!(self.out, ")")?;
@@ -381,7 +381,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
writeln!(self.out, ";")?;
// then iterate the stores
let count = module.constants[const_handle].to_array_length().unwrap();
let stride = module.types[base].inner.size(&module.constants);
let stride = module.types[base].inner.size(module.to_ctx());
for i in 0..count {
self.temp_access_chain.push(SubAccess::Offset(i * stride));
let sv = StoreValue::TempIndex {

View File

@@ -877,7 +877,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
}
}
let ty_inner = &module.types[member.ty].inner;
last_offset = member.offset + ty_inner.size_hlsl(&module.types, &module.constants);
last_offset = member.offset + ty_inner.size_hlsl(module.to_ctx());
// The indentation is only for readability
write!(self.out, "{}", back::INDENT)?;

View File

@@ -77,7 +77,7 @@ const CLAMPED_LOD_LOAD_PREFIX: &str = "clamped_lod_e";
struct TypeContext<'a> {
handle: Handle<crate::Type>,
module: &'a crate::Module,
gctx: proc::GlobalCtx<'a>,
names: &'a FastHashMap<NameKey, String>,
access: crate::StorageAccess,
binding: Option<&'a super::ResolvedBinding>,
@@ -86,7 +86,7 @@ struct TypeContext<'a> {
impl<'a> Display for TypeContext<'a> {
fn fmt(&self, out: &mut Formatter<'_>) -> Result<(), FmtError> {
let ty = &self.module.types[self.handle];
let ty = &self.gctx.types[self.handle];
if ty.needs_alias() && !self.first_time {
let name = &self.names[&NameKey::Type(self.handle)];
return write!(out, "{name}");
@@ -223,7 +223,7 @@ impl<'a> Display for TypeContext<'a> {
} else if let crate::ArraySize::Constant(size) = size {
let constant_ctx = ConstantContext {
handle: size,
arena: &self.module.constants,
arena: self.gctx.constants,
names: self.names,
first_time: false,
};
@@ -271,7 +271,7 @@ impl<'a> TypedGlobalVariable<'a> {
};
let ty_name = TypeContext {
handle: var.ty,
module: self.module,
gctx: self.module.to_ctx(),
names: self.names,
access: storage_access,
binding: self.binding,
@@ -399,7 +399,7 @@ fn should_pack_struct_member(
}
let ty_inner = &module.types[member.ty].inner;
let last_offset = member.offset + ty_inner.size(&module.constants);
let last_offset = member.offset + ty_inner.size(module.to_ctx());
let next_offset = match members.get(index + 1) {
Some(next) => next.offset,
None => span,
@@ -1153,7 +1153,7 @@ impl<W: Write> Writer<W> {
crate::TypeInner::Array { base, stride, .. } => (
context.module.types[base]
.inner
.size(&context.module.constants),
.size(context.module.to_ctx()),
stride,
),
_ => return Err(Error::Validation),
@@ -1336,7 +1336,7 @@ impl<W: Write> Writer<W> {
crate::Expression::ZeroValue(ty) => {
let ty_name = TypeContext {
handle: ty,
module: context.module,
gctx: context.module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -2459,7 +2459,7 @@ impl<W: Write> Writer<W> {
TypeResolution::Handle(ty_handle) => {
let ty_name = TypeContext {
handle: ty_handle,
module: context.module,
gctx: context.module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3155,7 +3155,7 @@ impl<W: Write> Writer<W> {
} => {
let base_name = TypeContext {
handle: base,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3200,7 +3200,7 @@ impl<W: Write> Writer<W> {
writeln!(self.out, "{}char _pad{}[{}];", back::INDENT, index, pad)?;
}
let ty_inner = &module.types[member.ty].inner;
last_offset = member.offset + ty_inner.size(&module.constants);
last_offset = member.offset + ty_inner.size(module.to_ctx());
let member_name = &self.names[&NameKey::StructMember(handle, index as u32)];
@@ -3219,7 +3219,7 @@ impl<W: Write> Writer<W> {
None => {
let base_name = TypeContext {
handle: member.ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3250,7 +3250,7 @@ impl<W: Write> Writer<W> {
_ => {
let ty_name = TypeContext {
handle,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3310,7 +3310,7 @@ impl<W: Write> Writer<W> {
let name = &self.names[&NameKey::Constant(handle)];
let ty_name = TypeContext {
handle: ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3450,7 +3450,7 @@ impl<W: Write> Writer<W> {
Some(ref result) => {
let ty_name = TypeContext {
handle: result.ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3468,7 +3468,7 @@ impl<W: Write> Writer<W> {
let name = &self.names[&NameKey::FunctionArgument(fun_handle, index as u32)];
let param_type_name = TypeContext {
handle: arg.ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3517,7 +3517,7 @@ impl<W: Write> Writer<W> {
for (local_handle, local) in fun.local_variables.iter() {
let ty_name = TypeContext {
handle: local.ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3714,7 +3714,7 @@ impl<W: Write> Writer<W> {
let name = &self.names[name_key];
let ty_name = TypeContext {
handle: ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3758,7 +3758,7 @@ impl<W: Write> Writer<W> {
for (name, ty, binding) in result_members {
let ty_name = TypeContext {
handle: ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -3853,7 +3853,7 @@ impl<W: Write> Writer<W> {
let ty_name = TypeContext {
handle: ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,
@@ -4090,7 +4090,7 @@ impl<W: Write> Writer<W> {
let name = &self.names[&NameKey::EntryPointLocal(ep_index as _, local_handle)];
let ty_name = TypeContext {
handle: local.ty,
module,
gctx: module.to_ctx(),
names: &self.names,
access: crate::StorageAccess::empty(),
binding: None,

View File

@@ -1501,7 +1501,7 @@ impl Frontend {
offset: span,
});
span += self.module.types[ty].inner.size(&self.module.constants);
span += self.module.types[ty].inner.size(self.module.to_ctx());
let len = expressions.len();
let load = expressions.append(Expression::Load { pointer }, Default::default());

View File

@@ -53,10 +53,7 @@ impl<'source> ParsingContext<'source> {
ArraySize::Constant(constant)
};
frontend
.layouter
.update(&frontend.module.types, &frontend.module.constants)
.unwrap();
frontend.layouter.update(frontend.module.to_ctx()).unwrap();
let stride = frontend.layouter[*ty].to_stride();
*ty = frontend.module.types.insert(
Type {

View File

@@ -568,6 +568,13 @@ impl<I: Iterator<Item = u32>> super::Frontend<I> {
}
impl<'function> BlockContext<'function> {
pub(super) fn gctx(&self) -> crate::proc::GlobalCtx {
crate::proc::GlobalCtx {
types: self.type_arena,
constants: self.const_arena,
}
}
/// Consumes the `BlockContext` producing a Ir [`Block`](crate::Block)
fn lower(mut self) -> crate::Block {
fn lower_impl(

View File

@@ -2089,7 +2089,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let result_ty = self.lookup_type.lookup(result_type_id)?;
let inner = &ctx.type_arena[result_ty.handle].inner;
let kind = inner.scalar_kind().unwrap();
let size = inner.size(ctx.const_arena) as u8;
let size = inner.size(ctx.gctx()) as u8;
let left_cast = ctx.expressions.append(
crate::Expression::As {
@@ -4387,9 +4387,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let decor = self.future_decor.remove(&id).unwrap_or_default();
let base = self.lookup_type.lookup(type_id)?.handle;
self.layouter
.update(&module.types, &module.constants)
.unwrap();
self.layouter.update(module.to_ctx()).unwrap();
// HACK if the underlying type is an image or a sampler, let's assume
// that we're dealing with a binding-array
@@ -4470,9 +4468,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
let decor = self.future_decor.remove(&id).unwrap_or_default();
let base = self.lookup_type.lookup(type_id)?.handle;
self.layouter
.update(&module.types, &module.constants)
.unwrap();
self.layouter.update(module.to_ctx()).unwrap();
// HACK same case as in `parse_type_array()`
let inner = if let crate::TypeInner::Image { .. } | crate::TypeInner::Sampler { .. } =
@@ -4523,9 +4519,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
.as_ref()
.map_or(false, |decor| decor.storage_buffer);
self.layouter
.update(&module.types, &module.constants)
.unwrap();
self.layouter.update(module.to_ctx()).unwrap();
let mut members = Vec::<crate::StructMember>::with_capacity(inst.wc as usize - 2);
let mut member_lookups = Vec::with_capacity(members.capacity());

View File

@@ -471,9 +471,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
ctx.module.constants.fetch_or_append(size, Span::UNDEFINED),
),
stride: {
self.layouter
.update(&ctx.module.types, &ctx.module.constants)
.unwrap();
self.layouter.update(ctx.module.to_ctx()).unwrap();
self.layouter[base].to_stride()
},
};
@@ -645,9 +643,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
ast::ArraySize::Dynamic => crate::ArraySize::Dynamic,
};
self.layouter
.update(&ctx.module.types, &ctx.module.constants)
.unwrap();
self.layouter.update(ctx.module.to_ctx()).unwrap();
let ty = ctx.ensure_type_exists(crate::TypeInner::Array {
base,
size,

View File

@@ -343,7 +343,7 @@ impl<'a> ExpressionContext<'a, '_, '_> {
}
fn format_typeinner(&self, inner: &crate::TypeInner) -> String {
inner.to_wgsl(&self.module.types, &self.module.constants)
inner.to_wgsl(self.module.to_ctx())
}
fn format_type(&self, handle: Handle<crate::Type>) -> String {
@@ -624,14 +624,16 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
if let Some(explicit) = explicit_ty {
if explicit != inferred_type {
let ty = &ctx.module.types[explicit];
let explicit = ty.name.clone().unwrap_or_else(|| {
ty.inner.to_wgsl(&ctx.module.types, &ctx.module.constants)
});
let explicit = ty
.name
.clone()
.unwrap_or_else(|| ty.inner.to_wgsl(ctx.module.to_ctx()));
let ty = &ctx.module.types[inferred_type];
let inferred = ty.name.clone().unwrap_or_else(|| {
ty.inner.to_wgsl(&ctx.module.types, &ctx.module.constants)
});
let inferred = ty
.name
.clone()
.unwrap_or_else(|| ty.inner.to_wgsl(ctx.module.to_ctx()));
return Err(Error::InitializationTypeMismatch(
c.name.span,
@@ -2065,9 +2067,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
for member in s.members.iter() {
let ty = self.resolve_ast_type(member.ty, ctx.reborrow())?;
self.layouter
.update(&ctx.module.types, &ctx.module.constants)
.unwrap();
self.layouter.update(ctx.module.to_ctx()).unwrap();
let member_min_size = self.layouter[ty].size;
let member_min_alignment = self.layouter[ty].alignment;
@@ -2154,9 +2154,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
}
ast::Type::Array { base, size } => {
let base = self.resolve_ast_type(base, ctx.reborrow())?;
self.layouter
.update(&ctx.module.types, &ctx.module.constants)
.unwrap();
self.layouter.update(ctx.module.to_ctx()).unwrap();
crate::TypeInner::Array {
base,

View File

@@ -11,8 +11,6 @@ mod parse;
#[cfg(test)]
mod tests;
use crate::arena::{Arena, UniqueArena};
use crate::front::wgsl::error::Error;
use crate::front::wgsl::parse::Parser;
use thiserror::Error;
@@ -100,11 +98,7 @@ impl crate::TypeInner {
/// For example `vec3<f32>`.
///
/// Note: The names of a `TypeInner::Struct` is not known. Therefore this method will simply return "struct" for them.
fn to_wgsl(
&self,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
) -> String {
fn to_wgsl(&self, gctx: crate::proc::GlobalCtx) -> String {
use crate::TypeInner as Ti;
match *self {
@@ -128,7 +122,7 @@ impl crate::TypeInner {
format!("atomic<{}>", kind.to_wgsl(width))
}
Ti::Pointer { base, .. } => {
let base = &types[base];
let base = &gctx.types[base];
let name = base.name.as_deref().unwrap_or("unknown");
format!("ptr<{name}>")
}
@@ -136,11 +130,11 @@ impl crate::TypeInner {
format!("ptr<{}>", kind.to_wgsl(width))
}
Ti::Array { base, size, .. } => {
let member_type = &types[base];
let member_type = &gctx.types[base];
let base = member_type.name.as_deref().unwrap_or("unknown");
match size {
crate::ArraySize::Constant(size) => {
let constant = &constants[size];
let constant = &gctx.constants[size];
let size = constant
.name
.clone()
@@ -209,11 +203,11 @@ impl crate::TypeInner {
Ti::AccelerationStructure => "acceleration_structure".to_string(),
Ti::RayQuery => "ray_query".to_string(),
Ti::BindingArray { base, size, .. } => {
let member_type = &types[base];
let member_type = &gctx.types[base];
let base = member_type.name.as_deref().unwrap_or("unknown");
match size {
crate::ArraySize::Constant(size) => {
let size = constants[size].name.as_deref().unwrap_or("unknown");
let size = gctx.constants[size].name.as_deref().unwrap_or("unknown");
format!("binding_array<{base}, {size}>")
}
crate::ArraySize::Dynamic => format!("binding_array<{base}>"),
@@ -261,19 +255,23 @@ mod type_inner_tests {
Default::default(),
);
let gctx = crate::proc::GlobalCtx {
types: &types,
constants: &constants,
};
let array = crate::TypeInner::Array {
base: mytype1,
stride: 4,
size: crate::ArraySize::Constant(c),
};
assert_eq!(array.to_wgsl(&types, &constants), "array<MyType1, C>");
assert_eq!(array.to_wgsl(gctx), "array<MyType1, C>");
let mat = crate::TypeInner::Matrix {
rows: crate::VectorSize::Quad,
columns: crate::VectorSize::Bi,
width: 8,
};
assert_eq!(mat.to_wgsl(&types, &constants), "mat2x4<f64>");
assert_eq!(mat.to_wgsl(gctx), "mat2x4<f64>");
let ptr = crate::TypeInner::Pointer {
base: mytype2,
@@ -281,7 +279,7 @@ mod type_inner_tests {
access: crate::StorageAccess::default(),
},
};
assert_eq!(ptr.to_wgsl(&types, &constants), "ptr<MyType2>");
assert_eq!(ptr.to_wgsl(gctx), "ptr<MyType2>");
let img1 = crate::TypeInner::Image {
dim: crate::ImageDimension::D2,
@@ -291,36 +289,27 @@ mod type_inner_tests {
multi: true,
},
};
assert_eq!(
img1.to_wgsl(&types, &constants),
"texture_multisampled_2d<f32>"
);
assert_eq!(img1.to_wgsl(gctx), "texture_multisampled_2d<f32>");
let img2 = crate::TypeInner::Image {
dim: crate::ImageDimension::Cube,
arrayed: true,
class: crate::ImageClass::Depth { multi: false },
};
assert_eq!(img2.to_wgsl(&types, &constants), "texture_depth_cube_array");
assert_eq!(img2.to_wgsl(gctx), "texture_depth_cube_array");
let img3 = crate::TypeInner::Image {
dim: crate::ImageDimension::D2,
arrayed: false,
class: crate::ImageClass::Depth { multi: true },
};
assert_eq!(
img3.to_wgsl(&types, &constants),
"texture_depth_multisampled_2d"
);
assert_eq!(img3.to_wgsl(gctx), "texture_depth_multisampled_2d");
let array = crate::TypeInner::BindingArray {
base: mytype1,
size: crate::ArraySize::Constant(c),
};
assert_eq!(
array.to_wgsl(&types, &constants),
"binding_array<MyType1, C>"
);
assert_eq!(array.to_wgsl(gctx), "binding_array<MyType1, C>");
}
}

View File

@@ -1,4 +1,4 @@
use crate::arena::{Arena, Handle, UniqueArena};
use crate::arena::Handle;
use std::{fmt::Display, num::NonZeroU32, ops};
/// A newtype struct where its only valid values are powers of 2
@@ -165,15 +165,11 @@ impl Layouter {
/// constant arenas, and then assume that layouts are available for all
/// types.
#[allow(clippy::or_fun_call)]
pub fn update(
&mut self,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
) -> Result<(), LayoutError> {
pub fn update(&mut self, gctx: super::GlobalCtx) -> Result<(), LayoutError> {
use crate::TypeInner as Ti;
for (ty_handle, ty) in types.iter().skip(self.layouts.len()) {
let size = ty.inner.size(constants);
for (ty_handle, ty) in gctx.types.iter().skip(self.layouts.len()) {
let size = ty.inner.size(gctx);
let layout = match ty.inner {
Ti::Scalar { width, .. } | Ti::Atomic { width, .. } => {
let alignment = Alignment::new(width as u32)

View File

@@ -199,7 +199,7 @@ impl super::TypeInner {
}
/// Get the size of this type.
pub fn size(&self, constants: &super::Arena<super::Constant>) -> u32 {
pub fn size(&self, gctx: GlobalCtx) -> u32 {
match *self {
Self::Scalar { kind: _, width } | Self::Atomic { kind: _, width } => width as u32,
Self::Vector {
@@ -221,7 +221,7 @@ impl super::TypeInner {
} => {
let count = match size {
super::ArraySize::Constant(handle) => {
constants[handle].to_array_length().unwrap_or(1)
gctx.constants[handle].to_array_length().unwrap_or(1)
}
// A dynamically-sized array has to have at least one element
super::ArraySize::Dynamic => 1,
@@ -575,16 +575,31 @@ impl super::ImageClass {
}
}
impl crate::Module {
pub const fn to_ctx(&self) -> GlobalCtx<'_> {
GlobalCtx {
types: &self.types,
constants: &self.constants,
}
}
}
#[derive(Clone, Copy)]
pub struct GlobalCtx<'a> {
pub types: &'a crate::UniqueArena<crate::Type>,
pub constants: &'a crate::Arena<crate::Constant>,
}
#[test]
fn test_matrix_size() {
let constants = crate::Arena::new();
let module = crate::Module::default();
assert_eq!(
crate::TypeInner::Matrix {
columns: crate::VectorSize::Tri,
rows: crate::VectorSize::Tri,
width: 4
}
.size(&constants),
.size(module.to_ctx()),
48,
);
}

View File

@@ -1,8 +1,5 @@
#[cfg(feature = "validate")]
use crate::{
arena::{Arena, UniqueArena},
proc::TypeResolution,
};
use crate::proc::TypeResolution;
use crate::arena::Handle;
@@ -20,18 +17,17 @@ pub enum ComposeError {
#[cfg(feature = "validate")]
pub fn validate_compose(
self_ty_handle: Handle<crate::Type>,
constant_arena: &Arena<crate::Constant>,
type_arena: &UniqueArena<crate::Type>,
gctx: crate::proc::GlobalCtx,
component_resolutions: impl ExactSizeIterator<Item = TypeResolution>,
) -> Result<(), ComposeError> {
use crate::TypeInner as Ti;
match type_arena[self_ty_handle].inner {
match gctx.types[self_ty_handle].inner {
// vectors are composed from scalars or other vectors
Ti::Vector { size, kind, width } => {
let mut total = 0;
for (index, comp_res) in component_resolutions.enumerate() {
total += match *comp_res.inner_with(type_arena) {
total += match *comp_res.inner_with(gctx.types) {
Ti::Scalar {
kind: comp_kind,
width: comp_width,
@@ -74,7 +70,7 @@ pub fn validate_compose(
});
}
for (index, comp_res) in component_resolutions.enumerate() {
if comp_res.inner_with(type_arena) != &inner {
if comp_res.inner_with(gctx.types) != &inner {
log::error!("Matrix component[{}] type {:?}", index, comp_res);
return Err(ComposeError::ComponentType {
index: index as u32,
@@ -87,7 +83,7 @@ pub fn validate_compose(
size: crate::ArraySize::Constant(handle),
stride: _,
} => {
let count = constant_arena[handle].to_array_length().unwrap();
let count = gctx.constants[handle].to_array_length().unwrap();
if count as usize != component_resolutions.len() {
return Err(ComposeError::ComponentCount {
expected: count,
@@ -95,11 +91,11 @@ pub fn validate_compose(
});
}
for (index, comp_res) in component_resolutions.enumerate() {
let base_inner = &type_arena[base].inner;
let comp_res_inner = comp_res.inner_with(type_arena);
let base_inner = &gctx.types[base].inner;
let comp_res_inner = comp_res.inner_with(gctx.types);
// We don't support arrays of pointers, but it seems best not to
// embed that assumption here, so use `TypeInner::equivalent`.
if !base_inner.equivalent(comp_res_inner, type_arena) {
if !base_inner.equivalent(comp_res_inner, gctx.types) {
log::error!("Array component[{}] type {:?}", index, comp_res);
return Err(ComposeError::ComponentType {
index: index as u32,
@@ -116,11 +112,11 @@ pub fn validate_compose(
}
for (index, (member, comp_res)) in members.iter().zip(component_resolutions).enumerate()
{
let member_inner = &type_arena[member.ty].inner;
let comp_res_inner = comp_res.inner_with(type_arena);
let member_inner = &gctx.types[member.ty].inner;
let comp_res_inner = comp_res.inner_with(gctx.types);
// We don't support pointers in structs, but it seems best not to embed
// that assumption here, so use `TypeInner::equivalent`.
if !comp_res_inner.equivalent(member_inner, type_arena) {
if !comp_res_inner.equivalent(member_inner, gctx.types) {
log::error!("Struct component[{}] type {:?}", index, comp_res);
return Err(ComposeError::ComponentType {
index: index as u32,

View File

@@ -301,8 +301,7 @@ impl super::Validator {
E::Compose { ref components, ty } => {
validate_compose(
ty,
&module.constants,
&module.types,
module.to_ctx(),
components.iter().map(|&handle| info[handle].ty.clone()),
)?;
ShaderStages::all()

View File

@@ -894,8 +894,7 @@ impl super::Validator {
fn validate_local_var(
&self,
var: &crate::LocalVariable,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
gctx: crate::proc::GlobalCtx,
) -> Result<(), LocalVariableError> {
log::debug!("var {:?}", var);
let type_info = self
@@ -910,13 +909,13 @@ impl super::Validator {
}
if let Some(const_handle) = var.init {
match constants[const_handle].inner {
match gctx.constants[const_handle].inner {
crate::ConstantInner::Scalar { width, ref value } => {
let ty_inner = crate::TypeInner::Scalar {
width,
kind: value.scalar_kind(),
};
if types[var.ty].inner != ty_inner {
if gctx.types[var.ty].inner != ty_inner {
return Err(LocalVariableError::InitializerType);
}
}
@@ -942,7 +941,7 @@ impl super::Validator {
#[cfg(feature = "validate")]
for (var_handle, var) in fun.local_variables.iter() {
self.validate_local_var(var, &module.types, &module.constants)
self.validate_local_var(var, module.to_ctx())
.map_err(|source| {
FunctionError::LocalVariable {
handle: var_handle,

View File

@@ -395,12 +395,12 @@ impl super::Validator {
pub(super) fn validate_global_var(
&self,
var: &crate::GlobalVariable,
types: &UniqueArena<crate::Type>,
gctx: crate::proc::GlobalCtx,
) -> Result<(), GlobalVariableError> {
use super::TypeFlags;
log::debug!("var {:?}", var);
let inner_ty = match types[var.ty].inner {
let inner_ty = match gctx.types[var.ty].inner {
// A binding array is (mostly) supposed to behave the same as a
// series of individually bound resources, so we can (mostly)
// validate a `binding_array<T>` as if it were just a plain `T`.
@@ -444,7 +444,7 @@ impl super::Validator {
)
}
crate::AddressSpace::Handle => {
match types[inner_ty].inner {
match gctx.types[inner_ty].inner {
crate::TypeInner::Image { class, .. } => match class {
crate::ImageClass::Storage {
format:

View File

@@ -11,7 +11,7 @@ mod interface;
mod r#type;
#[cfg(feature = "validate")]
use crate::arena::{Arena, UniqueArena};
use crate::arena::UniqueArena;
use crate::{
arena::Handle,
@@ -296,10 +296,9 @@ impl Validator {
fn validate_constant(
&self,
handle: Handle<crate::Constant>,
constants: &Arena<crate::Constant>,
types: &UniqueArena<crate::Type>,
gctx: crate::proc::GlobalCtx,
) -> Result<(), ConstantError> {
let con = &constants[handle];
let con = &gctx.constants[handle];
match con.inner {
crate::ConstantInner::Scalar { width, ref value } => {
if self.check_width(value.scalar_kind(), width).is_err() {
@@ -309,11 +308,10 @@ impl Validator {
crate::ConstantInner::Composite { ty, ref components } => {
compose::validate_compose(
ty,
constants,
types,
gctx,
components
.iter()
.map(|&component| constants[component].inner.resolve_type()),
.map(|&component| gctx.constants[component].inner.resolve_type()),
)?;
}
}
@@ -331,17 +329,15 @@ impl Validator {
#[cfg(feature = "validate")]
Self::validate_module_handles(module).map_err(|e| e.with_span())?;
self.layouter
.update(&module.types, &module.constants)
.map_err(|e| {
let handle = e.ty;
ValidationError::from(e).with_span_handle(handle, &module.types)
})?;
self.layouter.update(module.to_ctx()).map_err(|e| {
let handle = e.ty;
ValidationError::from(e).with_span_handle(handle, &module.types)
})?;
#[cfg(feature = "validate")]
if self.flags.contains(ValidationFlags::CONSTANTS) {
for (handle, constant) in module.constants.iter() {
self.validate_constant(handle, &module.constants, &module.types)
self.validate_constant(handle, module.to_ctx())
.map_err(|source| {
ValidationError::Constant {
handle,
@@ -361,7 +357,7 @@ impl Validator {
for (handle, ty) in module.types.iter() {
let ty_info = self
.validate_type(handle, &module.types, &module.constants)
.validate_type(handle, module.to_ctx())
.map_err(|source| {
ValidationError::Type {
handle,
@@ -376,7 +372,7 @@ impl Validator {
#[cfg(feature = "validate")]
for (var_handle, var) in module.global_variables.iter() {
self.validate_global_var(var, &module.types)
self.validate_global_var(var, module.to_ctx())
.map_err(|source| {
ValidationError::GlobalVariable {
handle: var_handle,

View File

@@ -1,8 +1,5 @@
use super::Capabilities;
use crate::{
arena::{Arena, Handle, UniqueArena},
proc::Alignment,
};
use crate::{arena::Handle, proc::Alignment};
bitflags::bitflags! {
/// Flags associated with [`Type`]s by [`Validator`].
@@ -246,11 +243,10 @@ impl super::Validator {
pub(super) fn validate_type(
&self,
handle: Handle<crate::Type>,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
gctx: crate::proc::GlobalCtx,
) -> Result<TypeInfo, TypeError> {
use crate::TypeInner as Ti;
Ok(match types[handle].inner {
Ok(match gctx.types[handle].inner {
Ti::Scalar { kind, width } => {
self.check_width(kind, width)?;
let shareable = if kind.is_numeric() {
@@ -419,7 +415,7 @@ impl super::Validator {
let type_info_mask = match size {
crate::ArraySize::Constant(const_handle) => {
let constant = &constants[const_handle];
let constant = &gctx.constants[const_handle];
let length_is_positive = match *constant {
crate::Constant {
specialization: Some(_),
@@ -535,7 +531,7 @@ impl super::Validator {
}
}
let base_size = types[member.ty].inner.size(constants);
let base_size = gctx.types[member.ty].inner.size(gctx);
min_offset = member.offset + base_size;
if min_offset > span {
return Err(TypeError::MemberOutOfBounds {
@@ -579,14 +575,14 @@ impl super::Validator {
}
};
prev_struct_data = match types[member.ty].inner {
prev_struct_data = match gctx.types[member.ty].inner {
crate::TypeInner::Struct { span, .. } => Some((span, member.offset)),
_ => None,
};
// The last field may be an unsized array.
if !base_info.flags.contains(TypeFlags::SIZED) {
let is_array = match types[member.ty].inner {
let is_array = match gctx.types[member.ty].inner {
crate::TypeInner::Array { .. } => true,
_ => false,
};
@@ -635,7 +631,7 @@ impl super::Validator {
if base_info.flags.contains(TypeFlags::DATA) {
// Currently Naga only supports binding arrays of structs for non-handle types.
match types[base].inner {
match gctx.types[base].inner {
crate::TypeInner::Struct { .. } => {}
_ => return Err(TypeError::BindingArrayBaseTypeNotStruct(base)),
};