let mut enumerant_member_names = Vec::new();
let mut enumerant_items = Vec::new();
let mut enumerant_parse_operations = Vec::new();
+ let mut enumerant_display_mask_operations = Vec::new();
let mut enumerant_display_operations = Vec::new();
let mut none_name = "None";
for enumerant in enumerants {
none_name = enumerant.enumerant.as_ref();
continue;
}
+ let enumerant_name = &enumerant.enumerant;
let member_name = new_id(&enumerant.enumerant, SnakeCase);
let member_name = &member_name;
enumerant_member_names.push(member_name.clone());
pub struct #type_name;
});
enumerant_parse_operation = quote!{(Some(#type_name), words)};
- enumerant_display_operations.push(quote!{
- if let Some(#type_name) = &self.#member_name {
- unimplemented!();
+ enumerant_display_mask_operations.push(quote!{
+ if self.#member_name.is_some() {
+ if any_members {
+ write!(f, "|{}", #enumerant_name)?;
+ } else {
+ write!(f, " {}", #enumerant_name)?;
+ any_members = true;
+ }
}
});
+ enumerant_display_operations.push(quote!{});
} else {
- let mut enumerant_member_declarations = Vec::new();
- let mut enumerant_member_names = Vec::new();
+ let mut enumerant_parameter_declarations = Vec::new();
+ let mut enumerant_parameter_names = Vec::new();
let mut parse_enumerant_members = Vec::new();
+ let mut display_enumerant_members = Vec::new();
for (index, parameter) in enumerant.parameters.iter().enumerate() {
let name = new_id(format!("parameter_{}", index), SnakeCase);
let kind = new_id(¶meter.kind, CamelCase);
- enumerant_member_declarations.push(quote!{
+ enumerant_parameter_declarations.push(quote!{
pub #kind,
});
- enumerant_member_names.push(quote!{
+ enumerant_parameter_names.push(quote!{
#name,
});
parse_enumerant_members.push(quote!{
let (#name, words) = #kind::spirv_parse(words, parse_state)?;
});
+ display_enumerant_members.push(quote!{
+ #name.spirv_display(f)?;
+ });
}
enumerant_items.push(quote!{
#[derive(Clone, Debug, Default)]
- pub struct #type_name(#(#enumerant_member_declarations)*);
+ pub struct #type_name(#(#enumerant_parameter_declarations)*);
});
- let enumerant_member_names = &enumerant_member_names;
+ let enumerant_parameter_names = &enumerant_parameter_names;
enumerant_parse_operation = quote!{
#(#parse_enumerant_members)*
- (Some(#type_name(#(#enumerant_member_names)*)), words)
+ (Some(#type_name(#(#enumerant_parameter_names)*)), words)
};
+ enumerant_display_mask_operations.push(quote!{
+ if self.#member_name.is_some() {
+ if any_members {
+ write!(f, "|{}", #enumerant_name)?;
+ } else {
+ write!(f, " {}", #enumerant_name)?;
+ any_members = true;
+ }
+ }
+ });
enumerant_display_operations.push(quote!{
- if let Some(#type_name(#(#enumerant_member_names)*)) = &self.#member_name {
- unimplemented!();
+ if let Some(#type_name(#(#enumerant_parameter_names)*)) = &self.#member_name {
+ #(#display_enumerant_members)*
}
});
};
quote!{
impl SPIRVDisplay for #kind_id {
fn spirv_display(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut is_none = true;
- #(#enumerant_display_operations)*
- if is_none {
- write!(f, " {}", #none_name)
- } else {
- Ok(())
+ let mut any_members = false;
+ #(#enumerant_display_mask_operations)*
+ if !any_members {
+ write!(f, " {}", #none_name)?;
}
+ #(#enumerant_display_operations)*
+ Ok(())
}
}
}
};
instruction_extension_enumerants.push(instruction_extension_enumerant);
let mut parse_operations = Vec::new();
+ let mut display_operations = Vec::new();
let mut operand_names = Vec::new();
for operand in &instruction.operands {
let kind = new_id(&operand.kind, CamelCase);
parse_operations.push(quote!{
let (#name, words) = #kind::spirv_parse(words, parse_state)?;
});
+ display_operations.push(quote!{
+ #name.spirv_display(f)?;
+ });
operand_names.push(name);
}
let operand_names = &operand_names;
}
};
instruction_extension_parse_cases.push(instruction_extension_parse_case);
+ let display_opname = &instruction.opname;
let instruction_extension_display_case = quote!{
Instruction::#instruction_enumerant_name {
id_result_type,
id_result,
set,
#(#operand_names,)*
- } => unimplemented!(),
+ } => {
+ write!(
+ f,
+ "{}OpExtInst {} {} {}",
+ InstructionIndentAndResult(Some(*id_result)),
+ id_result_type,
+ set,
+ #display_opname,
+ )?;
+ #(#display_operations)*
+ writeln!(f)
+ }
};
instruction_extension_display_cases.push(instruction_extension_display_case);
}
let opcode = instruction.opcode;
let opname = new_id(remove_initial_op(instruction.opname.as_ref()), CamelCase);
let display_opname = instruction.opname.as_ref();
+ let display_opname_without_initial_op = remove_initial_op(display_opname);
let instruction_parse_case;
let instruction_display_case;
match &instruction.opname {
}
};
instruction_display_case = quote!{
- Instruction::SpecConstant32 { .. } => unimplemented!(),
- Instruction::SpecConstant64 { .. } => unimplemented!(),
+ Instruction::SpecConstant32 {
+ id_result_type,
+ id_result,
+ value,
+ } => {
+ write!(
+ f,
+ "{}{}",
+ InstructionIndentAndResult(Some(*id_result)),
+ "OpSpecConstant"
+ )?;
+ id_result_type.spirv_display(f)?;
+ writeln!(f, " {:#010X}", value)
+ }
+ Instruction::SpecConstant64 {
+ id_result_type,
+ id_result,
+ value,
+ } => {
+ write!(
+ f,
+ "{}{}",
+ InstructionIndentAndResult(Some(*id_result)),
+ "OpSpecConstant"
+ )?;
+ id_result_type.spirv_display(f)?;
+ writeln!(f, " {:#018X}", value)
+ }
};
}
ast::InstructionName::OpSpecConstant64 => {
let opcode = u32::from(opcode);
spec_constant_op_instruction_enumerants.push(instruction_enumerant.clone());
let mut parse_operations = Vec::new();
+ let mut display_operations = Vec::new();
let mut operand_names = Vec::new();
operand_names.push(new_id("id_result_type", SnakeCase));
operand_names.push(new_id("id_result", SnakeCase));
parse_operations.push(quote!{
let (#name, words) = #kind::spirv_parse(words, parse_state)?;
});
+ display_operations.push(quote!{
+ #name.spirv_display(f)?;
+ });
operand_names.push(name);
}
if let Some([operand1, operand2]) = instruction.operands.get(..2) {
instruction_spec_constant_display_cases.push(quote!{
OpSpecConstantOp::#opname {
#(#operand_names,)*
- } => unimplemented!(),
+ } => {
+ write!(f, "{}{}", InstructionIndentAndResult(Some(*id_result)), "OpSpecConstantOp")?;
+ id_result_type.spirv_display(f)?;
+ write!(f, " {}", #display_opname_without_initial_op)?;
+ #(#display_operations)*
+ writeln!(f)
+ }
});
}
instruction_enumerants.push(instruction_enumerant);
%38 = OpLabel
OpReturn
OpFunctionEnd
+"#;
+ println!("Line-by-line:");
+ for (a, b) in output.lines().zip(expected.lines()) {
+ println!("{}\n{}", a, b);
+ }
+ assert!(output == expected);
+ }
+
+ #[test]
+ fn parse_test2() {
+ let output = parse_and_dump(include_bytes!("../test_inputs/test2.spv")).unwrap();
+ let expected = r#"; SPIR-V
+; Version: 1.3
+; Generator: 0x70000
+; Bound: 12
+; Schema: 0
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Vertex %1 "main"
+ %2 = OpTypeVoid
+ %3 = OpTypeFloat 32
+ %4 = OpTypeVector %3 4
+ %5 = OpTypeFunction %2
+ %1 = OpFunction %2 None %5
+ %6 = OpLabel
+ %7 = OpImageSampleImplicitLod %4 %8 %9 Bias|MinLod %10 %11
+ OpReturn
+ OpFunctionEnd
+"#;
+ println!("Line-by-line:");
+ for (a, b) in output.lines().zip(expected.lines()) {
+ println!("{}\n{}", a, b);
+ }
+ assert!(output == expected);
+ }
+
+ #[test]
+ fn parse_test3() {
+ let output = parse_and_dump(include_bytes!("../test_inputs/test3.spv")).unwrap();
+ let expected = r#"; SPIR-V
+; Version: 1.0
+; Generator: 0x80007
+; Bound: 38
+; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %4 "main"
+ OpExecutionMode %4 LocalSize 1 1 1
+ OpSource GLSL 450
+ OpName %4 "main"
+ OpName %8 "f("
+ OpName %10 "g("
+ OpName %14 "h("
+ OpName %16 "A"
+ OpName %17 "B"
+ OpName %19 "C"
+ OpDecorate %16 SpecId 0
+ OpDecorate %17 SpecId 1
+ OpDecorate %19 SpecId 2
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypeFunction %6
+ %12 = OpTypeFloat 32
+ %13 = OpTypeFunction %12
+ %16 = OpSpecConstant %6 0x00000000
+ %17 = OpSpecConstant %6 0x00000001
+ %18 = OpSpecConstantOp %6 IMul %16 %17
+ %19 = OpSpecConstant %6 0x00000002
+ %20 = OpSpecConstantOp %6 SDiv %18 %19
+ %23 = OpSpecConstantOp %6 BitwiseAnd %16 %17
+ %24 = OpSpecConstantOp %6 BitwiseXor %23 %19
+ %29 = OpConstant %12 0x3F490FDB
+ %30 = OpTypeVector %12 2
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %35 = OpFunctionCall %6 %8
+ %36 = OpFunctionCall %6 %10
+ %37 = OpFunctionCall %12 %14
+ OpReturn
+ OpFunctionEnd
+ %8 = OpFunction %6 None %7
+ %9 = OpLabel
+ OpReturnValue %20
+ OpFunctionEnd
+ %10 = OpFunction %6 None %7
+ %11 = OpLabel
+ OpReturnValue %24
+ OpFunctionEnd
+ %14 = OpFunction %12 None %13
+ %15 = OpLabel
+ %27 = OpConvertSToF %12 %16
+ %28 = OpExtInst %12 %1 Cos %27
+ %31 = OpCompositeConstruct %30 %28 %29
+ %32 = OpExtInst %12 %1 Length %31
+ OpReturnValue %32
+ OpFunctionEnd
"#;
println!("Line-by-line:");
for (a, b) in output.lines().zip(expected.lines()) {