mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Struct member origin enum
This commit is contained in:
committed by
Dzmitry Malyshau
parent
5d6406b018
commit
33fe3a3dba
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
101
src/front/spv.rs
101
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<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 {
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
12
src/lib.rs
12
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<String>,
|
||||
pub binding: Option<Binding>,
|
||||
pub origin: MemberOrigin,
|
||||
pub ty: Handle<Type>,
|
||||
pub offset: u32,
|
||||
}
|
||||
|
||||
/// The number of dimensions an image has.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user