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<Type>` values that point to identical types.

This removes a number of duplicate types from the ir snapshots.

Fixes #1385.
This commit is contained in:
Jim Blandy
2021-09-17 16:22:29 -07:00
committed by Dzmitry Malyshau
parent d026577a91
commit 944a693ae5
32 changed files with 387 additions and 363 deletions

View File

@@ -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"]

View File

@@ -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<T> Handle<T> {
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<T>`, 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<T> {
set: IndexSet<T>,
/// 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<Span>,
}
impl<T> UniqueArena<T> {
/// 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<T>) -> Span {
#[cfg(feature = "span")]
{
*self
.span_info
.get(handle.index())
.unwrap_or(&Span::default())
}
#[cfg(not(feature = "span"))]
{
let _ = handle;
Span::default()
}
}
}
impl<T: Eq + hash::Hash> UniqueArena<T> {
/// 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<Item = (Handle<T>, &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<T>`], 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<T>`]: Handle
/// [`get_span`]: UniqueArena::get_span
pub fn fetch_or_append(&mut self, value: T, span: Span) -> Handle<T> {
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<Handle<T>> {
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<T>) -> Option<&T> {
self.set.get_index(handle.index())
}
}
impl<T> Default for UniqueArena<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: fmt::Debug + Eq + hash::Hash> fmt::Debug for UniqueArena<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
impl<T> ops::Index<Handle<T>> for UniqueArena<T> {
type Output = T;
fn index(&self, handle: Handle<T>) -> &T {
&self.set[handle.index()]
}
}
#[cfg(feature = "serialize")]
impl<T> serde::Serialize for UniqueArena<T>
where
T: Eq + hash::Hash,
T: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.set.serialize(serializer)
}
}
#[cfg(feature = "deserialize")]
impl<'de, T> serde::Deserialize<'de> for UniqueArena<T>
where
T: Eq + hash::Hash,
T: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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,
})
}
}

View File

