From 6a6aaeffd38d64ec69e2b0ac1a39b7768119d3f9 Mon Sep 17 00:00:00 2001 From: Andrew Woloszyn Date: Thu, 16 Jul 2015 09:48:47 -0400 Subject: [PATCH] Added a setStringsWithLengths() method to TShader. This allows us to pass through non null-terminated strings. --- glslang/MachineIndependent/Scan.h | 16 +++++++++++++--- glslang/MachineIndependent/ShaderLang.cpp | 23 +++++++++++++++++++---- glslang/Public/ShaderLang.h | 13 +++++++++++-- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/glslang/MachineIndependent/Scan.h b/glslang/MachineIndependent/Scan.h index 5c3b28cc..9c496216 100644 --- a/glslang/MachineIndependent/Scan.h +++ b/glslang/MachineIndependent/Scan.h @@ -69,7 +69,7 @@ public: if (currentSource >= numSources) return -1; - int ret = sources[currentSource][currentChar]; + int ret = peek(); ++loc[currentSource].column; if (ret == '\n') { ++loc[currentSource].line; @@ -85,8 +85,18 @@ public: { if (currentSource >= numSources) return -1; - - return sources[currentSource][currentChar]; + // Make sure we do not read off the end of a string. + // N.B. Sources can have a length of 0. + int sourceToRead = currentSource; + int charToRead = currentChar; + while(charToRead >= lengths[sourceToRead]) { + charToRead = 0; + sourceToRead += 1; + if (sourceToRead >= numSources) { + return -1; + } + } + return sources[sourceToRead][charToRead]; } // go back one character diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 15bc258f..02fdc094 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -599,6 +599,7 @@ bool ProcessDeferred( return success; } + // DoPreprocessing is a valid ProcessingContext template argument, // which only performs the preprocessing step of compilation. // It places the result in the "string" argument to its constructor. @@ -639,6 +640,7 @@ struct DoPreprocessing { adjustLine(line); outputStream << "#extension " << extension << " : " << behavior; }); + parseContext.setLineCallback([&adjustLine, &lastLine, &outputStream, &parseContext]( int curLineNo, int newLineNo, bool hasSource, int sourceNum) { // SourceNum is the number of the source-string that is being parsed. @@ -658,7 +660,6 @@ struct DoPreprocessing { lastLine = newLineNo; }); - parseContext.setVersionCallback( [&adjustLine, &outputStream](int line, int version, const char* str) { adjustLine(line); @@ -682,6 +683,7 @@ struct DoPreprocessing { adjustLine(line); outputStream << "#error " << errorMessage; }); + while (const char* tok = ppContext.tokenize(&token)) { int tokenLine = token.loc.line - 1; // start at 0; bool newLine = false; @@ -1216,7 +1218,7 @@ public: }; TShader::TShader(EShLanguage s) - : pool(0), stage(s), preamble("") + : pool(0), stage(s), preamble(""), lengths(nullptr) { infoSink = new TInfoSink; compiler = new TDeferredCompiler(stage, *infoSink); @@ -1231,6 +1233,19 @@ TShader::~TShader() delete pool; } +void TShader::setStrings(const char* const* s, int n) +{ + strings = s; + numStrings = n; + lengths = nullptr; +} + +void TShader::setStringsWithLengths(const char* const* s, const int* l, int n) +{ + strings = s; + numStrings = n; + lengths = l; +} // // Turn the shader strings into a parse tree in the TIntermediate. // @@ -1247,7 +1262,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion if (! preamble) preamble = ""; - return CompileDeferred(compiler, strings, numStrings, nullptr, preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, *intermediate); + return CompileDeferred(compiler, strings, numStrings, lengths, preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, *intermediate); } bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) @@ -1271,7 +1286,7 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources, preamble = ""; return PreprocessDeferred(compiler, strings, numStrings, - nullptr, preamble, EShOptNone, builtInResources, + lengths, preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, message, *intermediate, output_string); } diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index d753c8af..34ba48f8 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -269,7 +269,8 @@ bool InitializeProcess(); void FinalizeProcess(); // Make one TShader per shader that you will link into a program. Then provide -// the shader through setStrings(), then call parse(), then query the info logs. +// the shader through setStrings() or setStringsWithLengths(), then call parse(), +// then query the info logs. // Optionally use setPreamble() to set a special shader string that will be // processed before all others but won't affect the validity of #version. // @@ -282,7 +283,8 @@ class TShader { public: explicit TShader(EShLanguage); virtual ~TShader(); - void setStrings(const char* const* s, int n) { strings = s; numStrings = n; } + void setStrings(const char* const* s, int n); + void setStringsWithLengths(const char* const* s, const int* l, 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. @@ -304,7 +306,14 @@ protected: TCompiler* compiler; TIntermediate* intermediate; TInfoSink* infoSink; + // strings and lengths follow the standard for glShaderSource: + // strings is an array of numStrings pointers to string data. + // lengths can be null, but if not it is an array of numStrings + // 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. const char* const* strings; + const int* lengths; const char* preamble; int numStrings;