Parse Store, Composite extraction and composing from SPIR-V

This commit is contained in:
Dzmitry Malyshau
2020-02-24 13:38:34 -05:00
parent 17f31ca846
commit 84bc55e3d4
2 changed files with 145 additions and 11 deletions

View File

@@ -45,6 +45,7 @@ pub enum ParseError {
InvalidAccessType(spirv::Word),
InvalidAccessIndex(crate::Expression),
InvalidLoadType(spirv::Word),
InvalidStoreType(spirv::Word),
WrongFunctionResultType(spirv::Word),
WrongFunctionParameterType(spirv::Word),
BadString,
@@ -258,7 +259,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
}
inst.expect_at_least(4)?;
let result_type_id = self.next()?;
let id = self.next()?;
let result_id = self.next()?;
let base_id = self.next()?;
log::trace!("\t\t\tlooking up expr {:?}", base_id);
let mut acex = {
@@ -288,7 +289,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
ref other => return Err(ParseError::InvalidAccessIndex(other.clone()))
};
AccessExpression {
base_token: fun.expressions.append(crate::Expression::AccessMember {
base_token: fun.expressions.append(crate::Expression::AccessIndex {
base: acex.base_token,
index,
}),
@@ -313,15 +314,79 @@ impl<I: Iterator<Item = u32>> Parser<I> {
};
}
self.lookup_expression.insert(id, LookupExpression {
self.lookup_expression.insert(result_id, LookupExpression {
token: acex.base_token,
type_id: result_type_id,
});
}
Op::CompositeExtract => {
inst.expect_at_least(4)?;
let result_type_id = self.next()?;
let result_id = self.next()?;
let base_id = self.next()?;
log::trace!("\t\t\tlooking up expr {:?}", base_id);
let mut lexp = {
let expr = self.lookup_expression.lookup(base_id)?;
LookupExpression {
token: expr.token,
type_id: expr.type_id,
}
};
for _ in 4 .. inst.wc {
let index = self.next()?;
log::trace!("\t\t\tlooking up type {:?}", lexp.type_id);
let ty = self.lookup_type.lookup(lexp.type_id)?;
let type_id = match ty.value {
crate::Type::Struct(_) => {
*self.lookup_member_type_id
.get(&(lexp.type_id, index))
.ok_or(ParseError::InvalidAccessType(lexp.type_id))?
}
crate::Type::Array { .. } |
crate::Type::Vector { .. } |
crate::Type::Matrix { .. } => {
ty.base_id
.ok_or(ParseError::InvalidAccessType(lexp.type_id))?
}
ref other => return Err(ParseError::UnsupportedType(other.clone())),
};
lexp = LookupExpression {
token: fun.expressions.append(crate::Expression::AccessIndex {
base: lexp.token,
index,
}),
type_id,
};
}
self.lookup_expression.insert(result_id, LookupExpression {
token: lexp.token,
type_id: result_type_id,
});
}
Op::CompositeConstruct => {
inst.expect_at_least(3)?;
let result_type_id = self.next()?;
let id = self.next()?;
let mut components = Vec::with_capacity(inst.wc as usize - 2);
for _ in 3 .. inst.wc {
let comp_id = self.next()?;
log::trace!("\t\t\tlooking up expr {:?}", comp_id);
let lexp = self.lookup_expression.lookup(comp_id)?;
components.push(lexp.token);
}
let expr = crate::Expression::Compose {
components,
};
self.lookup_expression.insert(id, LookupExpression {
token: fun.expressions.append(expr),
type_id: result_type_id,
});
}
Op::Load => {
inst.expect_at_least(4)?;
let result_type_id = self.next()?;
let id = self.next()?;
let result_id = self.next()?;
let pointer_id = self.next()?;
if inst.wc != 4 {
inst.expect(5)?;
@@ -339,7 +404,64 @@ impl<I: Iterator<Item = u32>> Parser<I> {
let expr = crate::Expression::Load {
pointer: base_expr.token,
};
self.lookup_expression.insert(id, LookupExpression {
self.lookup_expression.insert(result_id, LookupExpression {
token: fun.expressions.append(expr),
type_id: result_type_id,
});
}
Op::Store => {
inst.expect_at_least(3)?;
let pointer_id = self.next()?;
let value_id = self.next()?;
if inst.wc != 3 {
inst.expect(4)?;
let _memory_access = self.next()?;
}
let base_expr = self.lookup_expression.lookup(pointer_id)?;
let base_type = self.lookup_type.lookup(base_expr.type_id)?;
match base_type.value {
crate::Type::Pointer { .. } => (),
ref other => return Err(ParseError::UnsupportedType(other.clone())),
};
let value_expr = self.lookup_expression.lookup(value_id)?;
if base_type.base_id != Some(value_expr.type_id) {
return Err(ParseError::InvalidStoreType(value_expr.type_id));
}
fun.body.push(crate::Statement::Store {
pointer: base_expr.token,
value: value_expr.token,
})
}
Op::Return => {
inst.expect(1)?;
fun.body.push(crate::Statement::Return { value: None });
break
}
Op::MatrixTimesVector => {
inst.expect(5)?;
let result_type_id = self.next()?;
let (res_size, res_width) = match self.lookup_type.lookup(result_type_id)?.value {
crate::Type::Vector { size, kind: crate::ScalarKind::Float, width } => (size, width),
ref other => return Err(ParseError::UnsupportedType(other.clone())),
};
let result_id = self.next()?;
let matrix_id = self.next()?;
let vector_id = self.next()?;
let matrix_lexp = self.lookup_expression.lookup(matrix_id)?;
let columns = match self.lookup_type.lookup(matrix_lexp.type_id)?.value {
crate::Type::Matrix { columns, rows, kind: crate::ScalarKind::Float, width } if rows == res_size && width == res_width => columns,
ref other => return Err(ParseError::UnsupportedType(other.clone())),
};
let vector_lexp = self.lookup_expression.lookup(vector_id)?.clone();
match self.lookup_type.lookup(vector_lexp.type_id)?.value {
crate::Type::Vector { size, kind: crate::ScalarKind::Float, width } if size == columns && width == res_width => (),
ref other => return Err(ParseError::UnsupportedType(other.clone())),
};
let expr = crate::Expression::MatrixTimesVector {
matrix: matrix_lexp.token,
vector: vector_lexp.token,
};
self.lookup_expression.insert(result_id, LookupExpression {
token: fun.expressions.append(expr),
type_id: result_type_id,
});
@@ -347,6 +469,7 @@ impl<I: Iterator<Item = u32>> Parser<I> {
_ => return Err(ParseError::UnsupportedInstruction(self.state, inst.op)),
}
}
Ok(())
}
fn make_expression_storage(&mut self) -> Storage<crate::Expression> {
@@ -763,7 +886,9 @@ impl<I: Iterator<Item = u32>> Parser<I> {
return Err(ParseError::WrongFunctionResultType(result_type))
}
crate::Function {
name: None,
name: self.future_decor
.remove(&fun_id)
.and_then(|dec| dec.name),
control: spirv::FunctionControl::from_bits(fun_control)
.ok_or(ParseError::UnsupportedFunctionControl(fun_control))?,
parameter_types: Vec::with_capacity(ft.parameter_type_ids.len()),
@@ -800,7 +925,6 @@ impl<I: Iterator<Item = u32>> Parser<I> {
fun_inst.expect(2)?;
let _id = self.next()?;
self.next_block(&mut fun)?;
break
}
Op::FunctionEnd => {
fun_inst.expect(1)?;

View File

@@ -25,7 +25,7 @@ pub struct Header {
pub type Bytes = u8;
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum VectorSize {
Bi = 2,
Tri = 3,
@@ -33,7 +33,7 @@ pub enum VectorSize {
}
#[repr(u8)]
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ScalarKind {
Sint,
Uint,
@@ -89,17 +89,23 @@ pub enum Expression {
base: Token<Expression>,
index: Token<Expression>, //int
},
AccessMember {
AccessIndex {
base: Token<Expression>,
index: u32,
},
Arithmetic,
Constant(Constant),
Compose {
components: Vec<Token<Expression>>,
},
FunctionParameter(u32),
GlobalVariable(Token<GlobalVariable>),
Load {
pointer: Token<Expression>,
},
MatrixTimesVector {
matrix: Token<Expression>,
vector: Token<Expression>,
},
}
pub type Block = Vec<Statement>;
@@ -123,6 +129,10 @@ pub enum Statement {
value: Option<Token<Expression>>,
},
Kill,
Store {
pointer: Token<Expression>,
value: Token<Expression>,
},
}
#[derive(Debug)]