@@ -22,7 +22,7 @@ const ATOMIC_REFERENCE: &str = "&";
struct TypeContext<'a> {
handle: Handle<crate::Type>,
arena: &'a crate::Arena<crate::Type>,
arena: &'a crate::UniqueArena<crate::Type>,
names: &'a FastHashMap<NameKey, String>,
access: crate::StorageAccess,
first_time: bool,
@@ -354,7 +354,7 @@ fn should_pack_struct_member(
}
}
fn needs_array_length(ty: Handle<crate::Type>, arena: &crate::Arena<crate::Type>) -> bool {
fn needs_array_length(ty: Handle<crate::Type>, arena: &crate::UniqueArena<crate::Type>) -> bool {
if let crate::TypeInner::Struct { ref members, .. } = arena[ty].inner {
if let Some(member) = members.last() {
if let crate::TypeInner::Array {

View File

@@ -1,4 +1,4 @@
use crate::{Arena, Handle};
use crate::{Handle, UniqueArena};
use spirv::Word;
pub(super) fn bytes_to_words(bytes: &[u8]) -> Vec<Word> {
@@ -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<crate::Type>,
arena: &Arena<crate::Type>,
arena: &UniqueArena<crate::Type>,
built_in: crate::BuiltIn,
) -> bool {
if let Some(&crate::Binding::BuiltIn(bi)) = binding {

View File

@@ -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<crate::Type>,
arena: &UniqueArena<crate::Type>,
handle: Handle<crate::Type>,
class: spirv::StorageClass,
) -> Result<Word, Error> {
@@ -766,7 +766,7 @@ impl Writer {
fn write_type_declaration_arena(
&mut self,
arena: &Arena<crate::Type>,
arena: &UniqueArena<crate::Type>,
handle: Handle<crate::Type>,
) -> Result<Word, Error> {
let ty = &arena[handle];

View File

@@ -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<Type>,
pub types: &'a mut UniqueArena<Type>,
pub expressions: &'a Arena<Expression>,
pub constants: &'a mut Arena<Constant>,
}
@@ -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 {

View File

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

View File

@@ -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<Type>,
meta: Span,
layout: StructLayout,
types: &mut Arena<Type>,
types: &mut UniqueArena<Type>,
constants: &Arena<Constant>,
errors: &mut Vec<Error>,
) -> TypeAlignSpan {

View File

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

View File

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

View File

@@ -10,7 +10,7 @@ pub mod spv;
pub mod wgsl;
use crate::{
arena::{Arena, Handle},
arena::{Arena, Handle, UniqueArena},
proc::{ResolveContext, ResolveError, TypeResolution},
};
use std::ops;
@@ -81,7 +81,7 @@ impl Typifier {
pub fn get<'a>(
&'a self,
expr_handle: Handle<crate::Expression>,
types: &'a Arena<crate::Type>,
types: &'a UniqueArena<crate::Type>,
) -> &'a crate::TypeInner {
self.resolutions[expr_handle.index()].inner_with(types)
}

View File

@@ -477,7 +477,7 @@ impl<I: Iterator<Item = u32>> super::Parser<I> {
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 {

View File

@@ -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<crate::Expression>,
coordinate_ty: Handle<crate::Type>,
type_arena: &Arena<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
expressions: &mut Arena<crate::Expression>,
) -> (Handle<crate::Expression>, Option<Handle<crate::Expression>>) {
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<crate::Type>,
arena: &mut UniqueArena<crate::Type>,
) -> 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<I: Iterator<Item = u32>> super::Parser<I> {
pub(super) fn parse_image_write(
&mut self,
words_left: u16,
type_arena: &Arena<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
global_arena: &Arena<crate::GlobalVariable>,
arguments: &[FunctionArgument],
expressions: &mut Arena<crate::Expression>,

View File

@@ -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<crate::Constant>,
/// Type arena of the module being processed
type_arena: &'function Arena<crate::Type>,
type_arena: &'function UniqueArena<crate::Type>,
/// Global arena of the module being processed
global_arena: &'function Arena<crate::GlobalVariable>,
/// Arguments of the function currently being processed
@@ -991,7 +991,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
root_type_id: spirv::Word,
object_expr: Handle<crate::Expression>,
selections: &[spirv::Word],
type_arena: &Arena<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
expressions: &mut Arena<crate::Expression>,
span: crate::Span,
) -> Result<Handle<crate::Expression>, Error> {
@@ -3388,7 +3388,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
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<I: Iterator<Item = u32>> Parser<I> {
self.lookup_type.insert(
id,
LookupType {
handle: module.types.append(
handle: module.types.fetch_or_append(
crate::Type {
name: decor.name,
inner,
@@ -3777,7 +3777,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
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,
@@ -3862,7 +3862,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
arrayed: is_array,
};
let handle = module.types.append(
let handle = module.types.fetch_or_append(
crate::Type {
name: decor.name,
inner,
@@ -3905,7 +3905,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
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 },
@@ -4051,7 +4051,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
fn parse_null_constant(
&mut self,
inst: Instruction,
types: &Arena<crate::Type>,
types: &UniqueArena<crate::Type>,
constants: &mut Arena<crate::Constant>,
) -> Result<(u32, u32, Handle<crate::Constant>), Error> {
let start = self.data_offset;
@@ -4151,7 +4151,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
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) {

View File

@@ -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<crate::Type>,
type_arena: &Arena<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
constant_arena: &mut Arena<crate::Constant>,
span: crate::Span,
) -> Result<crate::ConstantInner, Error> {
@@ -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<crate::BuiltIn>,
ty: Handle<crate::Type>,
type_arena: &Arena<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
constant_arena: &mut Arena<crate::Constant>,
span: crate::Span,
) -> Result<Handle<crate::Constant>, Error> {

View File

@@ -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<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: &Arena<crate::Type>, constants: &Arena<crate::Constant>) -> String {
fn to_wgsl(
&self,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
) -> 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<crate::LocalVariable>,
expressions: &'out mut Arena<crate::Expression>,
named_expressions: &'out mut FastHashMap<Handle<crate::Expression>, String>,
types: &'out mut Arena<crate::Type>,
types: &'out mut UniqueArena<crate::Type>,
constants: &'out mut Arena<crate::Constant>,
global_vars: &'out Arena<crate::GlobalVariable>,
functions: &'out Arena<crate::Function>,
@@ -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<crate::Expression>,
types: &'out mut Arena<crate::Type>,
types: &'out mut UniqueArena<crate::Type>,
constants: &'out mut Arena<crate::Constant>,
global_vars: &'out Arena<crate::GlobalVariable>,
local_vars: &'out Arena<crate::LocalVariable>,
@@ -1993,7 +1997,7 @@ impl Parser {
first_token_span: TokenSpan<'a>,
lexer: &mut Lexer<'a>,
register_name: Option<&'a str>,
type_arena: &mut Arena<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<Handle<crate::Constant>, 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<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<Handle<crate::Constant>, 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<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<(&'a str, Span, Handle<crate::Type>, 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<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<ParsedVariable<'a>, 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<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<(Vec<crate::StructMember>, u32), Error<'a>> {
let mut offset = 0;
@@ -2722,7 +2726,7 @@ impl Parser {
lexer: &mut Lexer<'a>,
attribute: TypeAttributes,
word: &'a str,
type_arena: &mut Arena<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<Option<crate::TypeInner>, Error<'a>> {
if let Some((kind, width)) = conv::get_scalar_type(word) {
@@ -3034,7 +3038,7 @@ impl Parser {
name_span: Span,
debug_name: Option<&'a str>,
attribute: TypeAttributes,
type_arena: &mut Arena<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<Handle<crate::Type>, Error<'a>> {
Ok(match self.lookup_type.get(name) {
@@ -3061,7 +3065,7 @@ impl Parser {
&mut self,
lexer: &mut Lexer<'a>,
debug_name: Option<&'a str>,
type_arena: &mut Arena<crate::Type>,
type_arena: &mut UniqueArena<crate::Type>,
const_arena: &mut Arena<crate::Constant>,
) -> Result<(Handle<crate::Type>, crate::StorageAccess), Error<'a>> {
self.push_scope(Scope::TypeDecl, lexer);

View File

@@ -44,6 +44,15 @@ and compound expressions refer to their sub-expressions via `Handle<Expression>`
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<Type>,
pub types: UniqueArena<Type>,
/// Storage for the constants defined in this module.
pub constants: Arena<Constant>,
/// Storage for the global variables defined in this module.

View File

@@ -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<crate::Type>,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
) -> Result<(), InvalidBaseType> {
use crate::TypeInner as Ti;

View File

@@ -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<Type>`. 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<Type>`. Naga IR does have certain expressions whose types are not
/// certain to be present.
/// `UniqueArena<Type>`. 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<crate::Type>) -> &'a crate::TypeInner {
pub fn inner_with<'a>(&'a self, arena: &'a UniqueArena<crate::Type>) -> &'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<crate::Constant>,
pub types: &'a Arena<crate::Type>,
pub types: &'a UniqueArena<crate::Type>,
pub global_vars: &'a Arena<crate::GlobalVariable>,
pub local_vars: &'a Arena<crate::LocalVariable>,
pub functions: &'a Arena<crate::Function>,

View File

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

View File

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

View File

@@ -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<crate::Type>,
constant_arena: &Arena<crate::Constant>,
type_arena: &Arena<crate::Type>,
type_arena: &UniqueArena<crate::Type>,
component_resolutions: impl ExactSizeIterator<Item = TypeResolution>,
) -> Result<(), ComposeError> {
use crate::TypeInner as Ti;

View File

@@ -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<crate::Expression>,
types: &'a Arena<crate::Type>,
types: &'a UniqueArena<crate::Type>,
info: &'a FunctionInfo,
}

View File

@@ -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<crate::Expression>,
types: &'a Arena<crate::Type>,
types: &'a UniqueArena<crate::Type>,
global_vars: &'a Arena<crate::GlobalVariable>,
functions: &'a Arena<crate::Function>,
prev_infos: &'a [FunctionInfo],
@@ -627,7 +627,7 @@ impl super::Validator {
fn validate_local_var(
&self,
var: &crate::LocalVariable,
types: &Arena<crate::Type>,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
) -> Result<(), LocalVariableError> {
log::debug!("var {:?}", var);

View File

@@ -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<crate::Type>,
stage: crate::ShaderStage,
output: bool,
types: &'a Arena<crate::Type>,
types: &'a UniqueArena<crate::Type>,
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<crate::Type>,
types: &UniqueArena<crate::Type>,
) -> Result<(), GlobalVariableError> {
log::debug!("var {:?}", var);
let type_info = &self.types[var.ty.index()];

View File

@@ -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<crate::Constant>,
constants: &Arena<crate::Constant>,
types: &Arena<crate::Type>,
types: &UniqueArena<crate::Type>,
) -> Result<(), ConstantError> {
let con = &constants[handle];
match con.inner {

View File

@@ -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<crate::Type>,
types: &Arena<crate::Type>,
types: &UniqueArena<crate::Type>,
constants: &Arena<crate::Constant>,
) -> Result<TypeInfo, TypeError> {
use crate::TypeInner as Ti;

View File

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

View File

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

View File

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

View File

@@ -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(
@@ -225,6 +210,13 @@
class: Uniform,
),
),
(
name: None,
inner: Pointer(
base: 17,
class: Uniform,
),
),
(
name: None,
inner: Pointer(
@@ -239,76 +231,6 @@
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(
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(
@@ -330,111 +252,6 @@
class: Private,
),
),
(
name: None,
inner: Pointer(
base: 1,
class: Private,
),
),
(
name: None,
inner: Pointer(
base: 1,
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(
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: 4,
class: Private,
),
),
(
name: None,
inner: Image(
@@ -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,

View File

@@ -2,25 +2,25 @@
#include <metal_stdlib>
#include <simd/simd.h>
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]} };
}