Commit c555dddd by John Kessenich

glslang preprocessing: Add -E option to print out preprocessed GLSL, and do the…

glslang preprocessing: Add -E option to print out preprocessed GLSL, and do the work needed to generate a preprocessed stream. From Andrew Woloszyn <awoloszyn@google.com>. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@31508 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent 9288f46b
...@@ -71,6 +71,7 @@ enum TOptions { ...@@ -71,6 +71,7 @@ enum TOptions {
EOptionSpv = 0x0800, EOptionSpv = 0x0800,
EOptionHumanReadableSpv = 0x1000, EOptionHumanReadableSpv = 0x1000,
EOptionDefaultDesktop = 0x2000, EOptionDefaultDesktop = 0x2000,
EOptionOutputPreprocessed = 0x4000,
}; };
// //
...@@ -489,6 +490,9 @@ bool ProcessArguments(int argc, char* argv[]) ...@@ -489,6 +490,9 @@ bool ProcessArguments(int argc, char* argv[])
Options |= EOptionSpv; Options |= EOptionSpv;
Options |= EOptionLinkProgram; Options |= EOptionLinkProgram;
break; break;
case 'E':
Options |= EOptionOutputPreprocessed;
break;
case 'c': case 'c':
Options |= EOptionDumpConfig; Options |= EOptionDumpConfig;
break; break;
...@@ -536,6 +540,13 @@ bool ProcessArguments(int argc, char* argv[]) ...@@ -536,6 +540,13 @@ bool ProcessArguments(int argc, char* argv[])
} }
} }
// Make sure that -E is not specified alongside -V -H or -l.
if (Options & EOptionOutputPreprocessed &&
((Options &
(EOptionSpv | EOptionHumanReadableSpv | EOptionLinkProgram)))) {
return false;
}
return true; return true;
} }
...@@ -608,12 +619,19 @@ void CompileAndLinkShaders() ...@@ -608,12 +619,19 @@ void CompileAndLinkShaders()
usage(); usage();
return; return;
} }
const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100;
shader->setStrings(shaderStrings, 1); shader->setStrings(shaderStrings, 1);
if (Options & EOptionOutputPreprocessed) {
if (! shader->parse(&Resources, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages)) std::string str;
shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str);
puts(str.c_str());
FreeFileData(shaderStrings);
continue;
}
if (! shader->parse(&Resources, defaultVersion, false, messages))
CompileFailed = true; CompileFailed = true;
program.addShader(shader); program.addShader(shader);
if (! (Options & EOptionSuppressInfolog)) { if (! (Options & EOptionSuppressInfolog)) {
...@@ -629,7 +647,7 @@ void CompileAndLinkShaders() ...@@ -629,7 +647,7 @@ void CompileAndLinkShaders()
// Program-level processing... // Program-level processing...
// //
if (! program.link(messages)) if (!(Options & EOptionOutputPreprocessed) && ! program.link(messages))
LinkFailed = true; LinkFailed = true;
if (! (Options & EOptionSuppressInfolog)) { if (! (Options & EOptionSuppressInfolog)) {
...@@ -714,7 +732,8 @@ int C_DECL main(int argc, char* argv[]) ...@@ -714,7 +732,8 @@ int C_DECL main(int argc, char* argv[])
// 1) linking all arguments together, single-threaded, new C++ interface // 1) linking all arguments together, single-threaded, new C++ interface
// 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface // 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface
// //
if (Options & EOptionLinkProgram) { if (Options & EOptionLinkProgram ||
Options & EOptionOutputPreprocessed) {
glslang::InitializeProcess(); glslang::InitializeProcess();
CompileAndLinkShaders(); CompileAndLinkShaders();
glslang::FinalizeProcess(); glslang::FinalizeProcess();
...@@ -868,6 +887,7 @@ void usage() ...@@ -868,6 +887,7 @@ void usage()
"(Each option must be specified separately, but can go anywhere in the command line.)\n" "(Each option must be specified separately, but can go anywhere in the command line.)\n"
" -V create SPIR-V in file <stage>.spv\n" " -V create SPIR-V in file <stage>.spv\n"
" -H print human readable form of SPIR-V; turns on -V\n" " -H print human readable form of SPIR-V; turns on -V\n"
" -E print pre-processed GLSL; cannot be used with -V, -H, or -l.\n"
" -c configuration dump; use to create default configuration file (redirect to a .conf file)\n" " -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
" -d default to desktop (#version 110) when there is no version in the shader (default is ES version 100)\n" " -d default to desktop (#version 110) when there is no version in the shader (default is ES version 100)\n"
" -i intermediate tree (glslang AST) is printed out\n" " -i intermediate tree (glslang AST) is printed out\n"
......
#version 310 es
void main(){
gl_Position = vec4(3 + 2 + 2 * 4 + 2 + 3 * 2);
}
#version 310 es
#error This should show up in pp output .
int main(){
}
#version 310 es
#extension GL_OES_texture_3D : enable
#extension GL_EXT_frag_depth : disable
#extension GL_EXT_gpu_shader5 : require
#extension GL_EXT_shader_texture_image_samples : warn
#extension unknown_extension : require
int main(){
}
#version 310 es
int main(){
gl_Position = vec4(3 + 1, 3 + 4, 3 + 1);
gl_Position = vec4(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12);
gl_Position = vec4(4 + 3 + 3);
}
#line 300
#line 2
#line 10
#line 2
#line 0
#line 4
#line 8
void main(){
gl_Position = vec4(10);
}
#line 8 4
#line 12 3
#line 1
#version 310 es
#pragma optimize(on)
#pragma optimize(off)
#pragma debug(on)
#pragma debug(off)
#pragma undefined_pragma(x,4)
int main(){
}
#version 310 es
float fn(float x){ return x + 4.0;}
int main(){
gl_Position = vec4(1);
gl_Position = clamp(1, 2, 3);
gl_Position = vec4(1);
gl_Position = vec4(1, 2);
gl_Position = vec4(fn(3));
}
#version 310 es
#define X(Y) /*
*/ Y + 2
#define Y(Z) 2 * Z// asdf
#define Z(Y) /*
*/ \
2 /*
*/ + 3 \
* Y
void main() {
gl_Position = vec4(X(3) + Y(4) + Z(2));
}
#version 310 es
#define X
#if X
#if Y
#error This should not show up in pp output.
#endif
#error This should show up in pp output.
#else
#error This should not show up in pp output.
#endif
int main() {
}
#version 310 es
#extension GL_OES_texture_3D: enable
#extension GL_EXT_frag_depth: disable
#extension GL_EXT_gpu_shader5: require
#extension GL_EXT_shader_texture_image_samples: warn
#extension unknown_extension: require
int main() {
}
#version 310 es
#define X(n) n + 1
#define Y(n, z) n + z
#define Z(f) X(f)
#define REALLY_LONG_MACRO_NAME_WITH_MANY_PARAMETERS(X1, X2, X3, X4, X5, X6, X7,\
X8, X9, X10, X11, X12) X1+X2+X3+X4+X5+X6+X7+X8+X9+X10+X11+X12
#define A(\
Y\
)\
4 + 3 + Y
int main() {
gl_Position = vec4(X(3), Y(3, 4), Z(3));
gl_Position = vec4(REALLY_LONG_MACRO_NAME_WITH_MANY_PARAMETERS(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
gl_Position = vec4(A(3));
}
#line 300
#line 2
#line __LINE__ + 3
#line __FILE__ + 2
#line __FILE__ * __LINE__
#define X 4
#line X
#undef X
#define X(y) y + 3 + 2
#line X(3)
void main() {
gl_Position = vec4(__LINE__);
}
#line X(3) 4
#define Z(y, q) \
y*q*2 q
#line Z(2, 3)
#line 1
#version 310 es
#pragma optimize(on)
#pragma optimize(off)
#pragma debug(on)
#pragma debug(off)
#pragma undefined_pragma(x, 4)
int main() {
}
#version 310 es
#define X 1
#define Y clamp
#define Z X
#define F 1, 2
#define make_function \
float fn ( float x ) \
{\
return x + 4.0; \
}
make_function
int main() {
gl_Position = vec4(X);
gl_Position = Y(1, 2, 3);
gl_Position = vec4(Z);
gl_Position = vec4(F);
gl_Position = vec4(fn(3));
}
...@@ -55,6 +55,16 @@ while read t; do ...@@ -55,6 +55,16 @@ while read t; do
done < test-spirv-list done < test-spirv-list
# #
# Preprocessor tests
#
while read t; do
echo Running Preprocessor $t...
b=`basename $t`
$EXE -E $t > $TARGETDIR/$b.out
diff -b $BASEDIR/$b.out $TARGETDIR/$b.out || HASERROR=1
done < test-preprocessor-list
#
# grouped shaders for bulk (faster) tests # grouped shaders for bulk (faster) tests
# #
function runBulkTest { function runBulkTest {
......
preprocessor.edge_cases.vert
preprocessor.errors.vert
preprocessor.extensions.vert
preprocessor.function_macro.vert
preprocessor.line.vert
preprocessor.pragma.vert
preprocessor.simple.vert
...@@ -14,7 +14,6 @@ spv.double.comp ...@@ -14,7 +14,6 @@ spv.double.comp
spv.100ops.frag spv.100ops.frag
spv.130.frag spv.130.frag
spv.140.frag spv.140.frag
spv.140.vert
spv.150.geom spv.150.geom
spv.150.vert spv.150.vert
spv.300BuiltIns.vert spv.300BuiltIns.vert
......
...@@ -5226,20 +5226,25 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression, ...@@ -5226,20 +5226,25 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression,
return switchNode; return switchNode;
} }
void TParseContext::setCurrentLine(int line) void TParseContext::notifyVersion(int line, int version, const char* type_string)
{ {
currentScanner->setLine(line); if (versionCallback) {
if (lineCallback) { versionCallback(line, version, type_string);
lineCallback(line);
} }
} }
void TParseContext::notifyVersion(int line, int version, const char* type_string) void TParseContext::notifyErrorDirective(int line, const char* error_message)
{ {
if (versionCallback) { if (errorCallback) {
versionCallback(line, version, type_string); errorCallback(line, error_message);
} }
} }
void TParseContext::notifyLineDirective(int line, bool has_source, int source)
{
if (lineCallback) {
lineCallback(line, has_source, source);
}
}
} // end namespace glslang } // end namespace glslang
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "SymbolTable.h" #include "SymbolTable.h"
#include "localintermediate.h" #include "localintermediate.h"
#include "Scan.h" #include "Scan.h"
#include <functional>
#include <functional> #include <functional>
...@@ -200,10 +201,13 @@ public: ...@@ -200,10 +201,13 @@ public:
void addError() { ++numErrors; } void addError() { ++numErrors; }
int getNumErrors() const { return numErrors; } int getNumErrors() const { return numErrors; }
const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); } const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); }
void setCurrentLine(int line); void setCurrentLine(int line) { currentScanner->setLine(line); }
void setCurrentString(int string) { currentScanner->setString(string); } void setCurrentString(int string) { currentScanner->setString(string); }
void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
void notifyVersion(int line, int version, const char* type_string); void notifyVersion(int line, int version, const char* type_string);
void notifyErrorDirective(int line, const char* error_message);
void notifyLineDirective(int line, bool has_source, int source);
// The following are implemented in Versions.cpp to localize version/profile/stage/extensions control // The following are implemented in Versions.cpp to localize version/profile/stage/extensions control
void initializeExtensionBehavior(); void initializeExtensionBehavior();
...@@ -223,8 +227,9 @@ public: ...@@ -223,8 +227,9 @@ public:
void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; } void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; } void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
void setLineCallback(const std::function<void(int)>& func) { lineCallback = func; } void setLineCallback(const std::function<void(int, bool, int)>& func) { lineCallback = func; }
void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; } void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
protected: protected:
void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type); void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type);
...@@ -333,10 +338,11 @@ protected: ...@@ -333,10 +338,11 @@ protected:
// These, if set, will be called when a line, pragma ... is preprocessed. // These, if set, will be called when a line, pragma ... is preprocessed.
// They will be called with any parameters to the original directive. // They will be called with any parameters to the original directive.
std::function<void(int)> lineCallback; std::function<void(int, bool, int)> lineCallback;
std::function<void(int, const TVector<TString>&)> pragmaCallback; std::function<void(int, const TVector<TString>&)> pragmaCallback;
std::function<void(int, int, const char*)> versionCallback; std::function<void(int, int, const char*)> versionCallback;
std::function<void(int, const char*, const char*)> extensionCallback; std::function<void(int, const char*, const char*)> extensionCallback;
std::function<void(int, const char*)> errorCallback;
}; };
} // end namespace glslang } // end namespace glslang
......
...@@ -629,10 +629,15 @@ int TPpContext::CPPline(TPpToken* ppToken) ...@@ -629,10 +629,15 @@ int TPpContext::CPPline(TPpToken* ppToken)
return token; return token;
} }
int lineRes = 0; int lineRes = 0; // Line number after macro expansion.
int lineToken = 0;
int fileRes = 0; // Source file number after macro expansion.
bool hasFile = false;
bool lineErr = false; bool lineErr = false;
bool fileErr = false;
token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken);
if (! lineErr) { if (! lineErr) {
lineToken = lineRes;
if (token == '\n') if (token == '\n')
++lineRes; ++lineRes;
...@@ -648,14 +653,15 @@ int TPpContext::CPPline(TPpToken* ppToken) ...@@ -648,14 +653,15 @@ int TPpContext::CPPline(TPpToken* ppToken)
parseContext.setCurrentLine(lineRes); parseContext.setCurrentLine(lineRes);
if (token != '\n') { if (token != '\n') {
int fileRes = 0;
bool fileErr = false;
token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken); token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken);
if (! fileErr) if (! fileErr)
parseContext.setCurrentString(fileRes); parseContext.setCurrentString(fileRes);
hasFile = true;
} }
} }
if (!fileErr && !lineErr) {
parseContext.notifyLineDirective(lineToken, hasFile, fileRes);
}
token = extraTokenCheck(lineAtom, ppToken, token); token = extraTokenCheck(lineAtom, ppToken, token);
return token; return token;
...@@ -680,6 +686,7 @@ int TPpContext::CPPerror(TPpToken* ppToken) ...@@ -680,6 +686,7 @@ int TPpContext::CPPerror(TPpToken* ppToken)
message.append(" "); message.append(" ");
token = scanToken(ppToken); token = scanToken(ppToken);
} }
parseContext.notifyErrorDirective(loc.line, message.c_str());
//store this msg into the shader's information log..set the Compile Error flag!!!! //store this msg into the shader's information log..set the Compile Error flag!!!!
parseContext.error(loc, message.c_str(), "#error", ""); parseContext.error(loc, message.c_str(), "#error", "");
......
...@@ -245,6 +245,7 @@ SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* ...@@ -245,6 +245,7 @@ SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char*
// //
#include <list> #include <list>
#include <string>
class TCompiler; class TCompiler;
class TInfoSink; class TInfoSink;
...@@ -284,6 +285,10 @@ public: ...@@ -284,6 +285,10 @@ public:
// Equivalent to parse() without a default profile and without forcing defaults. // Equivalent to parse() without a default profile and without forcing defaults.
// Provided for backwards compatibility. // Provided for backwards compatibility.
bool parse(const TBuiltInResource*, int defaultVersion, bool forwardCompatible, EShMessages); bool parse(const TBuiltInResource*, int defaultVersion, bool forwardCompatible, EShMessages);
bool preprocess(const TBuiltInResource* builtInResources,
int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible,
EShMessages message, std::string* outputString);
const char* getInfoLog(); const char* getInfoLog();
const char* getInfoDebugLog(); const char* getInfoDebugLog();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment