mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-09 12:00:05 +00:00
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
This commit is contained in:
parent
9288f46b95
commit
c555dddd53
@ -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[])
|
|||||||
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[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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()
|
|||||||
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()
|
|||||||
// 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[])
|
|||||||
// 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()
|
|||||||
"(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"
|
||||||
|
18
Test/baseResults/preprocessor.edge_cases.vert.out
Normal file
18
Test/baseResults/preprocessor.edge_cases.vert.out
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
gl_Position = vec4(3 + 2 + 2 * 4 + 2 + 3 * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
18
Test/baseResults/preprocessor.errors.vert.out
Normal file
18
Test/baseResults/preprocessor.errors.vert.out
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#error This should show up in pp output .
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
14
Test/baseResults/preprocessor.extensions.vert.out
Normal file
14
Test/baseResults/preprocessor.extensions.vert.out
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#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(){
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
23
Test/baseResults/preprocessor.function_macro.vert.out
Normal file
23
Test/baseResults/preprocessor.function_macro.vert.out
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
26
Test/baseResults/preprocessor.line.vert.out
Normal file
26
Test/baseResults/preprocessor.line.vert.out
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
14
Test/baseResults/preprocessor.pragma.vert.out
Normal file
14
Test/baseResults/preprocessor.pragma.vert.out
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
#pragma optimize(on)
|
||||||
|
#pragma optimize(off)
|
||||||
|
#pragma debug(on)
|
||||||
|
#pragma debug(off)
|
||||||
|
|
||||||
|
#pragma undefined_pragma(x,4)
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
25
Test/baseResults/preprocessor.simple.vert.out
Normal file
25
Test/baseResults/preprocessor.simple.vert.out
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
15
Test/preprocessor.edge_cases.vert
Normal file
15
Test/preprocessor.edge_cases.vert
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#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));
|
||||||
|
}
|
15
Test/preprocessor.errors.vert
Normal file
15
Test/preprocessor.errors.vert
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#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() {
|
||||||
|
}
|
12
Test/preprocessor.extensions.vert
Normal file
12
Test/preprocessor.extensions.vert
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#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() {
|
||||||
|
}
|
||||||
|
|
20
Test/preprocessor.function_macro.vert
Normal file
20
Test/preprocessor.function_macro.vert
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#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));
|
||||||
|
}
|
39
Test/preprocessor.line.vert
Normal file
39
Test/preprocessor.line.vert
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#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
|
||||||
|
|
11
Test/preprocessor.pragma.vert
Normal file
11
Test/preprocessor.pragma.vert
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#version 310 es
|
||||||
|
|
||||||
|
#pragma optimize(on)
|
||||||
|
#pragma optimize(off)
|
||||||
|
#pragma debug(on)
|
||||||
|
#pragma debug(off)
|
||||||
|
|
||||||
|
#pragma undefined_pragma(x, 4)
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
}
|
22
Test/preprocessor.simple.vert
Normal file
22
Test/preprocessor.simple.vert
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#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));
|
||||||
|
}
|
@ -54,6 +54,16 @@ while read t; do
|
|||||||
esac
|
esac
|
||||||
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
|
||||||
#
|
#
|
||||||
|
7
Test/test-preprocessor-list
Normal file
7
Test/test-preprocessor-list
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
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
|
|||||||
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,14 +5226,6 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression,
|
|||||||
return switchNode;
|
return switchNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TParseContext::setCurrentLine(int line)
|
|
||||||
{
|
|
||||||
currentScanner->setLine(line);
|
|
||||||
if (lineCallback) {
|
|
||||||
lineCallback(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TParseContext::notifyVersion(int line, int version, const char* type_string)
|
void TParseContext::notifyVersion(int line, int version, const char* type_string)
|
||||||
{
|
{
|
||||||
if (versionCallback) {
|
if (versionCallback) {
|
||||||
@ -5241,5 +5233,18 @@ void TParseContext::notifyVersion(int line, int version, const char* type_string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TParseContext::notifyErrorDirective(int line, const char* error_message)
|
||||||
|
{
|
||||||
|
if (errorCallback) {
|
||||||
|
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 @@
|
|||||||
#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:
|
|||||||
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:
|
|||||||
|
|
||||||
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:
|
|||||||
|
|
||||||
// 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
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
// and the shading language compiler/linker.
|
// and the shading language compiler/linker.
|
||||||
//
|
//
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include "SymbolTable.h"
|
#include "SymbolTable.h"
|
||||||
#include "ParseHelper.h"
|
#include "ParseHelper.h"
|
||||||
#include "Scan.h"
|
#include "Scan.h"
|
||||||
@ -433,18 +435,17 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
|
|||||||
return correct;
|
return correct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the common setup and cleanup code for PreprocessDeferred and
|
||||||
|
// CompileDeferred.
|
||||||
|
// It takes any callable with a signature of
|
||||||
|
// bool (TParseContext& parseContext, TPpContext& ppContext,
|
||||||
|
// TInputScanner& input, bool versionWillBeError,
|
||||||
|
// TSymbolTable& , TIntermediate& ,
|
||||||
|
// EShOptimizationLevel , EShMessages );
|
||||||
|
// Which returns false if a failure was detected and true otherwise.
|
||||||
//
|
//
|
||||||
// Do a partial compile on the given strings for a single compilation unit
|
template<typename ProcessingContext>
|
||||||
// for a potential deferred link into a single stage (and deferred full compile of that
|
bool ProcessDeferred(
|
||||||
// stage through machine-dependent compilation).
|
|
||||||
//
|
|
||||||
// All preprocessing, parsing, semantic checks, etc. for a single compilation unit
|
|
||||||
// are done here.
|
|
||||||
//
|
|
||||||
// Return: The tree and other information is filled into the intermediate argument,
|
|
||||||
// and true is returned by the function for success.
|
|
||||||
//
|
|
||||||
bool CompileDeferred(
|
|
||||||
TCompiler* compiler,
|
TCompiler* compiler,
|
||||||
const char* const shaderStrings[],
|
const char* const shaderStrings[],
|
||||||
const int numStrings,
|
const int numStrings,
|
||||||
@ -459,7 +460,9 @@ bool CompileDeferred(
|
|||||||
bool forceDefaultVersionAndProfile,
|
bool forceDefaultVersionAndProfile,
|
||||||
bool forwardCompatible, // give errors for use of deprecated features
|
bool forwardCompatible, // give errors for use of deprecated features
|
||||||
EShMessages messages, // warnings/errors/AST; things to print out
|
EShMessages messages, // warnings/errors/AST; things to print out
|
||||||
TIntermediate& intermediate // returned tree, etc.
|
TIntermediate& intermediate, // returned tree, etc.
|
||||||
|
ProcessingContext& processingContext,
|
||||||
|
bool requireNonempty
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (! InitThread())
|
if (! InitThread())
|
||||||
@ -481,7 +484,7 @@ bool CompileDeferred(
|
|||||||
// string 2...numStrings+1: user's shader
|
// string 2...numStrings+1: user's shader
|
||||||
// string numStrings+2: "int;"
|
// string numStrings+2: "int;"
|
||||||
const int numPre = 2;
|
const int numPre = 2;
|
||||||
const int numPost = 1;
|
const int numPost = requireNonempty? 1 : 0;
|
||||||
size_t* lengths = new size_t[numStrings + numPre + numPost];
|
size_t* lengths = new size_t[numStrings + numPre + numPost];
|
||||||
const char** strings = new const char*[numStrings + numPre + numPost];
|
const char** strings = new const char*[numStrings + numPre + numPost];
|
||||||
for (int s = 0; s < numStrings; ++s) {
|
for (int s = 0; s < numStrings; ++s) {
|
||||||
@ -566,7 +569,6 @@ bool CompileDeferred(
|
|||||||
|
|
||||||
parseContext.initializeExtensionBehavior();
|
parseContext.initializeExtensionBehavior();
|
||||||
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
// Fill in the strings as outlined above.
|
// Fill in the strings as outlined above.
|
||||||
strings[0] = parseContext.getPreamble();
|
strings[0] = parseContext.getPreamble();
|
||||||
@ -574,33 +576,22 @@ bool CompileDeferred(
|
|||||||
strings[1] = customPreamble;
|
strings[1] = customPreamble;
|
||||||
lengths[1] = strlen(strings[1]);
|
lengths[1] = strlen(strings[1]);
|
||||||
assert(2 == numPre);
|
assert(2 == numPre);
|
||||||
strings[numStrings + numPre] = "\n int;";
|
if (requireNonempty) {
|
||||||
lengths[numStrings + numPre] = strlen(strings[numStrings + numPre]);
|
strings[numStrings + numPre] = "\n int;";
|
||||||
|
lengths[numStrings + numPre] = strlen(strings[numStrings + numPre]);
|
||||||
|
}
|
||||||
TInputScanner fullInput(numStrings + numPre + numPost, strings, lengths, numPre, numPost);
|
TInputScanner fullInput(numStrings + numPre + numPost, strings, lengths, numPre, numPost);
|
||||||
|
|
||||||
// Push a new symbol allocation scope that will get used for the shader's globals.
|
// Push a new symbol allocation scope that will get used for the shader's globals.
|
||||||
symbolTable.push();
|
symbolTable.push();
|
||||||
|
|
||||||
// Parse the full shader.
|
bool success = processingContext(parseContext, ppContext, fullInput,
|
||||||
if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError))
|
versionWillBeError, symbolTable,
|
||||||
success = false;
|
intermediate, optLevel, messages);
|
||||||
intermediate.addSymbolLinkageNodes(parseContext.linkage, parseContext.language, symbolTable);
|
|
||||||
|
|
||||||
// Clean up the symbol table. The AST is self-sufficient now.
|
// Clean up the symbol table. The AST is self-sufficient now.
|
||||||
delete symbolTableMemory;
|
delete symbolTableMemory;
|
||||||
|
|
||||||
if (success && intermediate.getTreeRoot()) {
|
|
||||||
if (optLevel == EShOptNoGeneration)
|
|
||||||
parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
|
|
||||||
else
|
|
||||||
success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.language);
|
|
||||||
} else if (! success) {
|
|
||||||
parseContext.infoSink.info.prefix(EPrefixError);
|
|
||||||
parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (messages & EShMsgAST)
|
|
||||||
intermediate.output(parseContext.infoSink, true);
|
|
||||||
|
|
||||||
delete [] lengths;
|
delete [] lengths;
|
||||||
delete [] strings;
|
delete [] strings;
|
||||||
@ -608,6 +599,216 @@ bool CompileDeferred(
|
|||||||
return success;
|
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.
|
||||||
|
struct DoPreprocessing {
|
||||||
|
explicit DoPreprocessing(std::string* string): outputString(string) {}
|
||||||
|
bool operator()(TParseContext& parseContext, TPpContext& ppContext,
|
||||||
|
TInputScanner& input, bool versionWillBeError,
|
||||||
|
TSymbolTable& , TIntermediate& ,
|
||||||
|
EShOptimizationLevel , EShMessages )
|
||||||
|
{
|
||||||
|
// This is a list of tokens that do not require a space before or after.
|
||||||
|
static const std::string unNeededSpaceTokens = ";()[]";
|
||||||
|
static const std::string noSpaceBeforeTokens = ",";
|
||||||
|
glslang::TPpToken token;
|
||||||
|
|
||||||
|
std::stringstream outputStream;
|
||||||
|
int lastLine = -1; // lastLine is the line number of the last token
|
||||||
|
// processed. It is tracked in order for new-lines to be inserted when
|
||||||
|
// a token appears on a new line.
|
||||||
|
int lastToken = -1;
|
||||||
|
parseContext.setScanner(&input);
|
||||||
|
ppContext.setInput(input, versionWillBeError);
|
||||||
|
|
||||||
|
// Inserts newlines and incremnets lastLine until
|
||||||
|
// lastLine >= line.
|
||||||
|
auto adjustLine = [&lastLine, &outputStream](int line) {
|
||||||
|
int tokenLine = line - 1;
|
||||||
|
while(lastLine < tokenLine) {
|
||||||
|
if (lastLine >= 0) {
|
||||||
|
outputStream << std::endl;
|
||||||
|
}
|
||||||
|
++lastLine;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
parseContext.setExtensionCallback([&adjustLine, &outputStream](
|
||||||
|
int line, const char* extension, const char* behavior) {
|
||||||
|
adjustLine(line);
|
||||||
|
outputStream << "#extension " << extension << " : " << behavior;
|
||||||
|
});
|
||||||
|
parseContext.setLineCallback([&lastLine, &outputStream](
|
||||||
|
int line, bool hasSource, int sourceNum) {
|
||||||
|
// SourceNum is the number of the source-string that is being parsed.
|
||||||
|
if (lastLine != -1) {
|
||||||
|
outputStream << std::endl;
|
||||||
|
}
|
||||||
|
outputStream << "#line " << line;
|
||||||
|
if (hasSource) {
|
||||||
|
outputStream << " " << sourceNum;
|
||||||
|
}
|
||||||
|
outputStream << std::endl;
|
||||||
|
lastLine = std::max(line - 1, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
parseContext.setVersionCallback(
|
||||||
|
[&adjustLine, &lastLine, &outputStream](int line, int version, const char* str) {
|
||||||
|
adjustLine(line);
|
||||||
|
outputStream << "#version " << version;
|
||||||
|
if (str) {
|
||||||
|
outputStream << " " << str;
|
||||||
|
}
|
||||||
|
outputStream << std::endl;
|
||||||
|
++lastLine;
|
||||||
|
});
|
||||||
|
|
||||||
|
parseContext.setPragmaCallback([&adjustLine, &outputStream](
|
||||||
|
int line, const glslang::TVector<glslang::TString>& ops) {
|
||||||
|
adjustLine(line);
|
||||||
|
outputStream << "#pragma ";
|
||||||
|
for(size_t i = 0; i < ops.size(); ++i) {
|
||||||
|
outputStream << ops[i];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
parseContext.setErrorCallback([&adjustLine, &outputStream](
|
||||||
|
int line, const char* errorMessage) {
|
||||||
|
adjustLine(line);
|
||||||
|
outputStream << "#error " << errorMessage;
|
||||||
|
});
|
||||||
|
while (const char* tok = ppContext.tokenize(&token)) {
|
||||||
|
int tokenLine = token.loc.line - 1; // start at 0;
|
||||||
|
bool newLine = false;
|
||||||
|
while (lastLine < tokenLine) {
|
||||||
|
if (lastLine > -1) {
|
||||||
|
outputStream << std::endl;
|
||||||
|
newLine = true;
|
||||||
|
}
|
||||||
|
++lastLine;
|
||||||
|
if (lastLine == tokenLine) {
|
||||||
|
// Don't emit whitespace onto empty lines.
|
||||||
|
// Copy any whitespace characters at the start of a line
|
||||||
|
// from the input to the output.
|
||||||
|
for(int i = 0; i < token.loc.column - 1; ++i) {
|
||||||
|
outputStream << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output a space in between tokens, but not at the start of a line,
|
||||||
|
// and also not around special tokens. This helps with readability
|
||||||
|
// and consistency.
|
||||||
|
if (!newLine &&
|
||||||
|
lastToken != -1 &&
|
||||||
|
(unNeededSpaceTokens.find((char)token.token) == std::string::npos) &&
|
||||||
|
(unNeededSpaceTokens.find((char)lastToken) == std::string::npos) &&
|
||||||
|
(noSpaceBeforeTokens.find((char)token.token) == std::string::npos)) {
|
||||||
|
outputStream << " ";
|
||||||
|
}
|
||||||
|
lastToken = token.token;
|
||||||
|
outputStream << tok;
|
||||||
|
}
|
||||||
|
outputStream << std::endl;
|
||||||
|
*outputString = outputStream.str();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::string* outputString;
|
||||||
|
};
|
||||||
|
|
||||||
|
// DoFullParse is a valid ProcessingConext template argument for fully
|
||||||
|
// parsing the shader. It populates the "intermediate" with the AST.
|
||||||
|
struct DoFullParse{
|
||||||
|
bool operator()(TParseContext& parseContext, TPpContext& ppContext,
|
||||||
|
TInputScanner& fullInput, bool versionWillBeError,
|
||||||
|
TSymbolTable& symbolTable, TIntermediate& intermediate,
|
||||||
|
EShOptimizationLevel optLevel, EShMessages messages)
|
||||||
|
{
|
||||||
|
bool success = true;
|
||||||
|
// Parse the full shader.
|
||||||
|
if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError))
|
||||||
|
success = false;
|
||||||
|
intermediate.addSymbolLinkageNodes(parseContext.linkage, parseContext.language, symbolTable);
|
||||||
|
|
||||||
|
if (success && intermediate.getTreeRoot()) {
|
||||||
|
if (optLevel == EShOptNoGeneration)
|
||||||
|
parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested.");
|
||||||
|
else
|
||||||
|
success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.language);
|
||||||
|
} else if (! success) {
|
||||||
|
parseContext.infoSink.info.prefix(EPrefixError);
|
||||||
|
parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messages & EShMsgAST)
|
||||||
|
intermediate.output(parseContext.infoSink, true);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Take a single compilation unit, and run the preprocessor on it.
|
||||||
|
// Return: True if there were no issues found in preprocessing,
|
||||||
|
// False if during preprocessing any unknown version, pragmas or
|
||||||
|
// extensions were found.
|
||||||
|
bool PreprocessDeferred(
|
||||||
|
TCompiler* compiler,
|
||||||
|
const char* const shaderStrings[],
|
||||||
|
const int numStrings,
|
||||||
|
const int* inputLengths,
|
||||||
|
const char* preamble,
|
||||||
|
const EShOptimizationLevel optLevel,
|
||||||
|
const TBuiltInResource* resources,
|
||||||
|
int defaultVersion, // use 100 for ES environment, 110 for desktop
|
||||||
|
EProfile defaultProfile,
|
||||||
|
bool forceDefaultVersionAndProfile,
|
||||||
|
bool forwardCompatible, // give errors for use of deprecated features
|
||||||
|
EShMessages messages, // warnings/errors/AST; things to print out
|
||||||
|
TIntermediate& intermediate, // returned tree, etc.
|
||||||
|
std::string* outputString)
|
||||||
|
{
|
||||||
|
DoPreprocessing parser(outputString);
|
||||||
|
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths,
|
||||||
|
preamble, optLevel, resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile,
|
||||||
|
forwardCompatible, messages, intermediate, parser, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// do a partial compile on the given strings for a single compilation unit
|
||||||
|
// for a potential deferred link into a single stage (and deferred full compile of that
|
||||||
|
// stage through machine-dependent compilation).
|
||||||
|
//
|
||||||
|
// all preprocessing, parsing, semantic checks, etc. for a single compilation unit
|
||||||
|
// are done here.
|
||||||
|
//
|
||||||
|
// return: the tree and other information is filled into the intermediate argument,
|
||||||
|
// and true is returned by the function for success.
|
||||||
|
//
|
||||||
|
bool CompileDeferred(
|
||||||
|
TCompiler* compiler,
|
||||||
|
const char* const shaderStrings[],
|
||||||
|
const int numStrings,
|
||||||
|
const int* inputLengths,
|
||||||
|
const char* preamble,
|
||||||
|
const EShOptimizationLevel optLevel,
|
||||||
|
const TBuiltInResource* resources,
|
||||||
|
int defaultVersion, // use 100 for ES environment, 110 for desktop
|
||||||
|
EProfile defaultProfile,
|
||||||
|
bool forceDefaultVersionAndProfile,
|
||||||
|
bool forwardCompatible, // give errors for use of deprecated features
|
||||||
|
EShMessages messages, // warnings/errors/AST; things to print out
|
||||||
|
TIntermediate& intermediate) // returned tree, etc.
|
||||||
|
{
|
||||||
|
DoFullParse parser;
|
||||||
|
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths,
|
||||||
|
preamble, optLevel, resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile,
|
||||||
|
forwardCompatible, messages, intermediate, parser, true);
|
||||||
|
}
|
||||||
|
|
||||||
} // end anonymous namespace for local functions
|
} // end anonymous namespace for local functions
|
||||||
|
|
||||||
|
|
||||||
@ -1026,7 +1227,8 @@ TShader::~TShader()
|
|||||||
//
|
//
|
||||||
// Returns true for success.
|
// Returns true for success.
|
||||||
//
|
//
|
||||||
bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages messages)
|
bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
|
||||||
|
bool forwardCompatible, EShMessages messages)
|
||||||
{
|
{
|
||||||
if (! InitThread())
|
if (! InitThread())
|
||||||
return false;
|
return false;
|
||||||
@ -1041,7 +1243,28 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
|
|||||||
|
|
||||||
bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
|
bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
|
||||||
{
|
{
|
||||||
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
|
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill in a string with the result of preprocessing ShaderStrings
|
||||||
|
// Returns true if all extensions, pragmas and version strings were valid.
|
||||||
|
bool TShader::preprocess(const TBuiltInResource* builtInResources,
|
||||||
|
int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
|
||||||
|
bool forwardCompatible,
|
||||||
|
EShMessages message, std::string* output_string)
|
||||||
|
{
|
||||||
|
if (! InitThread())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pool = new TPoolAllocator();
|
||||||
|
SetThreadPoolAllocator(*pool);
|
||||||
|
if (! preamble)
|
||||||
|
preamble = "";
|
||||||
|
|
||||||
|
return PreprocessDeferred(compiler, strings, numStrings,
|
||||||
|
nullptr, preamble, EShOptNone, builtInResources,
|
||||||
|
defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, message,
|
||||||
|
*intermediate, output_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* TShader::getInfoLog()
|
const char* TShader::getInfoLog()
|
||||||
|
@ -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)
|
|||||||
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)
|
|||||||
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*
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class TCompiler;
|
class TCompiler;
|
||||||
class TInfoSink;
|
class TInfoSink;
|
||||||
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user