From aea3c890d3caeff3f1538c8ae9e6b50d1fbe8626 Mon Sep 17 00:00:00 2001
From: Flavio <flavio.bortot@autodesk.com>
Date: Mon, 6 Feb 2017 11:46:35 -0800
Subject: [PATCH] Added --vn option to generate a C header file containing a
 variable assigned to the hex representation of the shader. This is a standard
 feature on Microsoft's HLSL compiler and it allows developers to include
 pre-compiled shaders directly into the code. This option enables "Hex
 output", so it is NOT required to specify -x as well. The output file name is
 preserved, so no ".h" extension is added. If you want the output file to have
 ".h" extension then you have to specify it on the output file name. The
 generated header file uses the "#pragma once" pragma to avoid multiple
 inclusions.

---
 SPIRV/GlslangToSpv.cpp    |  9 ++++++++-
 SPIRV/GlslangToSpv.h      |  2 +-
 StandAlone/StandAlone.cpp | 20 ++++++++++++++++++--
 3 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 0b48dfcdd..09566c906 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -5254,11 +5254,15 @@ void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName)
 }
 
 // Write SPIR-V out to a text file with 32-bit hexadecimal words
-void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName)
+void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName)
 {
     std::ofstream out;
     out.open(baseName, std::ios::binary | std::ios::out);
     out << "\t// " GLSLANG_REVISION " " GLSLANG_DATE << std::endl;
+	if (varName != nullptr) {
+		out << "\t #pragma once" << std::endl;
+		out << "const uint32_t " << varName << "[] = {" << std::endl;
+	}
     const int WORDS_PER_LINE = 8;
     for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) {
         out << "\t";
@@ -5271,6 +5275,9 @@ void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName)
         }
         out << std::endl;
     }
+	if (varName != nullptr) {
+		out << "};";
+	}
     out.close();
 }
 
diff --git a/SPIRV/GlslangToSpv.h b/SPIRV/GlslangToSpv.h
index ceb23b5a5..11e22f588 100644
--- a/SPIRV/GlslangToSpv.h
+++ b/SPIRV/GlslangToSpv.h
@@ -49,6 +49,6 @@ void GetSpirvVersion(std::string&);
 void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
 void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger);
 void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
-void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName);
+void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
 
 }
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index d133b5948..fb37f8f2b 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -163,6 +163,7 @@ const char* binaryFileName = nullptr;
 const char* entryPointName = nullptr;
 const char* sourceEntryPointName = nullptr;
 const char* shaderStageName = nullptr;
+const char* variableName = nullptr;
 
 std::array<unsigned int, EShLangCount> baseSamplerBinding;
 std::array<unsigned int, EShLangCount> baseTextureBinding;
@@ -302,7 +303,20 @@ void ProcessArguments(int argc, char* argv[])
                     } else if (lowerword == "no-storage-format" || // synonyms
                                lowerword == "nsf") {
                         Options |= EOptionNoStorageFormat;
-                    } else if (lowerword == "source-entrypoint" || // synonyms
+					}
+					else if (lowerword == "variable-name" || // synonyms
+						lowerword == "vn") {
+						Options |= EOptionOutputHexadecimal;
+						variableName = argv[1];
+						if (argc > 0) {
+							argc--;
+							argv++;
+						}
+						else
+							Error("no <C-variable-name> provided for --variable-name");
+						break;
+					}
+					else if (lowerword == "source-entrypoint" || // synonyms
                                lowerword == "sep") {
                         sourceEntryPointName = argv[1];
                         if (argc > 0) {
@@ -650,7 +664,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
                     if (! (Options & EOptionMemoryLeakMode)) {
                         printf("%s", logger.getAllMessages().c_str());
                         if (Options & EOptionOutputHexadecimal) {
-                            glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage));
+							glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage), variableName);
                         } else {
                             glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
                         }
@@ -987,6 +1001,8 @@ void usage()
            "\n"
            "  --keep-uncalled                         don't eliminate uncalled functions when linking\n"
            "  --ku                                    synonym for --keep-uncalled\n"
+		   "  --variable-name <name>                  Creates a C header file that contains a uint32_t array named <name> initialized with the shader binary code.\n"
+		   "  --vn <name>                             synonym for --variable-name <name>.\n"
            );
 
     exit(EFailUsage);
-- 
GitLab