diff --git a/src/arena.rs b/src/arena.rs index 66cf171ef0..9751beff53 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -141,7 +141,7 @@ impl Arena { } /// Get a mutable reference to an element in the arena. - pub fn mutate(&mut self, handle: Handle) -> &mut T { + pub fn get_mut(&mut self, handle: Handle) -> &mut T { self.data.get_mut(handle.index.get() as usize - 1).unwrap() } } diff --git a/src/back/msl.rs b/src/back/msl.rs index f3d909b0ca..34ca94ce99 100644 --- a/src/back/msl.rs +++ b/src/back/msl.rs @@ -833,7 +833,7 @@ impl Writer { 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 Writer { 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 Writer { 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 Writer { 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 Writer { 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 { diff --git a/src/front/glsl/mod.rs b/src/front/glsl/mod.rs index 0b2d661b5a..40d3729115 100644 --- a/src/front/glsl/mod.rs +++ b/src/front/glsl/mod.rs @@ -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() { diff --git a/src/front/spv.rs b/src/front/spv.rs index ae435eb691..fb9873b060 100644 --- a/src/front/spv.rs +++ b/src/front/spv.rs @@ -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 { + 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> Parser { 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> Parser { 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> Parser { 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> Parser { 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> Parser { 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> Parser { .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> Parser { | 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 { diff --git a/src/front/wgsl.rs b/src/front/wgsl.rs index c12a10b2e6..9ee23376a8 100644 --- a/src/front/wgsl.rs +++ b/src/front/wgsl.rs @@ -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, }); } } diff --git a/src/lib.rs b/src/lib.rs index 7463e1bc40..2bfe6ceb6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, - pub binding: Option, + pub origin: MemberOrigin, pub ty: Handle, - pub offset: u32, } /// The number of dimensions an image has. diff --git a/src/proc/validator.rs b/src/proc/validator.rs index 576baea68b..985ea5054c 100644 --- a/src/proc/validator.rs +++ b/src/proc/validator.rs @@ -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)); } }