Add scanner that can find '#version' across an array of non-null terminated, length-based, strings. Handle the ES error where #version is not the first thing found, while still supporting desktop behavior, and more generally support length-based multiple strings for a single shader.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22165 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
ebf0825ec4
commit
41cf6b540b
@ -79,8 +79,9 @@ void usage();
|
|||||||
void FreeFileData(char **data);
|
void FreeFileData(char **data);
|
||||||
char** ReadFileData(const char *fileName);
|
char** ReadFileData(const char *fileName);
|
||||||
void InfoLogMsg(const char* msg, const char* name, const int num);
|
void InfoLogMsg(const char* msg, const char* name, const int num);
|
||||||
//Added to accomodate the multiple strings.
|
|
||||||
int OutputMultipleStrings = 1;
|
// Use to test breaking a single shader file into multiple strings.
|
||||||
|
int NumShaderStrings = 1;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set up the per compile resources
|
// Set up the per compile resources
|
||||||
@ -255,21 +256,31 @@ static EShLanguage FindLanguage(char *name)
|
|||||||
bool CompileFile(const char *fileName, ShHandle compiler, int debugOptions, const TBuiltInResource *resources)
|
bool CompileFile(const char *fileName, ShHandle compiler, int debugOptions, const TBuiltInResource *resources)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char **data = ReadFileData(fileName);
|
char** shaderStrings = ReadFileData(fileName);
|
||||||
|
int* lengths = new int[NumShaderStrings];
|
||||||
|
|
||||||
|
// move to length-based strings, rather than null-terminated strings
|
||||||
|
for (int s = 0; s < NumShaderStrings; ++s)
|
||||||
|
lengths[s] = strlen(shaderStrings[s]);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
PROCESS_MEMORY_COUNTERS counters; // just for memory leak testing
|
PROCESS_MEMORY_COUNTERS counters; // just for memory leak testing
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!data)
|
if (! shaderStrings)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
EShMessages messages = EShMsgDefault;
|
EShMessages messages = EShMsgDefault;
|
||||||
if (debugOptions & EDebugOpRelaxedErrors)
|
if (debugOptions & EDebugOpRelaxedErrors)
|
||||||
messages = (EShMessages)(messages | EShMsgRelaxedErrors);
|
messages = (EShMessages)(messages | EShMsgRelaxedErrors);
|
||||||
for (int i = 0; i < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++i) {
|
for (int i = 0; i < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++i) {
|
||||||
for (int j = 0; j < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++j)
|
for (int j = 0; j < ((debugOptions & EDebugOpMemoryLeakMode) ? 100 : 1); ++j) {
|
||||||
ret = ShCompile(compiler, data, OutputMultipleStrings, EShOptNone, resources, debugOptions, 100, false, messages);
|
//ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, resources, debugOptions, 100, false, messages);
|
||||||
|
ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, resources, debugOptions, 100, false, messages);
|
||||||
|
//const char* multi[4] = { "# ve", "rsion", " 300 e", "s" };
|
||||||
|
//const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
|
||||||
|
//ret = ShCompile(compiler, multi, 4, 0, EShOptNone, resources, debugOptions, 100, false, messages);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (debugOptions & EDebugOpMemoryLeakMode) {
|
if (debugOptions & EDebugOpMemoryLeakMode) {
|
||||||
@ -279,7 +290,8 @@ bool CompileFile(const char *fileName, ShHandle compiler, int debugOptions, cons
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeFileData(data);
|
delete [] lengths;
|
||||||
|
FreeFileData(shaderStrings);
|
||||||
|
|
||||||
return ret ? true : false;
|
return ret ? true : false;
|
||||||
}
|
}
|
||||||
@ -366,11 +378,11 @@ char** ReadFileData(const char *fileName)
|
|||||||
if(count==0){
|
if(count==0){
|
||||||
return_data[0]=(char*)malloc(count+2);
|
return_data[0]=(char*)malloc(count+2);
|
||||||
return_data[0][0]='\0';
|
return_data[0][0]='\0';
|
||||||
OutputMultipleStrings=0;
|
NumShaderStrings=0;
|
||||||
return return_data;
|
return return_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = (int)(ceil)((float)count/(float)OutputMultipleStrings);
|
int len = (int)(ceil)((float)count/(float)NumShaderStrings);
|
||||||
int ptr_len=0,i=0;
|
int ptr_len=0,i=0;
|
||||||
while(count>0){
|
while(count>0){
|
||||||
return_data[i]=(char*)malloc(len+2);
|
return_data[i]=(char*)malloc(len+2);
|
||||||
@ -380,7 +392,7 @@ char** ReadFileData(const char *fileName)
|
|||||||
ptr_len+=(len);
|
ptr_len+=(len);
|
||||||
if(count<len){
|
if(count<len){
|
||||||
if(count==0){
|
if(count==0){
|
||||||
OutputMultipleStrings=(i+1);
|
NumShaderStrings=(i+1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len = count;
|
len = count;
|
||||||
@ -394,7 +406,7 @@ char** ReadFileData(const char *fileName)
|
|||||||
|
|
||||||
void FreeFileData(char **data)
|
void FreeFileData(char **data)
|
||||||
{
|
{
|
||||||
for(int i=0;i<OutputMultipleStrings;i++)
|
for(int i=0;i<NumShaderStrings;i++)
|
||||||
free(data[i]);
|
free(data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -154,6 +154,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test</Command>
|
|||||||
<ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" />
|
<ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" />
|
||||||
<ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />
|
<ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />
|
||||||
<ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />
|
<ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />
|
||||||
|
<ClCompile Include="glslang\MachineIndependent\Scan.cpp" />
|
||||||
<ClCompile Include="glslang\MachineIndependent\Versions.cpp" />
|
<ClCompile Include="glslang\MachineIndependent\Versions.cpp" />
|
||||||
<ClCompile Include="OGLCompilersDLL\InitializeDll.cpp" />
|
<ClCompile Include="OGLCompilersDLL\InitializeDll.cpp" />
|
||||||
<ClCompile Include="glslang\MachineIndependent\IntermTraverse.cpp" />
|
<ClCompile Include="glslang\MachineIndependent\IntermTraverse.cpp" />
|
||||||
@ -204,6 +205,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test</Command>
|
|||||||
<ClInclude Include="glslang\Include\Common.h" />
|
<ClInclude Include="glslang\Include\Common.h" />
|
||||||
<ClInclude Include="glslang\Include\ConstantUnion.h" />
|
<ClInclude Include="glslang\Include\ConstantUnion.h" />
|
||||||
<ClInclude Include="glslang\Include\InfoSink.h" />
|
<ClInclude Include="glslang\Include\InfoSink.h" />
|
||||||
|
<ClInclude Include="glslang\MachineIndependent\Scan.h" />
|
||||||
<ClInclude Include="glslang\MachineIndependent\Versions.h" />
|
<ClInclude Include="glslang\MachineIndependent\Versions.h" />
|
||||||
<ClInclude Include="OGLCompilersDLL\InitializeDll.h" />
|
<ClInclude Include="OGLCompilersDLL\InitializeDll.h" />
|
||||||
<ClInclude Include="glslang\Include\InitializeGlobals.h" />
|
<ClInclude Include="glslang\Include\InitializeGlobals.h" />
|
||||||
|
|||||||
@ -109,6 +109,9 @@
|
|||||||
<ClCompile Include="glslang\MachineIndependent\Constant.cpp">
|
<ClCompile Include="glslang\MachineIndependent\Constant.cpp">
|
||||||
<Filter>Machine Independent</Filter>
|
<Filter>Machine Independent</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="glslang\MachineIndependent\Scan.cpp">
|
||||||
|
<Filter>Machine Independent</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="glslang\MachineIndependent\Initialize.h">
|
<ClInclude Include="glslang\MachineIndependent\Initialize.h">
|
||||||
@ -216,6 +219,9 @@
|
|||||||
<ClInclude Include="glslang\MachineIndependent\Versions.h">
|
<ClInclude Include="glslang\MachineIndependent\Versions.h">
|
||||||
<Filter>Machine Independent</Filter>
|
<Filter>Machine Independent</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="glslang\MachineIndependent\Scan.h">
|
||||||
|
<Filter>Machine Independent</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<CustomBuild Include="glslang\MachineIndependent\glslang.y">
|
<CustomBuild Include="glslang\MachineIndependent\glslang.y">
|
||||||
|
|||||||
@ -11,12 +11,12 @@ LIBCODEGEN=./../GenericCodeGen/libCodeGen.a
|
|||||||
OBJECTS= Initialize.o IntermTraverse.o \
|
OBJECTS= Initialize.o IntermTraverse.o \
|
||||||
Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \
|
Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \
|
||||||
RemoveTree.o ShaderLang.o intermOut.o parseConst.o SymbolTable.o \
|
RemoveTree.o ShaderLang.o intermOut.o parseConst.o SymbolTable.o \
|
||||||
InfoSink.o Versions.o Constant.o
|
InfoSink.o Versions.o Constant.o Scan.o
|
||||||
|
|
||||||
SRCS= gen_glslang.cpp gen_glslang_tab.cpp Initialize.cpp IntermTraverse.cpp \
|
SRCS= gen_glslang.cpp gen_glslang_tab.cpp Initialize.cpp IntermTraverse.cpp \
|
||||||
Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \
|
Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \
|
||||||
RemoveTree.cpp ShaderLang.cpp SymbolTable.cpp intermOut.cpp \
|
RemoveTree.cpp ShaderLang.cpp SymbolTable.cpp intermOut.cpp \
|
||||||
parseConst.cpp InfoSink.cpp Versions.cpp Constant.cpp
|
parseConst.cpp InfoSink.cpp Versions.cpp Constant.cpp Scan.cpp
|
||||||
CPPFLAGS=$(DEFINE) $(INCLUDE) -fPIC
|
CPPFLAGS=$(DEFINE) $(INCLUDE) -fPIC
|
||||||
SHAREDOBJECT=./lib/libglslang.so
|
SHAREDOBJECT=./lib/libglslang.so
|
||||||
|
|
||||||
@ -161,3 +161,4 @@ parseConst.o: ../Public/ShaderLang.h
|
|||||||
InfoSink.o: ../Include/InfoSink.h
|
InfoSink.o: ../Include/InfoSink.h
|
||||||
Versions.o: ParseHelper.h Versions.h ../Include/ShHandle.h SymbolTable.h localintermediate.h
|
Versions.o: ParseHelper.h Versions.h ../Include/ShHandle.h SymbolTable.h localintermediate.h
|
||||||
Constant.o: localintermediate.h ../Include/intermediate.h ../Public/ShaderLang.h SymbolTable.h Versions.h
|
Constant.o: localintermediate.h ../Include/intermediate.h ../Public/ShaderLang.h SymbolTable.h Versions.h
|
||||||
|
Scan.o: Scan.h Versions.h
|
||||||
|
|||||||
216
glslang/MachineIndependent/Scan.cpp
Normal file
216
glslang/MachineIndependent/Scan.cpp
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
//
|
||||||
|
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||||
|
//Copyright (C) 2013 LunarG, Inc.
|
||||||
|
//
|
||||||
|
//All rights reserved.
|
||||||
|
//
|
||||||
|
//Redistribution and use in source and binary forms, with or without
|
||||||
|
//modification, are permitted provided that the following conditions
|
||||||
|
//are met:
|
||||||
|
//
|
||||||
|
// Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Scan.h"
|
||||||
|
|
||||||
|
namespace glslang {
|
||||||
|
|
||||||
|
// read past any white space
|
||||||
|
void ConsumeWhiteSpace(TInputScanner& input, bool& foundNonSpaceTab)
|
||||||
|
{
|
||||||
|
char c = input.peek(); // don't accidentally consume anything other than whitespace
|
||||||
|
while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
|
||||||
|
if (c == '\r' || c == '\n')
|
||||||
|
foundNonSpaceTab = true;
|
||||||
|
input.get();
|
||||||
|
c = input.peek();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if a comment was actually consumed
|
||||||
|
bool ConsumeComment(TInputScanner& input)
|
||||||
|
{
|
||||||
|
if (input.peek() != '/')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
input.get(); // consume the '/'
|
||||||
|
char c = input.peek();
|
||||||
|
if (c == '/') {
|
||||||
|
|
||||||
|
// a '//' style comment
|
||||||
|
input.get(); // consume the second '/'
|
||||||
|
c = input.get();
|
||||||
|
do {
|
||||||
|
while (c > 0 && c != '\\' && c != '\r' && c != '\n')
|
||||||
|
c = input.get();
|
||||||
|
|
||||||
|
if (c <= 0 || c == '\r' || c == '\n') {
|
||||||
|
while (c == '\r' || c == '\n')
|
||||||
|
c = input.get();
|
||||||
|
|
||||||
|
// we reached the end of the comment
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// it's a '\', so we need to keep going, after skipping what's escaped
|
||||||
|
|
||||||
|
// read the skipped character
|
||||||
|
c = input.get();
|
||||||
|
|
||||||
|
// if it's a two-character newline, skip both characters
|
||||||
|
if (c == '\r' && input.peek() == '\n')
|
||||||
|
input.get();
|
||||||
|
c = input.get();
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
// put back the last non-comment character
|
||||||
|
if (c > 0)
|
||||||
|
input.unget();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (c == '*') {
|
||||||
|
|
||||||
|
// a '/*' style comment
|
||||||
|
input.get(); // consume the '*'
|
||||||
|
c = input.get();
|
||||||
|
do {
|
||||||
|
while (c > 0 && c != '*')
|
||||||
|
c = input.get();
|
||||||
|
if (c == '*') {
|
||||||
|
c = input.get();
|
||||||
|
if (c == '/')
|
||||||
|
break; // end of comment
|
||||||
|
// not end of comment
|
||||||
|
} else // end of input
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// it's not a comment, put the '/' back
|
||||||
|
input.unget();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip whitespace, then skip a comment, rinse, repeat
|
||||||
|
void ConsumeWhitespaceComment(TInputScanner& input, bool& foundNonSpaceTab)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
ConsumeWhiteSpace(input, foundNonSpaceTab);
|
||||||
|
|
||||||
|
// if not starting a comment now, then done
|
||||||
|
char c = input.peek();
|
||||||
|
if (c != '/' || c < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// skip potential comment
|
||||||
|
foundNonSpaceTab = true;
|
||||||
|
if (! ConsumeComment(input))
|
||||||
|
return;
|
||||||
|
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if there was non-white space (e.g., a comment, newline) before the #version;
|
||||||
|
// otherwise, returns true.
|
||||||
|
//
|
||||||
|
// N.B. does not attempt to leave input in any particular known state
|
||||||
|
bool ScanVersion(TInputScanner& input, int& version, EProfile& profile)
|
||||||
|
{
|
||||||
|
// This function doesn't have to get all the semantics correct,
|
||||||
|
// just find the #version if there is a correct one present.
|
||||||
|
// The preprocessor will have the responsibility of getting all the semantics right.
|
||||||
|
|
||||||
|
version = 0; // means not found
|
||||||
|
profile = ENoProfile;
|
||||||
|
|
||||||
|
bool foundNonSpaceTab = false;
|
||||||
|
ConsumeWhitespaceComment(input, foundNonSpaceTab);
|
||||||
|
|
||||||
|
// #
|
||||||
|
if (input.get() != '#')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// whitespace
|
||||||
|
char c;
|
||||||
|
do {
|
||||||
|
c = input.get();
|
||||||
|
} while (c == ' ' || c == '\t');
|
||||||
|
|
||||||
|
if ( c != 'v' ||
|
||||||
|
input.get() != 'e' ||
|
||||||
|
input.get() != 'r' ||
|
||||||
|
input.get() != 's' ||
|
||||||
|
input.get() != 'i' ||
|
||||||
|
input.get() != 'o' ||
|
||||||
|
input.get() != 'n')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// whitespace
|
||||||
|
do {
|
||||||
|
c = input.get();
|
||||||
|
} while (c == ' ' || c == '\t');
|
||||||
|
|
||||||
|
// version number
|
||||||
|
while (c >= '0' && c <= '9') {
|
||||||
|
version = 10 * version + (c - '0');
|
||||||
|
c = input.get();
|
||||||
|
}
|
||||||
|
if (version == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// whitespace
|
||||||
|
while (c == ' ' || c == '\t')
|
||||||
|
c = input.get();
|
||||||
|
|
||||||
|
// profile
|
||||||
|
const int maxProfileLength = 13; // not including any 0
|
||||||
|
char profileString[maxProfileLength];
|
||||||
|
int profileLength;
|
||||||
|
for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) {
|
||||||
|
if (c < 0 || c == ' ' || c == '\t' || c == '\n' || c == '\r')
|
||||||
|
break;
|
||||||
|
profileString[profileLength] = c;
|
||||||
|
c = input.get();
|
||||||
|
}
|
||||||
|
if (c > 0 && c != ' ' && c != '\t' && c != '\n' && c != '\r')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0)
|
||||||
|
profile = EEsProfile;
|
||||||
|
else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0)
|
||||||
|
profile = ECoreProfile;
|
||||||
|
else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0)
|
||||||
|
profile = ECompatibilityProfile;
|
||||||
|
|
||||||
|
return foundNonSpaceTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // end glslang namespace
|
||||||
115
glslang/MachineIndependent/Scan.h
Normal file
115
glslang/MachineIndependent/Scan.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
//
|
||||||
|
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||||
|
//Copyright (C) 2013 LunarG, Inc.
|
||||||
|
//
|
||||||
|
//All rights reserved.
|
||||||
|
//
|
||||||
|
//Redistribution and use in source and binary forms, with or without
|
||||||
|
//modification, are permitted provided that the following conditions
|
||||||
|
//are met:
|
||||||
|
//
|
||||||
|
// Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following
|
||||||
|
// disclaimer in the documentation and/or other materials provided
|
||||||
|
// with the distribution.
|
||||||
|
//
|
||||||
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived
|
||||||
|
// from this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Versions.h"
|
||||||
|
|
||||||
|
namespace glslang {
|
||||||
|
|
||||||
|
//
|
||||||
|
// A character scanner that seamlessly, on read-only strings, reads across an
|
||||||
|
// array of strings without assuming null termination.
|
||||||
|
//
|
||||||
|
class TInputScanner {
|
||||||
|
public:
|
||||||
|
TInputScanner(int n, const char* const i[], int L[]) : numSources(n), sources(i), lengths(L), currentSource(0), currentChar(0) { }
|
||||||
|
|
||||||
|
// return of -1 means end of strings,
|
||||||
|
// anything else is the next character
|
||||||
|
|
||||||
|
// retrieve the next character and advance one character
|
||||||
|
char get()
|
||||||
|
{
|
||||||
|
if (currentSource >= numSources)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char ret = sources[currentSource][currentChar];
|
||||||
|
advance();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance one character
|
||||||
|
void advance()
|
||||||
|
{
|
||||||
|
++currentChar;
|
||||||
|
if (currentChar >= lengths[currentSource]) {
|
||||||
|
++currentSource;
|
||||||
|
currentChar = 0;
|
||||||
|
while (currentSource < numSources && lengths[currentSource] == 0)
|
||||||
|
++currentSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve the next character, no advance
|
||||||
|
char peek()
|
||||||
|
{
|
||||||
|
if (currentSource >= numSources)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return sources[currentSource][currentChar];
|
||||||
|
}
|
||||||
|
|
||||||
|
// go back one character
|
||||||
|
void unget()
|
||||||
|
{
|
||||||
|
if (currentChar > 0)
|
||||||
|
--currentChar;
|
||||||
|
else {
|
||||||
|
do {
|
||||||
|
--currentSource;
|
||||||
|
} while (currentSource > 0 && lengths[currentSource] == 0);
|
||||||
|
currentChar = lengths[currentSource] - 1;
|
||||||
|
if (currentChar < 0)
|
||||||
|
currentChar = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int numSources; // number of strings in source
|
||||||
|
const char* const *sources; // array of strings
|
||||||
|
const int *lengths; // length of each string
|
||||||
|
int currentSource;
|
||||||
|
int currentChar;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The location of these is still pending a grand design for going to a singular
|
||||||
|
// scanner for version finding, preprocessing, and tokenizing:
|
||||||
|
void ConsumeWhiteSpace(TInputScanner& input, bool& foundNonSpaceTab);
|
||||||
|
bool ConsumeComment(TInputScanner& input);
|
||||||
|
void ConsumeWhitespaceComment(TInputScanner& input, bool& foundNonSpaceTab);
|
||||||
|
bool ScanVersion(TInputScanner& input, int& version, EProfile& profile);
|
||||||
|
|
||||||
|
}; // end glslang namespace
|
||||||
@ -43,6 +43,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "SymbolTable.h"
|
#include "SymbolTable.h"
|
||||||
#include "ParseHelper.h"
|
#include "ParseHelper.h"
|
||||||
|
#include "Scan.h"
|
||||||
|
|
||||||
#include "../Include/ShHandle.h"
|
#include "../Include/ShHandle.h"
|
||||||
#include "InitializeDll.h"
|
#include "InitializeDll.h"
|
||||||
@ -206,132 +207,6 @@ void SetupBuiltinSymbolTable(int version, EProfile profile)
|
|||||||
SetGlobalPoolAllocatorPtr(savedGPA);
|
SetGlobalPoolAllocatorPtr(savedGPA);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if something whas consumed
|
|
||||||
bool ConsumeWhitespaceComment(const char*& s)
|
|
||||||
{
|
|
||||||
const char* startPoint = s;
|
|
||||||
|
|
||||||
// first, skip white space
|
|
||||||
while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') {
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// then, check for a comment
|
|
||||||
if (*s == '/') {
|
|
||||||
if (*(s+1) == '/') {
|
|
||||||
|
|
||||||
// a '//' style comment
|
|
||||||
s += 2;
|
|
||||||
do {
|
|
||||||
while (*s && *s != '\\' && *s != '\r' && *s != '\n')
|
|
||||||
++s;
|
|
||||||
|
|
||||||
if (*s == '\r' || *s == '\n' || *s == 0) {
|
|
||||||
while (*s == '\r' || *s == '\n')
|
|
||||||
++s;
|
|
||||||
|
|
||||||
// we reached the end of the comment
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// it's a '\', so we need to keep going, after skipping what's escaped
|
|
||||||
++s;
|
|
||||||
if (*s == '\r' && *(s+1) == '\n')
|
|
||||||
s += 2;
|
|
||||||
else {
|
|
||||||
// skip the escaped character
|
|
||||||
if (*s)
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (true);
|
|
||||||
|
|
||||||
} else if (*(s+1) == '*') {
|
|
||||||
|
|
||||||
// a '/*' style comment
|
|
||||||
s += 2;
|
|
||||||
do {
|
|
||||||
while (*s && *s != '*')
|
|
||||||
++s;
|
|
||||||
if (*s == '*') {
|
|
||||||
++s;
|
|
||||||
if (*s == '/') {
|
|
||||||
++s;
|
|
||||||
break;
|
|
||||||
} // else not end of comment, keep going
|
|
||||||
} else // end of string
|
|
||||||
break;
|
|
||||||
} while (true);
|
|
||||||
} // else it's not a comment
|
|
||||||
} // else it's not a comment
|
|
||||||
|
|
||||||
return startPoint != s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScanVersion(const char* const shaderStrings[], int numStrings, int& version, EProfile& profile)
|
|
||||||
{
|
|
||||||
// This function doesn't have to get all the semantics correct,
|
|
||||||
// just find the #version if there is a correct one present.
|
|
||||||
// The CPP will have the responsibility of getting all the semantics right.
|
|
||||||
|
|
||||||
version = 0; // means not found
|
|
||||||
profile = ENoProfile;
|
|
||||||
|
|
||||||
const char* s = &shaderStrings[0][0];
|
|
||||||
|
|
||||||
// TODO: semantics: ES error check: #version must be on first line
|
|
||||||
|
|
||||||
while (ConsumeWhitespaceComment(s))
|
|
||||||
;
|
|
||||||
|
|
||||||
// #
|
|
||||||
if (*s != '#')
|
|
||||||
return;
|
|
||||||
++s;
|
|
||||||
|
|
||||||
// whitespace
|
|
||||||
while (*s == ' ' || *s == '\t') {
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// version
|
|
||||||
if (strncmp(s, "version", 7) != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// whitespace
|
|
||||||
s += 7;
|
|
||||||
while (*s == ' ' || *s == '\t') {
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// version number
|
|
||||||
while (*s >= '0' && *s <= '9') {
|
|
||||||
version = 10 * version + (*s - '0');
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
if (version == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// whitespace
|
|
||||||
while (*s == ' ' || *s == '\t') {
|
|
||||||
++s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// profile
|
|
||||||
const char* end = s;
|
|
||||||
while (*end != ' ' && *end != '\t' && *end != '\n' && *end != '\r') {
|
|
||||||
if (*end == 0)
|
|
||||||
return;
|
|
||||||
++end;
|
|
||||||
}
|
|
||||||
int profileLength = end - s;
|
|
||||||
if (profileLength == 2 && strncmp(s, "es", profileLength) == 0)
|
|
||||||
profile = EEsProfile;
|
|
||||||
else if (profileLength == 4 && strncmp(s, "core", profileLength) == 0)
|
|
||||||
profile = ECoreProfile;
|
|
||||||
else if (profileLength == 13 && strncmp(s, "compatibility", profileLength) == 0)
|
|
||||||
profile = ECompatibilityProfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeduceProfile(TInfoSink& infoSink, int version, EProfile& profile)
|
bool DeduceProfile(TInfoSink& infoSink, int version, EProfile& profile)
|
||||||
{
|
{
|
||||||
const int FirstProfileVersion = 150;
|
const int FirstProfileVersion = 150;
|
||||||
@ -382,7 +257,6 @@ bool DeduceProfile(TInfoSink& infoSink, int version, EProfile& profile)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}; // end anonymous namespace for local functions
|
}; // end anonymous namespace for local functions
|
||||||
|
|
||||||
int ShInitialize()
|
int ShInitialize()
|
||||||
@ -479,6 +353,7 @@ int ShCompile(
|
|||||||
const ShHandle handle,
|
const ShHandle handle,
|
||||||
const char* const shaderStrings[],
|
const char* const shaderStrings[],
|
||||||
const int numStrings,
|
const int numStrings,
|
||||||
|
const int* inputLengths,
|
||||||
const EShOptimizationLevel optLevel,
|
const EShOptimizationLevel optLevel,
|
||||||
const TBuiltInResource* resources,
|
const TBuiltInResource* resources,
|
||||||
int debugOptions,
|
int debugOptions,
|
||||||
@ -487,7 +362,7 @@ int ShCompile(
|
|||||||
EShMessages messages // warnings/errors
|
EShMessages messages // warnings/errors
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!InitThread())
|
if (! InitThread())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (handle == 0)
|
if (handle == 0)
|
||||||
@ -497,17 +372,28 @@ int ShCompile(
|
|||||||
if (compiler == 0)
|
if (compiler == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
GlobalPoolAllocator.push();
|
|
||||||
compiler->infoSink.info.erase();
|
compiler->infoSink.info.erase();
|
||||||
compiler->infoSink.debug.erase();
|
compiler->infoSink.debug.erase();
|
||||||
|
|
||||||
if (numStrings == 0)
|
if (numStrings == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
GlobalPoolAllocator.push();
|
||||||
|
|
||||||
|
// move to length-based strings, rather than null-terminated strings
|
||||||
|
int* lengths = new int[numStrings];
|
||||||
|
for (int s = 0; s < numStrings; ++s) {
|
||||||
|
if (inputLengths == 0 || inputLengths[s] < 0)
|
||||||
|
lengths[s] = strlen(shaderStrings[s]);
|
||||||
|
else
|
||||||
|
lengths[s] = inputLengths[s];
|
||||||
|
}
|
||||||
|
|
||||||
int version;
|
int version;
|
||||||
EProfile profile;
|
EProfile profile;
|
||||||
bool versionStatementMissing = false;
|
bool versionStatementMissing = false;
|
||||||
ScanVersion(shaderStrings, numStrings, version, profile);
|
glslang::TInputScanner input(numStrings, shaderStrings, lengths);
|
||||||
|
bool versionNotFirst = ScanVersion(input, version, profile);
|
||||||
if (version == 0) {
|
if (version == 0) {
|
||||||
version = defaultVersion;
|
version = defaultVersion;
|
||||||
versionStatementMissing = true;
|
versionStatementMissing = true;
|
||||||
@ -533,6 +419,8 @@ int ShCompile(
|
|||||||
parseContext.initializeExtensionBehavior();
|
parseContext.initializeExtensionBehavior();
|
||||||
if (versionStatementMissing)
|
if (versionStatementMissing)
|
||||||
parseContext.warn(1, "statement missing: use #version on first line of shader", "#version", "");
|
parseContext.warn(1, "statement missing: use #version on first line of shader", "#version", "");
|
||||||
|
else if (profile == EEsProfile && version >= 300 && versionNotFirst)
|
||||||
|
parseContext.error(1, "statement must appear first in ESSL shader; before comments or newlines", "#version", "");
|
||||||
|
|
||||||
GlobalParseContext = &parseContext;
|
GlobalParseContext = &parseContext;
|
||||||
|
|
||||||
@ -553,7 +441,7 @@ int ShCompile(
|
|||||||
if (parseContext.insertBuiltInArrayAtGlobalLevel())
|
if (parseContext.insertBuiltInArrayAtGlobalLevel())
|
||||||
success = false;
|
success = false;
|
||||||
|
|
||||||
int ret = PaParseStrings(const_cast<char**>(shaderStrings), 0, numStrings, parseContext, parseContext.getPreamble());
|
int ret = PaParseStrings(const_cast<char**>(shaderStrings), lengths, numStrings, parseContext, parseContext.getPreamble());
|
||||||
if (ret)
|
if (ret)
|
||||||
success = false;
|
success = false;
|
||||||
intermediate.addSymbolLinkageNodes(parseContext.treeRoot, parseContext.linkage, parseContext.language, symbolTable);
|
intermediate.addSymbolLinkageNodes(parseContext.treeRoot, parseContext.linkage, parseContext.language, symbolTable);
|
||||||
@ -597,6 +485,7 @@ int ShCompile(
|
|||||||
// Throw away all the temporary memory used by the compilation process.
|
// Throw away all the temporary memory used by the compilation process.
|
||||||
//
|
//
|
||||||
GlobalPoolAllocator.pop();
|
GlobalPoolAllocator.pop();
|
||||||
|
delete [] lengths;
|
||||||
|
|
||||||
return success ? 1 : 0;
|
return success ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,6 +164,7 @@ SH_IMPORT_EXPORT int ShCompile(
|
|||||||
const ShHandle,
|
const ShHandle,
|
||||||
const char* const shaderStrings[],
|
const char* const shaderStrings[],
|
||||||
const int numStrings,
|
const int numStrings,
|
||||||
|
const int* lengths,
|
||||||
const EShOptimizationLevel,
|
const EShOptimizationLevel,
|
||||||
const TBuiltInResource *resources,
|
const TBuiltInResource *resources,
|
||||||
int debugOptions,
|
int debugOptions,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user