Add member offsets and array strides

This commit is contained in:
Dzmitry Malyshau
2020-06-18 23:53:44 -04:00
committed by Dzmitry Malyshau
parent eb559c5b32
commit a9228d2aed
6 changed files with 83 additions and 9 deletions

View File

@@ -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));
}
@@ -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,

View File

@@ -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);

View File

@@ -237,11 +237,13 @@ impl<'a> Parser<'a> {
unimplemented!()
}
},
stride: None,
},
})
} else {
ty
},
offset: 0, //TODO
});
if name.is_none() {
@@ -267,6 +269,7 @@ impl<'a> Parser<'a> {
ArraySpecifier::Unsized => ArraySize::Dynamic,
ArraySpecifier::ExplicitlySized(_expr) => unimplemented!(),
},
stride: None,
},
})
} else {
@@ -337,6 +340,7 @@ impl<'a> Parser<'a> {
inner: TypeInner::Array {
base: ty,
size: ArraySize::Dynamic,
stride: None,
},
}),
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),
@@ -447,6 +451,7 @@ impl<'a> Parser<'a> {
inner: TypeInner::Array {
base: ty,
size: ArraySize::Dynamic,
stride: None,
},
}),
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),
@@ -1066,6 +1071,7 @@ impl<'a> Parser<'a> {
ArraySpecifier::Unsized => TypeInner::Array {
base: handle,
size: ArraySize::Dynamic,
stride: None,
},
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),
}
@@ -1091,6 +1097,7 @@ impl<'a> Parser<'a> {
inner: TypeInner::Array {
base: ty,
size: ArraySize::Dynamic,
stride: None,
},
}),
ArraySpecifier::ExplicitlySized(_) => unimplemented!(),

View File

@@ -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] = &[];
@@ -54,6 +54,7 @@ pub enum Error {
InvalidBinding(spirv::Word),
WrongFunctionResultType(spirv::Word),
WrongFunctionParameterType(spirv::Word),
MissingDecoration(spirv::Decoration),
BadString,
IncompleteData,
}
@@ -125,6 +126,11 @@ 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>,
@@ -132,6 +138,9 @@ struct Decoration {
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 {
@@ -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 {
@@ -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),
@@ -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),
@@ -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,

View File

@@ -146,6 +146,7 @@ pub enum Error<'a> {
UnknownIdent(&'a str),
UnknownType(&'a str),
UnknownFunction(&'a str),
MissingMemberOffset(&'a str),
MutabilityViolation(&'a str),
Other,
}
@@ -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;
@@ -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)),
@@ -955,6 +957,9 @@ 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(';'))?;
@@ -962,6 +967,7 @@ impl Parser {
name: Some(name.to_owned()),
binding: None,
ty,
offset,
});
}
}
@@ -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)?;

View File

@@ -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>>;
@@ -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! {
@@ -96,6 +98,7 @@ pub enum TypeInner {
Array {
base: Handle<Type>,
size: ArraySize,
stride: Option<NonZeroU32>,
},
Struct {
members: Vec<StructMember>,