Added support for associating functions with extensions and performing validation when those functions are used in a shader.
BUG=25
Review URL: http://codereview.appspot.com/2141046
git-svn-id: https://angleproject.googlecode.com/svn/trunk@415 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Initialize.cpp b/src/compiler/Initialize.cpp
index df5e3fd..e55437a 100644
--- a/src/compiler/Initialize.cpp
+++ b/src/compiler/Initialize.cpp
@@ -601,6 +601,10 @@
symbolTable.relateToOperator("dFdx", EOpDFdx);
symbolTable.relateToOperator("dFdy", EOpDFdy);
symbolTable.relateToOperator("fwidth", EOpFwidth);
+
+ symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives");
+ symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives");
+ symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives");
}
break;
default: break;
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index 3c61615..ef01c5a 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -884,16 +884,22 @@
return false;
}
-bool TParseContext::extensionErrorCheck(int line, const char* extension)
-{
- if (extensionBehavior[extension] == EBhWarn) {
- infoSink.info.message(EPrefixWarning, ("extension " + TString(extension) + " is being used").c_str(), line);
- return false;
- }
- if (extensionBehavior[extension] == EBhDisable) {
- error(line, "extension", extension, "is disabled");
+bool TParseContext::extensionErrorCheck(int line, const TString& extension)
+{
+ TExtensionBehavior::const_iterator iter = extensionBehavior.find(extension);
+ if (iter == extensionBehavior.end()) {
+ error(line, "extension", extension.c_str(), "is not supported");
return true;
}
+ if (iter->second == EBhDisable) {
+ error(line, "extension", extension.c_str(), "is disabled");
+ return true;
+ }
+ if (iter->second == EBhWarn) {
+ TString msg = "extension " + extension + " is being used";
+ infoSink.info.message(EPrefixWarning, msg.c_str(), line);
+ return false;
+ }
return false;
}
diff --git a/src/compiler/ParseHelper.h b/src/compiler/ParseHelper.h
index fb29d94..5c72239 100644
--- a/src/compiler/ParseHelper.h
+++ b/src/compiler/ParseHelper.h
@@ -79,7 +79,7 @@
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
- bool extensionErrorCheck(int line, const char*);
+ bool extensionErrorCheck(int line, const TString&);
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
diff --git a/src/compiler/SymbolTable.cpp b/src/compiler/SymbolTable.cpp
index 1b08667..02817d4 100644
--- a/src/compiler/SymbolTable.cpp
+++ b/src/compiler/SymbolTable.cpp
@@ -140,6 +140,22 @@
}
}
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in extension. This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
+ if (it->second->isFunction()) {
+ TFunction* function = static_cast<TFunction*>(it->second);
+ if (function->getName() == name)
+ function->relateToExtension(ext);
+ }
+ }
+}
TSymbol::TSymbol(const TSymbol& copyOf)
{
diff --git a/src/compiler/SymbolTable.h b/src/compiler/SymbolTable.h
index 7476407..42cf736 100644
--- a/src/compiler/SymbolTable.h
+++ b/src/compiler/SymbolTable.h
@@ -156,8 +156,13 @@
const TString& getMangledName() const { return mangledName; }
const TType& getReturnType() const { return returnType; }
+
void relateToOperator(TOperator o) { op = o; }
TOperator getBuiltInOp() const { return op; }
+
+ void relateToExtension(const TString& ext) { extension = ext; }
+ const TString& getExtension() const { return extension; }
+
void setDefined() { defined = true; }
bool isDefined() { return defined; }
@@ -174,6 +179,7 @@
TType returnType;
TString mangledName;
TOperator op;
+ TString extension;
bool defined;
};
@@ -220,6 +226,7 @@
}
void relateToOperator(const char* name, TOperator op);
+ void relateToExtension(const char* name, const TString& ext);
void dump(TInfoSink &infoSink) const;
TSymbolTableLevel* clone(TStructureMap& remapper);
@@ -288,8 +295,16 @@
return symbol;
}
- TSymbolTableLevel* getGlobalLevel() { assert(table.size() >= 2); return table[1]; }
- void relateToOperator(const char* name, TOperator op) { table[0]->relateToOperator(name, op); }
+ TSymbolTableLevel* getGlobalLevel() {
+ assert(table.size() >= 2);
+ return table[1];
+ }
+ void relateToOperator(const char* name, TOperator op) {
+ table[0]->relateToOperator(name, op);
+ }
+ void relateToExtension(const char* name, const TString& ext) {
+ table[0]->relateToExtension(name, ext);
+ }
int getMaxSymbolId() { return uniqueId; }
void dump(TInfoSink &infoSink) const;
void copyTable(const TSymbolTable& copyOf);
diff --git a/src/compiler/glslang.y b/src/compiler/glslang.y
index 1044873..c96b8d8 100644
--- a/src/compiler/glslang.y
+++ b/src/compiler/glslang.y
@@ -501,9 +501,12 @@
fnCandidate = parseContext->findFunction($1.line, fnCall, &builtIn);
if (fnCandidate) {
//
- // A declared function. But, it might still map to a built-in
- // operation.
+ // A declared function.
//
+ if (builtIn && !fnCandidate->getExtension().empty() &&
+ parseContext->extensionErrorCheck($1.line, fnCandidate->getExtension())) {
+ parseContext->recover();
+ }
op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull) {
//