Add GLSL/ESSL validator/translator support for GL_EXT_shader_framebuffer_fetch.
BUG=angle:834
Change-Id: I2d4e25909a8e1266b9bb7f1d4421324143157c8a
Reviewed-on: https://chromium-review.googlesource.com/231032
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Erik Dahlström <ed@opera.com>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index 71221c9..87bf4ab 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -307,6 +307,10 @@
EvqFragData,
EvqFragDepth,
+ // built-ins written by the shader_framebuffer_fetch extension(s)
+ EvqLastFragColor,
+ EvqLastFragData,
+
// GLSL ES 3.0 vertex output and fragment input
EvqSmooth, // Incomplete qualifier, smooth is the default
EvqFlat, // Incomplete qualifier
@@ -396,6 +400,8 @@
case EvqSmoothIn: return "smooth in"; break;
case EvqCentroidIn: return "centroid in"; break;
case EvqFlatIn: return "flat in"; break;
+ case EvqLastFragColor: return "LastFragColor"; break;
+ case EvqLastFragData: return "LastFragData"; break;
default: return "unknown qualifier";
}
}
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index ab1c9dd..9b273e8 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -392,6 +392,9 @@
<< ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
<< ":EXT_frag_depth:" << compileResources.EXT_frag_depth
<< ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
+ << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
+ << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
+ << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index 10b21e6..043a251 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -620,6 +620,19 @@
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_FragDepthEXT", "GL_EXT_frag_depth");
}
+ if (resources.EXT_shader_framebuffer_fetch)
+ {
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_LastFragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqLastFragData, 4)));
+ }
+ else if (resources.NV_shader_framebuffer_fetch)
+ {
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_LastFragColor"), TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_LastFragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqLastFragData, 4)));
+ }
+ else if (resources.ARM_shader_framebuffer_fetch)
+ {
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_LastFragColorARM"), TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
+ }
} else {
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4)));
@@ -714,6 +727,14 @@
symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjLodEXT", "GL_EXT_shader_texture_lod");
symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeLodEXT", "GL_EXT_shader_texture_lod");
}
+ if (resources.NV_shader_framebuffer_fetch)
+ {
+ symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_LastFragColor", "GL_NV_shader_framebuffer_fetch");
+ }
+ else if (resources.ARM_shader_framebuffer_fetch)
+ {
+ symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_LastFragColorARM", "GL_ARM_shader_framebuffer_fetch");
+ }
break;
default: break;
}
@@ -737,6 +758,22 @@
TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
fragData.setArraySize(resources.MaxDrawBuffers);
symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData));
+
+ if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch) {
+ // Set up gl_LastFragData. The array size.
+ TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
+ lastFragData.setArraySize(resources.MaxDrawBuffers);
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
+
+ if (resources.EXT_shader_framebuffer_fetch)
+ {
+ symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_LastFragData", "GL_EXT_shader_framebuffer_fetch");
+ }
+ else if (resources.NV_shader_framebuffer_fetch)
+ {
+ symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_LastFragData", "GL_NV_shader_framebuffer_fetch");
+ }
+ }
}
break;
default: break;
@@ -758,4 +795,10 @@
extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
if (resources.EXT_shader_texture_lod)
extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined;
+ if (resources.EXT_shader_framebuffer_fetch)
+ extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined;
+ if (resources.NV_shader_framebuffer_fetch)
+ extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined;
+ if (resources.ARM_shader_framebuffer_fetch)
+ extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined;
}
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 8d21467..89ab9a5 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -796,9 +796,24 @@
bool sameScope = false;
TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope);
if (symbol == 0 || !sameScope) {
- if (reservedErrorCheck(line, identifier))
- return true;
-
+ bool needsReservedErrorCheck = true;
+
+ // gl_LastFragData may be redeclared with a new precision qualifier
+ if (identifier.compare(0, 15, "gl_LastFragData") == 0) {
+ if (type.arraySize == static_cast<const TVariable*>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", shaderVersion))->getConstPointer()->getIConst()) {
+ if (TSymbol* builtInSymbol = symbolTable.findBuiltIn(identifier, shaderVersion)) {
+ needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension());
+ }
+ } else {
+ error(line, "redeclaration of array with size != gl_MaxDrawBuffers", identifier.c_str());
+ return true;
+ }
+ }
+
+ if (needsReservedErrorCheck)
+ if (reservedErrorCheck(line, identifier))
+ return true;
+
variable = new TVariable(&identifier, TType(type));
if (type.arraySize)
diff --git a/src/compiler/translator/ShaderLang.cpp b/src/compiler/translator/ShaderLang.cpp
index ebbd68a..03a9aef 100644
--- a/src/compiler/translator/ShaderLang.cpp
+++ b/src/compiler/translator/ShaderLang.cpp
@@ -154,6 +154,9 @@
resources->EXT_frag_depth = 0;
resources->EXT_shader_texture_lod = 0;
resources->WEBGL_debug_shader_precision = 0;
+ resources->EXT_shader_framebuffer_fetch = 0;
+ resources->NV_shader_framebuffer_fetch = 0;
+ resources->ARM_shader_framebuffer_fetch = 0;
resources->NV_draw_buffers = 0;
diff --git a/src/compiler/translator/TranslatorESSL.cpp b/src/compiler/translator/TranslatorESSL.cpp
index e75eb90..3b50f7d 100644
--- a/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/compiler/translator/TranslatorESSL.cpp
@@ -50,7 +50,10 @@
for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
iter != extensionBehavior.end(); ++iter) {
if (iter->second != EBhUndefined) {
- if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
+ if (getResources().NV_shader_framebuffer_fetch && iter->first == "GL_EXT_shader_framebuffer_fetch") {
+ sink << "#extension GL_NV_shader_framebuffer_fetch : "
+ << getBehaviorString(iter->second) << "\n";
+ } else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
sink << "#extension GL_NV_draw_buffers : "
<< getBehaviorString(iter->second) << "\n";
} else {
diff --git a/src/compiler/translator/VariableInfo.cpp b/src/compiler/translator/VariableInfo.cpp
index d8e1378..67b7c8c 100644
--- a/src/compiler/translator/VariableInfo.cpp
+++ b/src/compiler/translator/VariableInfo.cpp
@@ -144,6 +144,7 @@
mFragCoordAdded(false),
mPositionAdded(false),
mPointSizeAdded(false),
+ mLastFragDataAdded(false),
mHashFunction(hashFunction),
mSymbolTable(symbolTable)
{
@@ -281,6 +282,22 @@
mPointSizeAdded = true;
}
return;
+ case EvqLastFragData:
+ if (!mLastFragDataAdded)
+ {
+ Varying info;
+ const char kName[] = "gl_LastFragData";
+ info.name = kName;
+ info.mappedName = kName;
+ info.type = GL_FLOAT_VEC4;
+ info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
+ info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
+ info.staticUse = true;
+ info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
+ mVaryings->push_back(info);
+ mLastFragDataAdded = true;
+ }
+ return;
default:
break;
}
diff --git a/src/compiler/translator/VariableInfo.h b/src/compiler/translator/VariableInfo.h
index 30c2a61..b0e0455 100644
--- a/src/compiler/translator/VariableInfo.h
+++ b/src/compiler/translator/VariableInfo.h
@@ -53,6 +53,7 @@
bool mPositionAdded;
bool mPointSizeAdded;
+ bool mLastFragDataAdded;
ShHashFunction64 mHashFunction;