From 0f6509d4e598ec7e874b13fc68e6b7a0fffece67 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Fri, 17 Sep 2021 16:22:29 -0700 Subject: [PATCH] Use `UniqueArena` for types. Ensure that each distinct type occurs only once in `Module::types`, so that we can use `Eq` on `Type` or `TypeInner` for type equivalence, without being confused by differing `Handle` values that point to identical types. This removes a number of duplicate types from the ir snapshots. --- Cargo.toml | 5 +- src/arena.rs | 195 +++++++++++++++++++- src/back/msl/writer.rs | 4 +- src/back/spv/helpers.rs | 4 +- src/back/spv/writer.rs | 6 +- src/front/glsl/constants.rs | 18 +- src/front/glsl/functions.rs | 2 +- src/front/glsl/offset.rs | 4 +- src/front/glsl/parser/declarations.rs | 2 +- src/front/glsl/parser/types.rs | 2 +- src/front/mod.rs | 4 +- src/front/spv/function.rs | 2 +- src/front/spv/image.rs | 24 +-- src/front/spv/mod.rs | 32 ++-- src/front/spv/null.rs | 20 +- src/front/wgsl/mod.rs | 34 ++-- src/lib.rs | 21 ++- src/proc/layouter.rs | 4 +- src/proc/typifier.rs | 10 +- src/span.rs | 2 +- src/valid/analyzer.rs | 4 +- src/valid/compose.rs | 4 +- src/valid/expression.rs | 4 +- src/valid/function.rs | 6 +- src/valid/interface.rs | 6 +- src/valid/mod.rs | 4 +- src/valid/type.rs | 4 +- tests/out/analysis/shadow.info.ron | 60 +++--- tests/out/glsl/quad-vert.main.Vertex.glsl | 4 +- tests/out/hlsl/quad-vert.hlsl | 12 +- tests/out/ir/shadow.ron | 213 ++-------------------- tests/out/msl/quad-vert.msl | 24 +-- 32 files changed, 382 insertions(+), 358 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 935ece3f92..8d577643d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ bitflags = "1" bit-set = "0.5" codespan-reporting = { version = "0.11.0", optional = true } fxhash = "0.2" +indexmap = "1.6" # 1.7 has MSRV 1.49 log = "0.4" num-traits = "0.2" spirv = { version = "0.2", optional = true } @@ -36,8 +37,8 @@ glsl-in = ["pp-rs"] glsl-validate = [] glsl-out = ["petgraph"] msl-out = [] -serialize = ["serde"] -deserialize = ["serde"] +serialize = ["serde", "indexmap/serde-1"] +deserialize = ["serde", "indexmap/serde-1"] spv-in = ["petgraph", "spirv"] spv-out = ["spirv"] wgsl-in = ["codespan-reporting", "hexf-parse"] diff --git a/src/arena.rs b/src/arena.rs index 93cba7c501..ed1aa3e0b7 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -6,8 +6,11 @@ use std::{cmp::Ordering, fmt, hash, marker::PhantomData, num::NonZeroU32, ops}; type Index = NonZeroU32; use crate::Span; +use indexmap::set::IndexSet; /// A strongly typed reference to an arena item. +/// +/// A `Handle` value can be used as an index into an [`Arena`] or [`UniqueArena`]. #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] #[cfg_attr( @@ -81,7 +84,8 @@ impl Handle { use std::convert::TryFrom; let handle_index = u32::try_from(index + 1) - .and_then(Index::try_from) + .ok() + .and_then(Index::new) .expect("Failed to insert into UniqueArena. Handle overflows"); Handle::new(handle_index) } @@ -369,3 +373,192 @@ mod tests { assert!(arena[t1] != arena[t2]); } } + +/// An arena whose elements are guaranteed to be unique. +/// +/// A `UniqueArena` holds a set of unique values of type `T`, each with an +/// associated [`Span`]. Inserting a value returns a `Handle`, which can be +/// used to index the `UniqueArena` and obtain shared access to the `T` element. +/// Access via a `Handle` is an array lookup - no hash lookup is necessary. +/// +/// The element type must implement `Eq` and `Hash`. Insertions of equivalent +/// elements, according to `Eq`, all return the same `Handle`. +/// +/// Once inserted, elements may not be mutated. +/// +/// `UniqueArena` is similar to [`Arena`]: If `Arena` is vector-like, +/// `UniqueArena` is `HashSet`-like. +pub struct UniqueArena { + set: IndexSet, + + /// Spans for the elements, indexed by handle. + /// + /// The length of this vector is always equal to `set.len()`. `IndexSet` + /// promises that its elements "are indexed in a compact range, without + /// holes in the range 0..set.len()", so we can always use the indices + /// returned by insertion as indices into this vector. + #[cfg(feature = "span")] + span_info: Vec, +} + +impl UniqueArena { + /// Create a new arena with no initial capacity allocated. + pub fn new() -> Self { + UniqueArena { + set: IndexSet::new(), + #[cfg(feature = "span")] + span_info: Vec::new(), + } + } + + /// Return the current number of items stored in this arena. + pub fn len(&self) -> usize { + self.set.len() + } + + /// Return `true` if the arena contains no elements. + pub fn is_empty(&self) -> bool { + self.set.is_empty() + } + + /// Clears the arena, keeping all allocations. + pub fn clear(&mut self) { + self.set.clear(); + #[cfg(feature = "span")] + self.span_info.clear(); + } + + /// Return the span associated with `handle`. + /// + /// If a value has been inserted multiple times, the span returned is the + /// one provided with the first insertion. + /// + /// If the `span` feature is not enabled, always return `Span::default`. + /// This can be detected with [`Span::is_defined`]. + pub fn get_span(&self, handle: Handle) -> Span { + #[cfg(feature = "span")] + { + *self + .span_info + .get(handle.index()) + .unwrap_or(&Span::default()) + } + #[cfg(not(feature = "span"))] + { + let _ = handle; + Span::default() + } + } +} + +impl UniqueArena { + /// Returns an iterator over the items stored in this arena, returning both + /// the item's handle and a reference to it. + pub fn iter(&self) -> impl DoubleEndedIterator, &T)> { + self.set.iter().enumerate().map(|(i, v)| { + let position = i + 1; + let index = unsafe { Index::new_unchecked(position as u32) }; + (Handle::new(index), v) + }) + } + + /// Insert a new value into the arena. + /// + /// Return a [`Handle`], which can be used to index this arena to get a + /// shared reference to the element. + /// + /// If this arena already contains an element that is `Eq` to `value`, + /// return a `Handle` to the existing element, and drop `value`. + /// + /// When the `span` feature is enabled, if `value` is inserted into the + /// arena, associate `span` with it. An element's span can be retrieved with + /// the [`get_span`] method. + /// + /// [`Handle`]: Handle + /// [`get_span`]: UniqueArena::get_span + pub fn fetch_or_append(&mut self, value: T, span: Span) -> Handle { + let (index, added) = self.set.insert_full(value); + + #[cfg(feature = "span")] + { + if added { + debug_assert!(index == self.span_info.len()); + self.span_info.push(span); + } + + debug_assert!(self.set.len() == self.span_info.len()); + } + + Handle::from_usize(index) + } + + /// Return this arena's handle for `value`, if present. + /// + /// If this arena already contains an element equal to `value`, + /// return its handle. Otherwise, return `None`. + pub fn get(&self, value: &T) -> Option> { + self.set + .get_index_of(value) + .map(|index| unsafe { Handle::from_usize_unchecked(index) }) + } + + /// Return this arena's value at `handle`, if that is a valid handle. + pub fn try_get(&self, handle: Handle) -> Option<&T> { + self.set.get_index(handle.index()) + } +} + +impl Default for UniqueArena { + fn default() -> Self { + Self::new() + } +} + +impl fmt::Debug for UniqueArena { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_map().entries(self.iter()).finish() + } +} + +impl ops::Index> for UniqueArena { + type Output = T; + fn index(&self, handle: Handle) -> &T { + &self.set[handle.index()] + } +} + +#[cfg(feature = "serialize")] +impl serde::Serialize for UniqueArena +where + T: Eq + hash::Hash, + T: serde::Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.set.serialize(serializer) + } +} + +#[cfg(feature = "deserialize")] +impl<'de, T> serde::Deserialize<'de> for UniqueArena +where + T: Eq + hash::Hash, + T: serde::Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let set = IndexSet::deserialize(deserializer)?; + #[cfg(feature = "span")] + let span_info = std::iter::repeat(Span::default()).take(set.len()).collect(); + + Ok(Self { + set, + #[cfg(feature = "span")] + span_info, + }) + } +} diff --git a/src/back/msl/writer.rs b/src/back/msl/writer.rs index 0bf159e545..8f0368908b 100644 --- a/src/back/msl/writer.rs +++ b/src/back/msl/writer.rs @@ -22,7 +22,7 @@ const ATOMIC_REFERENCE: &str = "&"; struct TypeContext<'a> { handle: Handle, - arena: &'a crate::Arena, + arena: &'a crate::UniqueArena, names: &'a FastHashMap, access: crate::StorageAccess, first_time: bool, @@ -354,7 +354,7 @@ fn should_pack_struct_member( } } -fn needs_array_length(ty: Handle, arena: &crate::Arena) -> bool { +fn needs_array_length(ty: Handle, arena: &crate::UniqueArena) -> bool { if let crate::TypeInner::Struct { ref members, .. } = arena[ty].inner { if let Some(member) = members.last() { if let crate::TypeInner::Array { diff --git a/src/back/spv/helpers.rs b/src/back/spv/helpers.rs index fe8fbaf757..aa7952ad29 100644 --- a/src/back/spv/helpers.rs +++ b/src/back/spv/helpers.rs @@ -1,4 +1,4 @@ -use crate::{Arena, Handle}; +use crate::{Handle, UniqueArena}; use spirv::Word; pub(super) fn bytes_to_words(bytes: &[u8]) -> Vec { @@ -35,7 +35,7 @@ pub(super) fn map_storage_class(class: crate::StorageClass) -> spirv::StorageCla pub(super) fn contains_builtin( binding: Option<&crate::Binding>, ty: Handle, - arena: &Arena, + arena: &UniqueArena, built_in: crate::BuiltIn, ) -> bool { if let Some(&crate::Binding::BuiltIn(bi)) = binding { diff --git a/src/back/spv/writer.rs b/src/back/spv/writer.rs index c9d62f50b8..dfe088cd65 100644 --- a/src/back/spv/writer.rs +++ b/src/back/spv/writer.rs @@ -6,7 +6,7 @@ use super::{ PipelineOptions, ResultMember, Writer, WriterFlags, BITS_PER_BYTE, }; use crate::{ - arena::{Arena, Handle}, + arena::{Handle, UniqueArena}, proc::TypeResolution, valid::{FunctionInfo, ModuleInfo}, }; @@ -195,7 +195,7 @@ impl Writer { pub(super) fn get_pointer_id( &mut self, - arena: &Arena, + arena: &UniqueArena, handle: Handle, class: spirv::StorageClass, ) -> Result { @@ -766,7 +766,7 @@ impl Writer { fn write_type_declaration_arena( &mut self, - arena: &Arena, + arena: &UniqueArena, handle: Handle, ) -> Result { let ty = &arena[handle]; diff --git a/src/front/glsl/constants.rs b/src/front/glsl/constants.rs index e39a596217..1584e9b526 100644 --- a/src/front/glsl/constants.rs +++ b/src/front/glsl/constants.rs @@ -1,12 +1,12 @@ use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, BinaryOperator, Constant, ConstantInner, Expression, ScalarKind, ScalarValue, Type, TypeInner, UnaryOperator, }; #[derive(Debug)] pub struct ConstantSolver<'a> { - pub types: &'a mut Arena, + pub types: &'a mut UniqueArena, pub expressions: &'a Arena, pub constants: &'a mut Arena, } @@ -531,18 +531,18 @@ mod tests { use crate::{ Arena, Constant, ConstantInner, Expression, ScalarKind, ScalarValue, Type, TypeInner, - UnaryOperator, VectorSize, + UnaryOperator, UniqueArena, VectorSize, }; use super::ConstantSolver; #[test] fn unary_op() { - let mut types = Arena::new(); + let mut types = UniqueArena::new(); let mut expressions = Arena::new(); let mut constants = Arena::new(); - let vec_ty = types.append( + let vec_ty = types.fetch_or_append( Type { name: None, inner: TypeInner::Vector { @@ -698,7 +698,7 @@ mod tests { ); let mut solver = ConstantSolver { - types: &mut Arena::new(), + types: &mut UniqueArena::new(), expressions: &expressions, constants: &mut constants, }; @@ -716,11 +716,11 @@ mod tests { #[test] fn access() { - let mut types = Arena::new(); + let mut types = UniqueArena::new(); let mut expressions = Arena::new(); let mut constants = Arena::new(); - let matrix_ty = types.append( + let matrix_ty = types.fetch_or_append( Type { name: None, inner: TypeInner::Matrix { @@ -732,7 +732,7 @@ mod tests { Default::default(), ); - let vec_ty = types.append( + let vec_ty = types.fetch_or_append( Type { name: None, inner: TypeInner::Vector { diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index f080c2d48d..e46ababac1 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -900,7 +900,7 @@ impl Parser { } let (ty, value) = if !components.is_empty() { - let ty = self.module.types.append( + let ty = self.module.types.fetch_or_append( Type { name: None, inner: TypeInner::Struct { diff --git a/src/front/glsl/offset.rs b/src/front/glsl/offset.rs index 0884802323..01c2edd15e 100644 --- a/src/front/glsl/offset.rs +++ b/src/front/glsl/offset.rs @@ -13,7 +13,7 @@ use super::{ error::{Error, ErrorKind}, Span, }; -use crate::{front::align_up, Arena, Constant, Handle, Type, TypeInner}; +use crate::{front::align_up, Arena, Constant, Handle, Type, TypeInner, UniqueArena}; /// Struct with information needed for defining a struct member. /// @@ -39,7 +39,7 @@ pub fn calculate_offset( mut ty: Handle, meta: Span, layout: StructLayout, - types: &mut Arena, + types: &mut UniqueArena, constants: &Arena, errors: &mut Vec, ) -> TypeAlignSpan { diff --git a/src/front/glsl/parser/declarations.rs b/src/front/glsl/parser/declarations.rs index 47506c060e..8ef71ef284 100644 --- a/src/front/glsl/parser/declarations.rs +++ b/src/front/glsl/parser/declarations.rs @@ -497,7 +497,7 @@ impl<'source> ParsingContext<'source> { let span = self.parse_struct_declaration_list(parser, &mut members, layout)?; self.expect(parser, TokenValue::RightBrace)?; - let mut ty = parser.module.types.append( + let mut ty = parser.module.types.fetch_or_append( Type { name: Some(ty_name), inner: TypeInner::Struct { diff --git a/src/front/glsl/parser/types.rs b/src/front/glsl/parser/types.rs index c056c1395a..3dc00c33fd 100644 --- a/src/front/glsl/parser/types.rs +++ b/src/front/glsl/parser/types.rs @@ -47,7 +47,7 @@ impl<'source> ParsingContext<'source> { self.parse_struct_declaration_list(parser, &mut members, StructLayout::Std140)?; let end_meta = self.expect(parser, TokenValue::RightBrace)?.meta; meta.subsume(end_meta); - let ty = parser.module.types.append( + let ty = parser.module.types.fetch_or_append( Type { name: Some(ty_name.clone()), inner: TypeInner::Struct { diff --git a/src/front/mod.rs b/src/front/mod.rs index 292acf3da3..86adc64e4d 100644 --- a/src/front/mod.rs +++ b/src/front/mod.rs @@ -8,7 +8,7 @@ pub mod spv; pub mod wgsl; use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, proc::{ResolveContext, ResolveError, TypeResolution}, }; use std::ops; @@ -79,7 +79,7 @@ impl Typifier { pub fn get<'a>( &'a self, expr_handle: Handle, - types: &'a Arena, + types: &'a UniqueArena, ) -> &'a crate::TypeInner { self.resolutions[expr_handle.index()].inner_with(types) } diff --git a/src/front/spv/function.rs b/src/front/spv/function.rs index 05b8fc6564..1af33c2f53 100644 --- a/src/front/spv/function.rs +++ b/src/front/spv/function.rs @@ -478,7 +478,7 @@ impl> super::Parser { let span = crate::Span::total_span( components.iter().map(|h| function.expressions.get_span(*h)), ); - let ty = module.types.append( + let ty = module.types.fetch_or_append( crate::Type { name: None, inner: crate::TypeInner::Struct { diff --git a/src/front/spv/image.rs b/src/front/spv/image.rs index b46fcbce1a..c58fe370f5 100644 --- a/src/front/spv/image.rs +++ b/src/front/spv/image.rs @@ -1,5 +1,5 @@ use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, FunctionArgument, }; @@ -62,7 +62,7 @@ fn extract_image_coordinates( extra_coordinate: ExtraCoordinate, base: Handle, coordinate_ty: Handle, - type_arena: &Arena, + type_arena: &UniqueArena, expressions: &mut Arena, ) -> (Handle, Option>) { let (given_size, kind) = match type_arena[coordinate_ty].inner { @@ -74,13 +74,13 @@ fn extract_image_coordinates( let required_size = image_dim.required_coordinate_size(); let required_ty = required_size.map(|size| { type_arena - .fetch_if(|ty| { - ty.inner - == crate::TypeInner::Vector { - size, - kind, - width: 4, - } + .get(&crate::Type { + name: None, + inner: crate::TypeInner::Vector { + size, + kind, + width: 4, + }, }) .expect("Required coordinate type should have been set up by `parse_type_image`!") }); @@ -184,7 +184,7 @@ fn extract_image_coordinates( pub(super) fn patch_comparison_type( flags: SamplingFlags, var: &mut crate::GlobalVariable, - arena: &mut Arena, + arena: &mut UniqueArena, ) -> bool { if !flags.contains(SamplingFlags::COMPARISON) { return true; @@ -211,7 +211,7 @@ pub(super) fn patch_comparison_type( }; let name = original_ty.name.clone(); - var.ty = arena.append( + var.ty = arena.fetch_or_append( crate::Type { name, inner: ty_inner, @@ -257,7 +257,7 @@ impl> super::Parser { pub(super) fn parse_image_write( &mut self, words_left: u16, - type_arena: &Arena, + type_arena: &UniqueArena, global_arena: &Arena, arguments: &[FunctionArgument], expressions: &mut Arena, diff --git a/src/front/spv/mod.rs b/src/front/spv/mod.rs index ef3ad51a6e..4de67974f9 100644 --- a/src/front/spv/mod.rs +++ b/src/front/spv/mod.rs @@ -35,7 +35,7 @@ pub use error::Error; use function::*; use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, proc::Layouter, FastHashMap, }; @@ -495,7 +495,7 @@ struct BlockContext<'function> { /// Constants arena of the module being processed const_arena: &'function mut Arena, /// Type arena of the module being processed - type_arena: &'function Arena, + type_arena: &'function UniqueArena, /// Global arena of the module being processed global_arena: &'function Arena, /// Arguments of the function currently being processed @@ -991,7 +991,7 @@ impl> Parser { root_type_id: spirv::Word, object_expr: Handle, selections: &[spirv::Word], - type_arena: &Arena, + type_arena: &UniqueArena, expressions: &mut Arena, span: crate::Span, ) -> Result, Error> { @@ -3388,7 +3388,7 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: self.future_decor.remove(&id).and_then(|dec| dec.name), inner, @@ -3423,7 +3423,7 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: self.future_decor.remove(&id).and_then(|dec| dec.name), inner, @@ -3453,7 +3453,7 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: self.future_decor.remove(&id).and_then(|dec| dec.name), inner, @@ -3490,7 +3490,7 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: self.future_decor.remove(&id).and_then(|dec| dec.name), inner, @@ -3529,7 +3529,7 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: decor.and_then(|dec| dec.name), inner, @@ -3593,7 +3593,7 @@ impl> Parser { base_lookup_ty.clone() } else { LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: decor.and_then(|dec| dec.name), inner: crate::TypeInner::Pointer { @@ -3636,7 +3636,7 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: decor.name, inner, @@ -3673,7 +3673,7 @@ impl> Parser { self.lookup_type.insert( id, LookupType { - handle: module.types.append( + handle: module.types.fetch_or_append( crate::Type { name: decor.name, inner, @@ -3775,7 +3775,7 @@ impl> Parser { members, }; - let ty_handle = module.types.append( + let ty_handle = module.types.fetch_or_append( crate::Type { name: parent_decor.and_then(|dec| dec.name), inner, @@ -3860,7 +3860,7 @@ impl> Parser { arrayed: is_array, }; - let handle = module.types.append( + let handle = module.types.fetch_or_append( crate::Type { name: decor.name, inner, @@ -3903,7 +3903,7 @@ impl> Parser { inst.expect(2)?; let id = self.next()?; let decor = self.future_decor.remove(&id).unwrap_or_default(); - let handle = module.types.append( + let handle = module.types.fetch_or_append( crate::Type { name: decor.name, inner: crate::TypeInner::Sampler { comparison: false }, @@ -4049,7 +4049,7 @@ impl> Parser { fn parse_null_constant( &mut self, inst: Instruction, - types: &Arena, + types: &UniqueArena, constants: &mut Arena, ) -> Result<(u32, u32, Handle), Error> { let start = self.data_offset; @@ -4149,7 +4149,7 @@ impl> Parser { class: crate::ImageClass::Storage { format, access }, }, }; - effective_ty = module.types.append(ty, Default::default()); + effective_ty = module.types.fetch_or_append(ty, Default::default()); } let ext_class = match self.lookup_storage_buffer_types.get(&effective_ty) { diff --git a/src/front/spv/null.rs b/src/front/spv/null.rs index b6c8ca33ca..5d40dfa913 100644 --- a/src/front/spv/null.rs +++ b/src/front/spv/null.rs @@ -1,5 +1,5 @@ use super::Error; -use crate::arena::{Arena, Handle}; +use crate::arena::{Arena, Handle, UniqueArena}; fn make_scalar_inner(kind: crate::ScalarKind, width: crate::Bytes) -> crate::ConstantInner { crate::ConstantInner::Scalar { @@ -15,7 +15,7 @@ fn make_scalar_inner(kind: crate::ScalarKind, width: crate::Bytes) -> crate::Con pub fn generate_null_constant( ty: Handle, - type_arena: &Arena, + type_arena: &UniqueArena, constant_arena: &mut Arena, span: crate::Span, ) -> Result { @@ -42,13 +42,13 @@ pub fn generate_null_constant( } => { // If we successfully declared a matrix type, we have declared a vector type for it too. let vector_ty = type_arena - .fetch_if(|t| { - t.inner - == crate::TypeInner::Vector { - kind: crate::ScalarKind::Float, - size: rows, - width, - } + .get(&crate::Type { + name: None, + inner: crate::TypeInner::Vector { + kind: crate::ScalarKind::Float, + size: rows, + width, + }, }) .unwrap(); let vector_inner = generate_null_constant(vector_ty, type_arena, constant_arena, span)?; @@ -116,7 +116,7 @@ pub fn generate_null_constant( pub fn generate_default_built_in( built_in: Option, ty: Handle, - type_arena: &Arena, + type_arena: &UniqueArena, constant_arena: &mut Arena, span: crate::Span, ) -> Result, Error> { diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index 455c6d2746..eae6ce8b19 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -9,7 +9,7 @@ mod number_literals; mod tests; use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, proc::{ ensure_block_returns, Alignment, Layouter, ResolveContext, ResolveError, TypeResolution, }, @@ -486,7 +486,11 @@ impl crate::TypeInner { /// For example `vec3`. /// /// Note: The names of a `TypeInner::Struct` is not known. Therefore this method will simply return "struct" for them. - fn to_wgsl(&self, types: &Arena, constants: &Arena) -> String { + fn to_wgsl( + &self, + types: &UniqueArena, + constants: &Arena, + ) -> String { use crate::TypeInner as Ti; match *self { @@ -584,7 +588,7 @@ impl crate::TypeInner { mod type_inner_tests { #[test] fn to_wgsl() { - let mut types = crate::Arena::new(); + let mut types = crate::UniqueArena::new(); let mut constants = crate::Arena::new(); let c = constants.append( crate::Constant { @@ -598,7 +602,7 @@ mod type_inner_tests { Default::default(), ); - let mytype1 = types.append( + let mytype1 = types.fetch_or_append( crate::Type { name: Some("MyType1".to_string()), inner: crate::TypeInner::Struct { @@ -609,7 +613,7 @@ mod type_inner_tests { }, Default::default(), ); - let mytype2 = types.append( + let mytype2 = types.fetch_or_append( crate::Type { name: Some("MyType2".to_string()), inner: crate::TypeInner::Struct { @@ -707,7 +711,7 @@ struct StatementContext<'input, 'temp, 'out> { variables: &'out mut Arena, expressions: &'out mut Arena, named_expressions: &'out mut FastHashMap, String>, - types: &'out mut Arena, + types: &'out mut UniqueArena, constants: &'out mut Arena, global_vars: &'out Arena, functions: &'out Arena, @@ -763,7 +767,7 @@ struct ExpressionContext<'input, 'temp, 'out> { lookup_ident: &'temp FastHashMap<&'input str, TypedExpression>, typifier: &'temp mut super::Typifier, expressions: &'out mut Arena, - types: &'out mut Arena, + types: &'out mut UniqueArena, constants: &'out mut Arena, global_vars: &'out Arena, local_vars: &'out Arena, @@ -1993,7 +1997,7 @@ impl Parser { first_token_span: TokenSpan<'a>, lexer: &mut Lexer<'a>, register_name: Option<&'a str>, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { self.push_scope(Scope::ConstantExpr, lexer); @@ -2068,7 +2072,7 @@ impl Parser { fn parse_const_expression<'a>( &mut self, lexer: &mut Lexer<'a>, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { self.parse_const_expression_impl(lexer.next(), lexer, None, type_arena, const_arena) @@ -2560,7 +2564,7 @@ impl Parser { fn parse_variable_ident_decl<'a>( &mut self, lexer: &mut Lexer<'a>, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result<(&'a str, Span, Handle, crate::StorageAccess), Error<'a>> { let (name, name_span) = lexer.next_ident_with_span()?; @@ -2572,7 +2576,7 @@ impl Parser { fn parse_variable_decl<'a>( &mut self, lexer: &mut Lexer<'a>, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { self.push_scope(Scope::VariableDecl, lexer); @@ -2624,7 +2628,7 @@ impl Parser { fn parse_struct_body<'a>( &mut self, lexer: &mut Lexer<'a>, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result<(Vec, u32), Error<'a>> { let mut offset = 0; @@ -2720,7 +2724,7 @@ impl Parser { lexer: &mut Lexer<'a>, attribute: TypeAttributes, word: &'a str, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { if let Some((kind, width)) = conv::get_scalar_type(word) { @@ -3032,7 +3036,7 @@ impl Parser { name_span: Span, debug_name: Option<&'a str>, attribute: TypeAttributes, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result, Error<'a>> { Ok(match self.lookup_type.get(name) { @@ -3059,7 +3063,7 @@ impl Parser { &mut self, lexer: &mut Lexer<'a>, debug_name: Option<&'a str>, - type_arena: &mut Arena, + type_arena: &mut UniqueArena, const_arena: &mut Arena, ) -> Result<(Handle, crate::StorageAccess), Error<'a>> { self.push_scope(Scope::TypeDecl, lexer); diff --git a/src/lib.rs b/src/lib.rs index afc93094d0..bc0681d9f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,6 +44,15 @@ and compound expressions refer to their sub-expressions via `Handle` values. (When examining the serialized form of a `Module`, note that the first element of an `Arena` has an index of 1, not 0.) +A [`UniqueArena`] is just like an `Arena`, except that it stores only a single +instance of each value. The value type must implement `Eq` and `Hash`. Like an +`Arena`, inserting a value into a `UniqueArena` returns a `Handle` which can be +used to efficiently access the value, without a hash lookup. Inserting a value +multiple times returns the same `Handle`. + +If the `span` feature is enabled, both `Arena` and `UniqueArena` can associate a +source code span with each element. + ## Function Calls Naga's representation of function calls is unusual. Most languages treat @@ -203,7 +212,7 @@ pub mod proc; mod span; pub mod valid; -pub use crate::arena::{Arena, Handle, Range}; +pub use crate::arena::{Arena, Handle, Range, UniqueArena}; use std::{ collections::{HashMap, HashSet}, @@ -412,7 +421,7 @@ pub enum Sampling { /// Member of a user-defined structure. // Clone is used only for error reporting and is not intended for end users -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serialize", derive(Serialize))] #[cfg_attr(feature = "deserialize", derive(Deserialize))] pub struct StructMember { @@ -531,7 +540,7 @@ pub enum ImageClass { } /// A data type declared in the module. -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serialize", derive(Serialize))] #[cfg_attr(feature = "deserialize", derive(Deserialize))] pub struct Type { @@ -542,7 +551,7 @@ pub struct Type { } /// Enum with additional information, depending on the kind of type. -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serialize", derive(Serialize))] #[cfg_attr(feature = "deserialize", derive(Deserialize))] pub enum TypeInner { @@ -704,7 +713,7 @@ pub enum ConstantInner { } /// Describes how an input/output variable is to be bound. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serialize", derive(Serialize))] #[cfg_attr(feature = "deserialize", derive(Deserialize))] pub enum Binding { @@ -1552,7 +1561,7 @@ pub struct EntryPoint { #[cfg_attr(feature = "deserialize", derive(Deserialize))] pub struct Module { /// Storage for the types defined in this module. - pub types: Arena, + pub types: UniqueArena, /// Storage for the constants defined in this module. pub constants: Arena, /// Storage for the global variables defined in this module. diff --git a/src/proc/layouter.rs b/src/proc/layouter.rs index f2921f15e5..5facecdac2 100644 --- a/src/proc/layouter.rs +++ b/src/proc/layouter.rs @@ -1,4 +1,4 @@ -use crate::arena::{Arena, Handle}; +use crate::arena::{Arena, Handle, UniqueArena}; use std::{num::NonZeroU32, ops}; pub type Alignment = NonZeroU32; @@ -64,7 +64,7 @@ impl Layouter { pub fn update( &mut self, - types: &Arena, + types: &UniqueArena, constants: &Arena, ) -> Result<(), InvalidBaseType> { use crate::TypeInner as Ti; diff --git a/src/proc/typifier.rs b/src/proc/typifier.rs index 4a38ea6fd1..4f27b85d0a 100644 --- a/src/proc/typifier.rs +++ b/src/proc/typifier.rs @@ -1,4 +1,4 @@ -use crate::arena::{Arena, Handle}; +use crate::arena::{Arena, Handle, UniqueArena}; use thiserror::Error; @@ -10,8 +10,8 @@ use thiserror::Error; /// You might expect such a function to simply return a `Handle`. However, /// we want type resolution to be a read-only process, and that would limit the /// possible results to types already present in the expression's associated -/// `Arena`. Naga IR does have certain expressions whose types are not -/// certain to be present. +/// `UniqueArena`. Naga IR does have certain expressions whose types are +/// not certain to be present. /// /// So instead, type resolution returns a `TypeResolution` enum: either a /// [`Handle`], referencing some type in the arena, or a [`Value`], holding a @@ -104,7 +104,7 @@ impl TypeResolution { } } - pub fn inner_with<'a>(&'a self, arena: &'a Arena) -> &'a crate::TypeInner { + pub fn inner_with<'a>(&'a self, arena: &'a UniqueArena) -> &'a crate::TypeInner { match *self { Self::Handle(handle) => &arena[handle].inner, Self::Value(ref inner) => inner, @@ -197,7 +197,7 @@ pub enum ResolveError { pub struct ResolveContext<'a> { pub constants: &'a Arena, - pub types: &'a Arena, + pub types: &'a UniqueArena, pub global_vars: &'a Arena, pub local_vars: &'a Arena, pub functions: &'a Arena, diff --git a/src/span.rs b/src/span.rs index 2324b5b8b5..3eaadd212f 100644 --- a/src/span.rs +++ b/src/span.rs @@ -53,7 +53,7 @@ impl Span { } /// Check wether `self` was defined or is a default/unknown span - fn is_defined(&self) -> bool { + pub fn is_defined(&self) -> bool { *self != Self::default() } } diff --git a/src/valid/analyzer.rs b/src/valid/analyzer.rs index dc9e291663..3045defef3 100644 --- a/src/valid/analyzer.rs +++ b/src/valid/analyzer.rs @@ -869,8 +869,8 @@ fn uniform_control_flow() { }, Default::default(), ); - let mut type_arena = Arena::new(); - let ty = type_arena.append( + let mut type_arena = crate::UniqueArena::new(); + let ty = type_arena.fetch_or_append( crate::Type { name: None, inner: crate::TypeInner::Vector { diff --git a/src/valid/compose.rs b/src/valid/compose.rs index e25a7379d0..378f22faa3 100644 --- a/src/valid/compose.rs +++ b/src/valid/compose.rs @@ -1,5 +1,5 @@ use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, proc::TypeResolution, }; @@ -19,7 +19,7 @@ pub enum ComposeError { pub fn validate_compose( self_ty_handle: Handle, constant_arena: &Arena, - type_arena: &Arena, + type_arena: &UniqueArena, component_resolutions: impl ExactSizeIterator, ) -> Result<(), ComposeError> { use crate::TypeInner as Ti; diff --git a/src/valid/expression.rs b/src/valid/expression.rs index e3e189453b..56a464f9c5 100644 --- a/src/valid/expression.rs +++ b/src/valid/expression.rs @@ -1,6 +1,6 @@ use super::{compose::validate_compose, ComposeError, FunctionInfo, ShaderStages, TypeFlags}; use crate::{ - arena::{Arena, Handle}, + arena::{Handle, UniqueArena}, proc::{ProcError, ResolveError}, }; @@ -113,7 +113,7 @@ pub enum ExpressionError { struct ExpressionTypeResolver<'a> { root: Handle, - types: &'a Arena, + types: &'a UniqueArena, info: &'a FunctionInfo, } diff --git a/src/valid/function.rs b/src/valid/function.rs index ddfcb60bb8..79917722bb 100644 --- a/src/valid/function.rs +++ b/src/valid/function.rs @@ -2,7 +2,7 @@ use super::{ analyzer::{UniformityDisruptor, UniformityRequirements}, ExpressionError, FunctionInfo, ModuleInfo, ShaderStages, TypeFlags, ValidationFlags, }; -use crate::arena::{Arena, Handle}; +use crate::arena::{Arena, Handle, UniqueArena}; use bit_set::BitSet; #[derive(Clone, Debug, thiserror::Error)] @@ -144,7 +144,7 @@ struct BlockContext<'a> { abilities: ControlFlowAbility, info: &'a FunctionInfo, expressions: &'a Arena, - types: &'a Arena, + types: &'a UniqueArena, global_vars: &'a Arena, functions: &'a Arena, prev_infos: &'a [FunctionInfo], @@ -627,7 +627,7 @@ impl super::Validator { fn validate_local_var( &self, var: &crate::LocalVariable, - types: &Arena, + types: &UniqueArena, constants: &Arena, ) -> Result<(), LocalVariableError> { log::debug!("var {:?}", var); diff --git a/src/valid/interface.rs b/src/valid/interface.rs index ff3f2401cd..eb24656177 100644 --- a/src/valid/interface.rs +++ b/src/valid/interface.rs @@ -3,7 +3,7 @@ use super::{ Capabilities, Disalignment, FunctionError, ModuleInfo, ShaderStages, TypeFlags, ValidationFlags, }; -use crate::arena::{Arena, Handle}; +use crate::arena::{Handle, UniqueArena}; use bit_set::BitSet; @@ -93,7 +93,7 @@ struct VaryingContext<'a> { ty: Handle, stage: crate::ShaderStage, output: bool, - types: &'a Arena, + types: &'a UniqueArena, location_mask: &'a mut BitSet, built_in_mask: u32, capabilities: Capabilities, @@ -320,7 +320,7 @@ impl super::Validator { pub(super) fn validate_global_var( &self, var: &crate::GlobalVariable, - types: &Arena, + types: &UniqueArena, ) -> Result<(), GlobalVariableError> { log::debug!("var {:?}", var); let type_info = &self.types[var.ty.index()]; diff --git a/src/valid/mod.rs b/src/valid/mod.rs index 5441fb2ef7..3278d6ce14 100644 --- a/src/valid/mod.rs +++ b/src/valid/mod.rs @@ -6,7 +6,7 @@ mod interface; mod r#type; use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, proc::{InvalidBaseType, Layouter}, FastHashSet, }; @@ -217,7 +217,7 @@ impl Validator { &self, handle: Handle, constants: &Arena, - types: &Arena, + types: &UniqueArena, ) -> Result<(), ConstantError> { let con = &constants[handle]; match con.inner { diff --git a/src/valid/type.rs b/src/valid/type.rs index ef1cc7e721..540818ca23 100644 --- a/src/valid/type.rs +++ b/src/valid/type.rs @@ -1,6 +1,6 @@ use super::Capabilities; use crate::{ - arena::{Arena, Handle}, + arena::{Arena, Handle, UniqueArena}, proc::Alignment, }; @@ -187,7 +187,7 @@ impl super::Validator { pub(super) fn validate_type( &self, handle: Handle, - types: &Arena, + types: &UniqueArena, constants: &Arena, ) -> Result { use crate::TypeInner as Ti; diff --git a/tests/out/analysis/shadow.info.ron b/tests/out/analysis/shadow.info.ron index f5695163b2..07bb11eebc 100644 --- a/tests/out/analysis/shadow.info.ron +++ b/tests/out/analysis/shadow.info.ron @@ -54,7 +54,7 @@ ref_count: 0, assignable_global: Some(3), ty: Value(Pointer( - base: 14, + base: 13, class: Uniform, )), ), @@ -95,7 +95,7 @@ ), ref_count: 1, assignable_global: Some(1), - ty: Handle(56), + ty: Handle(30), ), ( uniformity: ( @@ -106,7 +106,7 @@ ), ref_count: 1, assignable_global: Some(2), - ty: Handle(57), + ty: Handle(31), ), ( uniformity: ( @@ -118,7 +118,7 @@ ref_count: 0, assignable_global: Some(4), ty: Value(Pointer( - base: 21, + base: 20, class: Storage( access: ( bits: 1, @@ -770,7 +770,7 @@ ), ref_count: 1, assignable_global: None, - ty: Handle(9), + ty: Handle(6), ), ( uniformity: ( @@ -781,7 +781,7 @@ ), ref_count: 1, assignable_global: None, - ty: Handle(9), + ty: Handle(6), ), ( uniformity: ( @@ -792,7 +792,7 @@ ), ref_count: 1, assignable_global: None, - ty: Handle(9), + ty: Handle(6), ), ( uniformity: ( @@ -831,7 +831,7 @@ ), ref_count: 1, assignable_global: None, - ty: Handle(9), + ty: Handle(6), ), ( uniformity: ( @@ -857,7 +857,7 @@ ), ref_count: 2, assignable_global: None, - ty: Handle(9), + ty: Handle(6), ), ( uniformity: ( @@ -1120,7 +1120,7 @@ ref_count: 1, assignable_global: Some(3), ty: Value(Pointer( - base: 14, + base: 13, class: Uniform, )), ), @@ -1161,7 +1161,7 @@ ), ref_count: 0, assignable_global: Some(1), - ty: Handle(56), + ty: Handle(30), ), ( uniformity: ( @@ -1172,7 +1172,7 @@ ), ref_count: 0, assignable_global: Some(2), - ty: Handle(57), + ty: Handle(31), ), ( uniformity: ( @@ -1184,7 +1184,7 @@ ref_count: 7, assignable_global: Some(4), ty: Value(Pointer( - base: 21, + base: 20, class: Storage( access: ( bits: 1, @@ -1798,7 +1798,7 @@ ref_count: 1, assignable_global: Some(3), ty: Value(Pointer( - base: 13, + base: 12, class: Uniform, )), ), @@ -1892,7 +1892,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 20, + base: 19, class: Storage( access: ( bits: 1, @@ -1921,7 +1921,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 19, + base: 18, class: Storage( access: ( bits: 1, @@ -1939,7 +1939,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 18, + base: 17, class: Storage( access: ( bits: 1, @@ -1956,7 +1956,7 @@ ), ref_count: 1, assignable_global: None, - ty: Handle(18), + ty: Handle(17), ), ( uniformity: ( @@ -2027,7 +2027,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 20, + base: 19, class: Storage( access: ( bits: 1, @@ -2056,7 +2056,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 19, + base: 18, class: Storage( access: ( bits: 1, @@ -2126,7 +2126,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 20, + base: 19, class: Storage( access: ( bits: 1, @@ -2155,7 +2155,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 19, + base: 18, class: Storage( access: ( bits: 1, @@ -2225,7 +2225,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 20, + base: 19, class: Storage( access: ( bits: 1, @@ -2254,7 +2254,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 19, + base: 18, class: Storage( access: ( bits: 1, @@ -2500,7 +2500,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 20, + base: 19, class: Storage( access: ( bits: 1, @@ -2529,7 +2529,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 19, + base: 18, class: Storage( access: ( bits: 1, @@ -2599,7 +2599,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 20, + base: 19, class: Storage( access: ( bits: 1, @@ -2628,7 +2628,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 19, + base: 18, class: Storage( access: ( bits: 1, @@ -2698,7 +2698,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 20, + base: 19, class: Storage( access: ( bits: 1, @@ -2727,7 +2727,7 @@ ref_count: 1, assignable_global: Some(4), ty: Value(Pointer( - base: 19, + base: 18, class: Storage( access: ( bits: 1, diff --git a/tests/out/glsl/quad-vert.main.Vertex.glsl b/tests/out/glsl/quad-vert.main.Vertex.glsl index e42681b2e7..5203c330ea 100644 --- a/tests/out/glsl/quad-vert.main.Vertex.glsl +++ b/tests/out/glsl/quad-vert.main.Vertex.glsl @@ -3,7 +3,7 @@ precision highp float; precision highp int; -struct type10 { +struct type9 { vec2 member; vec4 gen_gl_Position; float gen_gl_PointSize; @@ -47,7 +47,7 @@ void main() { float _e12 = perVertexStruct.gen_gl_PointSize; float _e13[1] = perVertexStruct.gen_gl_ClipDistance; float _e14[1] = perVertexStruct.gen_gl_CullDistance; - type10 _tmp_return = type10(_e10, _e11, _e12, _e13, _e14); + type9 _tmp_return = type9(_e10, _e11, _e12, _e13, _e14); _vs2fs_location0 = _tmp_return.member; gl_Position = _tmp_return.gen_gl_Position; gl_Position.yz = vec2(-gl_Position.y, gl_Position.z * 2.0 - gl_Position.w); diff --git a/tests/out/hlsl/quad-vert.hlsl b/tests/out/hlsl/quad-vert.hlsl index ea6323b5a9..261468de18 100644 --- a/tests/out/hlsl/quad-vert.hlsl +++ b/tests/out/hlsl/quad-vert.hlsl @@ -6,7 +6,7 @@ struct gl_PerVertex { float gl_CullDistance[1] : SV_CullDistance; }; -struct type10 { +struct type9 { linear float2 member : LOC0; float4 gl_Position : SV_Position; float gl_PointSize : PSIZE; @@ -36,8 +36,8 @@ void main1() return; } -type10 Constructtype10(float2 arg0, float4 arg1, float arg2, float arg3[1], float arg4[1]) { - type10 ret; +type9 Constructtype9(float2 arg0, float4 arg1, float arg2, float arg3[1], float arg4[1]) { + type9 ret; ret.member = arg0; ret.gl_Position = arg1; ret.gl_PointSize = arg2; @@ -56,7 +56,7 @@ VertexOutput_main main(float2 a_uv : LOC1, float2 a_pos : LOC0) float _expr12 = perVertexStruct.gl_PointSize; float _expr13[1] = perVertexStruct.gl_ClipDistance; float _expr14[1] = perVertexStruct.gl_CullDistance; - const type10 type10_ = Constructtype10(_expr10, _expr11, _expr12, _expr13, _expr14); - const VertexOutput_main type10_1 = { type10_.member, type10_.gl_Position, type10_.gl_ClipDistance, type10_.gl_CullDistance, type10_.gl_PointSize }; - return type10_1; + const type9 type9_ = Constructtype9(_expr10, _expr11, _expr12, _expr13, _expr14); + const VertexOutput_main type9_1 = { type9_.member, type9_.gl_Position, type9_.gl_ClipDistance, type9_.gl_CullDistance, type9_.gl_PointSize }; + return type9_1; } diff --git a/tests/out/ir/shadow.ron b/tests/out/ir/shadow.ron index 763aa28e9c..4dae9ffae9 100644 --- a/tests/out/ir/shadow.ron +++ b/tests/out/ir/shadow.ron @@ -62,14 +62,6 @@ comparison: false, ), ), - ( - name: None, - inner: Vector( - size: Bi, - kind: Float, - width: 4, - ), - ), ( name: None, inner: Scalar( @@ -106,7 +98,7 @@ members: [ ( name: Some("num_lights"), - ty: 13, + ty: 12, binding: None, offset: 0, ), @@ -117,14 +109,14 @@ ( name: None, inner: Pointer( - base: 14, + base: 13, class: Uniform, ), ), ( name: None, inner: Pointer( - base: 13, + base: 12, class: Uniform, ), ), @@ -150,7 +142,7 @@ members: [ ( name: Some("proj"), - ty: 18, + ty: 17, binding: None, offset: 0, ), @@ -173,7 +165,7 @@ ( name: None, inner: Array( - base: 19, + base: 18, size: Dynamic, stride: 96, ), @@ -185,7 +177,7 @@ members: [ ( name: Some("data"), - ty: 20, + ty: 19, binding: None, offset: 0, ), @@ -196,7 +188,7 @@ ( name: None, inner: Pointer( - base: 21, + base: 20, class: Storage( access: ( bits: 0, @@ -204,13 +196,6 @@ ), ), ), - ( - name: None, - inner: Pointer( - base: 20, - class: Uniform, - ), - ), ( name: None, inner: Pointer( @@ -228,28 +213,7 @@ ( name: None, inner: Pointer( - base: 4, - class: Private, - ), - ), - ( - name: None, - inner: Pointer( - base: 2, - class: Private, - ), - ), - ( - name: None, - inner: Pointer( - base: 20, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 19, + base: 17, class: Uniform, ), ), @@ -257,135 +221,16 @@ name: None, inner: Pointer( base: 4, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 1, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 20, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 19, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 4, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 1, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 20, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 19, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 4, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 1, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 1, - class: Private, - ), - ), - ( - name: None, - inner: Pointer( - base: 1, class: Private, ), ), ( name: None, inner: Pointer( - base: 1, + base: 2, class: Private, ), ), - ( - name: None, - inner: Pointer( - base: 20, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 19, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 4, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 1, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 20, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 19, - class: Uniform, - ), - ), ( name: None, inner: Pointer( @@ -400,38 +245,10 @@ class: Uniform, ), ), - ( - name: None, - inner: Pointer( - base: 20, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 19, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 4, - class: Uniform, - ), - ), ( name: None, inner: Pointer( base: 1, - class: Uniform, - ), - ), - ( - name: None, - inner: Pointer( - base: 4, class: Private, ), ), @@ -778,7 +595,7 @@ group: 0, binding: 2, )), - ty: 56, + ty: 30, init: None, ), ( @@ -788,7 +605,7 @@ group: 0, binding: 3, )), - ty: 57, + ty: 31, init: None, ), ( @@ -798,7 +615,7 @@ group: 0, binding: 0, )), - ty: 14, + ty: 13, init: None, ), ( @@ -812,7 +629,7 @@ group: 0, binding: 1, )), - ty: 21, + ty: 20, init: None, ), ( @@ -924,14 +741,14 @@ index: 1, ), Compose( - ty: 9, + ty: 6, components: [ 51, 52, ], ), Compose( - ty: 9, + ty: 6, components: [ 13, 22, diff --git a/tests/out/msl/quad-vert.msl b/tests/out/msl/quad-vert.msl index ef2264a137..8caf6fc498 100644 --- a/tests/out/msl/quad-vert.msl +++ b/tests/out/msl/quad-vert.msl @@ -2,25 +2,25 @@ #include #include -struct type6 { +struct type5 { float inner[1u]; }; struct gl_PerVertex { metal::float4 gl_Position; float gl_PointSize; - type6 gl_ClipDistance; - type6 gl_CullDistance; + type5 gl_ClipDistance; + type5 gl_CullDistance; }; -struct type10 { +struct type9 { metal::float2 member; metal::float4 gl_Position; float gl_PointSize; - type6 gl_ClipDistance; - type6 gl_CullDistance; + type5 gl_ClipDistance; + type5 gl_CullDistance; }; -constant metal::float4 const_type4_ = {0.0, 0.0, 0.0, 1.0}; -constant type6 const_type6_ = {0.0}; -constant gl_PerVertex const_gl_PerVertex = {const_type4_, 1.0, const_type6_, const_type6_}; +constant metal::float4 const_type3_ = {0.0, 0.0, 0.0, 1.0}; +constant type5 const_type5_ = {0.0}; +constant gl_PerVertex const_gl_PerVertex = {const_type3_, 1.0, const_type5_, const_type5_}; void main2( thread metal::float2& v_uv, @@ -60,8 +60,8 @@ vertex main1Output main1( metal::float2 _e10 = v_uv; metal::float4 _e11 = perVertexStruct.gl_Position; float _e12 = perVertexStruct.gl_PointSize; - type6 _e13 = perVertexStruct.gl_ClipDistance; - type6 _e14 = perVertexStruct.gl_CullDistance; - const auto _tmp = type10 {_e10, _e11, _e12, _e13, _e14}; + type5 _e13 = perVertexStruct.gl_ClipDistance; + type5 _e14 = perVertexStruct.gl_CullDistance; + const auto _tmp = type9 {_e10, _e11, _e12, _e13, _e14}; return main1Output { _tmp.member, _tmp.gl_Position, _tmp.gl_PointSize, {_tmp.gl_ClipDistance.inner[0]} }; }