From 1719fb207ac11df4ac02b379dabe811596828bed Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Tue, 21 Jul 2015 10:23:43 -0400 Subject: [PATCH] Add mechanism for specifying names for source strings. Expose a new method setStringsWithLengthsAndNames() in the interface which allows the caller to set descriptive names for source strings. These names can be used in error messages. --- glslang/MachineIndependent/Scan.h | 6 ++- glslang/MachineIndependent/ShaderLang.cpp | 66 +++++++++++++++++------ glslang/Public/ShaderLang.h | 6 +++ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/glslang/MachineIndependent/Scan.h b/glslang/MachineIndependent/Scan.h index a6eb8091..ff7bfa2f 100644 --- a/glslang/MachineIndependent/Scan.h +++ b/glslang/MachineIndependent/Scan.h @@ -51,7 +51,7 @@ const int EndOfInput = -1; // class TInputScanner { public: - TInputScanner(int n, const char* const s[], size_t L[], int b = 0, int f = 0) : + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, int b = 0, int f = 0) : numSources(n), sources(reinterpret_cast(s)), // up to this point, common usage is "char*", but now we need positive 8-bit characters lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f) @@ -60,6 +60,10 @@ public: for (int i = 0; i < numSources; ++i) { loc[i].init(); } + if (names != nullptr) { + for (int i = 0; i < numSources; ++i) + loc[i].name = names[i]; + } loc[currentSource].string = -stringBias; loc[currentSource].line = 1; loc[currentSource].column = 0; diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 3955c0b1..e98df614 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -450,6 +450,7 @@ bool ProcessDeferred( const char* const shaderStrings[], const int numStrings, const int* inputLengths, + const char* const stringNames[], const char* customPreamble, const EShOptimizationLevel optLevel, const TBuiltInResource* resources, @@ -485,8 +486,10 @@ bool ProcessDeferred( // string numStrings+2: "int;" const int numPre = 2; const int numPost = requireNonempty? 1 : 0; - size_t* lengths = new size_t[numStrings + numPre + numPost]; - const char** strings = new const char*[numStrings + numPre + numPost]; + const int numTotal = numPre + numStrings + numPost; + size_t* lengths = new size_t[numTotal]; + const char** strings = new const char*[numTotal]; + const char** names = new const char*[numTotal]; for (int s = 0; s < numStrings; ++s) { strings[s + numPre] = shaderStrings[s]; if (inputLengths == 0 || inputLengths[s] < 0) @@ -494,6 +497,13 @@ bool ProcessDeferred( else lengths[s + numPre] = inputLengths[s]; } + if (stringNames != nullptr) { + for (int s = 0; s < numStrings; ++s) + names[s + numPre] = stringNames[s]; + } else { + for (int s = 0; s < numStrings; ++s) + names[s + numPre] = nullptr; + } // First, without using the preprocessor or parser, find the #version, so we know what // symbol tables, processing rules, etc. to set up. This does not need the extra strings @@ -573,14 +583,18 @@ bool ProcessDeferred( // Fill in the strings as outlined above. strings[0] = parseContext.getPreamble(); lengths[0] = strlen(strings[0]); + names[0] = nullptr; strings[1] = customPreamble; lengths[1] = strlen(strings[1]); + names[1] = nullptr; assert(2 == numPre); if (requireNonempty) { - strings[numStrings + numPre] = "\n int;"; - lengths[numStrings + numPre] = strlen(strings[numStrings + numPre]); + const int postIndex = numStrings + numPre; + strings[postIndex] = "\n int;"; + lengths[postIndex] = strlen(strings[numStrings + numPre]); + names[postIndex] = nullptr; } - TInputScanner fullInput(numStrings + numPre + numPost, strings, lengths, numPre, numPost); + TInputScanner fullInput(numStrings + numPre + numPost, strings, lengths, names, numPre, numPost); // Push a new symbol allocation scope that will get used for the shader's globals. symbolTable.push(); @@ -595,6 +609,7 @@ bool ProcessDeferred( delete [] lengths; delete [] strings; + delete [] names; return success; } @@ -814,6 +829,7 @@ bool PreprocessDeferred( const char* const shaderStrings[], const int numStrings, const int* inputLengths, + const char* const stringNames[], const char* preamble, const EShOptimizationLevel optLevel, const TBuiltInResource* resources, @@ -826,8 +842,9 @@ bool PreprocessDeferred( std::string* outputString) { DoPreprocessing parser(outputString); - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, - preamble, optLevel, resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, + return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, + preamble, optLevel, resources, defaultVersion, + defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, intermediate, parser, false); } @@ -848,6 +865,7 @@ bool CompileDeferred( const char* const shaderStrings[], const int numStrings, const int* inputLengths, + const char* const stringNames[], const char* preamble, const EShOptimizationLevel optLevel, const TBuiltInResource* resources, @@ -859,8 +877,9 @@ bool CompileDeferred( TIntermediate& intermediate) // returned tree, etc. { DoFullParse parser; - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, - preamble, optLevel, resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, + return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, + preamble, optLevel, resources, defaultVersion, + defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, intermediate, parser, true); } @@ -1003,7 +1022,9 @@ int ShCompile( compiler->infoSink.debug.erase(); TIntermediate intermediate(compiler->getLanguage()); - bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, "", optLevel, resources, defaultVersion, ENoProfile, false, forwardCompatible, messages, intermediate); + bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, + "", optLevel, resources, defaultVersion, ENoProfile, false, + forwardCompatible, messages, intermediate); // // Call the machine dependent compiler @@ -1262,7 +1283,7 @@ public: }; TShader::TShader(EShLanguage s) - : pool(0), stage(s), preamble(""), lengths(nullptr) + : pool(0), stage(s), preamble(""), lengths(nullptr), stringNames(nullptr) { infoSink = new TInfoSink; compiler = new TDeferredCompiler(stage, *infoSink); @@ -1290,6 +1311,16 @@ void TShader::setStringsWithLengths(const char* const* s, const int* l, int n) numStrings = n; lengths = l; } + +void TShader::setStringsWithLengthsAndNames( + const char* const* s, const int* l, const char* const* names, int n) +{ + strings = s; + numStrings = n; + lengths = l; + stringNames = names; +} + // // Turn the shader strings into a parse tree in the TIntermediate. // @@ -1306,7 +1337,10 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion if (! preamble) preamble = ""; - return CompileDeferred(compiler, strings, numStrings, lengths, preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, *intermediate); + return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, + preamble, EShOptNone, builtInResources, defaultVersion, + defaultProfile, forceDefaultVersionAndProfile, + forwardCompatible, messages, *intermediate); } bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) @@ -1329,10 +1363,10 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources, if (! preamble) preamble = ""; - return PreprocessDeferred(compiler, strings, numStrings, - lengths, preamble, EShOptNone, builtInResources, - defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, message, - *intermediate, output_string); + return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, + EShOptNone, builtInResources, defaultVersion, + defaultProfile, forceDefaultVersionAndProfile, + forwardCompatible, message, *intermediate, output_string); } const char* TShader::getInfoLog() diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 34ba48f8..edca638c 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -285,6 +285,8 @@ public: virtual ~TShader(); void setStrings(const char* const* s, int n); void setStringsWithLengths(const char* const* s, const int* l, int n); + void setStringsWithLengthsAndNames( + const char* const* s, const int* l, const char* const* names, int n); void setPreamble(const char* s) { preamble = s; } bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages); // Equivalent to parse() without a default profile and without forcing defaults. @@ -312,8 +314,12 @@ protected: // integers containing the length of the associated strings. // if lengths is null or lengths[n] < 0 the associated strings[n] is // assumed to be null-terminated. + // stringNames is the optional names for all the strings. If stringNames + // is null, then none of the strings has name. If a certain element in + // stringNames is null, then the corresponding string does not have name. const char* const* strings; const int* lengths; + const char* const* stringNames; const char* preamble; int numStrings;