Run cargo fmt and enable monocodus (#63)

This commit is contained in:
João Capucho
2020-06-09 19:49:12 +01:00
committed by GitHub
parent b91b9ca987
commit f94b486d8b
11 changed files with 1053 additions and 679 deletions

View File

@@ -3,5 +3,3 @@ version: 1.0.0
rust:
formatter:
name: rustfmt
ignore_paths:
- ".*"

View File

@@ -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 <input> <output>");
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(),

View File

@@ -1 +1 @@
pub mod msl;
pub mod msl;

View File

@@ -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<ResolvedBinding, Error> {
fn resolve_binding(
&self,
binding: &crate::Binding,
mode: LocationMode,
) -> Result<ResolvedBinding, Error> {
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<crate::Type> {
const CLASS: &'static str = "Type";
fn id(&self) -> usize { self.index() }
fn id(&self) -> usize {
self.index()
}
}
impl Indexed for crate::Handle<crate::GlobalVariable> {
const CLASS: &'static str = "global";
fn id(&self) -> usize { self.index() }
fn id(&self) -> usize {
self.index()
}
}
impl Indexed for crate::Handle<crate::LocalVariable> {
const CLASS: &'static str = "local";
fn id(&self) -> usize { self.index() }
fn id(&self) -> usize {
self.index()
}
}
impl Indexed for crate::Handle<crate::Function> {
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<crate::Function>);
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<crate::Function>);
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<String> {
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<W: Write>(&self, formatter: &mut W, terminator: &str) -> Result<(), Error> {
fn try_fmt_decorated<W: Write>(
&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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
}
}
} 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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
}
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
} 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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
// 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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
}
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
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<W: Write> Writer<W> {
// 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)?;

File diff suppressed because it is too large Load Diff

View File

@@ -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<crate::Expression>> {
type Value = Handle<crate::Expression>;
fn lookup(&self, key: &'a str) -> Result<Self::Value, Error<'a>> {
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<crate::Expression>) -> Result<Handle<crate::Type>, Error<'a>> {
fn resolve_type(
&mut self,
handle: Handle<crate::Expression>,
) -> Result<Handle<crate::Type>, 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<crate::BinaryOperator>,
mut parser: impl FnMut(&mut Lexer<'a>, ExpressionContext<'a, '_, '_>) -> Result<Handle<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 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<Handle<crate::Type>, 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))?;

View File

@@ -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<Type>, class: spirv::StorageClass },
Array { base: Handle<Type>, size: ArraySize },
Struct { members: Vec<StructMember> },
Image { base: Handle<Type>, 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<Type>,
class: spirv::StorageClass,
},
Array {
base: Handle<Type>,
size: ArraySize,
},
Struct {
members: Vec<StructMember>,
},
Image {
base: Handle<Type>,
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! {

View File

@@ -1,6 +1,4 @@
use crate::{
arena::{Arena, Handle},
};
use crate::arena::{Arena, Handle};
struct Interface<'a> {
expressions: &'a Arena<crate::Expression>,
@@ -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);
}

View File

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

View File

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

View File

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