Struct member origin enum

This commit is contained in:
Dzmitry Malyshau
2020-07-03 23:29:05 -04:00
committed by Dzmitry Malyshau
parent 5d6406b018
commit 33fe3a3dba
7 changed files with 109 additions and 64 deletions

View File

@@ -141,7 +141,7 @@ impl<T> Arena<T> {
}
/// Get a mutable reference to an element in the arena.
pub fn mutate(&mut self, handle: Handle<T>) -> &mut T {
pub fn get_mut(&mut self, handle: Handle<T>) -> &mut T {
self.data.get_mut(handle.index.get() as usize - 1).unwrap()
}
}

View File

@@ -833,7 +833,7 @@ impl<W: Write> Writer<W> {
writeln!(self.out, "using namespace metal;")?;
writeln!(self.out)?;
self.write_type_defs(module, options)?;
self.write_type_defs(module)?;
writeln!(self.out)?;
self.write_functions(module, options)?;
@@ -841,7 +841,7 @@ impl<W: Write> Writer<W> {
Ok(())
}
fn write_type_defs(&mut self, module: &crate::Module, options: Options) -> Result<(), Error> {
fn write_type_defs(&mut self, module: &crate::Module) -> Result<(), Error> {
for (handle, ty) in module.types.iter() {
let name = ty.name.or_index(handle);
match ty.inner {
@@ -905,10 +905,14 @@ impl<W: Write> Writer<W> {
let name = member.name.or_index(MemberIndex(index));
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)?;
resolved.try_fmt_decorated(&mut self.out, "")?;
match member.origin {
crate::MemberOrigin::BuiltIn(built_in) => {
ResolvedBinding::BuiltIn(built_in)
.try_fmt_decorated(&mut self.out, "")?;
}
crate::MemberOrigin::Offset(_) => {
//TODO
}
}
writeln!(self.out, ";")?;
}
@@ -1043,14 +1047,12 @@ impl<W: Write> Writer<W> {
module.types[ty_handle].inner
{
for (index, member) in members.iter().enumerate() {
if let Some(ref binding @ crate::Binding::Location(_)) =
member.binding
{
if let crate::MemberOrigin::BuiltIn(built_in) = member.origin {
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)?;
write!(self.out, "\t{} {}", ty_name, name)?;
resolved.try_fmt_decorated(&mut self.out, ";\n")?;
ResolvedBinding::BuiltIn(built_in)
.try_fmt_decorated(&mut self.out, ";\n")?;
}
}
} else if let Some(ref binding @ crate::Binding::Location(_)) = var.binding
@@ -1092,13 +1094,16 @@ impl<W: Write> Writer<W> {
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
.as_ref()
.ok_or(Error::MissingBinding(handle))?;
let resolved = options.resolve_binding(binding, out_mode)?;
write!(self.out, "\t{} {}", ty_name, name)?;
resolved.try_fmt_decorated(&mut self.out, ";\n")?;
match member.origin {
crate::MemberOrigin::BuiltIn(built_in) => {
write!(self.out, "\t{} {}", ty_name, name)?;
ResolvedBinding::BuiltIn(built_in)
.try_fmt_decorated(&mut self.out, ";\n")?;
}
crate::MemberOrigin::Offset(_) => {
//TODO
}
}
}
} else {
let tyvar = TypedGlobalVariable {

View File

@@ -142,18 +142,15 @@ impl<'a> Parser<'a> {
let mut index = 0;
for field in block.fields {
let binding = field
.qualifier
.and_then(|qualifier| Self::parse_type_qualifier(qualifier).1);
let ty = self.parse_type(field.ty).unwrap();
for ident in field.identifiers {
let field_name = ident.ident.0;
let origin = crate::MemberOrigin::Offset(0); //TODO
fields.push(StructMember {
name: Some(field_name.clone()),
binding: binding.clone(),
origin,
ty: if let Some(array_spec) = ident.array_spec {
self.types.fetch_or_append(Type {
name: None,
@@ -171,7 +168,6 @@ impl<'a> Parser<'a> {
} else {
ty
},
offset: 0, //TODO
});
if name.is_none() {

View File

@@ -40,8 +40,8 @@ pub enum Error {
InvalidParameter(spirv::Op),
InvalidOperandCount(spirv::Op, u16),
InvalidOperand,
InvalidDecoration(spirv::Word),
InvalidId(spirv::Word),
InvalidDecoration(spirv::Word),
InvalidTypeWidth(spirv::Word),
InvalidSign(spirv::Word),
InvalidInnerType(spirv::Word),
@@ -242,6 +242,32 @@ impl Decoration {
_ => None,
}
}
fn get_origin(&self) -> Result<crate::MemberOrigin, Error> {
match *self {
Decoration {
location: Some(_), ..
}
| Decoration {
desc_set: Some(_), ..
}
| Decoration {
desc_index: Some(_),
..
} => Err(Error::MissingDecoration(spirv::Decoration::Offset)),
Decoration {
built_in: Some(built_in),
offset: None,
..
} => Ok(crate::MemberOrigin::BuiltIn(built_in)),
Decoration {
built_in: None,
offset: Some(offset),
..
} => Ok(crate::MemberOrigin::Offset(offset)),
_ => Err(Error::MissingDecoration(spirv::Decoration::Offset)),
}
}
}
bitflags::bitflags! {
@@ -981,6 +1007,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
Op::Decorate => self.parse_decorate(inst),
Op::MemberDecorate => self.parse_member_decorate(inst),
Op::TypeVoid => self.parse_type_void(inst),
Op::TypeBool => self.parse_type_bool(inst, &mut module),
Op::TypeInt => self.parse_type_int(inst, &mut module),
Op::TypeFloat => self.parse_type_float(inst, &mut module),
Op::TypeVector => self.parse_type_vector(inst, &mut module),
@@ -1009,7 +1036,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
if flags == SamplingFlags::all() {
return Err(Error::InconsistentComparisonSampling(handle));
}
let ty = module.types.mutate(handle);
let ty = module.types.get_mut(handle);
match ty.inner {
crate::TypeInner::Sampler { ref mut comparison } => {
assert!(!*comparison);
@@ -1210,6 +1237,31 @@ impl<I: Iterator<Item = u32>> Parser<I> {
Ok(())
}
fn parse_type_bool(
&mut self,
inst: Instruction,
module: &mut crate::Module,
) -> Result<(), Error> {
self.switch(ModuleState::Type, inst.op)?;
inst.expect(2)?;
let id = self.next()?;
let inner = crate::TypeInner::Scalar {
kind: crate::ScalarKind::Bool,
width: 1,
};
self.lookup_type.insert(
id,
LookupType {
handle: module.types.append(crate::Type {
name: self.future_decor.remove(&id).and_then(|dec| dec.name),
inner,
}),
base_id: None,
},
);
Ok(())
}
fn parse_type_int(
&mut self,
inst: Instruction,
@@ -1412,7 +1464,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
module: &mut crate::Module,
) -> Result<(), Error> {
self.switch(ModuleState::Type, inst.op)?;
inst.expect(4)?;
inst.expect(3)?;
let id = self.next()?;
let type_id = self.next()?;
@@ -1443,6 +1495,12 @@ impl<I: Iterator<Item = u32>> Parser<I> {
self.switch(ModuleState::Type, inst.op)?;
inst.expect_at_least(2)?;
let id = self.next()?;
let decor = self.future_decor.remove(&id);
if let Some(ref decor) = decor {
if decor.block.is_some() {
// do nothing
}
}
let mut members = Vec::with_capacity(inst.wc as usize - 2);
for i in 0..u32::from(inst.wc) - 2 {
let type_id = self.next()?;
@@ -1452,23 +1510,14 @@ impl<I: Iterator<Item = u32>> Parser<I> {
.future_member_decor
.remove(&(id, i))
.unwrap_or_default();
let binding = decor.get_binding();
let origin = decor.get_origin()?;
members.push(crate::StructMember {
name: decor.name,
binding,
origin,
ty,
offset: decor
.offset
.ok_or(Error::MissingDecoration(spirv::Decoration::Offset))?,
});
}
let inner = crate::TypeInner::Struct { members };
let decor = self.future_decor.remove(&id);
if let Some(ref decor) = decor {
if decor.block.is_some() {
// do nothing
}
}
self.lookup_type.insert(
id,
LookupType {
@@ -1719,26 +1768,10 @@ impl<I: Iterator<Item = u32>> Parser<I> {
| crate::TypeInner::Pointer {
base,
class: crate::StorageClass::Output,
} => {
match module.types[base].inner {
crate::TypeInner::Struct { ref members } => {
// we don't expect binding decoration on I/O structs,
// but we do expect them on all of the members
for member in members {
if member.binding.is_none() {
log::warn!(
"Struct {:?} member {:?} doesn't have a binding",
base,
member
);
return Err(Error::InvalidBinding(id));
}
}
None
}
_ => Some(dec.get_binding().ok_or(Error::InvalidBinding(id))?),
}
}
} => match module.types[base].inner {
crate::TypeInner::Struct { members: _ } => None,
_ => Some(dec.get_binding().ok_or(Error::InvalidBinding(id))?),
},
_ => Some(dec.get_binding().ok_or(Error::InvalidBinding(id))?),
};
let var = crate::GlobalVariable {

View File

@@ -975,9 +975,8 @@ impl Parser {
lexer.expect(Token::Separator(';'))?;
members.push(crate::StructMember {
name: Some(name.to_owned()),
binding: None,
origin: crate::MemberOrigin::Offset(offset),
ty,
offset,
});
}
}

View File

@@ -122,14 +122,22 @@ pub enum ArraySize {
Dynamic,
}
/// Describes where a struct member is placed.
#[derive(Clone, Debug, PartialEq)]
pub enum MemberOrigin {
/// Built-in shader variable.
BuiltIn(BuiltIn),
/// Offset within the struct.
Offset(u32),
}
/// Member of a user-defined structure.
// Clone is used only for error reporting and is not intended for end users
#[derive(Clone, Debug, PartialEq)]
pub struct StructMember {
pub name: Option<String>,
pub binding: Option<Binding>,
pub origin: MemberOrigin,
pub ty: Handle<Type>,
pub offset: u32,
}
/// The number of dimensions an image has.

View File

@@ -26,7 +26,11 @@ impl Validator {
Ti::Scalar { kind, width }
| Ti::Vector { kind, width, .. }
| Ti::Matrix { kind, width, .. } => {
if width != 4 {
let expected = match kind {
crate::ScalarKind::Bool => 1,
_ => 4,
};
if width != expected {
return Err(ValidationError::InvalidTypeWidth(kind, width));
}
}