diff --git a/shader-parser/src/parse.rs b/shader-parser/src/parse.rs index 4bfccd0e..74e6c75c 100644 --- a/shader-parser/src/parse.rs +++ b/shader-parser/src/parse.rs @@ -66,6 +66,7 @@ pub enum ParseError { IncompleteInstruction, UnknownCapability(u32), UnknownExecutionModel(u32), + UnknownStorageClass(u32), } #[derive(Debug, Clone)] @@ -79,10 +80,23 @@ pub struct Spirv { pub enum Instruction { Unknown(u16, Vec), Nop, + Name { target_id: u32, name: String }, + MemberName { target_id: u32, member: u32, name: String }, ExtInstImport { result_id: u32, name: String }, EntryPoint { execution: ExecutionModel, id: u32, name: String, interface: Vec }, Capability(Capability), + TypeVoid { result_id: u32 }, + TypeBool { result_id: u32 }, + TypeInt { result_id: u32, width: u32, signedness: bool }, + TypeFloat { result_id: u32, width: u32 }, + TypeVector { result_id: u32, component_id: u32, count: u32 }, + TypeArray { result_id: u32, type_id: u32, length_id: u32 }, + TypeRuntimeArray { result_id: u32, type_id: u32 }, + TypeStruct { result_id: u32, member_types: Vec }, + TypeOpaque { result_id: u32, name: String }, + TypePointer { result_id: u32, storage_class: StorageClass, type_id: u32 }, FunctionEnd, + Variable { result_type_id: u32, result_id: u32, storage_class: StorageClass, initializer: Option }, Kill, Return, } @@ -105,6 +119,8 @@ fn parse_instruction(i: &[u32]) -> Result<(Instruction, &[u32]), ParseError> { fn decode_instruction(opcode: u16, operands: &[u32]) -> Result { Ok(match opcode { 0 => Instruction::Nop, + 5 => Instruction::Name { target_id: operands[0], name: parse_string(&operands[1..]).0 }, + 6 => Instruction::MemberName { target_id: operands[0], member: operands[1], name: parse_string(&operands[2..]).0 }, 11 => Instruction::ExtInstImport { result_id: operands[0], name: parse_string(&operands[1..]).0 @@ -119,7 +135,22 @@ fn decode_instruction(opcode: u16, operands: &[u32]) -> Result Instruction::Capability(try!(Capability::from_num(operands[0]))), + 19 => Instruction::TypeVoid { result_id: operands[0] }, + 20 => Instruction::TypeBool { result_id: operands[0] }, + 21 => Instruction::TypeInt { result_id: operands[0], width: operands[1], signedness: operands[2] != 0 }, + 22 => Instruction::TypeFloat { result_id: operands[0], width: operands[1] }, + 23 => Instruction::TypeVector { result_id: operands[0], component_id: operands[1], count: operands[2] }, + 28 => Instruction::TypeArray { result_id: operands[0], type_id: operands[1], length_id: operands[2] }, + 29 => Instruction::TypeRuntimeArray { result_id: operands[0], type_id: operands[1] }, + 30 => Instruction::TypeStruct { result_id: operands[0], member_types: operands[1..].to_owned() }, + 31 => Instruction::TypeOpaque { result_id: operands[0], name: parse_string(&operands[1..]).0 }, + 32 => Instruction::TypePointer { result_id: operands[0], storage_class: try!(StorageClass::from_num(operands[1])), type_id: operands[2] }, 56 => Instruction::FunctionEnd, + 59 => Instruction::Variable { + result_type_id: operands[0], result_id: operands[1], + storage_class: try!(StorageClass::from_num(operands[2])), + initializer: operands.get(3).map(|&v| v) + }, 252 => Instruction::Kill, 253 => Instruction::Return, _ => Instruction::Unknown(opcode, operands.to_owned()), @@ -289,13 +320,49 @@ impl ExecutionModel { } } +#[derive(Debug, Clone)] +pub enum StorageClass { + UniformConstant, + Input, + Uniform, + Output, + Workgroup, + CrossWorkgroup, + Private, + Function, + Generic, + PushConstant, + AtomicCounter, + Image, +} + +impl StorageClass { + fn from_num(num: u32) -> Result { + match num { + 0 => Ok(StorageClass::UniformConstant), + 1 => Ok(StorageClass::Input), + 2 => Ok(StorageClass::Uniform), + 3 => Ok(StorageClass::Output), + 4 => Ok(StorageClass::Workgroup), + 5 => Ok(StorageClass::CrossWorkgroup), + 6 => Ok(StorageClass::Private), + 7 => Ok(StorageClass::Function), + 8 => Ok(StorageClass::Generic), + 9 => Ok(StorageClass::PushConstant), + 10 => Ok(StorageClass::AtomicCounter), + 11 => Ok(StorageClass::Image), + _ => Err(ParseError::UnknownStorageClass(num)), + } + } +} + #[cfg(test)] mod test { use parse; #[test] fn test() { - let data = include_bytes!("../tests/frag.spv"); - parse::parse_spirv(data).unwrap(); + let data = include_bytes!("../examples/example.spv"); + println!("{:?}", parse::parse_spirv(data).unwrap()); } }