diff --git a/.monocodus b/.monocodus index 59d8a47119..b429007b97 100644 --- a/.monocodus +++ b/.monocodus @@ -3,5 +3,3 @@ version: 1.0.0 rust: formatter: name: rustfmt - ignore_paths: - - ".*" diff --git a/examples/convert.rs b/examples/convert.rs index c03e1d8fd1..ba6e6a4a1d 100644 --- a/examples/convert.rs +++ b/examples/convert.rs @@ -1,4 +1,4 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use std::{env, fs}; #[derive(Hash, PartialEq, Eq, Serialize, Deserialize)] @@ -27,7 +27,7 @@ fn main() { let module = if args.len() <= 1 { println!("Call with "); - return + return; } else if args[1].ends_with(".spv") { let input = fs::read(&args[1]).unwrap(); naga::front::spirv::parse_u8_slice(&input).unwrap() @@ -43,8 +43,7 @@ fn main() { return; } - let param_path = std::path::PathBuf::from(&args[1]) - .with_extension("ron"); + let param_path = std::path::PathBuf::from(&args[1]).with_extension("ron"); let params = match fs::read_to_string(param_path) { Ok(string) => ron::de::from_str(&string).unwrap(), Err(_) => Parameters::default(), diff --git a/src/back/mod.rs b/src/back/mod.rs index f4f1fce17b..4a194befe0 100644 --- a/src/back/mod.rs +++ b/src/back/mod.rs @@ -1 +1 @@ -pub mod msl; \ No newline at end of file +pub mod msl; diff --git a/src/back/msl.rs b/src/back/msl.rs index a2086ef7f0..20fe75cb00 100644 --- a/src/back/msl.rs +++ b/src/back/msl.rs @@ -14,16 +14,9 @@ the output struct. If there is a structure in the outputs, and it contains any b we move them up to the root output structure that we define ourselves. !*/ -use std::{ - fmt::{ - Display, Error as FmtError, Formatter, Write, - }, -}; +use std::fmt::{Display, Error as FmtError, Formatter, Write}; -use crate::{ - arena::Handle, - FastHashMap, -}; +use crate::{arena::Handle, FastHashMap}; /// Expect all the global variables to have a pointer type, /// like in SPIR-V. @@ -49,7 +42,10 @@ enum ResolvedBinding { BuiltIn(spirv::BuiltIn), Attribute(spirv::Word), Color(spirv::Word), - User { prefix: &'static str, index: spirv::Word }, + User { + prefix: &'static str, + index: spirv::Word, + }, Resource(BindTarget), } @@ -61,7 +57,7 @@ impl Level { } impl Display for Level { fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), FmtError> { - (0 .. self.0).map(|_| formatter.write_str("\t")).collect() + (0..self.0).map(|_| formatter.write_str("\t")).collect() } } @@ -115,7 +111,11 @@ pub struct Options<'a> { } impl Options<'_> { - fn resolve_binding(&self, binding: &crate::Binding, mode: LocationMode) -> Result { + fn resolve_binding( + &self, + binding: &crate::Binding, + mode: LocationMode, + ) -> Result { match *binding { crate::Binding::BuiltIn(built_in) => Ok(ResolvedBinding::BuiltIn(built_in)), crate::Binding::Location(index) => match mode { @@ -134,13 +134,11 @@ impl Options<'_> { .cloned() .map(ResolvedBinding::Resource) .ok_or(Error::MissingBindTarget(source)) - } } } } - trait Indexed { const CLASS: &'static str; const PREFIX: bool = false; @@ -149,42 +147,58 @@ trait Indexed { impl Indexed for crate::Handle { const CLASS: &'static str = "Type"; - fn id(&self) -> usize { self.index() } + fn id(&self) -> usize { + self.index() + } } impl Indexed for crate::Handle { const CLASS: &'static str = "global"; - fn id(&self) -> usize { self.index() } + fn id(&self) -> usize { + self.index() + } } impl Indexed for crate::Handle { const CLASS: &'static str = "local"; - fn id(&self) -> usize { self.index() } + fn id(&self) -> usize { + self.index() + } } impl Indexed for crate::Handle { const CLASS: &'static str = "function"; - fn id(&self) -> usize { self.index() } + fn id(&self) -> usize { + self.index() + } } struct MemberIndex(usize); impl Indexed for MemberIndex { const CLASS: &'static str = "field"; - fn id(&self) -> usize { self.0 } + fn id(&self) -> usize { + self.0 + } } struct ParameterIndex(usize); impl Indexed for ParameterIndex { const CLASS: &'static str = "param"; - fn id(&self) -> usize { self.0 } + fn id(&self) -> usize { + self.0 + } } struct InputStructIndex(crate::Handle); impl Indexed for InputStructIndex { const CLASS: &'static str = "Input"; const PREFIX: bool = true; - fn id(&self) -> usize { self.0.index() } + fn id(&self) -> usize { + self.0.index() + } } struct OutputStructIndex(crate::Handle); impl Indexed for OutputStructIndex { const CLASS: &'static str = "Output"; const PREFIX: bool = true; - fn id(&self) -> usize { self.0.index() } + fn id(&self) -> usize { + self.0.index() + } } enum NameSource<'a> { @@ -192,9 +206,7 @@ enum NameSource<'a> { Index(usize), } -const RESERVED_NAMES: &[&str] = &[ - "main", -]; +const RESERVED_NAMES: &[&str] = &["main"]; struct Name<'a> { class: &'static str, @@ -203,10 +215,14 @@ struct Name<'a> { impl Display for Name<'_> { fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), FmtError> { match self.source { - NameSource::Custom { name, prefix: false } if RESERVED_NAMES.contains(&name) => { - write!(formatter, "{}_", name) - } - NameSource::Custom { name, prefix: false } => formatter.write_str(name), + NameSource::Custom { + name, + prefix: false, + } if RESERVED_NAMES.contains(&name) => write!(formatter, "{}_", name), + NameSource::Custom { + name, + prefix: false, + } => formatter.write_str(name), NameSource::Custom { name, prefix: true } => { let (head, tail) = name.split_at(1); write!(formatter, "{}{}{}", self.class, head.to_uppercase(), tail) @@ -232,7 +248,10 @@ impl AsName for Option { Name { class: I::CLASS, source: match *self { - Some(ref name) if !name.is_empty() => NameSource::Custom { name, prefix: I::PREFIX }, + Some(ref name) if !name.is_empty() => NameSource::Custom { + name, + prefix: I::PREFIX, + }, _ => NameSource::Index(index.id()), }, } @@ -250,9 +269,9 @@ impl<'a> TypedGlobalVariable<'a> { let var = &self.module.global_variables[self.handle]; let name = var.name.or_index(self.handle); let (space_qualifier, reference) = match var.class { - spirv::StorageClass::Uniform | - spirv::StorageClass::UniformConstant | - spirv::StorageClass::StorageBuffer => { + spirv::StorageClass::Uniform + | spirv::StorageClass::UniformConstant + | spirv::StorageClass::StorageBuffer => { let space = if self.usage.contains(crate::GlobalUse::STORE) { "device " } else { @@ -260,18 +279,18 @@ impl<'a> TypedGlobalVariable<'a> { }; (space, "&") } - _ => ("", "") + _ => ("", ""), }; if GLOBAL_POINTERS { let ty = &self.module.types[var.ty]; match ty.inner { - crate::TypeInner::Pointer { base, class } => { + crate::TypeInner::Pointer { base, class } => { let ty_handle = match class { - spirv::StorageClass::Input | - spirv::StorageClass::Output | - spirv::StorageClass::Uniform | - spirv::StorageClass::UniformConstant => base, - _ => var.ty + spirv::StorageClass::Input + | spirv::StorageClass::Output + | spirv::StorageClass::Uniform + | spirv::StorageClass::UniformConstant => base, + _ => var.ty, }; let ty_name = self.module.types[ty_handle].name.or_index(ty_handle); Ok(write!(formatter, "{} {}", ty_name, name)?) @@ -280,7 +299,11 @@ impl<'a> TypedGlobalVariable<'a> { } } else { let ty_name = self.module.types[var.ty].name.or_index(var.ty); - Ok(write!(formatter, "{}{}{} {}", space_qualifier, ty_name, reference, name)?) + Ok(write!( + formatter, + "{}{}{} {}", + space_qualifier, ty_name, reference, name + )?) } } } @@ -298,12 +321,8 @@ impl ResolvedBinding { }; Ok(formatter.write_str(name)?) } - ResolvedBinding::Attribute(index) => { - Ok(write!(formatter, "attribute({})", index)?) - } - ResolvedBinding::Color(index) => { - Ok(write!(formatter, "color({})", index)?) - } + ResolvedBinding::Attribute(index) => Ok(write!(formatter, "attribute({})", index)?), + ResolvedBinding::Color(index) => Ok(write!(formatter, "color({})", index)?), ResolvedBinding::User { prefix, index } => { Ok(write!(formatter, "user({}{})", prefix, index)?) } @@ -321,7 +340,11 @@ impl ResolvedBinding { } } - fn try_fmt_decorated(&self, formatter: &mut W, terminator: &str) -> Result<(), Error> { + fn try_fmt_decorated( + &self, + formatter: &mut W, + terminator: &str, + ) -> Result<(), Error> { formatter.write_str(" [[")?; self.try_fmt(formatter)?; formatter.write_str("]]")?; @@ -356,7 +379,11 @@ const LOCATION_INPUT_STRUCT_NAME: &str = "input"; const COMPONENTS: &[char] = &['x', 'y', 'z', 'w']; fn separate(is_last: bool) -> &'static str { - if is_last { "" } else { "," } + if is_last { + "" + } else { + "," + } } #[derive(Debug)] @@ -410,9 +437,15 @@ impl Writer { write!(self.out, ".{}", name)?; Ok(module.borrow_type(member.ty)) } - crate::TypeInner::Matrix { rows, kind, width, .. } => { + crate::TypeInner::Matrix { + rows, kind, width, .. + } => { write!(self.out, ".{}", COMPONENTS[index as usize])?; - Ok(MaybeOwned::Owned(crate::TypeInner::Vector { size: rows, kind, width })) + Ok(MaybeOwned::Owned(crate::TypeInner::Vector { + size: rows, + kind, + width, + })) } crate::TypeInner::Vector { kind, width, .. } => { write!(self.out, ".{}", COMPONENTS[index as usize])?; @@ -428,14 +461,17 @@ impl Writer { ref other => Err(Error::UnexpectedIndexing(other.clone())), } } - crate::Expression::Constant(handle) => { - self.put_constant(handle, module) - } + crate::Expression::Constant(handle) => self.put_constant(handle, module), crate::Expression::Compose { ty, ref components } => { let inner = &module.types[ty].inner; match *inner { crate::TypeInner::Vector { size, kind, .. } => { - write!(self.out, "{}{}(", scalar_kind_string(kind), vector_size_string(size))?; + write!( + self.out, + "{}{}(", + scalar_kind_string(kind), + vector_size_string(size) + )?; for (i, &handle) in components.iter().enumerate() { if i != 0 { write!(self.out, ",")?; @@ -461,7 +497,7 @@ impl Writer { } } } else if let crate::TypeInner::Struct { .. } = *inner { - return Ok(MaybeOwned::Borrowed(inner)); + return Ok(MaybeOwned::Borrowed(inner)); } write!(self.out, "{}.", OUTPUT_STRUCT_NAME)?; } @@ -486,9 +522,7 @@ impl Writer { crate::Expression::Load { pointer } => { //write!(self.out, "*")?; match *self.put_expression(pointer, function, module)?.borrow() { - crate::TypeInner::Pointer { base, .. } => { - Ok(module.borrow_type(base)) - } + crate::TypeInner::Pointer { base, .. } => Ok(module.borrow_type(base)), ref other => Err(Error::UnexpectedLoadPointer(other.clone())), } } @@ -523,20 +557,42 @@ impl Writer { Ok(if op_str.len() == 1 { match (ty_left.borrow(), ty_right.borrow()) { - (&crate::TypeInner::Scalar { kind, width }, &crate::TypeInner::Scalar { .. }) => - MaybeOwned::Owned(crate::TypeInner::Scalar { kind, width }), - (&crate::TypeInner::Scalar { .. }, &crate::TypeInner::Vector { size, kind, width }) | - (&crate::TypeInner::Vector { size, kind, width }, &crate::TypeInner::Scalar { .. }) | - (&crate::TypeInner::Vector { size, kind, width }, &crate::TypeInner::Vector { .. }) => - MaybeOwned::Owned(crate::TypeInner::Vector { size, kind, width }), - (other_left, other_right) => - return Err(Error::UnableToInferBinaryOpOutput(other_left.clone(), op, other_right.clone())), + ( + &crate::TypeInner::Scalar { kind, width }, + &crate::TypeInner::Scalar { .. }, + ) => MaybeOwned::Owned(crate::TypeInner::Scalar { kind, width }), + ( + &crate::TypeInner::Scalar { .. }, + &crate::TypeInner::Vector { size, kind, width }, + ) + | ( + &crate::TypeInner::Vector { size, kind, width }, + &crate::TypeInner::Scalar { .. }, + ) + | ( + &crate::TypeInner::Vector { size, kind, width }, + &crate::TypeInner::Vector { .. }, + ) => MaybeOwned::Owned(crate::TypeInner::Vector { size, kind, width }), + (other_left, other_right) => { + return Err(Error::UnableToInferBinaryOpOutput( + other_left.clone(), + op, + other_right.clone(), + )) + } } } else { - MaybeOwned::Owned(crate::TypeInner::Scalar { kind: crate::ScalarKind::Bool, width: 1 }) + MaybeOwned::Owned(crate::TypeInner::Scalar { + kind: crate::ScalarKind::Bool, + width: 1, + }) }) } - crate::Expression::ImageSample { image, sampler, coordinate } => { + crate::Expression::ImageSample { + image, + sampler, + coordinate, + } => { let ty_image = self.put_expression(image, function, module)?; write!(self.out, ".sample(")?; self.put_expression(sampler, function, module)?; @@ -548,58 +604,67 @@ impl Writer { ref other => Err(Error::UnexpectedImageType(other.clone())), } } - crate::Expression::Call { ref name, ref arguments } => { - match name.as_str() { - "cos" | - "normalize" | - "sin" => { - write!(self.out, "{}(", name)?; - let result = self.put_expression(arguments[0], function, module)?; - write!(self.out, ")")?; - Ok(result) - } - "fclamp" => { - write!(self.out, "clamp(")?; - let result = self.put_expression(arguments[0], function, module)?; - write!(self.out, ", ")?; - self.put_expression(arguments[1], function, module)?; - write!(self.out, ", ")?; - self.put_expression(arguments[2], function, module)?; - write!(self.out, ")")?; - Ok(result) - } - "atan2" => { - write!(self.out, "{}(", name)?; - let result = self.put_expression(arguments[0], function, module)?; - write!(self.out, ", ")?; - self.put_expression(arguments[1], function, module)?; - write!(self.out, ")")?; - Ok(result) - } - "distance" => { - write!(self.out, "distance(")?; - let result = match *self.put_expression(arguments[0], function, module)?.borrow() { - crate::TypeInner::Vector { kind, width, .. } => crate::TypeInner::Scalar { kind, width }, - ref other => return Err(Error::UnexpectedDistanceArgument(other.clone())), - }; - write!(self.out, ", ")?; - self.put_expression(arguments[1], function, module)?; - write!(self.out, ")")?; - Ok(MaybeOwned::Owned(result)) - } - "length" => { - write!(self.out, "length(")?; - let result = match *self.put_expression(arguments[0], function, module)?.borrow() { - crate::TypeInner::Vector { kind, width, .. } => crate::TypeInner::Scalar { kind, width }, - ref other => return Err(Error::UnexpectedDistanceArgument(other.clone())), - }; - write!(self.out, ")")?; - Ok(MaybeOwned::Owned(result)) - } - - other => Err(Error::UnsupportedCall(other.to_owned())), + crate::Expression::Call { + ref name, + ref arguments, + } => match name.as_str() { + "cos" | "normalize" | "sin" => { + write!(self.out, "{}(", name)?; + let result = self.put_expression(arguments[0], function, module)?; + write!(self.out, ")")?; + Ok(result) } - } + "fclamp" => { + write!(self.out, "clamp(")?; + let result = self.put_expression(arguments[0], function, module)?; + write!(self.out, ", ")?; + self.put_expression(arguments[1], function, module)?; + write!(self.out, ", ")?; + self.put_expression(arguments[2], function, module)?; + write!(self.out, ")")?; + Ok(result) + } + "atan2" => { + write!(self.out, "{}(", name)?; + let result = self.put_expression(arguments[0], function, module)?; + write!(self.out, ", ")?; + self.put_expression(arguments[1], function, module)?; + write!(self.out, ")")?; + Ok(result) + } + "distance" => { + write!(self.out, "distance(")?; + let result = match *self + .put_expression(arguments[0], function, module)? + .borrow() + { + crate::TypeInner::Vector { kind, width, .. } => { + crate::TypeInner::Scalar { kind, width } + } + ref other => return Err(Error::UnexpectedDistanceArgument(other.clone())), + }; + write!(self.out, ", ")?; + self.put_expression(arguments[1], function, module)?; + write!(self.out, ")")?; + Ok(MaybeOwned::Owned(result)) + } + "length" => { + write!(self.out, "length(")?; + let result = match *self + .put_expression(arguments[0], function, module)? + .borrow() + { + crate::TypeInner::Vector { kind, width, .. } => { + crate::TypeInner::Scalar { kind, width } + } + ref other => return Err(Error::UnexpectedDistanceArgument(other.clone())), + }; + write!(self.out, ")")?; + Ok(MaybeOwned::Owned(result)) + } + + other => Err(Error::UnsupportedCall(other.to_owned())), + }, ref other => Err(Error::UnsupportedExpression(other.clone())), } } @@ -655,7 +720,11 @@ impl Writer { log::trace!("statement[{}] {:?}", level.0, statement); match *statement { crate::Statement::Empty => {} - crate::Statement::If { condition, ref accept, ref reject } => { + crate::Statement::If { + condition, + ref accept, + ref reject, + } => { write!(self.out, "{}if (", level)?; self.put_expression(condition, function, module)?; writeln!(self.out, ") {{")?; @@ -670,7 +739,10 @@ impl Writer { } writeln!(self.out, "{}}}", level)?; } - crate::Statement::Loop { ref body, ref continuing } => { + crate::Statement::Loop { + ref body, + ref continuing, + } => { writeln!(self.out, "{}while(true) {{", level)?; for s in body { self.put_statement(level.next(), s, function, has_output, module)?; @@ -733,20 +805,38 @@ impl Writer { match ty.inner { crate::TypeInner::Scalar { kind, .. } => { write!(self.out, "typedef {} {}", scalar_kind_string(kind), name)?; - }, + } crate::TypeInner::Vector { size, kind, .. } => { - write!(self.out, "typedef {}{} {}", scalar_kind_string(kind), vector_size_string(size), name)?; - }, - crate::TypeInner::Matrix { columns, rows, kind, .. } => { - write!(self.out, "typedef {}{}x{} {}", scalar_kind_string(kind), vector_size_string(columns), vector_size_string(rows), name)?; + write!( + self.out, + "typedef {}{} {}", + scalar_kind_string(kind), + vector_size_string(size), + name + )?; + } + crate::TypeInner::Matrix { + columns, + rows, + kind, + .. + } => { + write!( + self.out, + "typedef {}{}x{} {}", + scalar_kind_string(kind), + vector_size_string(columns), + vector_size_string(rows), + name + )?; } crate::TypeInner::Pointer { base, class } => { let base_name = module.types[base].name.or_index(base); let class_name = match class { - spirv::StorageClass::Input | - spirv::StorageClass::Output => continue, - spirv::StorageClass::Uniform | - spirv::StorageClass::UniformConstant => "constant", + spirv::StorageClass::Input | spirv::StorageClass::Output => continue, + spirv::StorageClass::Uniform | spirv::StorageClass::UniformConstant => { + "constant" + } other => { log::warn!("Unexpected pointer class {:?}", other); "" @@ -760,7 +850,11 @@ impl Writer { crate::ArraySize::Static(length) => length, crate::ArraySize::Dynamic => 1, }; - write!(self.out, "typedef {} {}[{}]", base_name, name, resolved_size)?; + write!( + self.out, + "typedef {} {}[{}]", + base_name, name, resolved_size + )?; } crate::TypeInner::Struct { ref members } => { writeln!(self.out, "struct {} {{", name)?; @@ -769,7 +863,8 @@ impl Writer { let base_name = module.types[member.ty].name.or_index(member.ty); write!(self.out, "\t{} {}", base_name, name)?; if let Some(ref binding) = member.binding { - let resolved = options.resolve_binding(binding, LocationMode::Intermediate)?; + let resolved = + options.resolve_binding(binding, LocationMode::Intermediate)?; resolved.try_fmt_decorated(&mut self.out, "")?; } writeln!(self.out, ";")?; @@ -790,7 +885,9 @@ impl Writer { return Err(Error::InvalidImageFlags(flags)); } "sample" - } else if flags.contains(crate::ImageFlags::CAN_LOAD | crate::ImageFlags::CAN_STORE) { + } else if flags + .contains(crate::ImageFlags::CAN_LOAD | crate::ImageFlags::CAN_STORE) + { "read_write" } else if flags.contains(crate::ImageFlags::CAN_STORE) { "write" @@ -799,7 +896,11 @@ impl Writer { } else { return Err(Error::InvalidImageFlags(flags)); }; - write!(self.out, "typedef texture{}<{}, access::{}> {}", dim, base_name, access, name)?; + write!( + self.out, + "typedef texture{}<{}, access::{}> {}", + dim, base_name, access, name + )?; } crate::TypeInner::Sampler => { write!(self.out, "typedef sampler {}", name)?; @@ -820,7 +921,7 @@ impl Writer { match var.class { spirv::StorageClass::Input => { if let Some(crate::Binding::Location(_)) = var.binding { - continue + continue; } } spirv::StorageClass::Output => continue, @@ -846,32 +947,52 @@ impl Writer { // make dedicated input/output structs if let Some(em) = exec_model { if let Some(return_type) = fun.return_type { - return Err(Error::ExecutionModelReturnType(em, return_type)) + return Err(Error::ExecutionModelReturnType(em, return_type)); } let (em_str, in_mode, out_mode) = match em { - spirv::ExecutionModel::Vertex => ("vertex", LocationMode::VertexInput, LocationMode::Intermediate), - spirv::ExecutionModel::Fragment => ("fragment", LocationMode::Intermediate, LocationMode::FragmentOutput), - spirv::ExecutionModel::GLCompute => ("kernel", LocationMode::Uniform, LocationMode::Uniform), + spirv::ExecutionModel::Vertex => ( + "vertex", + LocationMode::VertexInput, + LocationMode::Intermediate, + ), + spirv::ExecutionModel::Fragment => ( + "fragment", + LocationMode::Intermediate, + LocationMode::FragmentOutput, + ), + spirv::ExecutionModel::GLCompute => { + ("kernel", LocationMode::Uniform, LocationMode::Uniform) + } _ => return Err(Error::UnsupportedExecutionModel(em)), }; let location_input_name = fun.name.or_index(InputStructIndex(fun_handle)); if em != spirv::ExecutionModel::GLCompute { writeln!(self.out, "struct {} {{", location_input_name)?; - for ((handle, var), &usage) in module.global_variables.iter().zip(&fun.global_usage) { - if var.class != spirv::StorageClass::Input || !usage.contains(crate::GlobalUse::LOAD) { - continue + for ((handle, var), &usage) in + module.global_variables.iter().zip(&fun.global_usage) + { + if var.class != spirv::StorageClass::Input + || !usage.contains(crate::GlobalUse::LOAD) + { + continue; } // if it's a struct, lift all the built-in contents up to the root let mut ty_handle = var.ty; if GLOBAL_POINTERS { - if let crate::TypeInner::Pointer { base, .. } = module.types[var.ty].inner { + if let crate::TypeInner::Pointer { base, .. } = + module.types[var.ty].inner + { ty_handle = base; } } - if let crate::TypeInner::Struct { ref members } = module.types[ty_handle].inner { + if let crate::TypeInner::Struct { ref members } = + module.types[ty_handle].inner + { for (index, member) in members.iter().enumerate() { - if let Some(ref binding@crate::Binding::Location(_)) = member.binding { + if let Some(ref binding @ crate::Binding::Location(_)) = + member.binding + { let name = member.name.or_index(MemberIndex(index)); let ty_name = module.types[member.ty].name.or_index(member.ty); let resolved = options.resolve_binding(binding, in_mode)?; @@ -879,8 +1000,13 @@ impl Writer { resolved.try_fmt_decorated(&mut self.out, ";\n")?; } } - } else if let Some(ref binding@crate::Binding::Location(_)) = var.binding { - let tyvar = TypedGlobalVariable { module, handle, usage: crate::GlobalUse::empty() }; + } else if let Some(ref binding @ crate::Binding::Location(_)) = var.binding + { + let tyvar = TypedGlobalVariable { + module, + handle, + usage: crate::GlobalUse::empty(), + }; let resolved = options.resolve_binding(binding, in_mode)?; write!(self.out, "\t")?; @@ -890,22 +1016,31 @@ impl Writer { } writeln!(self.out, "}};")?; writeln!(self.out, "struct {} {{", output_name)?; - for ((handle, var), &usage) in module.global_variables.iter().zip(&fun.global_usage) { - if var.class != spirv::StorageClass::Output || !usage.contains(crate::GlobalUse::STORE) { - continue + for ((handle, var), &usage) in + module.global_variables.iter().zip(&fun.global_usage) + { + if var.class != spirv::StorageClass::Output + || !usage.contains(crate::GlobalUse::STORE) + { + continue; } // if it's a struct, lift all the built-in contents up to the root let mut ty_handle = var.ty; if GLOBAL_POINTERS { - if let crate::TypeInner::Pointer { base, .. } = module.types[var.ty].inner { + if let crate::TypeInner::Pointer { base, .. } = + module.types[var.ty].inner + { ty_handle = base; } } - if let crate::TypeInner::Struct { ref members } = module.types[ty_handle].inner { + if let crate::TypeInner::Struct { ref members } = + module.types[ty_handle].inner + { for (index, member) in members.iter().enumerate() { let name = member.name.or_index(MemberIndex(index)); let ty_name = module.types[member.ty].name.or_index(member.ty); - let binding = member.binding + let binding = member + .binding .as_ref() .ok_or(Error::MissingBinding(handle))?; let resolved = options.resolve_binding(binding, out_mode)?; @@ -913,7 +1048,11 @@ impl Writer { resolved.try_fmt_decorated(&mut self.out, ";\n")?; } } else { - let tyvar = TypedGlobalVariable { module, handle, usage: crate::GlobalUse::empty() }; + let tyvar = TypedGlobalVariable { + module, + handle, + usage: crate::GlobalUse::empty(), + }; write!(self.out, "\t")?; tyvar.try_fmt(&mut self.out)?; if let Some(ref binding) = var.binding { @@ -926,31 +1065,46 @@ impl Writer { writeln!(self.out, "}};")?; writeln!(self.out, "{} {} {}(", em_str, output_name, fun_name)?; let separator = separate(last_used_global.is_none()); - writeln!(self.out, "\t{} {} [[stage_in]]{}", - location_input_name, LOCATION_INPUT_STRUCT_NAME, separator)?; + writeln!( + self.out, + "\t{} {} [[stage_in]]{}", + location_input_name, LOCATION_INPUT_STRUCT_NAME, separator + )?; } else { writeln!(self.out, "{} void {}(", em_str, fun_name)?; } - for ((handle, var), &usage) in module.global_variables.iter().zip(&fun.global_usage) { + for ((handle, var), &usage) in module.global_variables.iter().zip(&fun.global_usage) + { if usage.is_empty() || var.class == spirv::StorageClass::Output { - continue + continue; } if var.class == spirv::StorageClass::Input { if let Some(crate::Binding::Location(_)) = var.binding { // location inputs are put into a separate struct - continue + continue; } } let loc_mode = match (em, var.class) { - (spirv::ExecutionModel::Vertex, spirv::StorageClass::Input) => LocationMode::VertexInput, - (spirv::ExecutionModel::Vertex, spirv::StorageClass::Output) | - (spirv::ExecutionModel::Fragment, spirv::StorageClass::Input) => LocationMode::Intermediate, - (spirv::ExecutionModel::Fragment, spirv::StorageClass::Output) => LocationMode::FragmentOutput, + (spirv::ExecutionModel::Vertex, spirv::StorageClass::Input) => { + LocationMode::VertexInput + } + (spirv::ExecutionModel::Vertex, spirv::StorageClass::Output) + | (spirv::ExecutionModel::Fragment, spirv::StorageClass::Input) => { + LocationMode::Intermediate + } + (spirv::ExecutionModel::Fragment, spirv::StorageClass::Output) => { + LocationMode::FragmentOutput + } _ => LocationMode::Uniform, }; - let resolved = options.resolve_binding(var.binding.as_ref().unwrap(), loc_mode)?; - let tyvar = TypedGlobalVariable { module, handle, usage }; + let resolved = + options.resolve_binding(var.binding.as_ref().unwrap(), loc_mode)?; + let tyvar = TypedGlobalVariable { + module, + handle, + usage, + }; let separator = separate(last_used_global == Some(handle)); write!(self.out, "\t")?; tyvar.try_fmt(&mut self.out)?; @@ -962,14 +1116,19 @@ impl Writer { Some(type_id) => module.types[type_id].name.or_index(type_id), None => Name { class: "", - source: NameSource::Custom { name: "void", prefix: false }, + source: NameSource::Custom { + name: "void", + prefix: false, + }, }, }; writeln!(self.out, "{} {}(", result_type_name, fun_name)?; for (index, &ty) in fun.parameter_types.iter().enumerate() { let name = Name::from(ParameterIndex(index)); let member_type_name = module.types[ty].name.or_index(ty); - let separator = separate(index + 1 == fun.parameter_types.len() && last_used_global.is_none()); + let separator = separate( + index + 1 == fun.parameter_types.len() && last_used_global.is_none(), + ); writeln!(self.out, "\t{} {}{}", member_type_name, name, separator)?; } } @@ -977,16 +1136,20 @@ impl Writer { // write down function body let has_output = match exec_model { - Some(spirv::ExecutionModel::Vertex) | - Some(spirv::ExecutionModel::Fragment) => { + Some(spirv::ExecutionModel::Vertex) | Some(spirv::ExecutionModel::Fragment) => { writeln!(self.out, "\t{} {};", output_name, OUTPUT_STRUCT_NAME)?; true } - _ => false + _ => false, }; for (local_handle, local) in fun.local_variables.iter() { let ty_name = module.types[local.ty].name.or_index(local.ty); - write!(self.out, "\t{} {}", ty_name, local.name.or_index(local_handle))?; + write!( + self.out, + "\t{} {}", + ty_name, + local.name.or_index(local_handle) + )?; if let Some(value) = local.init { write!(self.out, " = ")?; self.put_expression(value, fun, module)?; diff --git a/src/front/spirv.rs b/src/front/spirv.rs index 142d00576e..1ebd1b1f06 100644 --- a/src/front/spirv.rs +++ b/src/front/spirv.rs @@ -18,14 +18,9 @@ use crate::{ use num_traits::cast::FromPrimitive; use std::convert::TryInto; -pub const SUPPORTED_CAPABILITIES: &[spirv::Capability] = &[ - spirv::Capability::Shader, -]; -pub const SUPPORTED_EXTENSIONS: &[&str] = &[ -]; -pub const SUPPORTED_EXT_SETS: &[&str] = &[ - "GLSL.std.450", -]; +pub const SUPPORTED_CAPABILITIES: &[spirv::Capability] = &[spirv::Capability::Shader]; +pub const SUPPORTED_EXTENSIONS: &[&str] = &[]; +pub const SUPPORTED_EXT_SETS: &[&str] = &["GLSL.std.450"]; #[derive(Debug)] pub enum Error { @@ -265,7 +260,7 @@ impl> Parser { Ok(Instruction { op, wc }) } - fn next_string(&mut self, mut count: u16) -> Result<(String, u16), Error>{ + fn next_string(&mut self, mut count: u16) -> Result<(String, u16), Error> { self.temp_bytes.clear(); loop { if count == 0 { @@ -273,10 +268,10 @@ impl> Parser { } count -= 1; let chars = self.next()?.to_le_bytes(); - let pos = chars.iter().position(|&c| c == 0).unwrap_or(4); - self.temp_bytes.extend_from_slice(&chars[.. pos]); + let pos = chars.iter().position(|&c| c == 0).unwrap_or(4); + self.temp_bytes.extend_from_slice(&chars[..pos]); if pos < 4 { - break + break; } } std::str::from_utf8(&self.temp_bytes) @@ -317,7 +312,7 @@ impl> Parser { } other => { log::warn!("Unknown decoration {:?}", other); - for _ in base_words + 1 .. inst.wc { + for _ in base_words + 1..inst.wc { let _var = self.next()?; } } @@ -354,14 +349,20 @@ impl> Parser { type_id: ptr_type.base_id.unwrap(), } }; - for _ in 4 .. inst.wc { + for _ in 4..inst.wc { 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_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, .. } => (), + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Uint, + .. + } + | crate::TypeInner::Scalar { + kind: crate::ScalarKind::Sint, + .. + } => (), _ => return Err(Error::UnsupportedType(index_type_handle)), } log::trace!("\t\t\tlooking up type {:?}", acex.type_id); @@ -373,41 +374,50 @@ impl> Parser { 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.handle)), + _ => { + return Err(Error::InvalidAccessIndex( + index_expr.handle, + )) + } } } - _ => return Err(Error::InvalidAccessIndex(index_expr.handle)) + _ => return Err(Error::InvalidAccessIndex(index_expr.handle)), }; AccessExpression { - base_handle: fun.expressions.append(crate::Expression::AccessIndex { - base: acex.base_handle, - index, - }), - type_id: *self.lookup_member_type_id + base_handle: fun.expressions.append( + crate::Expression::AccessIndex { + base: acex.base_handle, + index, + }, + ), + type_id: *self + .lookup_member_type_id .get(&(acex.type_id, index)) .ok_or(Error::InvalidAccessType(acex.type_id))?, } } - crate::TypeInner::Array { .. } | - crate::TypeInner::Vector { .. } | - crate::TypeInner::Matrix { .. } => { - AccessExpression { - 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))?, - } - } + crate::TypeInner::Array { .. } + | crate::TypeInner::Vector { .. } + | crate::TypeInner::Matrix { .. } => AccessExpression { + 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.handle)), }; } - self.lookup_expression.insert(result_id, LookupExpression { - handle: acex.base_handle, - type_id: result_type_id, - }); + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: acex.base_handle, + type_id: result_type_id, + }, + ); } Op::CompositeExtract => { inst.expect_at_least(4)?; @@ -422,22 +432,20 @@ impl> Parser { type_id: expr.type_id, } }; - for _ in 4 .. inst.wc { + for _ in 4..inst.wc { 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_arena[type_lookup.handle].inner { - crate::TypeInner::Struct { .. } => { - *self.lookup_member_type_id - .get(&(lexp.type_id, index)) - .ok_or(Error::InvalidAccessType(lexp.type_id))? - } - crate::TypeInner::Array { .. } | - crate::TypeInner::Vector { .. } | - crate::TypeInner::Matrix { .. } => { - type_lookup.base_id - .ok_or(Error::InvalidAccessType(lexp.type_id))? - } + crate::TypeInner::Struct { .. } => *self + .lookup_member_type_id + .get(&(lexp.type_id, index)) + .ok_or(Error::InvalidAccessType(lexp.type_id))?, + crate::TypeInner::Array { .. } + | crate::TypeInner::Vector { .. } + | crate::TypeInner::Matrix { .. } => type_lookup + .base_id + .ok_or(Error::InvalidAccessType(lexp.type_id))?, _ => return Err(Error::UnsupportedType(type_lookup.handle)), }; lexp = LookupExpression { @@ -449,17 +457,20 @@ impl> Parser { }; } - self.lookup_expression.insert(result_id, LookupExpression { - handle: lexp.handle, - type_id: result_type_id, - }); + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: lexp.handle, + type_id: result_type_id, + }, + ); } Op::CompositeConstruct => { inst.expect_at_least(3)?; let result_type_id = self.next()?; let id = self.next()?; - let mut components = Vec::with_capacity(inst.wc as usize - 2); - for _ in 3 .. inst.wc { + let mut components = Vec::with_capacity(inst.wc as usize - 2); + for _ in 3..inst.wc { let comp_id = self.next()?; log::trace!("\t\t\tlooking up expr {:?}", comp_id); let lexp = self.lookup_expression.lookup(comp_id)?; @@ -469,10 +480,13 @@ impl> Parser { ty: self.lookup_type.lookup(result_type_id)?.handle, components, }; - self.lookup_expression.insert(id, LookupExpression { - handle: fun.expressions.append(expr), - type_id: result_type_id, - }); + self.lookup_expression.insert( + id, + LookupExpression { + handle: fun.expressions.append(expr), + type_id: result_type_id, + }, + ); } Op::Load => { inst.expect_at_least(4)?; @@ -495,10 +509,13 @@ impl> Parser { let expr = crate::Expression::Load { pointer: base_expr.handle, }; - self.lookup_expression.insert(result_id, LookupExpression { - handle: fun.expressions.append(expr), - type_id: result_type_id, - }); + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: fun.expressions.append(expr), + type_id: result_type_id, + }, + ); } Op::Store => { inst.expect_at_least(3)?; @@ -526,14 +543,18 @@ impl> Parser { Op::Return => { inst.expect(1)?; fun.body.push(crate::Statement::Return { value: None }); - break + break; } Op::VectorTimesScalar => { 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_arena[result_type_loookup.handle].inner { - crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } => (size, width), + crate::TypeInner::Vector { + size, + kind: crate::ScalarKind::Float, + width, + } => (size, width), _ => return Err(Error::UnsupportedType(result_type_loookup.handle)), }; let result_id = self.next()?; @@ -542,13 +563,20 @@ impl> Parser { let vector_lexp = self.lookup_expression.lookup(vector_id)?; let vector_type_lookup = self.lookup_type.lookup(vector_lexp.type_id)?; match type_arena[vector_type_lookup.handle].inner { - crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } if size == res_size && width == res_width => (), + crate::TypeInner::Vector { + size, + kind: crate::ScalarKind::Float, + width, + } if size == res_size && width == res_width => (), _ => 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_arena[scalar_type_lookup.handle].inner { - crate::TypeInner::Scalar { kind: crate::ScalarKind::Float, width } if width == res_width => (), + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + width, + } if width == res_width => (), _ => return Err(Error::UnsupportedType(scalar_type_lookup.handle)), }; let expr = crate::Expression::Binary { @@ -556,17 +584,24 @@ impl> Parser { left: vector_lexp.handle, right: scalar_lexp.handle, }; - self.lookup_expression.insert(result_id, LookupExpression { - handle: fun.expressions.append(expr), - type_id: result_type_id, - }); + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: fun.expressions.append(expr), + type_id: result_type_id, + }, + ); } Op::MatrixTimesVector => { 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_arena[result_type_loookup.handle].inner { - crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } => (size, width), + crate::TypeInner::Vector { + size, + kind: crate::ScalarKind::Float, + width, + } => (size, width), _ => return Err(Error::UnsupportedType(result_type_loookup.handle)), }; let result_id = self.next()?; @@ -575,13 +610,22 @@ impl> Parser { 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_arena[matrix_type_lookup.handle].inner { - crate::TypeInner::Matrix { columns, rows, kind: crate::ScalarKind::Float, width } if rows == res_size && width == res_width => columns, + 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.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_arena[vector_type_lookup.handle].inner { - crate::TypeInner::Vector { size, kind: crate::ScalarKind::Float, width } if size == columns && width == res_width => (), + crate::TypeInner::Vector { + size, + kind: crate::ScalarKind::Float, + width, + } if size == columns && width == res_width => (), _ => return Err(Error::UnsupportedType(vector_type_lookup.handle)), }; let expr = crate::Expression::Binary { @@ -589,10 +633,13 @@ impl> Parser { left: matrix_lexp.handle, right: vector_lexp.handle, }; - self.lookup_expression.insert(result_id, LookupExpression { - handle: fun.expressions.append(expr), - type_id: result_type_id, - }); + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: fun.expressions.append(expr), + type_id: result_type_id, + }, + ); } Op::SampledImage => { inst.expect(5)?; @@ -603,10 +650,13 @@ impl> Parser { let image_lexp = self.lookup_expression.lookup(image_id)?; 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.handle, - sampler: sampler_lexp.handle, - }); + self.lookup_sampled_image.insert( + result_id, + LookupSampledImage { + image: image_lexp.handle, + sampler: sampler_lexp.handle, + }, + ); } Op::ImageSampleImplicitLod => { inst.expect_at_least(5)?; @@ -618,8 +668,14 @@ impl> Parser { let coord_lexp = self.lookup_expression.lookup(coordinate_id)?; let coord_type_lookup = self.lookup_type.lookup(coord_lexp.type_id)?; match type_arena[coord_type_lookup.handle].inner { - crate::TypeInner::Scalar { kind: crate::ScalarKind::Float, .. } | - crate::TypeInner::Vector { kind: crate::ScalarKind::Float, .. } => (), + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + .. + } + | crate::TypeInner::Vector { + kind: crate::ScalarKind::Float, + .. + } => (), _ => return Err(Error::UnsupportedType(coord_type_lookup.handle)), } //TODO: compare the result type @@ -628,10 +684,13 @@ impl> Parser { sampler: si_lexp.sampler, coordinate: coord_lexp.handle, }; - self.lookup_expression.insert(result_id, LookupExpression { - handle: fun.expressions.append(expr), - type_id: result_type_id, - }); + self.lookup_expression.insert( + result_id, + LookupExpression { + handle: fun.expressions.append(expr), + type_id: result_type_id, + }, + ); } _ => return Err(Error::UnsupportedInstruction(self.state, inst.op)), } @@ -644,17 +703,23 @@ impl> Parser { 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, - handle: expressions.append(crate::Expression::GlobalVariable(var.handle)), - }); + self.lookup_expression.insert( + id, + LookupExpression { + type_id: var.type_id, + 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, - handle: expressions.append(crate::Expression::Constant(con.handle)), - }); + self.lookup_expression.insert( + id, + LookupExpression { + type_id: con.type_id, + handle: expressions.append(crate::Expression::Constant(con.handle)), + }, + ); } // done expressions @@ -806,10 +871,7 @@ impl> Parser { exec_model, name, function_id, - variable_ids: self.data - .by_ref() - .take(left as usize) - .collect(), + variable_ids: self.data.by_ref().take(left as usize).collect(), }; entry_points.push(ep); Ok(()) @@ -828,7 +890,7 @@ impl> Parser { fn parse_source(&mut self, inst: Instruction) -> Result<(), Error> { self.switch(ModuleState::Source, inst.op)?; - for _ in 1 .. inst.wc { + for _ in 1..inst.wc { let _ = self.next()?; } Ok(()) @@ -849,10 +911,7 @@ impl> Parser { if left != 0 { return Err(Error::InvalidOperand); } - self.future_decor - .entry(id) - .or_default() - .name = Some(name); + self.future_decor.entry(id).or_default().name = Some(name); Ok(()) } @@ -876,9 +935,7 @@ impl> Parser { self.switch(ModuleState::Annotation, inst.op)?; inst.expect_at_least(3)?; let id = self.next()?; - let mut dec = self.future_decor - .remove(&id) - .unwrap_or_default(); + let mut dec = self.future_decor.remove(&id).unwrap_or_default(); self.next_decoration(inst, 2, &mut dec)?; self.future_decor.insert(id, dec); Ok(()) @@ -889,7 +946,8 @@ impl> Parser { inst.expect_at_least(4)?; let id = self.next()?; let member = self.next()?; - let mut dec = self.future_member_decor + let mut dec = self + .future_member_decor .remove(&(id, member)) .unwrap_or_default(); self.next_decoration(inst, 3, &mut dec)?; @@ -925,15 +983,16 @@ impl> Parser { .try_into() .map_err(|_| Error::InvalidTypeWidth(width))?, }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor - .remove(&id) - .and_then(|dec| dec.name), - inner, - }), - base_id: None, - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: None, + }, + ); Ok(()) } @@ -952,15 +1011,16 @@ impl> Parser { .try_into() .map_err(|_| Error::InvalidTypeWidth(width))?, }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor - .remove(&id) - .and_then(|dec| dec.name), - inner, - }), - base_id: None, - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: None, + }, + ); Ok(()) } @@ -984,15 +1044,16 @@ impl> Parser { kind, width, }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor - .remove(&id) - .and_then(|dec| dec.name), - inner, - }), - base_id: Some(type_id), - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: Some(type_id), + }, + ); Ok(()) } @@ -1016,15 +1077,16 @@ impl> Parser { }, _ => return Err(Error::InvalidInnerType(vector_type_id)), }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor - .remove(&id) - .and_then(|dec| dec.name), - inner, - }), - base_id: Some(vector_type_id), - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: Some(vector_type_id), + }, + ); Ok(()) } @@ -1033,14 +1095,14 @@ impl> Parser { inst.expect_at_least(3)?; let id = self.next()?; let return_type_id = self.next()?; - let parameter_type_ids = self.data - .by_ref() - .take(inst.wc as usize - 3) - .collect(); - self.lookup_function_type.insert(id, LookupFunctionType { - parameter_type_ids, - return_type_id, - }); + let parameter_type_ids = self.data.by_ref().take(inst.wc as usize - 3).collect(); + self.lookup_function_type.insert( + id, + LookupFunctionType { + parameter_type_ids, + return_type_id, + }, + ); Ok(()) } @@ -1058,15 +1120,16 @@ impl> Parser { base: self.lookup_type.lookup(type_id)?.handle, class: map_storage_class(storage)?, }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor - .remove(&id) - .and_then(|dec| dec.name), - inner, - }), - base_id: Some(type_id), - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: Some(type_id), + }, + ); Ok(()) } @@ -1084,15 +1147,16 @@ impl> Parser { base: self.lookup_type.lookup(type_id)?.handle, size: crate::ArraySize::Static(length), }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor - .remove(&id) - .and_then(|dec| dec.name), - inner, - }), - base_id: Some(type_id), - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: Some(type_id), + }, + ); Ok(()) } @@ -1109,13 +1173,16 @@ impl> Parser { base: self.lookup_type.lookup(type_id)?.handle, size: crate::ArraySize::Dynamic, }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - inner, - }), - base_id: Some(type_id), - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: Some(type_id), + }, + ); Ok(()) } @@ -1128,11 +1195,12 @@ impl> Parser { inst.expect_at_least(2)?; let id = self.next()?; let mut members = Vec::with_capacity(inst.wc as usize - 2); - for i in 0 .. u32::from(inst.wc) - 2 { + for i in 0..u32::from(inst.wc) - 2 { let type_id = self.next()?; 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 + let decor = self + .future_member_decor .remove(&(id, i)) .unwrap_or_default(); let binding = decor.get_binding(); @@ -1142,16 +1210,17 @@ impl> Parser { ty, }); } - let inner = crate::TypeInner::Struct { - members - }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: self.future_decor.remove(&id).and_then(|dec| dec.name), - inner, - }), - base_id: None, - }); + let inner = crate::TypeInner::Struct { members }; + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + inner, + }), + base_id: None, + }, + ); Ok(()) } @@ -1190,22 +1259,23 @@ impl> Parser { } }; - let decor = self.future_decor - .remove(&id) - .unwrap_or_default(); + let decor = self.future_decor.remove(&id).unwrap_or_default(); let inner = crate::TypeInner::Image { base: self.lookup_type.lookup(sample_type_id)?.handle, dim: spirv::Dim::from_u32(dim).ok_or(Error::UnsupportedDim(dim))?, flags, }; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: decor.name, - inner, - }), - base_id: Some(sample_type_id), - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: decor.name, + inner, + }), + base_id: Some(sample_type_id), + }, + ); Ok(()) } @@ -1214,10 +1284,13 @@ impl> Parser { inst.expect(3)?; let id = self.next()?; let image_id = self.next()?; - self.lookup_type.insert(id, LookupType { - handle: self.lookup_type.lookup(image_id)?.handle, - base_id: Some(image_id), - }); + self.lookup_type.insert( + id, + LookupType { + handle: self.lookup_type.lookup(image_id)?.handle, + base_id: Some(image_id), + }, + ); Ok(()) } @@ -1229,17 +1302,18 @@ impl> Parser { self.switch(ModuleState::Type, inst.op)?; inst.expect(2)?; let id = self.next()?; - let decor = self.future_decor - .remove(&id) - .unwrap_or_default(); + let decor = self.future_decor.remove(&id).unwrap_or_default(); let inner = crate::TypeInner::Sampler; - self.lookup_type.insert(id, LookupType { - handle: module.types.append(crate::Type { - name: decor.name, - inner, - }), - base_id: None, - }); + self.lookup_type.insert( + id, + LookupType { + handle: module.types.append(crate::Type { + name: decor.name, + inner, + }), + base_id: None, + }, + ); Ok(()) } @@ -1255,7 +1329,10 @@ impl> Parser { let type_lookup = self.lookup_type.lookup(type_id)?; let ty = type_lookup.handle; let inner = match module.types[type_lookup.handle].inner { - crate::TypeInner::Scalar { kind: crate::ScalarKind::Uint, width } => { + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Uint, + width, + } => { let low = self.next()?; let high = if width > 32 { inst.expect(4)?; @@ -1265,7 +1342,10 @@ impl> Parser { }; crate::ConstantInner::Uint((u64::from(high) << 32) | u64::from(low)) } - crate::TypeInner::Scalar { kind: crate::ScalarKind::Sint, width } => { + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Sint, + width, + } => { use std::cmp::Ordering; let low = self.next()?; let high = match width.cmp(&32) { @@ -1273,12 +1353,15 @@ impl> Parser { Ordering::Greater => { inst.expect(4)?; self.next()? - }, - Ordering::Equal => !0 + } + Ordering::Equal => !0, }; crate::ConstantInner::Sint(((u64::from(high) << 32) | u64::from(low)) as i64) } - crate::TypeInner::Scalar { kind: crate::ScalarKind::Float, width } => { + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + width, + } => { let low = self.next()?; let extended = match width { 32 => f64::from(f32::from_bits(low)), @@ -1291,19 +1374,20 @@ impl> Parser { }; crate::ConstantInner::Float(extended) } - _ => return Err(Error::UnsupportedType(type_lookup.handle)) + _ => return Err(Error::UnsupportedType(type_lookup.handle)), }; - self.lookup_constant.insert(id, LookupConstant { - handle: module.constants.append(crate::Constant { - name: self.future_decor - .remove(&id) - .and_then(|dec| dec.name), - specialization: None, //TODO - inner, - ty, - }), - type_id, - }); + self.lookup_constant.insert( + id, + LookupConstant { + handle: module.constants.append(crate::Constant { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + specialization: None, //TODO + inner, + ty, + }), + type_id, + }, + ); Ok(()) } @@ -1328,17 +1412,18 @@ impl> Parser { constituents.push(constant.handle); } - self.lookup_constant.insert(id, LookupConstant { - handle: module.constants.append(crate::Constant { - name: self.future_decor - .remove(&id) - .and_then(|dec|dec.name), - specialization: None, - inner: crate::ConstantInner::Composite(constituents), - ty - }), - type_id - }); + self.lookup_constant.insert( + id, + LookupConstant { + handle: module.constants.append(crate::Constant { + name: self.future_decor.remove(&id).and_then(|dec| dec.name), + specialization: None, + inner: crate::ConstantInner::Composite(constituents), + ty, + }), + type_id, + }, + ); Ok(()) } @@ -1358,38 +1443,39 @@ impl> Parser { let _init = self.next()?; //TODO } let lookup_type = self.lookup_type.lookup(type_id)?; - let dec = self.future_decor + let dec = self + .future_decor .remove(&id) .ok_or(Error::InvalidBinding(id))?; 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 } => { + crate::TypeInner::Pointer { + base, + class: spirv::StorageClass::Input, + } + | crate::TypeInner::Pointer { + base, + class: spirv::StorageClass::Output, + } => { match module.types[base].inner { crate::TypeInner::Struct { ref members } => { // we don't expect binding decoration on I/O structs, // but we do expect them on all of the members for member in members { if member.binding.is_none() { - log::warn!("Struct {:?} member {:?} doesn't have a binding", base, member); + log::warn!( + "Struct {:?} member {:?} doesn't have a binding", + base, + member + ); return Err(Error::InvalidBinding(id)); } } None } - _ => { - Some(dec - .get_binding() - .ok_or(Error::InvalidBinding(id))? - ) - } + _ => Some(dec.get_binding().ok_or(Error::InvalidBinding(id))?), } } - _ => { - Some(dec - .get_binding() - .ok_or(Error::InvalidBinding(id))? - ) - } + _ => Some(dec.get_binding().ok_or(Error::InvalidBinding(id))?), }; let var = crate::GlobalVariable { name: dec.name, @@ -1397,10 +1483,13 @@ impl> Parser { binding, ty: lookup_type.handle, }; - self.lookup_variable.insert(id, LookupVariable { - handle: module.global_variables.append(var), - type_id, - }); + self.lookup_variable.insert( + id, + LookupVariable { + handle: module.global_variables.append(var), + type_id, + }, + ); Ok(()) } @@ -1418,12 +1507,10 @@ impl> Parser { let mut fun = { let ft = self.lookup_function_type.lookup(fun_type)?; if ft.return_type_id != result_type { - return Err(Error::WrongFunctionResultType(result_type)) + return Err(Error::WrongFunctionResultType(result_type)); } crate::Function { - name: self.future_decor - .remove(&fun_id) - .and_then(|dec| dec.name), + name: self.future_decor.remove(&fun_id).and_then(|dec| dec.name), control: spirv::FunctionControl::from_bits(fun_control) .ok_or(Error::UnsupportedFunctionControl(fun_control))?, parameter_types: Vec::with_capacity(ft.parameter_type_ids.len()), @@ -1441,15 +1528,20 @@ impl> Parser { // read parameters for i in 0..fun.parameter_types.capacity() { match self.next_inst()? { - Instruction { op: spirv::Op::FunctionParameter, wc: 3 } => { + Instruction { + op: spirv::Op::FunctionParameter, + wc: 3, + } => { let type_id = self.next()?; let _id = self.next()?; //Note: we redo the lookup in order to work around `self` borrowing - if type_id != self.lookup_function_type - .lookup(fun_type)? - .parameter_type_ids[i] + if type_id + != self + .lookup_function_type + .lookup(fun_type)? + .parameter_type_ids[i] { - return Err(Error::WrongFunctionParameterType(type_id)) + return Err(Error::WrongFunctionParameterType(type_id)); } let ty = self.lookup_type.lookup(type_id)?.handle; fun.parameter_types.push(ty); @@ -1469,13 +1561,14 @@ impl> Parser { } spirv::Op::FunctionEnd => { fun_inst.expect(1)?; - break + break; } - _ => return Err(Error::UnsupportedInstruction(self.state, fun_inst.op)) + _ => return Err(Error::UnsupportedInstruction(self.state, fun_inst.op)), } } // done - fun.global_usage = crate::GlobalUse::scan(&fun.expressions, &fun.body, &module.global_variables); + fun.global_usage = + crate::GlobalUse::scan(&fun.expressions, &fun.body, &module.global_variables); let handle = module.functions.append(fun); self.lookup_function.insert(fun_id, handle); self.lookup_expression.clear(); @@ -1501,14 +1594,11 @@ mod test { fn parse() { let bin = vec![ // Magic number. Version number: 1.0. - 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, // Generator number: 0. Bound: 0. - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // Reserved word: 0. - 0x00, 0x00, 0x00, 0x00, - // OpMemoryModel. Logical. - 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - // GLSL450. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved word: 0. + 0x00, 0x00, 0x00, 0x00, // OpMemoryModel. Logical. + 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // GLSL450. 0x01, 0x00, 0x00, 0x00, ]; let _ = super::parse_u8_slice(&bin).unwrap(); diff --git a/src/front/wgsl.rs b/src/front/wgsl.rs index 2059a79af6..5e34032ff4 100644 --- a/src/front/wgsl.rs +++ b/src/front/wgsl.rs @@ -1,10 +1,9 @@ use crate::{ arena::{Arena, Handle}, - proc::{Typifier, ResolveError}, + proc::{ResolveError, Typifier}, FastHashMap, }; - #[derive(Debug, PartialEq)] pub enum Token<'a> { Separator(char), @@ -29,7 +28,7 @@ mod lex { fn _consume_str<'a>(input: &'a str, what: &str) -> Option<&'a str> { if input.starts_with(what) { - Some(&input[what.len() ..]) + Some(&input[what.len()..]) } else { None } @@ -56,12 +55,8 @@ mod lex { (Token::Separator(cur), input) } } - ';' | ',' | '.' => { - (Token::Separator(cur), chars.as_str()) - } - '(' | ')' | '{' | '}' => { - (Token::Paren(cur), chars.as_str()) - } + ';' | ',' | '.' => (Token::Separator(cur), chars.as_str()), + '(' | ')' | '{' | '}' => (Token::Paren(cur), chars.as_str()), '<' | '>' => { input = chars.as_str(); let next = chars.next(); @@ -86,19 +81,19 @@ mod lex { (Token::Paren(cur), input) } } - '0' ..= '9' => { - let (number, rest) = consume_any(input, |c| (c>='0' && c<='9' || c=='.')); + '0'..='9' => { + let (number, rest) = consume_any(input, |c| (c >= '0' && c <= '9' || c == '.')); (Token::Number(number), rest) } 'a'..='z' | 'A'..='Z' | '_' => { - let (word, rest) = consume_any(input, |c| c.is_alphanumeric() || c=='_'); + let (word, rest) = consume_any(input, |c| c.is_alphanumeric() || c == '_'); (Token::Word(word), rest) } '"' => { let base = chars.as_str(); let len = match chars.position(|c| c == '"') { Some(pos) => pos, - None => return (Token::UnterminatedString, chars.as_str()) + None => return (Token::UnterminatedString, chars.as_str()), }; (Token::String(&base[..len]), chars.as_str()) } @@ -110,9 +105,7 @@ mod lex { (Token::Operation(cur), input) } } - '+' | '*' | '/' | '%' | '^' => { - (Token::Operation(cur), chars.as_str()) - } + '+' | '*' | '/' | '%' | '^' => (Token::Operation(cur), chars.as_str()), '!' => { if chars.next() == Some('=') { (Token::LogicalOperation(cur), chars.as_str()) @@ -120,7 +113,7 @@ mod lex { (Token::Operation(cur), input) } } - '=' | '&' | '|' => { + '=' | '&' | '|' => { input = chars.as_str(); if chars.next() == Some(cur) { (Token::LogicalOperation(cur), chars.as_str()) @@ -128,13 +121,11 @@ mod lex { (Token::Operation(cur), input) } } - '#' => { - match chars.position(|c| c == '\n' || c == '\r') { - Some(_) => consume_token(chars.as_str()), - None => (Token::End, chars.as_str()) - } - } - _ => (Token::Unknown(cur), chars.as_str()) + '#' => match chars.position(|c| c == '\n' || c == '\r') { + Some(_) => consume_token(chars.as_str()), + None => (Token::End, chars.as_str()), + }, + _ => (Token::Unknown(cur), chars.as_str()), } } } @@ -254,9 +245,7 @@ trait StringValueLookup<'a> { impl<'a> StringValueLookup<'a> for FastHashMap<&'a str, Handle> { type Value = Handle; fn lookup(&self, key: &'a str) -> Result> { - self.get(key) - .cloned() - .ok_or(Error::UnknownIdent(key)) + self.get(key).cloned().ok_or(Error::UnknownIdent(key)) } } @@ -319,9 +308,21 @@ impl<'a> ExpressionContext<'a, '_, '_> { } } - fn resolve_type(&mut self, handle: Handle) -> Result, Error<'a>> { + fn resolve_type( + &mut self, + handle: Handle, + ) -> Result, Error<'a>> { self.typifier - .resolve(handle, self.expressions, self.types, self.constants, self.global_vars, self.local_vars,&Arena::new(),&FastHashMap::default()) + .resolve( + handle, + self.expressions, + self.types, + self.constants, + self.global_vars, + self.local_vars, + &Arena::new(), + &FastHashMap::default(), + ) .map_err(Error::InvalidResolve) } @@ -329,7 +330,10 @@ impl<'a> ExpressionContext<'a, '_, '_> { &mut self, lexer: &mut Lexer<'a>, classifier: impl Fn(Token<'a>) -> Option, - mut parser: impl FnMut(&mut Lexer<'a>, ExpressionContext<'a, '_, '_>) -> Result, Error<'a>>, + mut parser: impl FnMut( + &mut Lexer<'a>, + ExpressionContext<'a, '_, '_>, + ) -> Result, Error<'a>>, ) -> Result, Error<'a>> { let mut left = parser(lexer, self.reborrow())?; while let Some(op) = classifier(lexer.peek()) { @@ -345,7 +349,6 @@ impl<'a> ExpressionContext<'a, '_, '_> { } } - #[derive(Clone, Debug, PartialEq)] pub enum Scope { Decoration, @@ -411,16 +414,16 @@ impl Parser { } } - fn get_constant_inner(word: &str) -> Result<(crate::ConstantInner, crate::ScalarKind), Error<'_>> { + fn get_constant_inner( + word: &str, + ) -> Result<(crate::ConstantInner, crate::ScalarKind), Error<'_>> { if word.contains('.') { - word - .parse() - .map(|f|(crate::ConstantInner::Float(f), crate::ScalarKind::Float)) + word.parse() + .map(|f| (crate::ConstantInner::Float(f), crate::ScalarKind::Float)) .map_err(|err| Error::BadFloat(word, err)) } else { - word - .parse() - .map(|i|(crate::ConstantInner::Sint(i), crate::ScalarKind::Sint)) + word.parse() + .map(|i| (crate::ConstantInner::Sint(i), crate::ScalarKind::Sint)) .map_err(|err| Error::BadInteger(word, err)) } } @@ -484,7 +487,7 @@ impl Parser { width: 1, }, ctx.types, - ) + ), }); crate::Expression::Constant(handle) } @@ -499,7 +502,7 @@ impl Parser { width: 1, }, ctx.types, - ) + ), }); crate::Expression::Constant(handle) } @@ -512,7 +515,7 @@ impl Parser { ty: Typifier::deduce_type_handle( crate::TypeInner::Scalar { kind, width: 32 }, ctx.types, - ) + ), }); crate::Expression::Constant(handle) } @@ -576,24 +579,31 @@ impl Parser { let index = members .iter() .position(|m| m.name.as_deref() == Some(name)) - .ok_or(Error::BadAccessor(name))? as u32; + .ok_or(Error::BadAccessor(name))? + as u32; crate::Expression::AccessIndex { base: handle, index, } } - crate::TypeInner::Vector { size, kind, width } | - crate::TypeInner::Matrix { columns: size, kind, width, .. } => { + crate::TypeInner::Vector { size, kind, width } + | crate::TypeInner::Matrix { + columns: size, + kind, + width, + .. + } => { const MEMBERS: [char; 4] = ['x', 'y', 'z', 'w']; if name.len() > 1 { let mut components = Vec::with_capacity(name.len()); for ch in name.chars() { let expr = crate::Expression::AccessIndex { base: handle, - index: MEMBERS[.. size as usize] + index: MEMBERS[..size as usize] .iter() .position(|&m| m == ch) - .ok_or(Error::BadAccessor(name))? as u32, + .ok_or(Error::BadAccessor(name))? + as u32, }; components.push(ctx.expressions.append(expr)); } @@ -603,8 +613,15 @@ impl Parser { 4 => crate::VectorSize::Quad, _ => return Err(Error::BadAccessor(name)), }; - let inner = if let crate::TypeInner::Matrix { rows, .. } = base_type.inner { - crate::TypeInner::Matrix { columns: size, rows, kind, width } + let inner = if let crate::TypeInner::Matrix { rows, .. } = + base_type.inner + { + crate::TypeInner::Matrix { + columns: size, + rows, + kind, + width, + } } else { crate::TypeInner::Vector { size, kind, width } }; @@ -614,10 +631,11 @@ impl Parser { } } else { let ch = name.chars().next().unwrap(); - let index = MEMBERS[.. size as usize] + let index = MEMBERS[..size as usize] .iter() .position(|&m| m == ch) - .ok_or(Error::BadAccessor(name))? as u32; + .ok_or(Error::BadAccessor(name))? + as u32; crate::Expression::AccessIndex { base: handle, index, @@ -670,35 +688,25 @@ impl Parser { self.scopes.push(Scope::SingularExpr); let backup = lexer.clone(); let expression = match lexer.next() { - Token::Operation('-') => { - Some(crate::Expression::Unary { - op: crate::UnaryOperator::Negate, - expr: self.parse_singular_expression(lexer, ctx.reborrow())?, - }) - } - Token::Operation('!') => { - Some(crate::Expression::Unary { - op: crate::UnaryOperator::Not, - expr: self.parse_singular_expression(lexer, ctx.reborrow())?, - }) - } + Token::Operation('-') => Some(crate::Expression::Unary { + op: crate::UnaryOperator::Negate, + expr: self.parse_singular_expression(lexer, ctx.reborrow())?, + }), + Token::Operation('!') => Some(crate::Expression::Unary { + op: crate::UnaryOperator::Not, + expr: self.parse_singular_expression(lexer, ctx.reborrow())?, + }), Token::Word(word) => { if let Some(fun) = get_intrinsic(word) { lexer.expect(Token::Paren('('))?; let argument = self.parse_primary_expression(lexer, ctx.reborrow())?; lexer.expect(Token::Paren(')'))?; - Some(crate::Expression::Intrinsic { - fun, - argument, - }) + Some(crate::Expression::Intrinsic { fun, argument }) } else if let Some(axis) = get_derivative(word) { lexer.expect(Token::Paren('('))?; let expr = self.parse_primary_expression(lexer, ctx.reborrow())?; lexer.expect(Token::Paren(')'))?; - Some(crate::Expression::Derivative { - axis, - expr, - }) + Some(crate::Expression::Derivative { axis, expr }) } else if word == "dot" { lexer.expect(Token::Paren('('))?; let a = self.parse_primary_expression(lexer, ctx.reborrow())?; @@ -743,49 +751,73 @@ impl Parser { |token| match token { Token::LogicalOperation('=') => Some(crate::BinaryOperator::Equal), Token::LogicalOperation('!') => Some(crate::BinaryOperator::NotEqual), - _ => None + _ => None, }, // relational_expression - |lexer, mut context| context.parse_binary_op( - lexer, - |token| match token { - Token::Paren('<') => Some(crate::BinaryOperator::Less), - Token::Paren('>') => Some(crate::BinaryOperator::Greater), - Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual), - Token::LogicalOperation('>') => Some(crate::BinaryOperator::GreaterEqual), - _ => None, - }, - // shift_expression - |lexer, mut context| context.parse_binary_op( + |lexer, mut context| { + context.parse_binary_op( lexer, |token| match token { - Token::ShiftOperation('<') => Some(crate::BinaryOperator::ShiftLeftLogical), - Token::ShiftOperation('>') => Some(crate::BinaryOperator::ShiftRightLogical), - Token::ArithmeticShiftOperation('>') => Some(crate::BinaryOperator::ShiftRightArithmetic), + Token::Paren('<') => Some(crate::BinaryOperator::Less), + Token::Paren('>') => Some(crate::BinaryOperator::Greater), + Token::LogicalOperation('<') => Some(crate::BinaryOperator::LessEqual), + Token::LogicalOperation('>') => Some(crate::BinaryOperator::GreaterEqual), _ => None, }, - // additive_expression - |lexer, mut context| context.parse_binary_op( - lexer, - |token| match token { - Token::Operation('+') => Some(crate::BinaryOperator::Add), - Token::Operation('-') => Some(crate::BinaryOperator::Subtract), - _ => None, - }, - // multiplicative_expression - |lexer, mut context| context.parse_binary_op( + // shift_expression + |lexer, mut context| { + context.parse_binary_op( lexer, |token| match token { - Token::Operation('*') => Some(crate::BinaryOperator::Multiply), - Token::Operation('/') => Some(crate::BinaryOperator::Divide), - Token::Operation('%') => Some(crate::BinaryOperator::Modulo), + Token::ShiftOperation('<') => { + Some(crate::BinaryOperator::ShiftLeftLogical) + } + Token::ShiftOperation('>') => { + Some(crate::BinaryOperator::ShiftRightLogical) + } + Token::ArithmeticShiftOperation('>') => { + Some(crate::BinaryOperator::ShiftRightArithmetic) + } _ => None, }, - |lexer, context| self.parse_singular_expression(lexer, context), - ), - ), - ), - ), + // additive_expression + |lexer, mut context| { + context.parse_binary_op( + lexer, + |token| match token { + Token::Operation('+') => Some(crate::BinaryOperator::Add), + Token::Operation('-') => { + Some(crate::BinaryOperator::Subtract) + } + _ => None, + }, + // multiplicative_expression + |lexer, mut context| { + context.parse_binary_op( + lexer, + |token| match token { + Token::Operation('*') => { + Some(crate::BinaryOperator::Multiply) + } + Token::Operation('/') => { + Some(crate::BinaryOperator::Divide) + } + Token::Operation('%') => { + Some(crate::BinaryOperator::Modulo) + } + _ => None, + }, + |lexer, context| { + self.parse_singular_expression(lexer, context) + }, + ) + }, + ) + }, + ) + }, + ) + }, ) } @@ -803,38 +835,52 @@ impl Parser { _ => None, }, // logical_and_expression - |lexer, mut context| context.parse_binary_op( - lexer, - |token| match token { - Token::LogicalOperation('&') => Some(crate::BinaryOperator::LogicalAnd), - _ => None, - }, - // inclusive_or_expression - |lexer, mut context| context.parse_binary_op( + |lexer, mut context| { + context.parse_binary_op( lexer, |token| match token { - Token::Operation('|') => Some(crate::BinaryOperator::InclusiveOr), + Token::LogicalOperation('&') => Some(crate::BinaryOperator::LogicalAnd), _ => None, }, - // exclusive_or_expression - |lexer, mut context| context.parse_binary_op( - lexer, - |token| match token { - Token::Operation('^') => Some(crate::BinaryOperator::ExclusiveOr), - _ => None, - }, - // and_expression - |lexer, mut context| context.parse_binary_op( + // inclusive_or_expression + |lexer, mut context| { + context.parse_binary_op( lexer, |token| match token { - Token::Operation('&') => Some(crate::BinaryOperator::And), + Token::Operation('|') => Some(crate::BinaryOperator::InclusiveOr), _ => None, }, - |lexer, context| self.parse_equality_expression(lexer, context), - ), - ), - ), - ), + // exclusive_or_expression + |lexer, mut context| { + context.parse_binary_op( + lexer, + |token| match token { + Token::Operation('^') => { + Some(crate::BinaryOperator::ExclusiveOr) + } + _ => None, + }, + // and_expression + |lexer, mut context| { + context.parse_binary_op( + lexer, + |token| match token { + Token::Operation('&') => { + Some(crate::BinaryOperator::And) + } + _ => None, + }, + |lexer, context| { + self.parse_equality_expression(lexer, context) + }, + ) + }, + ) + }, + ) + }, + ) + }, )?; self.scopes.pop(); Ok(handle) @@ -927,24 +973,18 @@ impl Parser { ) -> Result, Error<'a>> { self.scopes.push(Scope::TypeDecl); let inner = match lexer.next() { - Token::Word("f32") => { - crate::TypeInner::Scalar { - kind: crate::ScalarKind::Float, - width: 32, - } - } - Token::Word("i32") => { - crate::TypeInner::Scalar { - kind: crate::ScalarKind::Sint, - width: 32, - } - } - Token::Word("u32") => { - crate::TypeInner::Scalar { - kind: crate::ScalarKind::Uint, - width: 32, - } - } + Token::Word("f32") => crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + width: 32, + }, + Token::Word("i32") => crate::TypeInner::Scalar { + kind: crate::ScalarKind::Sint, + width: 32, + }, + Token::Word("u32") => crate::TypeInner::Scalar { + kind: crate::ScalarKind::Uint, + width: 32, + }, Token::Word("vec2") => { let (kind, width) = lexer.next_scalar_generic()?; crate::TypeInner::Vector { @@ -1024,7 +1064,8 @@ impl Parser { } Token::Word(name) => { self.scopes.pop(); - return self.lookup_type + return self + .lookup_type .get(name) .cloned() .ok_or(Error::UnknownType(name)); @@ -1054,7 +1095,8 @@ impl Parser { } let (name, ty) = self.parse_variable_ident_decl(lexer, context.types)?; let init = if lexer.skip(Token::Operation('=')) { - let value = self.parse_general_expression(lexer, context.as_expression())?; + let value = + self.parse_general_expression(lexer, context.as_expression())?; if let crate::Expression::Constant(_) = context.expressions[value] { Init::Uniform(value) } else { @@ -1070,12 +1112,17 @@ impl Parser { init: match init { Init::Uniform(value) => Some(value), _ => None, - } + }, }); - let expr_id = context.expressions.append(crate::Expression::LocalVariable(var_id)); + let expr_id = context + .expressions + .append(crate::Expression::LocalVariable(var_id)); context.lookup_ident.insert(name, expr_id); match init { - Init::Variable(value) => crate::Statement::Store { pointer: expr_id, value }, + Init::Variable(value) => crate::Statement::Store { + pointer: expr_id, + value, + }, _ => crate::Statement::Empty, } } @@ -1086,13 +1133,12 @@ impl Parser { None }; lexer.expect(Token::Separator(';'))?; - crate::Statement::Return { - value - } + crate::Statement::Return { value } } "if" => { lexer.expect(Token::Paren('('))?; - let condition = self.parse_general_expression(lexer, context.as_expression())?; + let condition = + self.parse_general_expression(lexer, context.as_expression())?; lexer.expect(Token::Paren(')'))?; let accept = self.parse_block(lexer, context.reborrow())?; let reject = if lexer.skip(Token::Word("else")) { @@ -1121,10 +1167,7 @@ impl Parser { None => break, } } - crate::Statement::Loop { - body, - continuing - } + crate::Statement::Loop { body, continuing } } "break" => crate::Statement::Break, "continue" => crate::Statement::Continue, @@ -1133,7 +1176,8 @@ impl Parser { let var_expr = context.lookup_ident.lookup(ident)?; let left = self.parse_postfix(lexer, context.as_expression(), var_expr)?; lexer.expect(Token::Operation('='))?; - let value = self.parse_general_expression(lexer, context.as_expression())?; + let value = + self.parse_general_expression(lexer, context.as_expression())?; lexer.expect(Token::Separator(';'))?; crate::Statement::Store { pointer: left, @@ -1186,9 +1230,11 @@ impl Parser { if !parameter_types.is_empty() { lexer.expect(Token::Separator(','))?; } - let (param_name, param_type) = self.parse_variable_ident_decl(lexer, &mut module.types)?; + let (param_name, param_type) = + self.parse_variable_ident_decl(lexer, &mut module.types)?; let param_index = parameter_types.len() as u32; - let expression_token = expressions.append(crate::Expression::FunctionParameter(param_index)); + let expression_token = + expressions.append(crate::Expression::FunctionParameter(param_index)); lookup_ident.insert(param_name, expression_token); parameter_types.push(param_type); } @@ -1202,15 +1248,18 @@ impl Parser { // read body let mut local_variables = Arena::new(); let mut typifier = Typifier::new(); - let body = self.parse_block(lexer, StatementContext { - lookup_ident: &mut lookup_ident, - typifier: &mut typifier, - variables: &mut local_variables, - expressions: &mut expressions, - types: &mut module.types, - constants: &mut module.constants, - global_vars: &module.global_variables, - })?; + let body = self.parse_block( + lexer, + StatementContext { + lookup_ident: &mut lookup_ident, + typifier: &mut typifier, + variables: &mut local_variables, + expressions: &mut expressions, + types: &mut module.types, + constants: &mut module.constants, + global_vars: &module.global_variables, + }, + )?; // done let global_usage = crate::GlobalUse::scan(&expressions, &body, &module.global_variables); self.scopes.pop(); @@ -1261,14 +1310,16 @@ impl Parser { Token::DoubleParen(']') => { break; } - Token::Separator(',') => { - } + Token::Separator(',') => {} other => return Err(Error::Unexpected(other)), } } match (bind_set, bind_index) { (Some(set), Some(index)) if binding.is_none() => { - binding = Some(crate::Binding::Descriptor { set, binding: index }); + binding = Some(crate::Binding::Descriptor { + set, + binding: index, + }); } _ if binding.is_none() => return Err(Error::Other), _ => {} @@ -1277,7 +1328,7 @@ impl Parser { } // read items match lexer.next() { - Token::Separator(';') => {}, + Token::Separator(';') => {} Token::Word("import") => { self.scopes.push(Scope::ImportDecl); let path = match lexer.next() { @@ -1288,9 +1339,7 @@ impl Parser { let namespace = lexer.next_ident()?; lexer.expect(Token::Separator(';'))?; match path { - "GLSL.std.450" => { - self.std_namespace = Some(namespace.to_owned()) - } + "GLSL.std.450" => self.std_namespace = Some(namespace.to_owned()), _ => return Err(Error::UnknownImport(path)), } self.scopes.pop(); @@ -1305,7 +1354,8 @@ impl Parser { Token::Word("const") => { let (name, ty) = self.parse_variable_ident_decl(lexer, &mut module.types)?; lexer.expect(Token::Operation('='))?; - let inner = self.parse_const_expression(lexer, &mut module.types, &mut module.constants)?; + let inner = + self.parse_const_expression(lexer, &mut module.types, &mut module.constants)?; lexer.expect(Token::Separator(';'))?; crate::proc::check_constant_types(&inner, &module.types[ty].inner)?; let const_handle = module.constants.append(crate::Constant { @@ -1317,7 +1367,8 @@ impl Parser { 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 (name, class, ty) = + self.parse_variable_decl(lexer, &mut module.types, &mut module.constants)?; let var_handle = module.global_variables.append(crate::GlobalVariable { name: Some(name.to_owned()), class: match class { @@ -1334,7 +1385,8 @@ impl Parser { binding: binding.take(), ty, }); - lookup_global_expression.insert(name, crate::Expression::GlobalVariable(var_handle)); + lookup_global_expression + .insert(name, crate::Expression::GlobalVariable(var_handle)); } Token::Word("fn") => { self.parse_function_decl(lexer, module, &lookup_global_expression)?; @@ -1344,7 +1396,7 @@ impl Parser { let export_name = if lexer.skip(Token::Word("as")) { match lexer.next() { Token::String(name) => Some(name), - other => return Err(Error::Unexpected(other)) + other => return Err(Error::Unexpected(other)), } } else { None @@ -1352,7 +1404,8 @@ impl Parser { lexer.expect(Token::Operation('='))?; let fun_ident = lexer.next_ident()?; lexer.expect(Token::Separator(';'))?; - let (fun_handle, _) = module.functions + let (fun_handle, _) = module + .functions .iter() .find(|(_, fun)| fun.name.as_deref() == Some(fun_ident)) .ok_or(Error::UnknownFunction(fun_ident))?; diff --git a/src/lib.rs b/src/lib.rs index c9359c001d..67660c33e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,13 +74,37 @@ pub struct Type { // Clone is used only for error reporting and is not intended for end users #[derive(Clone, Debug, PartialEq)] 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: Handle, class: spirv::StorageClass }, - Array { base: Handle, size: ArraySize }, - Struct { members: Vec }, - Image { base: Handle, dim: spirv::Dim, flags: ImageFlags }, + Scalar { + kind: ScalarKind, + width: Bytes, + }, + Vector { + size: VectorSize, + kind: ScalarKind, + width: Bytes, + }, + Matrix { + columns: VectorSize, + rows: VectorSize, + kind: ScalarKind, + width: Bytes, + }, + Pointer { + base: Handle, + class: spirv::StorageClass, + }, + Array { + base: Handle, + size: ArraySize, + }, + Struct { + members: Vec, + }, + Image { + base: Handle, + dim: spirv::Dim, + flags: ImageFlags, + }, Sampler, } @@ -106,7 +130,10 @@ pub enum ConstantInner { pub enum Binding { BuiltIn(spirv::BuiltIn), Location(spirv::Word), - Descriptor { set: spirv::Word, binding: spirv::Word }, + Descriptor { + set: spirv::Word, + binding: spirv::Word, + }, } bitflags::bitflags! { diff --git a/src/proc/interface.rs b/src/proc/interface.rs index 9522ac981b..e441064092 100644 --- a/src/proc/interface.rs +++ b/src/proc/interface.rs @@ -1,6 +1,4 @@ -use crate::{ - arena::{Arena, Handle}, -}; +use crate::arena::{Arena, Handle}; struct Interface<'a> { expressions: &'a Arena, @@ -24,7 +22,7 @@ impl<'a> Interface<'a> { self.add_inputs(comp); } } - E::FunctionParameter(_) => {}, + E::FunctionParameter(_) => {} E::GlobalVariable(handle) => { self.uses[handle.index()] |= crate::GlobalUse::LOAD; } @@ -32,7 +30,11 @@ impl<'a> Interface<'a> { E::Load { pointer } => { self.add_inputs(pointer); } - E::ImageSample { image, sampler, coordinate } => { + E::ImageSample { + image, + sampler, + coordinate, + } => { self.add_inputs(image); self.add_inputs(sampler); self.add_inputs(coordinate); @@ -70,26 +72,34 @@ impl<'a> Interface<'a> { for statement in block { use crate::Statement as S; match *statement { - S::Empty | - S::Break | - S::Continue | - S::Kill => (), + S::Empty | S::Break | S::Continue | S::Kill => (), S::Block(ref b) => { self.collect(b); } - S::If { condition, ref accept, ref reject } => { + S::If { + condition, + ref accept, + ref reject, + } => { self.add_inputs(condition); self.collect(accept); self.collect(reject); } - S::Switch { selector, ref cases, ref default } => { + S::Switch { + selector, + ref cases, + ref default, + } => { self.add_inputs(selector); for &(ref case, _) in cases.values() { self.collect(case); } self.collect(default); } - S::Loop { ref body, ref continuing } => { + S::Loop { + ref body, + ref continuing, + } => { self.collect(body); self.collect(continuing); } diff --git a/src/proc/mod.rs b/src/proc/mod.rs index dc2dd64b4d..e4b181a697 100644 --- a/src/proc/mod.rs +++ b/src/proc/mod.rs @@ -1,4 +1,4 @@ mod interface; mod typifier; -pub use typifier::{ResolveError, Typifier, UnexpectedConstantTypeError, check_constant_types}; +pub use typifier::{check_constant_types, ResolveError, Typifier, UnexpectedConstantTypeError}; diff --git a/src/proc/typifier.rs b/src/proc/typifier.rs index ed87c964a6..3144046741 100644 --- a/src/proc/typifier.rs +++ b/src/proc/typifier.rs @@ -207,29 +207,38 @@ pub struct UnexpectedConstantTypeError(crate::ConstantInner, crate::TypeInner); pub fn check_constant_types( inner: &crate::ConstantInner, - type_inner: &crate::TypeInner + type_inner: &crate::TypeInner, ) -> Result<(), UnexpectedConstantTypeError> { match (inner, type_inner) { ( crate::ConstantInner::Sint(_), - crate::TypeInner::Scalar { kind: crate::ScalarKind::Sint, width: _ }, + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Sint, + width: _, + }, ) => Ok(()), ( crate::ConstantInner::Uint(_), - crate::TypeInner::Scalar { kind: crate::ScalarKind::Uint, width: _ }, + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Uint, + width: _, + }, ) => Ok(()), ( crate::ConstantInner::Float(_), - crate::TypeInner::Scalar { kind: crate::ScalarKind::Float, width: _ }, + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + width: _, + }, ) => Ok(()), ( crate::ConstantInner::Bool(_), - crate::TypeInner::Scalar { kind: crate::ScalarKind::Bool, width: _ }, + crate::TypeInner::Scalar { + kind: crate::ScalarKind::Bool, + width: _, + }, ) => Ok(()), - ( - crate::ConstantInner::Composite(_inner), - _ - ) => Ok(()), // TODO recursively check composite types + (crate::ConstantInner::Composite(_inner), _) => Ok(()), // TODO recursively check composite types (other_inner, other_type_inner) => Err(UnexpectedConstantTypeError( other_inner.clone(), other_type_inner.clone(), diff --git a/tests/convert.rs b/tests/convert.rs index 4150ed8242..85bb15d7a2 100644 --- a/tests/convert.rs +++ b/tests/convert.rs @@ -12,11 +12,21 @@ fn convert_quad() { let mut binding_map = msl::BindingMap::default(); binding_map.insert( msl::BindSource { set: 0, binding: 0 }, - msl::BindTarget { buffer: None, texture: Some(1), sampler: None, mutable: false }, + msl::BindTarget { + buffer: None, + texture: Some(1), + sampler: None, + mutable: false, + }, ); binding_map.insert( msl::BindSource { set: 0, binding: 1 }, - msl::BindTarget { buffer: None, texture: None, sampler: Some(1), mutable: false }, + msl::BindTarget { + buffer: None, + texture: None, + sampler: Some(1), + mutable: false, + }, ); let options = msl::Options { binding_map: &binding_map, @@ -33,15 +43,30 @@ fn convert_boids() { let mut binding_map = msl::BindingMap::default(); binding_map.insert( msl::BindSource { set: 0, binding: 0 }, - msl::BindTarget { buffer: Some(0), texture: None, sampler: None, mutable: false }, + msl::BindTarget { + buffer: Some(0), + texture: None, + sampler: None, + mutable: false, + }, ); binding_map.insert( msl::BindSource { set: 0, binding: 1 }, - msl::BindTarget { buffer: Some(1), texture: None, sampler: Some(1), mutable: false }, + msl::BindTarget { + buffer: Some(1), + texture: None, + sampler: Some(1), + mutable: false, + }, ); binding_map.insert( msl::BindSource { set: 0, binding: 2 }, - msl::BindTarget { buffer: Some(2), texture: None, sampler: Some(1), mutable: false }, + msl::BindTarget { + buffer: Some(2), + texture: None, + sampler: Some(1), + mutable: false, + }, ); let options = msl::Options { binding_map: &binding_map,