Skip to content

Commit

Permalink
Add member offsets and array strides
Browse files Browse the repository at this point in the history
  • Loading branch information
kvark committed Jun 19, 2020
1 parent eb559c5 commit a9228d2
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 9 deletions.
12 changes: 10 additions & 2 deletions src/back/msl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,11 @@ impl<W: Write> Writer<W> {
write!(self.out, ".{}", COMPONENTS[index as usize])?;
Ok(MaybeOwned::Owned(crate::TypeInner::Scalar { kind, width }))
}
crate::TypeInner::Array { base, size } => {
crate::TypeInner::Array {
base,
size,
stride: _,
} => {
if let crate::ArraySize::Static(length) = size {
return Err(Error::AccessIndexExceedsStaticLength(index, length));
}
Expand Down Expand Up @@ -844,7 +848,11 @@ impl<W: Write> Writer<W> {
};
write!(self.out, "typedef {} {} *{}", class_name, base_name, name)?;
}
crate::TypeInner::Array { base, size } => {
crate::TypeInner::Array {
base,
size,
stride: _,
} => {
let base_name = module.types[base].name.or_index(base);
let resolved_size = match size {
crate::ArraySize::Static(length) => length,
Expand Down
10 changes: 9 additions & 1 deletion src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,15 @@ impl Writer {

self.lookup_type.insert(id, handle);
}
crate::TypeInner::Array { base, size } => {
crate::TypeInner::Array { base, size, stride } => {
if let Some(array_stride) = stride {
let mut instruction = Instruction::new(Op::Decorate);
instruction.add_operand(id);
instruction.add_operand(Decoration::ArrayStride as u32);
instruction.add_operand(array_stride.get());
self.annotations.push(instruction);
}

let type_id = self.get_type_id(arena, handle);

instruction = Instruction::new(Op::TypeArray);
Expand Down
7 changes: 7 additions & 0 deletions src/front/glsl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,13 @@ impl<'a> Parser<'a> {
unimplemented!()
}
},
stride: None,
},
})
} else {
ty
},
offset: 0, //TODO
});

if name.is_none() {
Expand All @@ -267,6 +269,7 @@ impl<'a> Parser<'a> {
ArraySpecifier::Unsized => ArraySize::Dynamic,
ArraySpecifier::ExplicitlySized(_expr) => unimplemented!(),
},
stride: None,
},
})
} else {
Expand Down Expand Up @@ -337,6 +340,7 @@ impl<'a> Parser<'a> {
inner: TypeInner::Array {
base: ty,
size: ArraySize::Dynamic,
stride: None,
},
}),
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),
Expand Down Expand Up @@ -447,6 +451,7 @@ impl<'a> Parser<'a> {
inner: TypeInner::Array {
base: ty,
size: ArraySize::Dynamic,
stride: None,
},
}),
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),
Expand Down Expand Up @@ -1066,6 +1071,7 @@ impl<'a> Parser<'a> {
ArraySpecifier::Unsized => TypeInner::Array {
base: handle,
size: ArraySize::Dynamic,
stride: None,
},
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),
}
Expand All @@ -1091,6 +1097,7 @@ impl<'a> Parser<'a> {
inner: TypeInner::Array {
base: ty,
size: ArraySize::Dynamic,
stride: None,
},
}),
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),
Expand Down
46 changes: 42 additions & 4 deletions src/front/spv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
};

use num_traits::cast::FromPrimitive;
use std::convert::TryInto;
use std::{convert::TryInto, num::NonZeroU32};

