From 65c2eed65de3bb7cebab16f944359ba310dde15d Mon Sep 17 00:00:00 2001 From: LoopDawg Date: Thu, 18 May 2017 16:13:04 -0600 Subject: [PATCH] Remapper: handle embedded opcode in OpSpecConstantOp OpSpecConstantOp contains an embedded opcode which is given as a literal argument to the OpSpecConstantOp. The subsequent arguments are as the embedded op would expect, which may be a mixture of IDs and literals. This adds support for that to the remapper binary parser. Upon seeing such an embedded op, the parser flips over to parsing the argument list as appropriate for that opcode. Fixes #882. --- SPIRV/SPVRemapper.cpp | 14 +++++++++- Test/baseResults/remap.specconst.comp.out | 33 +++++++++++++++++++++++ gtests/Remap.FromFile.cpp | 1 + 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 Test/baseResults/remap.specconst.comp.out diff --git a/SPIRV/SPVRemapper.cpp b/SPIRV/SPVRemapper.cpp index 9b127050..e8031d02 100755 --- a/SPIRV/SPVRemapper.cpp +++ b/SPIRV/SPVRemapper.cpp @@ -464,8 +464,8 @@ namespace spv { { const auto instructionStart = word; const unsigned wordCount = asWordCount(instructionStart); - const spv::Op opCode = asOpCode(instructionStart); const int nextInst = word++ + wordCount; + spv::Op opCode = asOpCode(instructionStart); if (nextInst > int(spv.size())) error("spir instruction terminated too early"); @@ -506,6 +506,18 @@ namespace spv { // Store IDs from instruction in our map for (int op = 0; numOperands > 0; ++op, --numOperands) { + // SpecConstantOp is special: it includes the operands of another opcode which is + // given as a literal in the 3rd word. We will switch over to pretending that the + // opcode being processed is the literal opcode value of the SpecConstantOp. See the + // SPIRV spec for details. This way we will handle IDs and literals as appropriate for + // the embedded op. + if (opCode == spv::OpSpecConstantOp) { + if (op == 0) { + opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp. + --numOperands; + } + } + switch (spv::InstructionDesc[opCode].operands.getClass(op)) { case spv::OperandId: case spv::OperandScope: diff --git a/Test/baseResults/remap.specconst.comp.out b/Test/baseResults/remap.specconst.comp.out new file mode 100644 index 00000000..141c1a47 --- /dev/null +++ b/Test/baseResults/remap.specconst.comp.out @@ -0,0 +1,33 @@ +remap.specconst.comp +Warning, version 450 is not yet complete; most version-specific features are present, but some are missing. + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 16104 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 5663 "main" + ExecutionMode 5663 LocalSize 1 1 1 + Decorate 2 SpecId 0 + Decorate 3 SpecId 1 + Decorate 4 SpecId 2 + Decorate 5 BuiltIn WorkgroupSize + 8: TypeVoid + 1282: TypeFunction 8 + 11: TypeInt 32 0 + 2: 11(int) SpecConstant 1 + 3: 11(int) SpecConstant 1 + 4: 11(int) SpecConstant 1 + 20: TypeVector 11(int) 3 + 5: 20(ivec3) SpecConstantComposite 2 3 4 + 6: 11(int) SpecConstantOp 81 5 0 + 7: 11(int) SpecConstantOp 81 5 1(GLSL.std.450) + 9: 11(int) SpecConstantOp 81 5 2 + 10: 11(int) SpecConstantOp 132 7 9 + 12: 11(int) SpecConstantOp 128 6 10 + 5663: 8 Function None 1282 + 16103: Label + Return + FunctionEnd diff --git a/gtests/Remap.FromFile.cpp b/gtests/Remap.FromFile.cpp index 9f25a6f2..50bce8e3 100644 --- a/gtests/Remap.FromFile.cpp +++ b/gtests/Remap.FromFile.cpp @@ -89,6 +89,7 @@ INSTANTIATE_TEST_CASE_P( { "remap.basic.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, { "remap.basic.dcefunc.frag", "main", Source::GLSL, spv::spirvbin_t::DCE_FUNCS }, { "remap.basic.strip.frag", "main", Source::GLSL, spv::spirvbin_t::STRIP }, + { "remap.specconst.comp", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, { "remap.switch.none.frag", "main", Source::GLSL, spv::spirvbin_t::NONE }, { "remap.switch.everything.frag", "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING }, { "remap.literal64.none.spv", "main", Source::GLSL, spv::spirvbin_t::NONE },