mirror of
https://github.com/libretro/glslang.git
synced 2024-12-13 19:23:20 +00:00
Improve robustness of extension checking, and its intersection with ES 100 features.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23388 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
c6b7e6350b
commit
816e9bc90b
45
Test/100.frag
Normal file
45
Test/100.frag
Normal file
@ -0,0 +1,45 @@
|
||||
#version 100
|
||||
|
||||
int a[3] = { 2, 3, 4, }; // ERROR
|
||||
|
||||
int uint;
|
||||
|
||||
attribute vec4 v[3]; // ERROR
|
||||
|
||||
float f = 2; // ERROR
|
||||
|
||||
uniform block { // ERROR
|
||||
int x;
|
||||
};
|
||||
|
||||
void foo(float);
|
||||
|
||||
void main()
|
||||
{
|
||||
foo(3); // ERROR
|
||||
int s = 1 << 4; // ERROR
|
||||
s = 16 >> 2; // ERROR
|
||||
if (a == a); // ERROR
|
||||
int b, c;
|
||||
b = c & 4; // ERROR
|
||||
b = c % 4; // ERROR
|
||||
b = c | 4; // ERROR
|
||||
b >>= 2; // ERROR
|
||||
b <<= 2; // ERROR
|
||||
b %= 3; // ERROR
|
||||
|
||||
struct S {
|
||||
float f;
|
||||
float a[10];
|
||||
} s1, s2;
|
||||
|
||||
s1 = s2; // ERROR
|
||||
if (s1 == s2); // ERROR
|
||||
if (s1 != s2); // ERROR
|
||||
|
||||
switch(b) { // ERROR
|
||||
}
|
||||
}
|
||||
|
||||
invariant gl_FragColor;
|
||||
float fa[]; // ERROR
|
@ -21,7 +21,7 @@ void main()
|
||||
gu[2] = 4.0; // ERROR, overflow
|
||||
}
|
||||
|
||||
g4 = foo(g5);
|
||||
g4 = foo(g5); // ERROR
|
||||
g5 = g4; // ERROR
|
||||
gu = g4; // ERROR
|
||||
|
||||
|
100
Test/baseResults/100.frag.out
Normal file
100
Test/baseResults/100.frag.out
Normal file
@ -0,0 +1,100 @@
|
||||
ERROR: 0:3: '{ } style initializers' : not supported with this profile: es
|
||||
ERROR: 0:3: 'initializer' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:3: '=' : cannot convert from 'const int' to '3-element array of mediump int'
|
||||
ERROR: 0:7: 'attribute' : not supported in this stage: fragment
|
||||
ERROR: 0:7: 'float' : type requires declaration of default precision qualifier
|
||||
ERROR: 0:9: '=' : cannot convert from 'const int' to 'mediump float'
|
||||
ERROR: 0:11: 'uniform block' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:19: 'foo' : no matching overloaded function found
|
||||
ERROR: 0:20: 'bit shift left' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:21: 'bit shift right' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:22: 'array comparison' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:24: 'bitwise and' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:25: '%' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:26: 'bitwise inclusive or' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:27: 'bit-shift right assign' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:28: 'bit-shift left assign' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:29: '%=' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:36: 'array assignment' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:37: 'array comparison' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:38: 'array comparison' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:40: 'switch' : Reserved word.
|
||||
ERROR: 0:40: 'switch statements' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:45: '' : array size required
|
||||
ERROR: 23 compilation errors. No code generated.
|
||||
|
||||
ERROR: node is still EOpNull!
|
||||
0:17 Function Definition: main( (void)
|
||||
0:17 Function Parameters:
|
||||
0:19 Sequence
|
||||
0:19 Constant:
|
||||
0:19 0.000000
|
||||
0:20 Sequence
|
||||
0:20 move second child to first child (mediump int)
|
||||
0:20 's' (mediump int)
|
||||
0:20 Constant:
|
||||
0:20 16 (const int)
|
||||
0:21 move second child to first child (mediump int)
|
||||
0:21 's' (mediump int)
|
||||
0:21 Constant:
|
||||
0:21 4 (const int)
|
||||
0:22 Test condition and select (void)
|
||||
0:22 Condition
|
||||
0:22 Compare Equal (bool)
|
||||
0:22 'a' (3-element array of mediump int)
|
||||
0:22 'a' (3-element array of mediump int)
|
||||
0:22 true case is null
|
||||
0:24 move second child to first child (mediump int)
|
||||
0:24 'b' (mediump int)
|
||||
0:24 bitwise and (mediump int)
|
||||
0:24 'c' (mediump int)
|
||||
0:24 Constant:
|
||||
0:24 4 (const int)
|
||||
0:25 move second child to first child (mediump int)
|
||||
0:25 'b' (mediump int)
|
||||
0:25 mod (mediump int)
|
||||
0:25 'c' (mediump int)
|
||||
0:25 Constant:
|
||||
0:25 4 (const int)
|
||||
0:26 move second child to first child (mediump int)
|
||||
0:26 'b' (mediump int)
|
||||
0:26 inclusive-or (mediump int)
|
||||
0:26 'c' (mediump int)
|
||||
0:26 Constant:
|
||||
0:26 4 (const int)
|
||||
0:27 right shift second child into first child (mediump int)
|
||||
0:27 'b' (mediump int)
|
||||
0:27 Constant:
|
||||
0:27 2 (const int)
|
||||
0:28 left shift second child into first child (mediump int)
|
||||
0:28 'b' (mediump int)
|
||||
0:28 Constant:
|
||||
0:28 2 (const int)
|
||||
0:29 mod second child into first child (mediump int)
|
||||
0:29 'b' (mediump int)
|
||||
0:29 Constant:
|
||||
0:29 3 (const int)
|
||||
0:36 move second child to first child (structure)
|
||||
0:36 's1' (structure)
|
||||
0:36 's2' (structure)
|
||||
0:37 Test condition and select (void)
|
||||
0:37 Condition
|
||||
0:37 Compare Equal (bool)
|
||||
0:37 's1' (structure)
|
||||
0:37 's2' (structure)
|
||||
0:37 true case is null
|
||||
0:38 Test condition and select (void)
|
||||
0:38 Condition
|
||||
0:38 Compare Not Equal (bool)
|
||||
0:38 's1' (structure)
|
||||
0:38 's2' (structure)
|
||||
0:38 true case is null
|
||||
0:40 'b' (mediump int)
|
||||
0:? Linker Objects
|
||||
0:? 'a' (3-element array of mediump int)
|
||||
0:? 'uint' (mediump int)
|
||||
0:? 'v' (smooth in 3-element array of mediump 4-component vector of float)
|
||||
0:? 'f' (mediump float)
|
||||
0:? '__anon__0' (layout(shared ) uniform block)
|
||||
0:? 'fa' (unsized array of mediump float)
|
||||
|
@ -4,14 +4,18 @@ ERROR: 0:9: 'arrayed type' : not supported for this version or the enabled exten
|
||||
ERROR: 0:9: 'arrayed type' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:11: 'arrayed constructor' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:21: '[' : array index out of range '2'
|
||||
ERROR: 0:24: 'array assignment' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:25: 'array assignment' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:25: 'assign' : cannot convert from '4-element array of mediump float' to '5-element array of mediump float'
|
||||
ERROR: 0:26: 'array assignment' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:26: 'assign' : cannot convert from '4-element array of mediump float' to 'unsized array of mediump float'
|
||||
ERROR: 0:28: 'foo' : no matching overloaded function found
|
||||
ERROR: 0:31: 'arrayed constructor' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:31: 'array comparison' : not supported for this version or the enabled extensions
|
||||
ERROR: 0:35: '[' : array index out of range '5'
|
||||
ERROR: 0:38: '[' : array index out of range '1000'
|
||||
ERROR: 0:39: '[' : array index out of range '-1'
|
||||
ERROR: 13 compilation errors. No code generated.
|
||||
ERROR: 17 compilation errors. No code generated.
|
||||
|
||||
ERROR: node is still EOpNull!
|
||||
0:9 Function Definition: foo(f1[5]; (4-element array of mediump float)
|
||||
@ -86,9 +90,9 @@ ERROR: node is still EOpNull!
|
||||
0:35 5.000000
|
||||
0:36 Function Call: foo(f1[5]; (4-element array of mediump float)
|
||||
0:36 'u' (5-element array of mediump float)
|
||||
0:38 move second child to first child (4-component vector of float)
|
||||
0:38 direct index (fragColor 4-component vector of float)
|
||||
0:38 'gl_FragData' (fragColor 32-element array of 4-component vector of float)
|
||||
0:38 move second child to first child (mediump 4-component vector of float)
|
||||
0:38 direct index (fragColor mediump 4-component vector of float)
|
||||
0:38 'gl_FragData' (fragColor 32-element array of mediump 4-component vector of float)
|
||||
0:38 Constant:
|
||||
0:38 1000 (const int)
|
||||
0:38 Constant:
|
||||
@ -96,9 +100,9 @@ ERROR: node is still EOpNull!
|
||||
0:38 1.000000
|
||||
0:38 1.000000
|
||||
0:38 1.000000
|
||||
0:39 move second child to first child (4-component vector of float)
|
||||
0:39 direct index (fragColor 4-component vector of float)
|
||||
0:39 'gl_FragData' (fragColor 32-element array of 4-component vector of float)
|
||||
0:39 move second child to first child (mediump 4-component vector of float)
|
||||
0:39 direct index (fragColor mediump 4-component vector of float)
|
||||
0:39 'gl_FragData' (fragColor 32-element array of mediump 4-component vector of float)
|
||||
0:39 Constant:
|
||||
0:39 -1 (const int)
|
||||
0:39 Constant:
|
||||
@ -106,9 +110,9 @@ ERROR: node is still EOpNull!
|
||||
0:39 1.000000
|
||||
0:39 1.000000
|
||||
0:39 1.000000
|
||||
0:40 move second child to first child (4-component vector of float)
|
||||
0:40 direct index (fragColor 4-component vector of float)
|
||||
0:40 'gl_FragData' (fragColor 32-element array of 4-component vector of float)
|
||||
0:40 move second child to first child (mediump 4-component vector of float)
|
||||
0:40 direct index (fragColor mediump 4-component vector of float)
|
||||
0:40 'gl_FragData' (fragColor 32-element array of mediump 4-component vector of float)
|
||||
0:40 Constant:
|
||||
0:40 3 (const int)
|
||||
0:40 Constant:
|
||||
|
@ -7,6 +7,7 @@ versionsClean.frag
|
||||
versionsClean.vert
|
||||
versionsErrors.frag
|
||||
versionsErrors.vert
|
||||
100.frag
|
||||
120.vert
|
||||
120.frag
|
||||
130.frag
|
||||
|
@ -580,6 +580,18 @@ public:
|
||||
|
||||
virtual bool isMatrix() const { return matrixCols ? true : false; }
|
||||
virtual bool isArray() const { return arraySizes != 0; }
|
||||
virtual bool containsArray() const
|
||||
{
|
||||
if (isArray())
|
||||
return true;
|
||||
if (! structure)
|
||||
return false;
|
||||
for (unsigned int i = 0; i < structure->size(); ++i) {
|
||||
if ((*structure)[i].type->containsArray())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int getArraySize() const { return arraySizes->sizes.front(); }
|
||||
void setArraySizes(TArraySizes* s)
|
||||
{
|
||||
|
@ -35,10 +35,16 @@
|
||||
//
|
||||
|
||||
//
|
||||
// Create strings that declare built-in definitions, add built-ins that
|
||||
// cannot be expressed in the files, and establish mappings between
|
||||
// Create strings that declare built-in definitions, add built-ins programmatically
|
||||
// that cannot be expressed in the strings, and establish mappings between
|
||||
// built-in functions and operators.
|
||||
//
|
||||
// Where to put a built-in:
|
||||
// TBuiltIns::initialize(version,profile) context-independent textual built-ins; add them to the right string
|
||||
// TBuiltIns::initialize(resources,...) context-dependent textual built-ins; add them to the right string
|
||||
// IdentifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table
|
||||
// IdentifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table
|
||||
//
|
||||
|
||||
#include "../Include/intermediate.h"
|
||||
#include "Initialize.h"
|
||||
@ -50,14 +56,16 @@ const bool ForwardCompatibility = false;
|
||||
|
||||
TBuiltIns::TBuiltIns()
|
||||
{
|
||||
// Set up textual representations for making all the permutations
|
||||
// of texturing/imaging functions.
|
||||
prefixes[EbtFloat] = "";
|
||||
prefixes[EbtInt] = "i";
|
||||
prefixes[EbtUint] = "u";
|
||||
|
||||
postfixes[2] = "2";
|
||||
postfixes[3] = "3";
|
||||
postfixes[4] = "4";
|
||||
|
||||
// Map from symbolic class of texturing dimension to numeric dimensions.
|
||||
dimMap[Esd1D] = 1;
|
||||
dimMap[Esd2D] = 2;
|
||||
dimMap[EsdRect] = 2;
|
||||
@ -70,14 +78,16 @@ TBuiltIns::~TBuiltIns()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Add all context-independent built-in functions and variables that are present
|
||||
// for the given version and profile. Share common ones across stages, otherwise
|
||||
// make stage-specific entries.
|
||||
//
|
||||
// Most built-ins variables can be added as simple text strings. Some need to
|
||||
// be added programmatically, which is done later in IdentifyBuiltIns() below.
|
||||
//
|
||||
void TBuiltIns::initialize(int version, EProfile profile)
|
||||
{
|
||||
// TODO: Performance/Memory: consider an extra outer scope for built-ins common across all stages
|
||||
|
||||
//
|
||||
// Initialize all the built-in strings for parsing.
|
||||
//
|
||||
|
||||
{
|
||||
//============================================================================
|
||||
//
|
||||
@ -1011,6 +1021,10 @@ void TBuiltIns::initialize(int version, EProfile profile)
|
||||
//printf("%s\n", commonBuiltins.c_str();
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function for initialize(), to add the second set of names for texturing,
|
||||
// when adding context-independent built-in functions.
|
||||
//
|
||||
void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile)
|
||||
{
|
||||
TBasicType bTypes[3] = { EbtFloat, EbtInt, EbtUint };
|
||||
@ -1081,6 +1095,10 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function for add2ndGenerationSamplingImaging(),
|
||||
// when adding context-independent built-in functions.
|
||||
//
|
||||
void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
|
||||
{
|
||||
//
|
||||
@ -1109,15 +1127,21 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int versi
|
||||
s.append(",int);\n");
|
||||
else
|
||||
s.append(");\n");
|
||||
|
||||
// TODO: 4.2 Functionality: imaging functions
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function for add2ndGenerationSamplingImaging(),
|
||||
// when adding context-independent built-in functions.
|
||||
//
|
||||
void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
|
||||
{
|
||||
// TODO: 4.2 Functionality: imaging functions
|
||||
}
|
||||
|
||||
//
|
||||
// Helper function for add2ndGenerationSamplingImaging(),
|
||||
// when adding context-independent built-in functions.
|
||||
//
|
||||
void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
|
||||
{
|
||||
// make one string per stage to contain all functions of the passed-in type for that stage
|
||||
@ -1297,6 +1321,11 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int ve
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Add context-dependent built-in functions and variables that are present
|
||||
// for the given version and profile. Share common ones across stages, otherwise
|
||||
// make stage-specific entries.
|
||||
//
|
||||
void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, EShLanguage language)
|
||||
{
|
||||
//
|
||||
@ -1448,6 +1477,12 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Finish adding/processing context-independent built-in symbols.
|
||||
// 1) Programmatically add symbols that could not be added by simple text strings above.
|
||||
// 2) Map built-in functions to operators, for those that will turn into an operation node
|
||||
// instead of remaining a function call.
|
||||
//
|
||||
void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable)
|
||||
{
|
||||
TPrecisionQualifier pq;
|
||||
@ -1643,11 +1678,13 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Add context-dependent (resource-specific) built-ins not yet handled. These
|
||||
// would be ones that need to be programmatically added because they cannot
|
||||
// be added by simple text strings.
|
||||
//
|
||||
void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
|
||||
{
|
||||
//
|
||||
// Set resource-specific built-ins not yet handled.
|
||||
//
|
||||
switch(language) {
|
||||
|
||||
case EShLangFragment:
|
||||
|
@ -45,6 +45,15 @@
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// This is made to hold parseable strings for almost all the built-in
|
||||
// functions and variables for one specific combination of version
|
||||
// and profile. (Some still need to be added programmatically.)
|
||||
//
|
||||
// The strings are organized by
|
||||
// commonBuiltins: intersection of all stages' built-ins, processed just once
|
||||
// stageBuiltins[]: anything a stage needs that's not in commonBuiltins
|
||||
//
|
||||
class TBuiltIns {
|
||||
public:
|
||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||
@ -64,7 +73,8 @@ protected:
|
||||
TString commonBuiltins;
|
||||
TString stageBuiltins[EShLangCount];
|
||||
|
||||
// Helpers for making text
|
||||
// Helpers for making textual representations of the permutations
|
||||
// of texturing/imaging functions.
|
||||
const char* postfixes[5];
|
||||
const char* prefixes[EbtNumTypes];
|
||||
int dimMap[EsdNumDims];
|
||||
|
@ -527,7 +527,8 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped*
|
||||
//
|
||||
|
||||
if (field == "length") {
|
||||
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", ".length");
|
||||
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, ".length");
|
||||
profileRequires(loc, EEsProfile, 300, 0, ".length");
|
||||
result = intermediate.addMethod(base, TType(EbtInt), &field, loc);
|
||||
} else
|
||||
error(loc, "only the length method is supported for array", field.c_str(), "");
|
||||
@ -851,8 +852,8 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
|
||||
TFunction* TParseContext::handleConstructorCall(TSourceLoc loc, TPublicType& publicType)
|
||||
{
|
||||
if (publicType.arraySizes) {
|
||||
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed constructor");
|
||||
profileRequires(loc, EEsProfile, 300, "GL_3DL_array_objects", "arrayed constructor");
|
||||
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed constructor");
|
||||
profileRequires(loc, EEsProfile, 300, 0, "arrayed constructor");
|
||||
}
|
||||
|
||||
publicType.qualifier.precision = EpqNone;
|
||||
@ -1648,8 +1649,10 @@ void TParseContext::arraySizeCheck(TSourceLoc loc, TIntermTyped* expr, int& size
|
||||
//
|
||||
bool TParseContext::arrayQualifierError(TSourceLoc loc, const TQualifier& qualifier)
|
||||
{
|
||||
if (qualifier.storage == EvqConst)
|
||||
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", "const array");
|
||||
if (qualifier.storage == EvqConst) {
|
||||
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "const array");
|
||||
profileRequires(loc, EEsProfile, 300, 0, "const array");
|
||||
}
|
||||
|
||||
if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) {
|
||||
requireProfile(loc, ~EEsProfile, "vertex input arrays");
|
||||
@ -1893,6 +1896,15 @@ void TParseContext::nestedStructCheck(TSourceLoc loc)
|
||||
++structNestingLevel;
|
||||
}
|
||||
|
||||
void TParseContext::arrayObjectCheck(TSourceLoc loc, const TType& type, const char* op)
|
||||
{
|
||||
// Some versions don't allow comparing arrays or structures containing arrays
|
||||
if (type.containsArray()) {
|
||||
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, op);
|
||||
profileRequires(loc, EEsProfile, 300, 0, op);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Layout qualifier stuff.
|
||||
//
|
||||
@ -2020,8 +2032,10 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
|
||||
declareArray(loc, identifier, type, variable, newDeclaration);
|
||||
}
|
||||
|
||||
if (initializer)
|
||||
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
|
||||
if (initializer) {
|
||||
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "initializer");
|
||||
profileRequires(loc, EEsProfile, 300, 0, "initializer");
|
||||
}
|
||||
} else {
|
||||
// non-array case
|
||||
if (! variable)
|
||||
|
@ -115,6 +115,7 @@ public:
|
||||
void paramCheck(TSourceLoc, TStorageQualifier qualifier, TType* type);
|
||||
void nestedBlockCheck(TSourceLoc);
|
||||
void nestedStructCheck(TSourceLoc);
|
||||
void arrayObjectCheck(TSourceLoc, const TType&, const char* op);
|
||||
|
||||
void setLayoutQualifier(TSourceLoc, TPublicType&, TString&);
|
||||
void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int);
|
||||
@ -161,7 +162,6 @@ public:
|
||||
|
||||
protected:
|
||||
const char* getPreamble();
|
||||
TExtensionBehavior getExtensionBehavior(const char* behavior);
|
||||
void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type);
|
||||
TVariable* declareNonArray(TSourceLoc, TString& identifier, TType&, bool& newDeclaration);
|
||||
void declareArray(TSourceLoc, TString& identifier, const TType&, TVariable*&, bool& newDeclaration);
|
||||
|
@ -48,7 +48,7 @@
|
||||
// To add a new hypothetical "Feature F" to the front end, where an extension
|
||||
// "XXX_extension_X" can be used to enable the feature, do the following.
|
||||
//
|
||||
// 1) Understand that specific features are what are error-checked for, not
|
||||
// OVERVIEW: Specific features are what are error-checked for, not
|
||||
// extensions: A specific Feature F might be enabled by an extension, or a
|
||||
// particular version in a particular profile, or a stage, or combinations, etc.
|
||||
//
|
||||
@ -66,11 +66,17 @@
|
||||
// will then always continue as if the tested feature was enabled.
|
||||
//
|
||||
// There is typically no if-testing or conditional parsing, just insertion of requirements.
|
||||
// However, if symbols specific to the extension are added (step 5), they will
|
||||
// only be added under tests that the minimum version and profile are present.
|
||||
//
|
||||
// 1) Add a symbol name for the extension string at the bottom of Versions.h:
|
||||
//
|
||||
// const char* const XXX_extension_X = "XXX_extension_X";
|
||||
//
|
||||
// 2) Add extension initialization to TParseContext::initializeExtensionBehavior(),
|
||||
// the first function below:
|
||||
//
|
||||
// extensionBehavior["XXX_extension_X"] = EBhDisable;
|
||||
// extensionBehavior[XXX_extension_X] = EBhDisable;
|
||||
//
|
||||
// 3) Insert a profile check in the feature's path (unless all profiles support the feature,
|
||||
// for some version level). That is, call requireProfile() to constrain the profiles, e.g.:
|
||||
@ -90,7 +96,7 @@
|
||||
// profileRequires(loc,
|
||||
// ECoreProfile | ECompatibilityProfile,
|
||||
// 420, // 0 if no version incorporated the feature into the core spec.
|
||||
// "XXX_extension_X", // can be a list of extensions that all add the feature
|
||||
// XXX_extension_X, // can be a list of extensions that all add the feature
|
||||
// "Feature F");
|
||||
//
|
||||
// This allows the feature if either A) one of the extensions is enabled or
|
||||
@ -117,6 +123,9 @@
|
||||
//
|
||||
// ~EEsProfile
|
||||
//
|
||||
// 5) If built-in symbols are added by the extension, add them in Initialize.cpp; see
|
||||
// the comment at the top of that file for where to put them.
|
||||
//
|
||||
|
||||
#include "ParseHelper.h"
|
||||
|
||||
@ -129,10 +138,14 @@ namespace glslang {
|
||||
//
|
||||
void TParseContext::initializeExtensionBehavior()
|
||||
{
|
||||
extensionBehavior["GL_ARB_texture_rectangle"] = EBhDisable;
|
||||
extensionBehavior["GL_3DL_array_objects"] = EBhDisable;
|
||||
extensionBehavior[GL_ARB_texture_rectangle] = EBhDisable;
|
||||
extensionBehavior[GL_3DL_array_objects] = EBhDisable;
|
||||
extensionBehavior[GL_ARB_shading_language_420pack] = EBhDisable;
|
||||
}
|
||||
|
||||
//
|
||||
// Map from profile enum to externally readable text name.
|
||||
//
|
||||
const char* ProfileName(EProfile profile)
|
||||
{
|
||||
switch (profile) {
|
||||
@ -159,6 +172,9 @@ void TParseContext::requireProfile(TSourceLoc loc, int profileMask, const char *
|
||||
error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
|
||||
}
|
||||
|
||||
//
|
||||
// Map from stage enum to externally readable text name.
|
||||
//
|
||||
const char* StageName(EShLanguage stage)
|
||||
{
|
||||
switch(stage) {
|
||||
@ -274,32 +290,27 @@ void TParseContext::requireNotRemoved(TSourceLoc loc, int profileMask, int remov
|
||||
}
|
||||
|
||||
//
|
||||
// Translate from text string of extension's behavior to enum.
|
||||
// Change the current state of an extension's behavior.
|
||||
//
|
||||
TExtensionBehavior TParseContext::getExtensionBehavior(const char* behavior)
|
||||
{
|
||||
if (! strcmp("require", behavior))
|
||||
return EBhRequire;
|
||||
else if (! strcmp("enable", behavior))
|
||||
return EBhEnable;
|
||||
else if (! strcmp("disable", behavior))
|
||||
return EBhDisable;
|
||||
else if (! strcmp("warn", behavior))
|
||||
return EBhWarn;
|
||||
else {
|
||||
error(currentLoc, "behavior not supported", "#extension", behavior);
|
||||
return EBhDisable;
|
||||
}
|
||||
}
|
||||
|
||||
void TParseContext::updateExtensionBehavior(const char* extName, const char* behaviorString)
|
||||
{
|
||||
TExtensionBehavior behavior = getExtensionBehavior(behaviorString);
|
||||
TMap<TString, TExtensionBehavior>:: iterator iter;
|
||||
TString msg;
|
||||
// Translate from text string of extension's behavior to an enum.
|
||||
TExtensionBehavior behavior = EBhDisable;
|
||||
if (! strcmp("require", behaviorString))
|
||||
behavior = EBhRequire;
|
||||
else if (! strcmp("enable", behaviorString))
|
||||
behavior = EBhEnable;
|
||||
else if (! strcmp("disable", behaviorString))
|
||||
behavior = EBhDisable;
|
||||
else if (! strcmp("warn", behaviorString))
|
||||
behavior = EBhWarn;
|
||||
else
|
||||
error(currentLoc, "behavior not supported", "#extension", behaviorString);
|
||||
|
||||
// special case for the 'all' extension
|
||||
// Update the current behavior
|
||||
TMap<TString, TExtensionBehavior>::iterator iter;
|
||||
if (! strcmp(extName, "all")) {
|
||||
// special case for the 'all' extension; apply it to every extension present
|
||||
if (behavior == EBhRequire || behavior == EBhEnable) {
|
||||
error(currentLoc, "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", "");
|
||||
return;
|
||||
@ -308,6 +319,7 @@ void TParseContext::updateExtensionBehavior(const char* extName, const char* beh
|
||||
iter->second = behavior;
|
||||
}
|
||||
} else {
|
||||
// Do the update for this single extension
|
||||
iter = extensionBehavior.find(TString(extName));
|
||||
if (iter == extensionBehavior.end()) {
|
||||
switch (behavior) {
|
||||
|
@ -40,16 +40,6 @@
|
||||
// Help manage multiple profiles, versions, extensions etc.
|
||||
//
|
||||
|
||||
//
|
||||
// The behaviors from "#extension extension_name : behavior"
|
||||
//
|
||||
typedef enum {
|
||||
EBhRequire,
|
||||
EBhEnable,
|
||||
EBhWarn,
|
||||
EBhDisable
|
||||
} TExtensionBehavior;
|
||||
|
||||
//
|
||||
// Profiles are set up for masking operations, so queries can be done on multiple
|
||||
// profiles at the same time.
|
||||
@ -65,4 +55,26 @@ typedef enum {
|
||||
EEsProfile = (1 << 3)
|
||||
} EProfile;
|
||||
|
||||
namespace glslang {
|
||||
|
||||
//
|
||||
// The behaviors from the GLSL "#extension extension_name : behavior"
|
||||
//
|
||||
typedef enum {
|
||||
EBhRequire,
|
||||
EBhEnable,
|
||||
EBhWarn,
|
||||
EBhDisable
|
||||
} TExtensionBehavior;
|
||||
|
||||
//
|
||||
// Symbolic names for extensions. Strings may be directly used when calling the
|
||||
// functions, but better to have the compiler do spelling checks.
|
||||
//
|
||||
const char* const GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle";
|
||||
const char* const GL_3DL_array_objects = "GL_3DL_array_objects";
|
||||
const char* const GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack";
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
#endif // _VERSIONS_INCLUDED_
|
||||
|
@ -463,6 +463,7 @@ multiplicative_expression
|
||||
}
|
||||
}
|
||||
| multiplicative_expression PERCENT unary_expression {
|
||||
parseContext.fullIntegerCheck($2.loc, "%");
|
||||
$$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, "%", $1->getCompleteString(), $3->getCompleteString());
|
||||
@ -552,24 +553,24 @@ relational_expression
|
||||
equality_expression
|
||||
: relational_expression { $$ = $1; }
|
||||
| equality_expression EQ_OP relational_expression {
|
||||
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
||||
$$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, "==", $1->getCompleteString(), $3->getCompleteString());
|
||||
TConstUnionArray unionArray(1);
|
||||
unionArray[0].setBConst(false);
|
||||
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.loc);
|
||||
} else if (($1->isArray() || $3->isArray()))
|
||||
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "==");
|
||||
}
|
||||
}
|
||||
| equality_expression NE_OP relational_expression {
|
||||
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
|
||||
$$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.binaryOpError($2.loc, "!=", $1->getCompleteString(), $3->getCompleteString());
|
||||
TConstUnionArray unionArray(1);
|
||||
unionArray[0].setBConst(false);
|
||||
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.loc);
|
||||
} else if (($1->isArray() || $3->isArray()))
|
||||
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "!=");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@ -664,23 +665,42 @@ conditional_expression
|
||||
assignment_expression
|
||||
: conditional_expression { $$ = $1; }
|
||||
| unary_expression assignment_operator assignment_expression {
|
||||
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array assignment");
|
||||
parseContext.lValueErrorCheck($2.loc, "assign", $1);
|
||||
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc);
|
||||
if ($$ == 0) {
|
||||
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
|
||||
$$ = $1;
|
||||
} else if (($1->isArray() || $3->isArray()))
|
||||
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "=");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
assignment_operator
|
||||
: EQUAL { $$.loc = $1.loc; $$.op = EOpAssign; }
|
||||
| MUL_ASSIGN { $$.loc = $1.loc; $$.op = EOpMulAssign; }
|
||||
| DIV_ASSIGN { $$.loc = $1.loc; $$.op = EOpDivAssign; }
|
||||
| MOD_ASSIGN { $$.loc = $1.loc; $$.op = EOpModAssign; }
|
||||
| ADD_ASSIGN { $$.loc = $1.loc; $$.op = EOpAddAssign; }
|
||||
| SUB_ASSIGN { $$.loc = $1.loc; $$.op = EOpSubAssign; }
|
||||
: EQUAL {
|
||||
$$.loc = $1.loc;
|
||||
$$.op = EOpAssign;
|
||||
}
|
||||
| MUL_ASSIGN {
|
||||
$$.loc = $1.loc;
|
||||
$$.op = EOpMulAssign;
|
||||
}
|
||||
| DIV_ASSIGN {
|
||||
$$.loc = $1.loc;
|
||||
$$.op = EOpDivAssign;
|
||||
}
|
||||
| MOD_ASSIGN {
|
||||
parseContext.fullIntegerCheck($1.loc, "%=");
|
||||
$$.loc = $1.loc;
|
||||
$$.op = EOpModAssign;
|
||||
}
|
||||
| ADD_ASSIGN {
|
||||
$$.loc = $1.loc;
|
||||
$$.op = EOpAddAssign;
|
||||
}
|
||||
| SUB_ASSIGN {
|
||||
$$.loc = $1.loc;
|
||||
$$.op = EOpSubAssign;
|
||||
}
|
||||
| LEFT_ASSIGN {
|
||||
parseContext.fullIntegerCheck($1.loc, "bit-shift left assign");
|
||||
$$.loc = $1.loc; $$.op = EOpLeftShiftAssign;
|
||||
@ -853,7 +873,7 @@ parameter_declarator
|
||||
// Type + name
|
||||
: type_specifier IDENTIFIER {
|
||||
if ($1.arraySizes) {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
|
||||
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
|
||||
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
|
||||
}
|
||||
@ -868,7 +888,7 @@ parameter_declarator
|
||||
}
|
||||
| type_specifier IDENTIFIER array_specifier {
|
||||
if ($1.arraySizes) {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
|
||||
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
|
||||
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
|
||||
}
|
||||
@ -989,7 +1009,7 @@ fully_specified_type
|
||||
$$ = $1;
|
||||
|
||||
if ($1.arraySizes) {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
|
||||
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
|
||||
if (parseContext.profile == EEsProfile)
|
||||
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
|
||||
@ -1001,7 +1021,7 @@ fully_specified_type
|
||||
parseContext.globalQualifierFix($1.loc, $1.qualifier, $2);
|
||||
|
||||
if ($2.arraySizes) {
|
||||
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
|
||||
parseContext.profileRequires($2.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
|
||||
parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
|
||||
if (parseContext.profile == EEsProfile)
|
||||
parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());
|
||||
@ -1676,28 +1696,28 @@ type_specifier_nonarray
|
||||
$$.sampler.set(EbtUint, EsdCube, true);
|
||||
}
|
||||
| SAMPLER2DRECT {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
|
||||
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtSampler;
|
||||
$$.sampler.set(EbtFloat, EsdRect);
|
||||
}
|
||||
| SAMPLER2DRECTSHADOW {
|
||||
parseContext.profileRequires($1.loc, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
parseContext.profileRequires($1.loc, ECoreProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
|
||||
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtSampler;
|
||||
$$.sampler.set(EbtFloat, EsdRect, false, true);
|
||||
}
|
||||
| ISAMPLER2DRECT {
|
||||
parseContext.profileRequires($1.loc, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
parseContext.profileRequires($1.loc, ECoreProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
|
||||
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtSampler;
|
||||
$$.sampler.set(EbtInt, EsdRect);
|
||||
}
|
||||
| USAMPLER2DRECT {
|
||||
parseContext.profileRequires($1.loc, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
parseContext.profileRequires($1.loc, ECoreProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
|
||||
|
||||
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
|
||||
$$.basicType = EbtSampler;
|
||||
@ -1992,7 +2012,7 @@ struct_declaration_list
|
||||
struct_declaration
|
||||
: type_specifier struct_declarator_list SEMICOLON {
|
||||
if ($1.arraySizes) {
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
|
||||
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
|
||||
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
|
||||
if (parseContext.profile == EEsProfile)
|
||||
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
|
||||
@ -2010,7 +2030,7 @@ struct_declaration
|
||||
}
|
||||
| type_qualifier type_specifier struct_declarator_list SEMICOLON {
|
||||
if ($2.arraySizes) {
|
||||
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
|
||||
parseContext.profileRequires($2.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
|
||||
parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
|
||||
if (parseContext.profile == EEsProfile)
|
||||
parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());
|
||||
@ -2062,9 +2082,15 @@ initializer
|
||||
$$ = $1;
|
||||
}
|
||||
| LEFT_BRACE initializer_list RIGHT_BRACE {
|
||||
const char* initFeature = "{ } style initializers";
|
||||
parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, initFeature);
|
||||
parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shading_language_420pack, initFeature);
|
||||
$$ = $2;
|
||||
}
|
||||
| LEFT_BRACE initializer_list COMMA RIGHT_BRACE {
|
||||
const char* initFeature = "{ } style initializers";
|
||||
parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, initFeature);
|
||||
parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shading_language_420pack, initFeature);
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
Loading…
Reference in New Issue
Block a user