pub const SUPPORTED_CAPABILITIES: &[spirv::Capability] = &[spirv::Capability::Shader];
pub const SUPPORTED_EXTENSIONS: &[&str] = &[];
Expand Down Expand Up @@ -54,6 +54,7 @@ pub enum Error {
InvalidBinding(spirv::Word),
WrongFunctionResultType(spirv::Word),
WrongFunctionParameterType(spirv::Word),
MissingDecoration(spirv::Decoration),
BadString,
IncompleteData,
}
Expand Down Expand Up @@ -125,13 +126,21 @@ fn map_storage_class(word: spirv::Word) -> Result<spirv::StorageClass, Error> {

type MemberIndex = u32;

#[derive(Debug, Default)]
struct Block {
buffer: bool,
}

#[derive(Debug, Default)]
struct Decoration {
name: Option<String>,
built_in: Option<spirv::BuiltIn>,
location: Option<spirv::Word>,
desc_set: Option<spirv::Word>,
desc_index: Option<spirv::Word>,
block: Option<Block>,
offset: Option<spirv::Word>,
array_stride: Option<NonZeroU32>,
}

impl Decoration {
Expand Down Expand Up @@ -310,6 +319,20 @@ impl<I: Iterator<Item = u32>> Parser<I> {
inst.expect(base_words + 2)?;
dec.desc_index = Some(self.next()?);
}
spirv::Decoration::Block => {
dec.block = Some(Block { buffer: false });
}
spirv::Decoration::BufferBlock => {
dec.block = Some(Block { buffer: true });
}
spirv::Decoration::Offset => {
inst.expect(base_words + 2)?;
dec.offset = Some(self.next()?);
}
spirv::Decoration::ArrayStride => {
inst.expect(base_words + 2)?;
dec.array_stride = NonZeroU32::new(self.next()?);
}
other => {
log::warn!("Unknown decoration {:?}", other);
for _ in base_words + 1..inst.wc {
Expand Down Expand Up @@ -1143,15 +1166,18 @@ impl<I: Iterator<Item = u32>> Parser<I> {
let id = self.next()?;
let type_id = self.next()?;
let length = self.next()?;

let decor = self.future_decor.remove(&id);
let inner = crate::TypeInner::Array {
base: self.lookup_type.lookup(type_id)?.handle,
size: crate::ArraySize::Static(length),
stride: decor.as_ref().and_then(|dec| dec.array_stride),
};
self.lookup_type.insert(
id,
LookupType {
handle: module.types.append(crate::Type {
name: self.future_decor.remove(&id).and_then(|dec| dec.name),
name: decor.and_then(|dec| dec.name),
inner,
}),
base_id: Some(type_id),
Expand All @@ -1169,15 +1195,18 @@ impl<I: Iterator<Item = u32>> Parser<I> {
inst.expect(4)?;
let id = self.next()?;
let type_id = self.next()?;

let decor = self.future_decor.remove(&id);
let inner = crate::TypeInner::Array {
base: self.lookup_type.lookup(type_id)?.handle,
size: crate::ArraySize::Dynamic,
stride: decor.as_ref().and_then(|dec| dec.array_stride),
};
self.lookup_type.insert(
id,
LookupType {
handle: module.types.append(crate::Type {
name: self.future_decor.remove(&id).and_then(|dec| dec.name),
name: decor.and_then(|dec| dec.name),
inner,
}),
base_id: Some(type_id),
Expand Down Expand Up @@ -1208,14 +1237,23 @@ impl<I: Iterator<Item = u32>> Parser<I> {
name: decor.name,
binding,
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 {
handle: module.types.append(crate::Type {
name: self.future_decor.remove(&id).and_then(|dec| dec.name),
name: decor.and_then(|dec| dec.name),
inner,
}),
base_id: None,
Expand Down
14 changes: 12 additions & 2 deletions src/front/wgsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ pub enum Error<'a> {
UnknownIdent(&'a str),
UnknownType(&'a str),
UnknownFunction(&'a str),
MissingMemberOffset(&'a str),
MutabilityViolation(&'a str),
Other,
}
Expand Down Expand Up @@ -930,6 +931,7 @@ impl Parser {
let mut members = Vec::new();
lexer.expect(Token::Paren('{'))?;
loop {
let mut offset = !0;
if lexer.skip(Token::DoubleParen('[')) {
self.scopes.push(Scope::Decoration);
let mut ready = true;
Expand All @@ -942,7 +944,7 @@ impl Parser {
ready = true;
}
Token::Word("offset") if ready => {
let _offset = lexer.next_uint_literal()?; //TODO
offset = lexer.next_uint_literal()?;
ready = false;
}
other => return Err(Error::Unexpected(other)),
Expand All @@ -955,13 +957,17 @@ impl Parser {
Token::Paren('}') => return Ok(members),
other => return Err(Error::Unexpected(other)),
};
if offset == !0 {
return Err(Error::MissingMemberOffset(name));
}
lexer.expect(Token::Separator(':'))?;
let ty = self.parse_type_decl(lexer, type_arena)?;
lexer.expect(Token::Separator(';'))?;
members.push(crate::StructMember {
name: Some(name.to_owned()),
binding: None,
ty,
offset,
});
}
}
Expand Down Expand Up @@ -1056,7 +1062,11 @@ impl Parser {
Token::Separator('>') => crate::ArraySize::Dynamic,
other => return Err(Error::Unexpected(other)),
};
crate::TypeInner::Array { base, size }
crate::TypeInner::Array {
base,
size,
stride: None,
}
}
Token::Word("struct") => {
let members = self.parse_struct_body(lexer, type_arena)?;
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub use crate::arena::{Arena, Handle};
use std::{
collections::{HashMap, HashSet},
hash::BuildHasherDefault,
num::NonZeroU32,
};

pub type FastHashMap<K, T> = HashMap<K, T, BuildHasherDefault<fxhash::FxHasher>>;
Expand Down Expand Up @@ -53,6 +54,7 @@ pub struct StructMember {
pub name: Option<String>,
pub binding: Option<Binding>,
pub ty: Handle<Type>,
pub offset: spirv::Word,
}

bitflags::bitflags! {
Expand Down Expand Up @@ -96,6 +98,7 @@ pub enum TypeInner {
Array {
base: Handle<Type>,
size: ArraySize,
stride: Option<NonZeroU32>,
},
Struct {
members: Vec<StructMember>,
Expand Down

0 comments on commit a9228d2

Please sign in to comment.