mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Run cargo fmt and enable monocodus (#63)
This commit is contained in:
@@ -3,5 +3,3 @@ version: 1.0.0
|
||||
rust:
|
||||
formatter:
|
||||
name: rustfmt
|
||||
ignore_paths:
|
||||
- ".*"
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -1 +1 @@
|
||||
pub mod msl;
|
||||
pub mod msl;
|
||||
|
||||
507
src/back/msl.rs
507
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<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
@@ -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))?;
|
||||
|
||||
43
src/lib.rs
43
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<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! {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user