mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Rename Token/Id to Handle and Storage to Arena consistently
This commit is contained in:
committed by
Dzmitry Malyshau
parent
7e0b004c16
commit
5e78c71a44
155
src/arena.rs
Normal file
155
src/arena.rs
Normal file
@@ -0,0 +1,155 @@
|
||||
use std::{
|
||||
fmt,
|
||||
hash,
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
/// An unique index in the arena array that a handle points to.
|
||||
///
|
||||
/// This type is independent of `spirv::Word`. `spirv::Word` is used in data
|
||||
/// representation. It holds a SPIR-V and refers to that instruction. In
|
||||
/// structured representation, we use Handle to refer to an SPIR-V instruction.
|
||||
/// Index is an implementation detail to Handle.
|
||||
type Index = u32;
|
||||
|
||||
/// A strongly typed reference to a SPIR-V element.
|
||||
pub struct Handle<T> {
|
||||
index: Index,
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Handle<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Handle {
|
||||
index: self.index,
|
||||
marker: self.marker,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> Copy for Handle<T> {}
|
||||
impl<T> PartialEq for Handle<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.index == other.index
|
||||
}
|
||||
}
|
||||
impl<T> Eq for Handle<T> {}
|
||||
impl<T> fmt::Debug for Handle<T> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Handle({})", self.index)
|
||||
}
|
||||
}
|
||||
impl<T> hash::Hash for Handle<T> {
|
||||
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
||||
self.index.hash(hasher)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Handle<T> {
|
||||
#[cfg(test)]
|
||||
pub const DUMMY: Self = Handle {
|
||||
index: !0,
|
||||
marker: PhantomData,
|
||||
};
|
||||
|
||||
pub(crate) fn new(index: Index) -> Self {
|
||||
Handle {
|
||||
index,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
self.index as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// An arena holding some kind of component (e.g., type, constant,
|
||||
/// instruction, etc.) that can be referenced.
|
||||
#[derive(Debug)]
|
||||
pub struct Arena<T> {
|
||||
/// Values of this arena.
|
||||
data: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T> Arena<T> {
|
||||
pub fn new() -> Self {
|
||||
Arena {
|
||||
data: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter<'a>(&'a self) -> impl Iterator<Item = (Handle<T>, &'a T)> {
|
||||
self.data
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, v)| (Handle::new(i as Index), v))
|
||||
}
|
||||
|
||||
/// Adds a new value to the arena, returning a typed handle.
|
||||
///
|
||||
/// The value is not linked to any SPIR-V module.
|
||||
pub fn append(&mut self, value: T) -> Handle<T> {
|
||||
let index = self.data.len() as Index;
|
||||
self.data.push(value);
|
||||
Handle::new(index)
|
||||
}
|
||||
|
||||
/// Adds a value with a check for uniqueness: returns a handle pointing to
|
||||
/// an existing element if its value matches the given one, or adds a new
|
||||
/// element otherwise.
|
||||
pub fn fetch_or_append(&mut self, value: T) -> Handle<T> where T: PartialEq {
|
||||
if let Some(index) = self.data.iter().position(|d| d == &value) {
|
||||
Handle::new(index as Index)
|
||||
} else {
|
||||
self.append(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Index<Handle<T>> for Arena<T> {
|
||||
type Output = T;
|
||||
fn index(&self, handle: Handle<T>) -> &T {
|
||||
&self.data[handle.index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn append_non_unique() {
|
||||
let mut arena: Arena<f64> = Arena::new();
|
||||
let t1 = arena.append(0.0);
|
||||
let t2 = arena.append(0.0);
|
||||
assert!(t1 != t2);
|
||||
assert!(arena[t1] == arena[t2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn append_unique() {
|
||||
let mut arena: Arena<f64> = Arena::new();
|
||||
let t1 = arena.append(std::f64::NAN);
|
||||
let t2 = arena.append(std::f64::NAN);
|
||||
assert!(t1 != t2);
|
||||
assert!(arena[t1] != arena[t2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_or_append_non_unique() {
|
||||
let mut arena: Arena<f64> = Arena::new();
|
||||
let t1 = arena.fetch_or_append(0.0);
|
||||
let t2 = arena.fetch_or_append(0.0);
|
||||
assert!(t1 == t2);
|
||||
assert!(arena[t1] == arena[t2])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_or_append_unique() {
|
||||
let mut arena: Arena<f64> = Arena::new();
|
||||
let t1 = arena.fetch_or_append(std::f64::NAN);
|
||||
let t2 = arena.fetch_or_append(std::f64::NAN);
|
||||
assert!(t1 != t2);
|
||||
assert!(arena[t1] != arena[t2]);
|
||||
}
|
||||
}
|
||||
100
src/back/msl.rs
100
src/back/msl.rs
@@ -21,7 +21,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
storage::Token,
|
||||
arena::Handle,
|
||||
FastHashMap, FastHashSet
|
||||
};
|
||||
|
||||
@@ -53,8 +53,8 @@ pub enum Error {
|
||||
Format(FmtError),
|
||||
UnsupportedExecutionModel(spirv::ExecutionModel),
|
||||
UnexpectedLocation,
|
||||
MixedExecutionModels(crate::Token<crate::Function>),
|
||||
MissingBinding(crate::Token<crate::GlobalVariable>),
|
||||
MixedExecutionModels(crate::Handle<crate::Function>),
|
||||
MissingBinding(crate::Handle<crate::GlobalVariable>),
|
||||
MissingBindTarget(BindSource),
|
||||
InvalidImageFlags(crate::ImageFlags),
|
||||
BadName(String),
|
||||
@@ -111,15 +111,15 @@ trait Indexed {
|
||||
fn id(&self) -> usize;
|
||||
}
|
||||
|
||||
impl Indexed for crate::Token<crate::Type> {
|
||||
impl Indexed for crate::Handle<crate::Type> {
|
||||
const CLASS: &'static str = "Type";
|
||||
fn id(&self) -> usize { self.index() }
|
||||
}
|
||||
impl Indexed for crate::Token<crate::GlobalVariable> {
|
||||
impl Indexed for crate::Handle<crate::GlobalVariable> {
|
||||
const CLASS: &'static str = "global";
|
||||
fn id(&self) -> usize { self.index() }
|
||||
}
|
||||
impl Indexed for crate::Token<crate::Function> {
|
||||
impl Indexed for crate::Handle<crate::Function> {
|
||||
const CLASS: &'static str = "function";
|
||||
fn id(&self) -> usize { self.index() }
|
||||
}
|
||||
@@ -134,13 +134,13 @@ impl Indexed for ParameterIndex {
|
||||
const CLASS: &'static str = "param";
|
||||
fn id(&self) -> usize { self.0 }
|
||||
}
|
||||
struct InputStructIndex(crate::Token<crate::Function>);
|
||||
struct InputStructIndex(crate::Handle<crate::Function>);
|
||||
impl Indexed for InputStructIndex {
|
||||
const CLASS: &'static str = "Input";
|
||||
const PREFIX: bool = true;
|
||||
fn id(&self) -> usize { self.0.index() }
|
||||
}
|
||||
struct OutputStructIndex(crate::Token<crate::Function>);
|
||||
struct OutputStructIndex(crate::Handle<crate::Function>);
|
||||
impl Indexed for OutputStructIndex {
|
||||
const CLASS: &'static str = "Output";
|
||||
const PREFIX: bool = true;
|
||||
@@ -208,22 +208,22 @@ impl<T: Display> Display for Starred<T> {
|
||||
|
||||
struct TypedGlobalVariable<'a> {
|
||||
module: &'a crate::Module,
|
||||
token: crate::Token<crate::GlobalVariable>,
|
||||
handle: crate::Handle<crate::GlobalVariable>,
|
||||
}
|
||||
impl Display for TypedGlobalVariable<'_> {
|
||||
fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
let var = &self.module.global_variables[self.token];
|
||||
let name = var.name.or_index(self.token);
|
||||
let var = &self.module.global_variables[self.handle];
|
||||
let name = var.name.or_index(self.handle);
|
||||
let ty = &self.module.types[var.ty];
|
||||
match ty.inner {
|
||||
crate::TypeInner::Pointer { base, class } => {
|
||||
let ty_token = match class {
|
||||
let ty_handle= match class {
|
||||
spirv::StorageClass::Input |
|
||||
spirv::StorageClass::Output |
|
||||
spirv::StorageClass::UniformConstant => base,
|
||||
_ => var.ty
|
||||
};
|
||||
let ty_name = self.module.types[ty_token].name.or_index(ty_token);
|
||||
let ty_name = self.module.types[ty_handle].name.or_index(ty_handle);
|
||||
write!(formatter, "{} {}", ty_name, name)
|
||||
}
|
||||
_ => panic!("Unexpected global type {:?}", var.ty),
|
||||
@@ -308,19 +308,19 @@ impl<T> MaybeOwned<'_, T> {
|
||||
}
|
||||
|
||||
impl crate::Module {
|
||||
fn borrow_type(&self, token: Token<crate::Type>) -> MaybeOwned<crate::TypeInner> {
|
||||
MaybeOwned::Borrowed(&self.types[token].inner)
|
||||
fn borrow_type(&self, handle: Handle<crate::Type>) -> MaybeOwned<crate::TypeInner> {
|
||||
MaybeOwned::Borrowed(&self.types[handle].inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Writer<W> {
|
||||
fn put_expression<'a>(
|
||||
&mut self,
|
||||
expr_token: crate::Token<crate::Expression>,
|
||||
expressions: &crate::Storage<crate::Expression>,
|
||||
expr_handle: crate::Handle<crate::Expression>,
|
||||
expressions: &crate::Arena<crate::Expression>,
|
||||
module: &'a crate::Module,
|
||||
) -> Result<MaybeOwned<'a, crate::TypeInner>, Error> {
|
||||
let expression = &expressions[expr_token];
|
||||
let expression = &expressions[expr_handle];
|
||||
log::trace!("expression {:?}", expression);
|
||||
match *expression {
|
||||
crate::Expression::AccessIndex { base, index } => {
|
||||
@@ -349,8 +349,8 @@ impl<W: Write> Writer<W> {
|
||||
ref other => panic!("Unexpected indexing of {:?}", other),
|
||||
}
|
||||
}
|
||||
crate::Expression::Constant(token) => {
|
||||
let kind = match module.constants[token].inner {
|
||||
crate::Expression::Constant(handle) => {
|
||||
let kind = match module.constants[handle].inner {
|
||||
crate::ConstantInner::Sint(value) => {
|
||||
write!(self.out, "{}", value)?;
|
||||
crate::ScalarKind::Sint
|
||||
@@ -376,11 +376,11 @@ impl<W: Write> Writer<W> {
|
||||
match *inner {
|
||||
crate::TypeInner::Vector { size, kind, .. } => {
|
||||
write!(self.out, "{}{}(", scalar_kind_string(kind), vector_size_string(size))?;
|
||||
for (i, &token) in components.iter().enumerate() {
|
||||
for (i, &handle) in components.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(self.out, ",")?;
|
||||
}
|
||||
self.put_expression(token, expressions, module)?;
|
||||
self.put_expression(handle, expressions, module)?;
|
||||
}
|
||||
write!(self.out, ")")?;
|
||||
}
|
||||
@@ -388,8 +388,8 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
Ok(MaybeOwned::Borrowed(inner))
|
||||
}
|
||||
crate::Expression::GlobalVariable(token) => {
|
||||
let var = &module.global_variables[token];
|
||||
crate::Expression::GlobalVariable(handle) => {
|
||||
let var = &module.global_variables[handle];
|
||||
let inner = &module.types[var.ty].inner;
|
||||
match var.class {
|
||||
spirv::StorageClass::Output => {
|
||||
@@ -407,7 +407,7 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
let name = var.name.or_index(token);
|
||||
let name = var.name.or_index(handle);
|
||||
write!(self.out, "{}", name)?;
|
||||
Ok(MaybeOwned::Borrowed(inner))
|
||||
}
|
||||
@@ -455,8 +455,8 @@ impl<W: Write> Writer<W> {
|
||||
|
||||
// write down complex types
|
||||
writeln!(self.out, "")?;
|
||||
for (token, ty) in module.types.iter() {
|
||||
let name = ty.name.or_index(token);
|
||||
for (handle, ty) in module.types.iter() {
|
||||
let name = ty.name.or_index(handle);
|
||||
match ty.inner {
|
||||
crate::TypeInner::Scalar { kind, .. } => {
|
||||
write!(self.out, "typedef {} {}", scalar_kind_string(kind), name)?;
|
||||
@@ -537,27 +537,27 @@ impl<W: Write> Writer<W> {
|
||||
// write down functions
|
||||
let mut uniforms_used = FastHashSet::default();
|
||||
writeln!(self.out, "")?;
|
||||
for (fun_token, fun) in module.functions.iter() {
|
||||
let fun_name = fun.name.or_index(fun_token);
|
||||
for (fun_handle, fun) in module.functions.iter() {
|
||||
let fun_name = fun.name.or_index(fun_handle);
|
||||
// find the entry point(s) and inputs/outputs
|
||||
let mut exec_model = None;
|
||||
let mut var_inputs = FastHashSet::default();
|
||||
let mut var_outputs = FastHashSet::default();
|
||||
for ep in module.entry_points.iter() {
|
||||
if ep.function == fun_token {
|
||||
if ep.function == fun_handle{
|
||||
var_inputs.extend(ep.inputs.iter().cloned());
|
||||
var_outputs.extend(ep.outputs.iter().cloned());
|
||||
if exec_model.is_some() {
|
||||
if exec_model != Some(ep.exec_model) {
|
||||
return Err(Error::MixedExecutionModels(fun_token));
|
||||
return Err(Error::MixedExecutionModels(fun_handle));
|
||||
}
|
||||
} else {
|
||||
exec_model = Some(ep.exec_model);
|
||||
}
|
||||
}
|
||||
}
|
||||
let input_name = fun.name.or_index(InputStructIndex(fun_token));
|
||||
let output_name = fun.name.or_index(OutputStructIndex(fun_token));
|
||||
let input_name = fun.name.or_index(InputStructIndex(fun_handle));
|
||||
let output_name = fun.name.or_index(OutputStructIndex(fun_handle));
|
||||
// make dedicated input/output structs
|
||||
if let Some(em) = exec_model {
|
||||
writeln!(self.out, "struct {} {{", input_name)?;
|
||||
@@ -567,9 +567,9 @@ impl<W: Write> Writer<W> {
|
||||
spirv::ExecutionModel::GLCompute => ("compute", LocationMode::Uniform, LocationMode::Uniform),
|
||||
_ => return Err(Error::UnsupportedExecutionModel(em)),
|
||||
};
|
||||
for &token in var_inputs.iter() {
|
||||
let var = &module.global_variables[token];
|
||||
let tyvar = TypedGlobalVariable { module, token };
|
||||
for &handle in var_inputs.iter() {
|
||||
let var = &module.global_variables[handle];
|
||||
let tyvar = TypedGlobalVariable { module, handle };
|
||||
write!(self.out, "\t{}", tyvar)?;
|
||||
if let Some(ref binding) = var.binding {
|
||||
let resolved = options.resolve_binding(binding, in_mode)?;
|
||||
@@ -579,8 +579,8 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
writeln!(self.out, "}};")?;
|
||||
writeln!(self.out, "struct {} {{", output_name)?;
|
||||
for &token in var_outputs.iter() {
|
||||
let var = &module.global_variables[token];
|
||||
for &handle in var_outputs.iter() {
|
||||
let var = &module.global_variables[handle];
|
||||
// if it's a struct, lift all the built-in contents up to the root
|
||||
if let crate::TypeInner::Pointer { base, .. } = module.types[var.ty].inner {
|
||||
if let crate::TypeInner::Struct { ref members } = module.types[base].inner {
|
||||
@@ -589,14 +589,14 @@ impl<W: Write> Writer<W> {
|
||||
let ty_name = module.types[member.ty].name.or_index(member.ty);
|
||||
let binding = member.binding
|
||||
.as_ref()
|
||||
.ok_or(Error::MissingBinding(token))?;
|
||||
.ok_or(Error::MissingBinding(handle))?;
|
||||
let resolved = options.resolve_binding(binding, out_mode)?;
|
||||
writeln!(self.out, "\t{} {} [[{}]];", ty_name, name, resolved)?;
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
let tyvar = TypedGlobalVariable { module, token };
|
||||
let tyvar = TypedGlobalVariable { module, handle };
|
||||
write!(self.out, "\t{}", tyvar)?;
|
||||
if let Some(ref binding) = var.binding {
|
||||
let resolved = options.resolve_binding(binding, out_mode)?;
|
||||
@@ -623,15 +623,15 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
}
|
||||
for (_, expr) in fun.expressions.iter() {
|
||||
if let crate::Expression::GlobalVariable(token) = *expr {
|
||||
let var = &module.global_variables[token];
|
||||
if var.class == spirv::StorageClass::UniformConstant && !uniforms_used.contains(&token) {
|
||||
uniforms_used.insert(token);
|
||||
if let crate::Expression::GlobalVariable(handle) = *expr {
|
||||
let var = &module.global_variables[handle];
|
||||
if var.class == spirv::StorageClass::UniformConstant && !uniforms_used.contains(&handle) {
|
||||
uniforms_used.insert(handle);
|
||||
let binding = var.binding
|
||||
.as_ref()
|
||||
.ok_or(Error::MissingBinding(token))?;
|
||||
.ok_or(Error::MissingBinding(handle))?;
|
||||
let resolved = options.resolve_binding(binding, LocationMode::Uniform)?;
|
||||
let var = TypedGlobalVariable { module, token };
|
||||
let var = TypedGlobalVariable { module, handle };
|
||||
writeln!(self.out, "\t{} [[{}]],", var, resolved)?;
|
||||
}
|
||||
}
|
||||
@@ -672,11 +672,11 @@ impl<W: Write> Writer<W> {
|
||||
match (value, exec_model) {
|
||||
(None, None) => (),
|
||||
(None, Some(_)) => self.out.write_str(NAME_OUTPUT)?,
|
||||
(Some(expr_token), None) => {
|
||||
self.put_expression(expr_token, &fun.expressions, module)?;
|
||||
(Some(expr_handle), None) => {
|
||||
self.put_expression(expr_handle, &fun.expressions, module)?;
|
||||
}
|
||||
(Some(expr_token), Some(_)) => {
|
||||
panic!("Unable to return value {:?} from an entry point!", expr_token)
|
||||
(Some(expr_handle), Some(_)) => {
|
||||
panic!("Unable to return value {:?} from an entry point!", expr_handle)
|
||||
}
|
||||
}
|
||||
writeln!(self.out, ";")?;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pub mod spirv;
|
||||
pub mod wgsl;
|
||||
|
||||
use crate::storage::Storage;
|
||||
use crate::arena::Arena;
|
||||
|
||||
pub const GENERATOR: u32 = 0;
|
||||
|
||||
@@ -9,10 +9,10 @@ impl crate::Module {
|
||||
fn from_header(header: crate::Header) -> Self {
|
||||
crate::Module {
|
||||
header,
|
||||
types: Storage::new(),
|
||||
constants: Storage::new(),
|
||||
global_variables: Storage::new(),
|
||||
functions: Storage::new(),
|
||||
types: Arena::new(),
|
||||
constants: Arena::new(),
|
||||
global_variables: Arena::new(),
|
||||
functions: Arena::new(),
|
||||
entry_points: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
## ID lookups
|
||||
|
||||
Our IR links to everything with `Token`, while SPIR-V uses IDs.
|
||||
Our IR links to everything with `Handle`, while SPIR-V uses IDs.
|
||||
In order to keep track of the associations, the parser has many lookup tables.
|
||||
There map `spirv::Word` into a specific IR token, plus potentially a bit of
|
||||
There map `spirv::Word` into a specific IR handle, plus potentially a bit of
|
||||
extra info, such as the related SPIR-V type ID.
|
||||
TODO: would be nice to find ways that avoid looking up as much
|
||||
|
||||
!*/
|
||||
|
||||
use crate::{
|
||||
storage::{Storage, Token},
|
||||
arena::{Arena, Handle},
|
||||
FastHashMap, FastHashSet,
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ pub enum Error {
|
||||
UnsupportedCapability(spirv::Capability),
|
||||
UnsupportedExtension(String),
|
||||
UnsupportedExtSet(String),
|
||||
UnsupportedType(Token<crate::Type>),
|
||||
UnsupportedType(Handle<crate::Type>),
|
||||
UnsupportedExecutionModel(u32),
|
||||
UnsupportedStorageClass(u32),
|
||||
UnsupportedFunctionControl(u32),
|
||||
@@ -60,7 +60,7 @@ pub enum Error {
|
||||
InvalidVectorSize(spirv::Word),
|
||||
InvalidVariableClass(spirv::StorageClass),
|
||||
InvalidAccessType(spirv::Word),
|
||||
InvalidAccessIndex(Token<crate::Expression>),
|
||||
InvalidAccessIndex(Handle<crate::Expression>),
|
||||
InvalidLoadType(spirv::Word),
|
||||
InvalidStoreType(spirv::Word),
|
||||
InvalidBinding(spirv::Word),
|
||||
@@ -197,32 +197,32 @@ struct EntryPoint {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LookupType {
|
||||
token: Token<crate::Type>,
|
||||
handle: Handle<crate::Type>,
|
||||
base_id: Option<spirv::Word>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LookupConstant {
|
||||
token: Token<crate::Constant>,
|
||||
handle: Handle<crate::Constant>,
|
||||
type_id: spirv::Word,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LookupVariable {
|
||||
token: Token<crate::GlobalVariable>,
|
||||
handle: Handle<crate::GlobalVariable>,
|
||||
type_id: spirv::Word,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct LookupExpression {
|
||||
token: Token<crate::Expression>,
|
||||
handle: Handle<crate::Expression>,
|
||||
type_id: spirv::Word,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct LookupSampledImage {
|
||||
image: Token<crate::Expression>,
|
||||
sampler: Token<crate::Expression>,
|
||||
image: Handle<crate::Expression>,
|
||||
sampler: Handle<crate::Expression>,
|
||||
}
|
||||
|
||||
pub struct Parser<I> {
|
||||
@@ -239,7 +239,7 @@ pub struct Parser<I> {
|
||||
lookup_expression: FastHashMap<spirv::Word, LookupExpression>,
|
||||
lookup_sampled_image: FastHashMap<spirv::Word, LookupSampledImage>,
|
||||
lookup_function_type: FastHashMap<spirv::Word, LookupFunctionType>,
|
||||
lookup_function: FastHashMap<spirv::Word, Token<crate::Function>>,
|
||||
lookup_function: FastHashMap<spirv::Word, Handle<crate::Function>>,
|
||||
}
|
||||
|
||||
impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
@@ -354,8 +354,8 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
fn next_block(
|
||||
&mut self,
|
||||
fun: &mut crate::Function,
|
||||
type_store: &Storage<crate::Type>,
|
||||
const_store: &Storage<crate::Constant>,
|
||||
type_arena: &Arena<crate::Type>,
|
||||
const_arena: &Arena<crate::Constant>,
|
||||
) -> Result<(), Error> {
|
||||
loop {
|
||||
use spirv::Op;
|
||||
@@ -364,7 +364,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
match inst.op {
|
||||
Op::AccessChain => {
|
||||
struct AccessExpression {
|
||||
base_token: Token<crate::Expression>,
|
||||
base_handle: Handle<crate::Expression>,
|
||||
type_id: spirv::Word,
|
||||
}
|
||||
inst.expect_at_least(4)?;
|
||||
@@ -376,7 +376,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let expr = self.lookup_expression.lookup(base_id)?;
|
||||
let ptr_type = self.lookup_type.lookup(expr.type_id)?;
|
||||
AccessExpression {
|
||||
base_token: expr.token,
|
||||
base_handle: expr.handle,
|
||||
type_id: ptr_type.base_id.unwrap(),
|
||||
}
|
||||
};
|
||||
@@ -384,29 +384,29 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let access_id = self.next()?;
|
||||
log::trace!("\t\t\tlooking up expr {:?}", access_id);
|
||||
let index_expr = self.lookup_expression.lookup(access_id)?.clone();
|
||||
let index_type_token = self.lookup_type.lookup(index_expr.type_id)?.token;
|
||||
match type_store[index_type_token].inner {
|
||||
let index_type_handle = self.lookup_type.lookup(index_expr.type_id)?.handle;
|
||||
match type_arena[index_type_handle].inner {
|
||||
crate::TypeInner::Scalar { kind: crate::ScalarKind::Uint, .. } |
|
||||
crate::TypeInner::Scalar { kind: crate::ScalarKind::Sint, .. } => (),
|
||||
_ => return Err(Error::UnsupportedType(index_type_token)),
|
||||
_ => return Err(Error::UnsupportedType(index_type_handle)),
|
||||
}
|
||||
log::trace!("\t\t\tlooking up type {:?}", acex.type_id);
|
||||
let type_lookup = self.lookup_type.lookup(acex.type_id)?;
|
||||
acex = match type_store[type_lookup.token].inner {
|
||||
acex = match type_arena[type_lookup.handle].inner {
|
||||
crate::TypeInner::Struct { .. } => {
|
||||
let index = match fun.expressions[index_expr.token] {
|
||||
crate::Expression::Constant(const_token) => {
|
||||
match const_store[const_token].inner {
|
||||
let index = match fun.expressions[index_expr.handle] {
|
||||
crate::Expression::Constant(const_handle) => {
|
||||
match const_arena[const_handle].inner {
|
||||
crate::ConstantInner::Uint(v) => v as u32,
|
||||
crate::ConstantInner::Sint(v) => v as u32,
|
||||
_ => return Err(Error::InvalidAccessIndex(index_expr.token)),
|
||||
_ => return Err(Error::InvalidAccessIndex(index_expr.handle)),
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::InvalidAccessIndex(index_expr.token))
|
||||
_ => return Err(Error::InvalidAccessIndex(index_expr.handle))
|
||||
};
|
||||
AccessExpression {
|
||||
base_token: fun.expressions.append(crate::Expression::AccessIndex {
|
||||
base: acex.base_token,
|
||||
base_handle: fun.expressions.append(crate::Expression::AccessIndex {
|
||||
base: acex.base_handle,
|
||||
index,
|
||||
}),
|
||||
type_id: *self.lookup_member_type_id
|
||||
@@ -418,20 +418,20 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
crate::TypeInner::Vector { .. } |
|
||||
crate::TypeInner::Matrix { .. } => {
|
||||
AccessExpression {
|
||||
base_token: fun.expressions.append(crate::Expression::Access {
|
||||
base: acex.base_token,
|
||||
index: index_expr.token,
|
||||
base_handle: fun.expressions.append(crate::Expression::Access {
|
||||
base: acex.base_handle,
|
||||
index: index_expr.handle,
|
||||
}),
|
||||
type_id: type_lookup.base_id
|
||||
.ok_or(Error::InvalidAccessType(acex.type_id))?,
|
||||
}
|
||||
}
|
||||
_ => return Err(Error::UnsupportedType(type_lookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(type_lookup.handle)),
|
||||
};
|
||||
}
|
||||
|
||||
self.lookup_expression.insert(result_id, LookupExpression {
|
||||
token: acex.base_token,
|
||||
handle: acex.base_handle,
|
||||
type_id: result_type_id,
|
||||
});
|
||||
}
|
||||
@@ -444,7 +444,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let mut lexp = {
|
||||
let expr = self.lookup_expression.lookup(base_id)?;
|
||||
LookupExpression {
|
||||
token: expr.token,
|
||||
handle: expr.handle,
|
||||
type_id: expr.type_id,
|
||||
}
|
||||
};
|
||||
@@ -452,7 +452,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let index = self.next()?;
|
||||
log::trace!("\t\t\tlooking up type {:?}", lexp.type_id);
|
||||
let type_lookup = self.lookup_type.lookup(lexp.type_id)?;
|
||||
let type_id = match type_store[type_lookup.token].inner {
|
||||
let type_id = match type_arena[type_lookup.handle].inner {
|
||||
crate::TypeInner::Struct { .. } => {
|
||||
*self.lookup_member_type_id
|
||||
.get(&(lexp.type_id, index))
|
||||
@@ -464,11 +464,11 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
type_lookup.base_id
|
||||
.ok_or(Error::InvalidAccessType(lexp.type_id))?
|
||||
}
|
||||
_ => return Err(Error::UnsupportedType(type_lookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(type_lookup.handle)),
|
||||
};
|
||||
lexp = LookupExpression {
|
||||
token: fun.expressions.append(crate::Expression::AccessIndex {
|
||||
base: lexp.token,
|
||||
handle: fun.expressions.append(crate::Expression::AccessIndex {
|
||||
base: lexp.handle,
|
||||
index,
|
||||
}),
|
||||
type_id,
|
||||
@@ -476,7 +476,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
}
|
||||
|
||||
self.lookup_expression.insert(result_id, LookupExpression {
|
||||
token: lexp.token,
|
||||
handle: lexp.handle,
|
||||
type_id: result_type_id,
|
||||
});
|
||||
}
|
||||
@@ -489,14 +489,14 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let comp_id = self.next()?;
|
||||
log::trace!("\t\t\tlooking up expr {:?}", comp_id);
|
||||
let lexp = self.lookup_expression.lookup(comp_id)?;
|
||||
components.push(lexp.token);
|
||||
components.push(lexp.handle);
|
||||
}
|
||||
let expr = crate::Expression::Compose {
|
||||
ty: self.lookup_type.lookup(result_type_id)?.token,
|
||||
ty: self.lookup_type.lookup(result_type_id)?.handle,
|
||||
components,
|
||||
};
|
||||
self.lookup_expression.insert(id, LookupExpression {
|
||||
token: fun.expressions.append(expr),
|
||||
handle: fun.expressions.append(expr),
|
||||
type_id: result_type_id,
|
||||
});
|
||||
}
|
||||
@@ -514,15 +514,15 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
if base_type.base_id != Some(result_type_id) {
|
||||
return Err(Error::InvalidLoadType(result_type_id));
|
||||
}
|
||||
match type_store[base_type.token].inner {
|
||||
match type_arena[base_type.handle].inner {
|
||||
crate::TypeInner::Pointer { .. } => (),
|
||||
_ => return Err(Error::UnsupportedType(base_type.token)),
|
||||
_ => return Err(Error::UnsupportedType(base_type.handle)),
|
||||
}
|
||||
let expr = crate::Expression::Load {
|
||||
pointer: base_expr.token,
|
||||
pointer: base_expr.handle,
|
||||
};
|
||||
self.lookup_expression.insert(result_id, LookupExpression {
|
||||
token: fun.expressions.append(expr),
|
||||
handle: fun.expressions.append(expr),
|
||||
type_id: result_type_id,
|
||||
});
|
||||
}
|
||||
@@ -536,17 +536,17 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
}
|
||||
let base_expr = self.lookup_expression.lookup(pointer_id)?;
|
||||
let base_type = self.lookup_type.lookup(base_expr.type_id)?;
|
||||
match type_store[base_type.token].inner {
|
||||
match type_arena[base_type.handle].inner {
|
||||
crate::TypeInner::Pointer { .. } => (),
|
||||
_ => return Err(Error::UnsupportedType(base_type.token)),
|
||||
_ => return Err(Error::UnsupportedType(base_type.handle)),
|
||||
};
|
||||
let value_expr = self.lookup_expression.lookup(value_id)?;
|
||||
if base_type.base_id != Some(value_expr.type_id) {
|
||||
return Err(Error::InvalidStoreType(value_expr.type_id));
|
||||
}
|
||||
fun.body.push(crate::Statement::Store {
|
||||
pointer: base_expr.token,
|
||||
value: value_expr.token,
|
||||
pointer: base_expr.handle,
|
||||
value: value_expr.handle,
|
||||
})
|
||||
}
|
||||
Op::Return => {
|
||||
@@ -558,28 +558,28 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
inst.expect(5)?;
|
||||
let result_type_id = self.next()?;
|
||||
let result_type_loookup = self.lookup_type.lookup(result_type_id)?;
|
||||
let (res_size, res_width) = match type_store[result_type_loookup.token].inner {
|
||||
let (res_size, res_width) = match type_arena[result_type_loookup.handle].inner {
|
||||
crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } => (size, width),
|
||||
_ => return Err(Error::UnsupportedType(result_type_loookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(result_type_loookup.handle)),
|
||||
};
|
||||
let result_id = self.next()?;
|
||||
let vector_id = self.next()?;
|
||||
let scalar_id = self.next()?;
|
||||
let vector_lexp = self.lookup_expression.lookup(vector_id)?;
|
||||
let vector_type_lookup = self.lookup_type.lookup(vector_lexp.type_id)?;
|
||||
match type_store[vector_type_lookup.token].inner {
|
||||
match type_arena[vector_type_lookup.handle].inner {
|
||||
crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } if size == res_size && width == res_width => (),
|
||||
_ => return Err(Error::UnsupportedType(vector_type_lookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(vector_type_lookup.handle)),
|
||||
};
|
||||
let scalar_lexp = self.lookup_expression.lookup(scalar_id)?.clone();
|
||||
let scalar_type_lookup = self.lookup_type.lookup(scalar_lexp.type_id)?;
|
||||
match type_store[scalar_type_lookup.token].inner {
|
||||
match type_arena[scalar_type_lookup.handle].inner {
|
||||
crate::TypeInner::Scalar { kind: crate::ScalarKind::Float, width } if width == res_width => (),
|
||||
_ => return Err(Error::UnsupportedType(scalar_type_lookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(scalar_type_lookup.handle)),
|
||||
};
|
||||
let expr = crate::Expression::Mul(vector_lexp.token, scalar_lexp.token);
|
||||
let expr = crate::Expression::Mul(vector_lexp.handle, scalar_lexp.handle);
|
||||
self.lookup_expression.insert(result_id, LookupExpression {
|
||||
token: fun.expressions.append(expr),
|
||||
handle: fun.expressions.append(expr),
|
||||
type_id: result_type_id,
|
||||
});
|
||||
}
|
||||
@@ -587,28 +587,28 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
inst.expect(5)?;
|
||||
let result_type_id = self.next()?;
|
||||
let result_type_loookup = self.lookup_type.lookup(result_type_id)?;
|
||||
let (res_size, res_width) = match type_store[result_type_loookup.token].inner {
|
||||
let (res_size, res_width) = match type_arena[result_type_loookup.handle].inner {
|
||||
crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } => (size, width),
|
||||
_ => return Err(Error::UnsupportedType(result_type_loookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(result_type_loookup.handle)),
|
||||
};
|
||||
let result_id = self.next()?;
|
||||
let matrix_id = self.next()?;
|
||||
let vector_id = self.next()?;
|
||||
let matrix_lexp = self.lookup_expression.lookup(matrix_id)?;
|
||||
let matrix_type_lookup = self.lookup_type.lookup(matrix_lexp.type_id)?;
|
||||
let columns = match type_store[matrix_type_lookup.token].inner {
|
||||
let columns = match type_arena[matrix_type_lookup.handle].inner {
|
||||
crate::TypeInner::Matrix { columns, rows, kind: crate::ScalarKind::Float, width } if rows == res_size && width == res_width => columns,
|
||||
_ => return Err(Error::UnsupportedType(matrix_type_lookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(matrix_type_lookup.handle)),
|
||||
};
|
||||
let vector_lexp = self.lookup_expression.lookup(vector_id)?.clone();
|
||||
let vector_type_lookup = self.lookup_type.lookup(vector_lexp.type_id)?;
|
||||
match type_store[vector_type_lookup.token].inner {
|
||||
match type_arena[vector_type_lookup.handle].inner {
|
||||
crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } if size == columns && width == res_width => (),
|
||||
_ => return Err(Error::UnsupportedType(vector_type_lookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(vector_type_lookup.handle)),
|
||||
};
|
||||
let expr = crate::Expression::Mul(matrix_lexp.token, vector_lexp.token);
|
||||
let expr = crate::Expression::Mul(matrix_lexp.handle, vector_lexp.handle);
|
||||
self.lookup_expression.insert(result_id, LookupExpression {
|
||||
token: fun.expressions.append(expr),
|
||||
handle: fun.expressions.append(expr),
|
||||
type_id: result_type_id,
|
||||
});
|
||||
}
|
||||
@@ -622,8 +622,8 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let sampler_lexp = self.lookup_expression.lookup(sampler_id)?;
|
||||
//TODO: compare the result type
|
||||
self.lookup_sampled_image.insert(result_id, LookupSampledImage {
|
||||
image: image_lexp.token,
|
||||
sampler: sampler_lexp.token,
|
||||
image: image_lexp.handle,
|
||||
sampler: sampler_lexp.handle,
|
||||
});
|
||||
}
|
||||
Op::ImageSampleImplicitLod => {
|
||||
@@ -635,19 +635,19 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let si_lexp = self.lookup_sampled_image.lookup(sampled_image_id)?;
|
||||
let coord_lexp = self.lookup_expression.lookup(coordinate_id)?;
|
||||
let coord_type_lookup = self.lookup_type.lookup(coord_lexp.type_id)?;
|
||||
match type_store[coord_type_lookup.token].inner {
|
||||
match type_arena[coord_type_lookup.handle].inner {
|
||||
crate::TypeInner::Scalar { kind: crate::ScalarKind::Float, .. } |
|
||||
crate::TypeInner::Vector { kind: crate::ScalarKind::Float, .. } => (),
|
||||
_ => return Err(Error::UnsupportedType(coord_type_lookup.token)),
|
||||
_ => return Err(Error::UnsupportedType(coord_type_lookup.handle)),
|
||||
}
|
||||
//TODO: compare the result type
|
||||
let expr = crate::Expression::ImageSample {
|
||||
image: si_lexp.image,
|
||||
sampler: si_lexp.sampler,
|
||||
coordinate: coord_lexp.token,
|
||||
coordinate: coord_lexp.handle,
|
||||
};
|
||||
self.lookup_expression.insert(result_id, LookupExpression {
|
||||
token: fun.expressions.append(expr),
|
||||
handle: fun.expressions.append(expr),
|
||||
type_id: result_type_id,
|
||||
});
|
||||
}
|
||||
@@ -657,21 +657,21 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_expression_storage(&mut self) -> Storage<crate::Expression> {
|
||||
let mut expressions = Storage::new();
|
||||
fn make_expression_storage(&mut self) -> Arena<crate::Expression> {
|
||||
let mut expressions = Arena::new();
|
||||
assert!(self.lookup_expression.is_empty());
|
||||
// register global variables
|
||||
for (&id, var) in self.lookup_variable.iter() {
|
||||
self.lookup_expression.insert(id, LookupExpression {
|
||||
type_id: var.type_id,
|
||||
token: expressions.append(crate::Expression::GlobalVariable(var.token)),
|
||||
handle: expressions.append(crate::Expression::GlobalVariable(var.handle)),
|
||||
});
|
||||
}
|
||||
// register constants
|
||||
for (&id, con) in self.lookup_constant.iter() {
|
||||
self.lookup_expression.insert(id, LookupExpression {
|
||||
type_id: con.type_id,
|
||||
token: expressions.append(crate::Expression::Constant(con.token)),
|
||||
handle: expressions.append(crate::Expression::Constant(con.handle)),
|
||||
});
|
||||
}
|
||||
// done
|
||||
@@ -863,7 +863,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
.map_err(|_| Error::InvalidTypeWidth(width))?,
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -884,7 +884,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
.map_err(|_| Error::InvalidTypeWidth(width))?,
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -899,7 +899,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let id = self.next()?;
|
||||
let type_id = self.next()?;
|
||||
let type_lookup = self.lookup_type.lookup(type_id)?;
|
||||
let (kind, width) = match module.types[type_lookup.token].inner {
|
||||
let (kind, width) = match module.types[type_lookup.handle].inner {
|
||||
crate::TypeInner::Scalar { kind, width } => (kind, width),
|
||||
_ => return Err(Error::InvalidInnerType(type_id)),
|
||||
};
|
||||
@@ -910,7 +910,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
width,
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -926,7 +926,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let vector_type_id = self.next()?;
|
||||
let num_columns = self.next()?;
|
||||
let vector_type_lookup = self.lookup_type.lookup(vector_type_id)?;
|
||||
let inner = match module.types[vector_type_lookup.token].inner {
|
||||
let inner = match module.types[vector_type_lookup.handle].inner {
|
||||
crate::TypeInner::Vector { size, kind, width } => crate::TypeInner::Matrix {
|
||||
columns: map_vector_size(num_columns)?,
|
||||
rows: size,
|
||||
@@ -936,7 +936,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
_ => return Err(Error::InvalidInnerType(vector_type_id)),
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -966,11 +966,11 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let storage = self.next()?;
|
||||
let type_id = self.next()?;
|
||||
let inner = crate::TypeInner::Pointer {
|
||||
base: self.lookup_type.lookup(type_id)?.token,
|
||||
base: self.lookup_type.lookup(type_id)?.handle,
|
||||
class: map_storage_class(storage)?,
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -986,11 +986,11 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let type_id = self.next()?;
|
||||
let length = self.next()?;
|
||||
let inner = crate::TypeInner::Array {
|
||||
base: self.lookup_type.lookup(type_id)?.token,
|
||||
base: self.lookup_type.lookup(type_id)?.handle,
|
||||
size: crate::ArraySize::Static(length),
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -1005,11 +1005,11 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let id = self.next()?;
|
||||
let type_id = self.next()?;
|
||||
let inner = crate::TypeInner::Array {
|
||||
base: self.lookup_type.lookup(type_id)?.token,
|
||||
base: self.lookup_type.lookup(type_id)?.handle,
|
||||
size: crate::ArraySize::Dynamic,
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -1025,7 +1025,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let mut members = Vec::with_capacity(inst.wc as usize - 2);
|
||||
for i in 0 .. inst.wc as u32 - 2 {
|
||||
let type_id = self.next()?;
|
||||
let ty = self.lookup_type.lookup(type_id)?.token;
|
||||
let ty = self.lookup_type.lookup(type_id)?.handle;
|
||||
self.lookup_member_type_id.insert((id, i), type_id);
|
||||
let decor = self.future_member_decor
|
||||
.remove(&(id, i))
|
||||
@@ -1041,7 +1041,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
members
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -1086,7 +1086,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
.unwrap_or_default();
|
||||
|
||||
let inner = crate::TypeInner::Image {
|
||||
base: self.lookup_type.lookup(sample_type_id)?.token,
|
||||
base: self.lookup_type.lookup(sample_type_id)?.handle,
|
||||
dim: if dim > LAST_KNOWN_DIM as u32 {
|
||||
return Err(Error::UnsupportedDim(dim));
|
||||
} else {
|
||||
@@ -1095,7 +1095,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
flags,
|
||||
};
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: decor.name,
|
||||
inner,
|
||||
}),
|
||||
@@ -1108,7 +1108,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let id = self.next()?;
|
||||
let image_id = self.next()?;
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: self.lookup_type.lookup(image_id)?.token,
|
||||
handle: self.lookup_type.lookup(image_id)?.handle,
|
||||
base_id: Some(image_id),
|
||||
});
|
||||
}
|
||||
@@ -1121,7 +1121,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
.unwrap_or_default();
|
||||
let inner = crate::TypeInner::Sampler;
|
||||
self.lookup_type.insert(id, LookupType {
|
||||
token: module.types.append(crate::Type {
|
||||
handle: module.types.append(crate::Type {
|
||||
name: decor.name,
|
||||
inner,
|
||||
}),
|
||||
@@ -1135,7 +1135,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let type_id = self.next()?;
|
||||
let id = self.next()?;
|
||||
let type_lookup = self.lookup_type.lookup(type_id)?;
|
||||
let inner = match module.types[type_lookup.token].inner {
|
||||
let inner = match module.types[type_lookup.handle].inner {
|
||||
crate::TypeInner::Scalar { kind: crate::ScalarKind::Uint, width } => {
|
||||
let low = self.next()?;
|
||||
let high = if width > 32 {
|
||||
@@ -1177,10 +1177,10 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
};
|
||||
crate::ConstantInner::Float(extended)
|
||||
}
|
||||
_ => return Err(Error::UnsupportedType(type_lookup.token))
|
||||
_ => return Err(Error::UnsupportedType(type_lookup.handle))
|
||||
};
|
||||
self.lookup_constant.insert(id, LookupConstant {
|
||||
token: module.constants.append(crate::Constant {
|
||||
handle: module.constants.append(crate::Constant {
|
||||
name: self.future_decor
|
||||
.remove(&id)
|
||||
.and_then(|dec| dec.name),
|
||||
@@ -1204,7 +1204,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
let dec = self.future_decor
|
||||
.remove(&id)
|
||||
.ok_or(Error::InvalidBinding(id))?;
|
||||
let binding = match module.types[lookup_type.token].inner {
|
||||
let binding = match module.types[lookup_type.handle].inner {
|
||||
crate::TypeInner::Pointer { base, class: spirv::StorageClass::Input } |
|
||||
crate::TypeInner::Pointer { base, class: spirv::StorageClass::Output } => {
|
||||
match module.types[base].inner {
|
||||
@@ -1238,11 +1238,10 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
name: dec.name,
|
||||
class: map_storage_class(storage)?,
|
||||
binding,
|
||||
ty: lookup_type.token,
|
||||
ty: lookup_type.handle,
|
||||
};
|
||||
let token = module.global_variables.append(var);
|
||||
self.lookup_variable.insert(id, LookupVariable {
|
||||
token,
|
||||
handle: module.global_variables.append(var),
|
||||
type_id,
|
||||
});
|
||||
}
|
||||
@@ -1268,7 +1267,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
return_type: if self.lookup_void_type.contains(&result_type) {
|
||||
None
|
||||
} else {
|
||||
Some(self.lookup_type.lookup(result_type)?.token)
|
||||
Some(self.lookup_type.lookup(result_type)?.handle)
|
||||
},
|
||||
expressions: self.make_expression_storage(),
|
||||
body: Vec::new(),
|
||||
@@ -1287,7 +1286,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
{
|
||||
return Err(Error::WrongFunctionParameterType(type_id))
|
||||
}
|
||||
let ty = self.lookup_type.lookup(type_id)?.token;
|
||||
let ty = self.lookup_type.lookup(type_id)?.handle;
|
||||
fun.parameter_types.push(ty);
|
||||
}
|
||||
Instruction { op, .. } => return Err(Error::InvalidParameter(op)),
|
||||
@@ -1311,8 +1310,8 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
}
|
||||
}
|
||||
// done
|
||||
let token = module.functions.append(fun);
|
||||
self.lookup_function.insert(fun_id, token);
|
||||
let handle = module.functions.append(fun);
|
||||
self.lookup_function.insert(fun_id, handle);
|
||||
self.lookup_expression.clear();
|
||||
self.lookup_sampled_image.clear();
|
||||
}
|
||||
@@ -1340,10 +1339,10 @@ impl<I: Iterator<Item = u32>> Parser<I> {
|
||||
outputs: Vec::new(),
|
||||
};
|
||||
for var_id in raw.variable_ids {
|
||||
let token = self.lookup_variable.lookup(var_id)?.token;
|
||||
match module.global_variables[token].class {
|
||||
spirv::StorageClass::Input => ep.inputs.push(token),
|
||||
spirv::StorageClass::Output => ep.outputs.push(token),
|
||||
let handle = self.lookup_variable.lookup(var_id)?.handle;
|
||||
match module.global_variables[handle].class {
|
||||
spirv::StorageClass::Input => ep.inputs.push(handle),
|
||||
spirv::StorageClass::Output => ep.outputs.push(handle),
|
||||
other => return Err(Error::InvalidVariableClass(other))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
storage::{Storage, Token as Id},
|
||||
arena::{Arena, Handle},
|
||||
FastHashMap,
|
||||
};
|
||||
|
||||
@@ -177,8 +177,8 @@ trait StringValueLookup<'a> {
|
||||
type Value;
|
||||
fn lookup(&self, key: &'a str) -> Result<Self::Value, Error<'a>>;
|
||||
}
|
||||
impl<'a> StringValueLookup<'a> for FastHashMap<&'a str, Id<crate::Expression>> {
|
||||
type Value = Id<crate::Expression>;
|
||||
impl<'a> StringValueLookup<'a> for FastHashMap<&'a str, Handle<crate::Expression>> {
|
||||
type Value = Handle<crate::Expression>;
|
||||
fn lookup(&self, key: &'a str) -> Result<Self::Value, Error<'a>> {
|
||||
self.get(key)
|
||||
.cloned()
|
||||
@@ -188,9 +188,9 @@ impl<'a> StringValueLookup<'a> for FastHashMap<&'a str, Id<crate::Expression>> {
|
||||
|
||||
struct ExpressionContext<'input,'temp, 'out> {
|
||||
function: &'out mut crate::Function,
|
||||
lookup_ident: &'temp FastHashMap<&'input str, Id<crate::Expression>>,
|
||||
types: &'out mut Storage<crate::Type>,
|
||||
constants: &'out mut Storage<crate::Constant>,
|
||||
lookup_ident: &'temp FastHashMap<&'input str, Handle<crate::Expression>>,
|
||||
types: &'out mut Arena<crate::Type>,
|
||||
constants: &'out mut Arena<crate::Constant>,
|
||||
}
|
||||
|
||||
impl<'a> ExpressionContext<'a, '_, '_> {
|
||||
@@ -208,8 +208,8 @@ impl<'a> ExpressionContext<'a, '_, '_> {
|
||||
lexer: &mut Lexer<'a>,
|
||||
middle: Token<'a>,
|
||||
op: crate::BinaryOperator,
|
||||
mut parser: impl FnMut(&mut Lexer<'a>, ExpressionContext<'a, '_, '_>) -> Result<Id<crate::Expression>, Error<'a>>,
|
||||
) -> Result<Id<crate::Expression>, Error<'a>> {
|
||||
mut parser: impl FnMut(&mut Lexer<'a>, ExpressionContext<'a, '_, '_>) -> Result<Handle<crate::Expression>, Error<'a>>,
|
||||
) -> Result<Handle<crate::Expression>, Error<'a>> {
|
||||
let mut left = parser(lexer, self.reborrow())?;
|
||||
while lexer.peek() == middle {
|
||||
let _ = lexer.next();
|
||||
@@ -233,7 +233,7 @@ pub struct ParseError<'a> {
|
||||
|
||||
pub struct Parser {
|
||||
scopes: Vec<Scope>,
|
||||
lookup_type: FastHashMap<String, Id<crate::Type>>,
|
||||
lookup_type: FastHashMap<String, Handle<crate::Type>>,
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
@@ -338,8 +338,8 @@ impl Parser {
|
||||
fn parse_const_expression<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
type_store: &mut Storage<crate::Type>,
|
||||
const_store: &mut Storage<crate::Constant>,
|
||||
type_arena: &mut Arena<crate::Type>,
|
||||
const_arena: &mut Arena<crate::Constant>,
|
||||
) -> Result<crate::ConstantInner, Error<'a>> {
|
||||
self.scopes.push(Scope::ConstantExpr);
|
||||
let inner = match lexer.peek() {
|
||||
@@ -356,10 +356,10 @@ impl Parser {
|
||||
Self::get_constant_inner(word)?
|
||||
}
|
||||
_ => {
|
||||
let _ty = self.parse_type_decl(lexer, type_store);
|
||||
let _ty = self.parse_type_decl(lexer, type_arena);
|
||||
Self::expect(lexer, Token::Paren('('))?;
|
||||
while lexer.peek() != Token::Paren(')') {
|
||||
let _ = self.parse_const_expression(lexer, type_store, const_store)?;
|
||||
let _ = self.parse_const_expression(lexer, type_arena, const_arena)?;
|
||||
}
|
||||
let _ = lexer.next();
|
||||
unimplemented!()
|
||||
@@ -373,7 +373,7 @@ impl Parser {
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Id<crate::Expression>, Error<'a>> {
|
||||
) -> Result<Handle<crate::Expression>, Error<'a>> {
|
||||
self.scopes.push(Scope::PrimaryExpr);
|
||||
let backup = lexer.clone();
|
||||
let expression = match lexer.next() {
|
||||
@@ -384,33 +384,33 @@ impl Parser {
|
||||
return Ok(expr);
|
||||
}
|
||||
Token::Word("true") => {
|
||||
let id = ctx.constants.append(crate::Constant {
|
||||
let handle = ctx.constants.append(crate::Constant {
|
||||
name: None,
|
||||
specialization: None,
|
||||
inner: crate::ConstantInner::Bool(true),
|
||||
});
|
||||
crate::Expression::Constant(id)
|
||||
crate::Expression::Constant(handle)
|
||||
}
|
||||
Token::Word("false") => {
|
||||
let id = ctx.constants.append(crate::Constant {
|
||||
let handle = ctx.constants.append(crate::Constant {
|
||||
name: None,
|
||||
specialization: None,
|
||||
inner: crate::ConstantInner::Bool(false),
|
||||
});
|
||||
crate::Expression::Constant(id)
|
||||
crate::Expression::Constant(handle)
|
||||
}
|
||||
Token::Number(word) => {
|
||||
let id = ctx.constants.append(crate::Constant {
|
||||
let handle = ctx.constants.append(crate::Constant {
|
||||
name: None,
|
||||
specialization: None,
|
||||
inner: Self::get_constant_inner(word)?,
|
||||
});
|
||||
crate::Expression::Constant(id)
|
||||
crate::Expression::Constant(handle)
|
||||
}
|
||||
Token::Word(word) => {
|
||||
if let Some(id) = ctx.lookup_ident.get(word) {
|
||||
if let Some(handle) = ctx.lookup_ident.get(word) {
|
||||
self.scopes.pop();
|
||||
return Ok(*id);
|
||||
return Ok(*handle);
|
||||
}
|
||||
*lexer = backup;
|
||||
let ty = self.parse_type_decl(lexer, ctx.types)?;
|
||||
@@ -436,7 +436,7 @@ impl Parser {
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut context: ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Id<crate::Expression>, Error<'a>> {
|
||||
) -> Result<Handle<crate::Expression>, Error<'a>> {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
Token::Operation('+'),
|
||||
@@ -454,9 +454,9 @@ impl Parser {
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut context: ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Id<crate::Expression>, Error<'a>> {
|
||||
) -> Result<Handle<crate::Expression>, Error<'a>> {
|
||||
self.scopes.push(Scope::GeneralExpr);
|
||||
let id = context.parse_binary_op(
|
||||
let handle = context.parse_binary_op(
|
||||
lexer,
|
||||
Token::LogicalOperation('|'),
|
||||
crate::BinaryOperator::LogicalOr,
|
||||
@@ -488,26 +488,26 @@ impl Parser {
|
||||
),
|
||||
)?;
|
||||
self.scopes.pop();
|
||||
Ok(id)
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
fn parse_variable_ident_decl<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
type_store: &mut Storage<crate::Type>,
|
||||
) -> Result<(&'a str, Id<crate::Type>), Error<'a>> {
|
||||
type_arena: &mut Arena<crate::Type>,
|
||||
) -> Result<(&'a str, Handle<crate::Type>), Error<'a>> {
|
||||
let name = Self::parse_ident(lexer)?;
|
||||
Self::expect(lexer, Token::Separator(':'))?;
|
||||
let ty = self.parse_type_decl(lexer, type_store)?;
|
||||
let ty = self.parse_type_decl(lexer, type_arena)?;
|
||||
Ok((name, ty))
|
||||
}
|
||||
|
||||
fn parse_variable_decl<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
type_store: &mut Storage<crate::Type>,
|
||||
const_store: &mut Storage<crate::Constant>,
|
||||
) -> Result<(&'a str, Option<spirv::StorageClass>, Id<crate::Type>), Error<'a>> {
|
||||
type_arena: &mut Arena<crate::Type>,
|
||||
const_arena: &mut Arena<crate::Constant>,
|
||||
) -> Result<(&'a str, Option<spirv::StorageClass>, Handle<crate::Type>), Error<'a>> {
|
||||
self.scopes.push(Scope::VariableDecl);
|
||||
let mut class = None;
|
||||
if let Token::Paren('<') = lexer.peek() {
|
||||
@@ -518,10 +518,10 @@ impl Parser {
|
||||
}
|
||||
let name = Self::parse_ident(lexer)?;
|
||||
Self::expect(lexer, Token::Separator(':'))?;
|
||||
let ty = self.parse_type_decl(lexer, type_store)?;
|
||||
let ty = self.parse_type_decl(lexer, type_arena)?;
|
||||
if let Token::Operation('=') = lexer.peek() {
|
||||
let _ = lexer.next();
|
||||
let _inner = self.parse_const_expression(lexer, type_store, const_store)?;
|
||||
let _inner = self.parse_const_expression(lexer, type_arena, const_arena)?;
|
||||
//TODO
|
||||
}
|
||||
Self::expect(lexer, Token::Separator(';'))?;
|
||||
@@ -532,7 +532,7 @@ impl Parser {
|
||||
fn parse_struct_body<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
type_store: &mut Storage<crate::Type>,
|
||||
type_arena: &mut Arena<crate::Type>,
|
||||
) -> Result<Vec<crate::StructMember>, Error<'a>> {
|
||||
let mut members = Vec::new();
|
||||
Self::expect(lexer, Token::Paren('{'))?;
|
||||
@@ -563,7 +563,7 @@ impl Parser {
|
||||
other => return Err(Error::Unexpected(other)),
|
||||
};
|
||||
Self::expect(lexer, Token::Separator(':'))?;
|
||||
let ty = self.parse_type_decl(lexer, type_store)?;
|
||||
let ty = self.parse_type_decl(lexer, type_arena)?;
|
||||
Self::expect(lexer, Token::Separator(';'))?;
|
||||
members.push(crate::StructMember {
|
||||
name: Some(name.to_owned()),
|
||||
@@ -576,8 +576,8 @@ impl Parser {
|
||||
fn parse_type_decl<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
type_store: &mut Storage<crate::Type>,
|
||||
) -> Result<Id<crate::Type>, Error<'a>> {
|
||||
type_arena: &mut Arena<crate::Type>,
|
||||
) -> Result<Handle<crate::Type>, Error<'a>> {
|
||||
self.scopes.push(Scope::TypeDecl);
|
||||
let inner = match lexer.next() {
|
||||
Token::Word("f32") => {
|
||||
@@ -653,13 +653,13 @@ impl Parser {
|
||||
Self::expect(lexer, Token::Paren('<'))?;
|
||||
let class = Self::get_storage_class(Self::parse_ident(lexer)?)?;
|
||||
Self::expect(lexer, Token::Separator(','))?;
|
||||
let base = self.parse_type_decl(lexer, type_store)?;
|
||||
let base = self.parse_type_decl(lexer, type_arena)?;
|
||||
Self::expect(lexer, Token::Paren('>'))?;
|
||||
crate::TypeInner::Pointer { base, class }
|
||||
}
|
||||
Token::Word("array") => {
|
||||
Self::expect(lexer, Token::Paren('<'))?;
|
||||
let base = self.parse_type_decl(lexer, type_store)?;
|
||||
let base = self.parse_type_decl(lexer, type_arena)?;
|
||||
let size = match lexer.next() {
|
||||
Token::Separator(',') => {
|
||||
let value = Self::parse_uint_literal(lexer)?;
|
||||
@@ -672,20 +672,20 @@ impl Parser {
|
||||
crate::TypeInner::Array { base, size }
|
||||
}
|
||||
Token::Word("struct") => {
|
||||
let members = self.parse_struct_body(lexer, type_store)?;
|
||||
let members = self.parse_struct_body(lexer, type_arena)?;
|
||||
crate::TypeInner::Struct { members }
|
||||
}
|
||||
other => return Err(Error::Unexpected(other)),
|
||||
};
|
||||
self.scopes.pop();
|
||||
|
||||
if let Some((token, _)) = type_store
|
||||
if let Some((token, _)) = type_arena
|
||||
.iter()
|
||||
.find(|(_, ty)| ty.inner == inner)
|
||||
{
|
||||
return Ok(token);
|
||||
}
|
||||
Ok(type_store.append(crate::Type {
|
||||
Ok(type_arena.append(crate::Type {
|
||||
name: None,
|
||||
inner,
|
||||
}))
|
||||
@@ -696,7 +696,7 @@ impl Parser {
|
||||
lexer: &mut Lexer<'a>,
|
||||
module: &mut crate::Module,
|
||||
lookup_global_expression: &FastHashMap<&'a str, crate::Expression>,
|
||||
) -> Result<Id<crate::Function>, Error<'a>> {
|
||||
) -> Result<Handle<crate::Function>, Error<'a>> {
|
||||
self.scopes.push(Scope::FunctionDecl);
|
||||
// read function name
|
||||
let mut lookup_ident = FastHashMap::default();
|
||||
@@ -706,13 +706,13 @@ impl Parser {
|
||||
control: spirv::FunctionControl::empty(),
|
||||
parameter_types: Vec::new(),
|
||||
return_type: None,
|
||||
expressions: Storage::new(),
|
||||
expressions: Arena::new(),
|
||||
body: Vec::new(),
|
||||
};
|
||||
// populare initial expressions
|
||||
for (&name, expression) in lookup_global_expression.iter() {
|
||||
let expr_id = fun.expressions.append(expression.clone());
|
||||
lookup_ident.insert(name, expr_id);
|
||||
let expr_handle = fun.expressions.append(expression.clone());
|
||||
lookup_ident.insert(name, expr_handle);
|
||||
}
|
||||
// read parameter list
|
||||
Self::expect(lexer, Token::Paren('('))?;
|
||||
@@ -721,8 +721,8 @@ impl Parser {
|
||||
Self::expect(lexer, Token::Separator(','))?;
|
||||
}
|
||||
let (param_name, param_type) = self.parse_variable_ident_decl(lexer, &mut module.types)?;
|
||||
let param_id = fun.parameter_types.len() as u32;
|
||||
let expression_token = fun.expressions.append(crate::Expression::FunctionParameter(param_id));
|
||||
let param_index = fun.parameter_types.len() as u32;
|
||||
let expression_token = fun.expressions.append(crate::Expression::FunctionParameter(param_index));
|
||||
lookup_ident.insert(param_name, expression_token);
|
||||
fun.parameter_types.push(param_type);
|
||||
}
|
||||
@@ -856,22 +856,22 @@ impl Parser {
|
||||
Self::expect(lexer, Token::Operation('='))?;
|
||||
let inner = self.parse_const_expression(lexer, &mut module.types, &mut module.constants)?;
|
||||
Self::expect(lexer, Token::Separator(';'))?;
|
||||
let const_id = module.constants.append(crate::Constant {
|
||||
let const_handle = module.constants.append(crate::Constant {
|
||||
name: Some(name.to_owned()),
|
||||
specialization: None,
|
||||
inner,
|
||||
});
|
||||
lookup_global_expression.insert(name, crate::Expression::Constant(const_id));
|
||||
lookup_global_expression.insert(name, crate::Expression::Constant(const_handle));
|
||||
}
|
||||
Token::Word("var") => {
|
||||
let (name, class, ty) = self.parse_variable_decl(lexer, &mut module.types, &mut module.constants)?;
|
||||
let var_id = module.global_variables.append(crate::GlobalVariable {
|
||||
let var_handle = module.global_variables.append(crate::GlobalVariable {
|
||||
name: Some(name.to_owned()),
|
||||
class: class.unwrap_or(spirv::StorageClass::Private),
|
||||
binding: binding.take(),
|
||||
ty,
|
||||
});
|
||||
lookup_global_expression.insert(name, crate::Expression::GlobalVariable(var_id));
|
||||
lookup_global_expression.insert(name, crate::Expression::GlobalVariable(var_handle));
|
||||
}
|
||||
Token::Word("fn") => {
|
||||
self.parse_function_decl(lexer, module, &lookup_global_expression)?;
|
||||
@@ -893,7 +893,7 @@ impl Parser {
|
||||
let function = module.functions
|
||||
.iter()
|
||||
.find(|(_, fun)| fun.name.as_ref().map(|s| s.as_str()) == Some(fun_ident))
|
||||
.map(|(id, _)| id)
|
||||
.map(|(handle, _)| handle)
|
||||
.ok_or(Error::UnknownFunction(fun_ident))?;
|
||||
module.entry_points.push(crate::EntryPoint {
|
||||
exec_model,
|
||||
|
||||
76
src/lib.rs
76
src/lib.rs
@@ -1,8 +1,8 @@
|
||||
mod arena;
|
||||
pub mod back;
|
||||
pub mod front;
|
||||
mod storage;
|
||||
|
||||
use crate::storage::{Storage, Token};
|
||||
use crate::arena::{Arena, Handle};
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
@@ -49,7 +49,7 @@ pub enum ArraySize {
|
||||
pub struct StructMember {
|
||||
pub name: Option<String>,
|
||||
pub binding: Option<Binding>,
|
||||
pub ty: Token<Type>,
|
||||
pub ty: Handle<Type>,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
@@ -73,10 +73,10 @@ pub enum TypeInner {
|
||||
Scalar { kind: ScalarKind, width: Bytes },
|
||||
Vector { size: VectorSize, kind: ScalarKind, width: Bytes },
|
||||
Matrix { columns: VectorSize, rows: VectorSize, kind: ScalarKind, width: Bytes },
|
||||
Pointer { base: Token<Type>, class: spirv::StorageClass },
|
||||
Array { base: Token<Type>, size: ArraySize },
|
||||
Pointer { base: Handle<Type>, class: spirv::StorageClass },
|
||||
Array { base: Handle<Type>, size: ArraySize },
|
||||
Struct { members: Vec<StructMember> },
|
||||
Image { base: Token<Type>, dim: spirv::Dim, flags: ImageFlags },
|
||||
Image { base: Handle<Type>, dim: spirv::Dim, flags: ImageFlags },
|
||||
Sampler,
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ pub struct GlobalVariable {
|
||||
pub name: Option<String>,
|
||||
pub class: spirv::StorageClass,
|
||||
pub binding: Option<Binding>,
|
||||
pub ty: Token<Type>,
|
||||
pub ty: Handle<Type>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@@ -125,33 +125,33 @@ pub enum BinaryOperator {
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Expression {
|
||||
Access {
|
||||
base: Token<Expression>,
|
||||
index: Token<Expression>, //int
|
||||
base: Handle<Expression>,
|
||||
index: Handle<Expression>, //int
|
||||
},
|
||||
AccessIndex {
|
||||
base: Token<Expression>,
|
||||
base: Handle<Expression>,
|
||||
index: u32,
|
||||
},
|
||||
Constant(Token<Constant>),
|
||||
Constant(Handle<Constant>),
|
||||
Compose {
|
||||
ty: Token<Type>,
|
||||
components: Vec<Token<Expression>>,
|
||||
ty: Handle<Type>,
|
||||
components: Vec<Handle<Expression>>,
|
||||
},
|
||||
FunctionParameter(u32),
|
||||
GlobalVariable(Token<GlobalVariable>),
|
||||
GlobalVariable(Handle<GlobalVariable>),
|
||||
Load {
|
||||
pointer: Token<Expression>,
|
||||
pointer: Handle<Expression>,
|
||||
},
|
||||
Mul(Token<Expression>, Token<Expression>),
|
||||
Mul(Handle<Expression>, Handle<Expression>),
|
||||
ImageSample {
|
||||
image: Token<Expression>,
|
||||
sampler: Token<Expression>,
|
||||
coordinate: Token<Expression>,
|
||||
image: Handle<Expression>,
|
||||
sampler: Handle<Expression>,
|
||||
coordinate: Handle<Expression>,
|
||||
},
|
||||
Binary {
|
||||
op: BinaryOperator,
|
||||
left: Token<Expression>,
|
||||
right: Token<Expression>,
|
||||
left: Handle<Expression>,
|
||||
right: Handle<Expression>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -164,26 +164,26 @@ pub enum Statement {
|
||||
Block(Block),
|
||||
VariableDeclaration {
|
||||
name: String,
|
||||
ty: Token<Type>,
|
||||
value: Option<Token<Expression>>,
|
||||
ty: Handle<Type>,
|
||||
value: Option<Handle<Expression>>,
|
||||
},
|
||||
If {
|
||||
condition: Token<Expression>, //bool
|
||||
condition: Handle<Expression>, //bool
|
||||
accept: Block,
|
||||
reject: Block,
|
||||
},
|
||||
Switch {
|
||||
selector: Token<Expression>, //int
|
||||
selector: Handle<Expression>, //int
|
||||
cases: FastHashMap<i32, (Block, Option<FallThrough>)>,
|
||||
default: Block,
|
||||
},
|
||||
Return {
|
||||
value: Option<Token<Expression>>,
|
||||
value: Option<Handle<Expression>>,
|
||||
},
|
||||
Kill,
|
||||
Store {
|
||||
pointer: Token<Expression>,
|
||||
value: Token<Expression>,
|
||||
pointer: Handle<Expression>,
|
||||
value: Handle<Expression>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -191,9 +191,9 @@ pub enum Statement {
|
||||
pub struct Function {
|
||||
pub name: Option<String>,
|
||||
pub control: spirv::FunctionControl,
|
||||
pub parameter_types: Vec<Token<Type>>,
|
||||
pub return_type: Option<Token<Type>>,
|
||||
pub expressions: Storage<Expression>,
|
||||
pub parameter_types: Vec<Handle<Type>>,
|
||||
pub return_type: Option<Handle<Type>>,
|
||||
pub expressions: Arena<Expression>,
|
||||
pub body: Block,
|
||||
}
|
||||
|
||||
@@ -201,17 +201,17 @@ pub struct Function {
|
||||
pub struct EntryPoint {
|
||||
pub exec_model: spirv::ExecutionModel,
|
||||
pub name: String,
|
||||
pub inputs: Vec<Token<GlobalVariable>>,
|
||||
pub outputs: Vec<Token<GlobalVariable>>,
|
||||
pub function: Token<Function>,
|
||||
pub inputs: Vec<Handle<GlobalVariable>>,
|
||||
pub outputs: Vec<Handle<GlobalVariable>>,
|
||||
pub function: Handle<Function>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Module {
|
||||
pub header: Header,
|
||||
pub types: Storage<Type>,
|
||||
pub constants: Storage<Constant>,
|
||||
pub global_variables: Storage<GlobalVariable>,
|
||||
pub functions: Storage<Function>,
|
||||
pub types: Arena<Type>,
|
||||
pub constants: Arena<Constant>,
|
||||
pub global_variables: Arena<GlobalVariable>,
|
||||
pub functions: Arena<Function>,
|
||||
pub entry_points: Vec<EntryPoint>,
|
||||
}
|
||||
|
||||
155
src/storage.rs
155
src/storage.rs
@@ -1,155 +0,0 @@
|
||||
use std::{
|
||||
fmt,
|
||||
hash,
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
/// An unique index in the storage array that a token points to.
|
||||
///
|
||||
/// This type is independent of `spirv::Word`. `spirv::Word` is used in data
|
||||
/// representation. It holds a SPIR-V and refers to that instruction. In
|
||||
/// structured representation, we use Token to refer to an SPIR-V instruction.
|
||||
/// Index is an implementation detail to Token.
|
||||
type Index = u32;
|
||||
|
||||
/// A strongly typed reference to a SPIR-V element.
|
||||
pub struct Token<T> {
|
||||
index: Index,
|
||||
marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Clone for Token<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Token {
|
||||
index: self.index,
|
||||
marker: self.marker,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> Copy for Token<T> {}
|
||||
impl<T> PartialEq for Token<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.index == other.index
|
||||
}
|
||||
}
|
||||
impl<T> Eq for Token<T> {}
|
||||
impl<T> fmt::Debug for Token<T> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Token({})", self.index)
|
||||
}
|
||||
}
|
||||
impl<T> hash::Hash for Token<T> {
|
||||
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
||||
self.index.hash(hasher)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Token<T> {
|
||||
#[cfg(test)]
|
||||
pub const DUMMY: Self = Token {
|
||||
index: !0,
|
||||
marker: PhantomData,
|
||||
};
|
||||
|
||||
pub(crate) fn new(index: Index) -> Self {
|
||||
Token {
|
||||
index,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn index(&self) -> usize {
|
||||
self.index as usize
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure holding some kind of SPIR-V entity (e.g., type, constant,
|
||||
/// instruction, etc.) that can be referenced.
|
||||
#[derive(Debug)]
|
||||
pub struct Storage<T> {
|
||||
/// Values of this storage.
|
||||
data: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T> Storage<T> {
|
||||
pub fn new() -> Self {
|
||||
Storage {
|
||||
data: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter<'a>(&'a self) -> impl Iterator<Item = (Token<T>, &'a T)> {
|
||||
self.data
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, v)| (Token::new(i as Index), v))
|
||||
}
|
||||
|
||||
/// Adds a new value to the storage, returning a typed token.
|
||||
///
|
||||
/// The value is not linked to any SPIR-V module.
|
||||
pub fn append(&mut self, value: T) -> Token<T> {
|
||||
let index = self.data.len() as Index;
|
||||
self.data.push(value);
|
||||
Token::new(index)
|
||||
}
|
||||
|
||||
/// Adds a value with a check for uniqueness: returns a token pointing to
|
||||
/// an existing element if its value matches the given one, or adds a new
|
||||
/// element otherwise.
|
||||
pub fn fetch_or_append(&mut self, value: T) -> Token<T> where T: PartialEq {
|
||||
if let Some(index) = self.data.iter().position(|d| d == &value) {
|
||||
Token::new(index as Index)
|
||||
} else {
|
||||
self.append(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> std::ops::Index<Token<T>> for Storage<T> {
|
||||
type Output = T;
|
||||
fn index(&self, token: Token<T>) -> &T {
|
||||
&self.data[token.index as usize]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn append_non_unique() {
|
||||
let mut storage: Storage<f64> = Storage::new();
|
||||
let t1 = storage.append(0.0);
|
||||
let t2 = storage.append(0.0);
|
||||
assert!(t1 != t2);
|
||||
assert!(storage[t1] == storage[t2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn append_unique() {
|
||||
let mut storage: Storage<f64> = Storage::new();
|
||||
let t1 = storage.append(std::f64::NAN);
|
||||
let t2 = storage.append(std::f64::NAN);
|
||||
assert!(t1 != t2);
|
||||
assert!(storage[t1] != storage[t2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_or_append_non_unique() {
|
||||
let mut storage: Storage<f64> = Storage::new();
|
||||
let t1 = storage.fetch_or_append(0.0);
|
||||
let t2 = storage.fetch_or_append(0.0);
|
||||
assert!(t1 == t2);
|
||||
assert!(storage[t1] == storage[t2])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_or_append_unique() {
|
||||
let mut storage: Storage<f64> = Storage::new();
|
||||
let t1 = storage.fetch_or_append(std::f64::NAN);
|
||||
let t2 = storage.fetch_or_append(std::f64::NAN);
|
||||
assert!(t1 != t2);
|
||||
assert!(storage[t1] != storage[t2]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user