mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Add member offsets and array strides
This commit is contained in:
committed by
Dzmitry Malyshau
parent
eb559c5b32
commit
a9228d2aed
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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!(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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>,
|
||||
|
||||
Reference in New Issue
Block a user