From e2156222d36df354fbfa49fcf264074e1768ea01 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Mon, 11 Jun 2018 18:12:15 -0600
Subject: [PATCH] SPV: Add option to print disassembly in standard form using
 SPIRV-Tools.

---
 SPIRV/CMakeLists.txt      |  1 +
 SPIRV/disassemble.cpp     | 21 +++++++++++++++++++++
 SPIRV/disassemble.h       |  4 ++++
 StandAlone/CMakeLists.txt |  1 +
 StandAlone/StandAlone.cpp | 15 +++++++++++++--
 5 files changed, 40 insertions(+), 2 deletions(-)
 mode change 100644 => 100755 StandAlone/StandAlone.cpp

diff --git a/SPIRV/CMakeLists.txt b/SPIRV/CMakeLists.txt
index 1e5513c73..bf2be167e 100755
--- a/SPIRV/CMakeLists.txt
+++ b/SPIRV/CMakeLists.txt
@@ -60,6 +60,7 @@ if(ENABLE_OPT)
         PRIVATE ${spirv-tools_SOURCE_DIR}/source
     )
     target_link_libraries(SPIRV glslang SPIRV-Tools-opt)
+    target_include_directories(SPIRV PUBLIC ../External)
 else()
     target_link_libraries(SPIRV glslang)
 endif(ENABLE_OPT)
diff --git a/SPIRV/disassemble.cpp b/SPIRV/disassemble.cpp
index b432e65d0..16770c478 100755
--- a/SPIRV/disassemble.cpp
+++ b/SPIRV/disassemble.cpp
@@ -716,4 +716,25 @@ void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
     SpirvStream.processInstructions();
 }
 
+#if ENABLE_OPT
+
+#include "spirv-tools/source/disassemble.h"
+
+// Use the SPIRV-Tools disassembler to print SPIR-V.
+void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
+{
+    spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
+    spv_text text;
+    spv_diagnostic diagnostic = nullptr;
+    spvBinaryToText(context, &spirv.front(), spirv.size(),
+        SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
+        &text, &diagnostic);
+    if (diagnostic == nullptr)
+        out << text->str;
+    else
+        spvDiagnosticPrint(diagnostic);
+}
+
+#endif
+
 }; // end namespace spv
diff --git a/SPIRV/disassemble.h b/SPIRV/disassemble.h
index 47cef65a5..bdde5cb4e 100755
--- a/SPIRV/disassemble.h
+++ b/SPIRV/disassemble.h
@@ -45,8 +45,12 @@
 
 namespace spv {
 
+    // disassemble with glslang custom disassembler
     void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
 
+    // disassemble with SPIRV-Tools disassembler
+    void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& stream);
+
 };  // end namespace spv
 
 #endif // disassembler_H
diff --git a/StandAlone/CMakeLists.txt b/StandAlone/CMakeLists.txt
index d500121df..5cea53d9f 100755
--- a/StandAlone/CMakeLists.txt
+++ b/StandAlone/CMakeLists.txt
@@ -33,6 +33,7 @@ endif(WIN32)
 
 target_link_libraries(glslangValidator ${LIBRARIES})
 target_link_libraries(spirv-remap ${LIBRARIES})
+target_include_directories(glslangValidator PUBLIC ../External)
 
 if(WIN32)
     source_group("Source" FILES ${SOURCES})
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
old mode 100644
new mode 100755
index 6736dbcbf..549cb0dd9
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -102,6 +102,7 @@ enum TOptions {
     EOptionDumpBareVersion      = (1 << 31),
 };
 bool targetHlslFunctionality1 = false;
+bool SpvToolsDisassembler = false;
 
 //
 // Return codes from main/exit().
@@ -506,6 +507,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
                         sourceEntryPointName = argv[1];
                         bumpArg();
                         break;
+                    } else if (lowerword == "spirv-dis") {
+                        SpvToolsDisassembler = true;
                     } else if (lowerword == "stdin") {
                         Options |= EOptionStdin;
                         shaderStageName = argv[1];
@@ -982,9 +985,15 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
                         } else {
                             glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
                         }
-                        if (Options & EOptionHumanReadableSpv) {
+#if ENABLE_OPT
+                        if (SpvToolsDisassembler)
+                            spv::SpirvToolsDisassemble(std::cout, spirv);
+#else
+                        if (SpvToolsDisassembler)
+                            printf("SPIRV-Tools is not enabled; use -H for human readable SPIR-V\n");
+#endif
+                        if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv))
                             spv::Disassemble(std::cout, spirv);
-                        }
                     }
                 }
             }
@@ -1405,6 +1414,8 @@ void usage()
            "  --shift-UBO-binding [stage] [num set]... per-descriptor-set shift values\n"
            "  --shift-cbuffer-binding [stage] num  synonym for --shift-UBO-binding\n"
            "  --shift-cbuffer-binding [stage] [num set]... per-descriptor-set shift values\n"
+           "  --spirv-dis                          output standard form disassembly; works only\n"
+           "                                       when a SPIR-V generation option is also used\n"
            "  --sub [stage] num                    synonym for --shift-UBO-binding\n"
            "  --source-entrypoint <name>           the given shader source function is\n"
            "                                       renamed to be the <name> given in -e\n"
-- 
GitLab