Added support for EXT_frag_depth
This change also required that support be added for associating built-in
variables with an extension, similar to how functions could be associated with
extensions previously.
R=alokp@chromium.org
Review URL: https://codereview.appspot.com/9827044
git-svn-id: http://angleproject.googlecode.com/svn/trunk@2248 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/include/GLSLANG/ShaderLang.h b/include/GLSLANG/ShaderLang.h
index b2b6e11..a0da456 100644
--- a/include/GLSLANG/ShaderLang.h
+++ b/include/GLSLANG/ShaderLang.h
@@ -215,6 +215,7 @@
int OES_EGL_image_external;
int ARB_texture_rectangle;
int EXT_draw_buffers;
+ int EXT_frag_depth;
// Set to 1 if highp precision is supported in the fragment language.
// Default is 0.
diff --git a/src/compiler/BaseTypes.h b/src/compiler/BaseTypes.h
index 0a3adfd..1631f4f 100644
--- a/src/compiler/BaseTypes.h
+++ b/src/compiler/BaseTypes.h
@@ -108,6 +108,7 @@
// built-ins written by fragment shader
EvqFragColor,
EvqFragData,
+ EvqFragDepth,
// end of list
EvqLast
@@ -139,6 +140,7 @@
case EvqFrontFacing: return "FrontFacing"; break;
case EvqFragColor: return "FragColor"; break;
case EvqFragData: return "FragData"; break;
+ case EvqFragDepth: return "FragDepth"; break;
default: return "unknown qualifier";
}
}
diff --git a/src/compiler/Initialize.cpp b/src/compiler/Initialize.cpp
index 97b46f8..4aa36b2 100644
--- a/src/compiler/Initialize.cpp
+++ b/src/compiler/Initialize.cpp
@@ -539,6 +539,10 @@
if (spec != SH_CSS_SHADERS_SPEC) {
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
+ if (resources.EXT_frag_depth) {
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
+ symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth");
+ }
} else {
symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true)));
@@ -656,4 +660,6 @@
extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
if (resources.EXT_draw_buffers)
extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
+ if (resources.EXT_frag_depth)
+ extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
}
diff --git a/src/compiler/OutputGLSL.cpp b/src/compiler/OutputGLSL.cpp
index 206f403..10a451c 100644
--- a/src/compiler/OutputGLSL.cpp
+++ b/src/compiler/OutputGLSL.cpp
@@ -19,3 +19,17 @@
{
return false;
}
+
+void TOutputGLSL::visitSymbol(TIntermSymbol* node)
+{
+ TInfoSinkBase& out = objSink();
+
+ if (node->getSymbol() == "gl_FragDepthEXT")
+ {
+ out << "gl_FragDepth";
+ }
+ else
+ {
+ TOutputGLSLBase::visitSymbol(node);
+ }
+}
diff --git a/src/compiler/OutputGLSL.h b/src/compiler/OutputGLSL.h
index 199b6f3..fa68ac8 100644
--- a/src/compiler/OutputGLSL.h
+++ b/src/compiler/OutputGLSL.h
@@ -20,6 +20,7 @@
protected:
virtual bool writeVariablePrecision(TPrecision);
+ virtual void visitSymbol(TIntermSymbol* node);
};
#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index c7ce5f2..3c4b8e1 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -52,6 +52,7 @@
mUsesPointCoord = false;
mUsesFrontFacing = false;
mUsesPointSize = false;
+ mUsesFragDepth = false;
mUsesXor = false;
mUsesMod1 = false;
mUsesMod2v = false;
@@ -189,6 +190,11 @@
out << "\n"
"static float4 gl_Color[1] = {float4(0, 0, 0, 0)};\n";
+ if (mUsesFragDepth)
+ {
+ out << "static float gl_Depth = 0.0;\n";
+ }
+
if (mUsesFragCoord)
{
out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
@@ -509,6 +515,11 @@
out << "#define GL_USES_POINT_SIZE\n";
}
+ if (mUsesFragDepth)
+ {
+ out << "#define GL_USES_FRAG_DEPTH\n";
+ }
+
if (mUsesDepthRange)
{
out << "struct gl_DepthRangeParameters\n"
@@ -843,6 +854,11 @@
mUsesPointSize = true;
out << name;
}
+ else if (name == "gl_FragDepthEXT")
+ {
+ mUsesFragDepth = true;
+ out << "gl_Depth";
+ }
else
{
TQualifier qualifier = node->getQualifier();
diff --git a/src/compiler/OutputHLSL.h b/src/compiler/OutputHLSL.h
index dc843fb..3a4c1da 100644
--- a/src/compiler/OutputHLSL.h
+++ b/src/compiler/OutputHLSL.h
@@ -97,6 +97,7 @@
bool mUsesPointCoord;
bool mUsesFrontFacing;
bool mUsesPointSize;
+ bool mUsesFragDepth;
bool mUsesXor;
bool mUsesMod1;
bool mUsesMod2v;
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index 040deb1..76855f1 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -925,6 +925,27 @@
return static_cast<const TFunction*>(symbol);
}
+bool TParseContext::isVariableBuiltIn(const TVariable* var)
+{
+ bool builtIn = false;
+ // First find by unmangled name to check whether the function name has been
+ // hidden by a variable name or struct typename.
+ const TSymbol* symbol = symbolTable.find(var->getName(), &builtIn);
+ if (symbol == 0) {
+ symbol = symbolTable.find(var->getMangledName(), &builtIn);
+ }
+
+ if (symbol == 0) {
+ return false;
+ }
+
+ if (!symbol->isVariable()) {
+ return false;
+ }
+
+ return builtIn;
+}
+
//
// Initializers show up in several places in the grammar. Have one set of
// code to handle them here.
diff --git a/src/compiler/ParseHelper.h b/src/compiler/ParseHelper.h
index b938b7d..289ec2f 100644
--- a/src/compiler/ParseHelper.h
+++ b/src/compiler/ParseHelper.h
@@ -105,6 +105,7 @@
bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);
const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0);
+ bool isVariableBuiltIn(const TVariable* pVar);
bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index dcf8b96..a67a627 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -126,6 +126,7 @@
resources->OES_EGL_image_external = 0;
resources->ARB_texture_rectangle = 0;
resources->EXT_draw_buffers = 0;
+ resources->EXT_frag_depth = 0;
// Disable highp precision in fragment shader by default.
resources->FragmentPrecisionHigh = 0;
diff --git a/src/compiler/SymbolTable.cpp b/src/compiler/SymbolTable.cpp
index 1e34f1a..f6b6ab6 100644
--- a/src/compiler/SymbolTable.cpp
+++ b/src/compiler/SymbolTable.cpp
@@ -223,10 +223,8 @@
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* symbol = it->second;
+ if (symbol->getName() == name)
+ symbol->relateToExtension(ext);
}
}
diff --git a/src/compiler/SymbolTable.h b/src/compiler/SymbolTable.h
index 5006973..f6e1959 100644
--- a/src/compiler/SymbolTable.h
+++ b/src/compiler/SymbolTable.h
@@ -50,13 +50,16 @@
virtual bool isVariable() const { return false; }
void setUniqueId(int id) { uniqueId = id; }
int getUniqueId() const { return uniqueId; }
- virtual void dump(TInfoSink &infoSink) const = 0;
+ virtual void dump(TInfoSink &infoSink) const = 0;
+ void relateToExtension(const TString& ext) { extension = ext; }
+ const TString& getExtension() const { return extension; }
private:
DISALLOW_COPY_AND_ASSIGN(TSymbol);
const TString *name;
unsigned int uniqueId; // For real comparing during code generation
+ TString extension;
};
//
@@ -156,9 +159,6 @@
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; }
@@ -175,7 +175,6 @@
TType returnType;
TString mangledName;
TOperator op;
- TString extension;
bool defined;
};
diff --git a/src/compiler/glslang.y b/src/compiler/glslang.y
index f85a745..8836378 100644
--- a/src/compiler/glslang.y
+++ b/src/compiler/glslang.y
@@ -197,7 +197,14 @@
context->error(@1, "variable expected", $1.string->c_str());
context->recover();
}
+
variable = static_cast<const TVariable*>(symbol);
+
+ if (context->isVariableBuiltIn(variable) &&
+ !variable->getExtension().empty() &&
+ context->extensionErrorCheck(@1, variable->getExtension())) {
+ context->recover();
+ }
}
// don't delete $1.string, it's used by error recovery, and the pool
diff --git a/src/compiler/glslang_tab.cpp b/src/compiler/glslang_tab.cpp
index cd401a9..3cc96a0 100644
--- a/src/compiler/glslang_tab.cpp
+++ b/src/compiler/glslang_tab.cpp
@@ -325,6 +325,14 @@
} \
} while (0)
+#define FRAG_VERT_ONLY(S, L) { \
+ if (context->shaderType != SH_FRAGMENT_SHADER && \
+ context->shaderType != SH_VERTEX_SHADER) { \
+ context->error(L, " supported in vertex/fragment shaders only ", S); \
+ context->recover(); \
+ } \
+}
+
#define VERTEX_ONLY(S, L) { \
if (context->shaderType != SH_VERTEX_SHADER) { \
context->error(L, " supported in vertex shaders only ", S); \
@@ -713,27 +721,27 @@
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 179, 179, 180, 183, 219, 222, 235, 240, 245,
- 251, 254, 329, 332, 433, 443, 456, 464, 564, 567,
- 575, 578, 584, 588, 595, 601, 610, 618, 673, 683,
- 686, 696, 706, 727, 728, 729, 734, 735, 743, 754,
- 755, 763, 774, 778, 779, 789, 799, 809, 822, 823,
- 833, 846, 850, 854, 858, 859, 872, 873, 886, 887,
- 900, 901, 918, 919, 932, 933, 934, 935, 936, 940,
- 943, 954, 962, 989, 994, 1008, 1045, 1048, 1055, 1063,
- 1084, 1105, 1115, 1143, 1148, 1158, 1163, 1173, 1176, 1179,
- 1182, 1188, 1195, 1198, 1220, 1238, 1262, 1285, 1289, 1307,
- 1315, 1347, 1367, 1388, 1397, 1420, 1423, 1429, 1437, 1445,
- 1453, 1463, 1470, 1473, 1476, 1482, 1485, 1500, 1504, 1508,
- 1512, 1516, 1521, 1526, 1531, 1536, 1541, 1546, 1551, 1556,
- 1561, 1566, 1571, 1576, 1580, 1584, 1592, 1600, 1604, 1617,
- 1617, 1631, 1631, 1640, 1643, 1659, 1695, 1699, 1705, 1712,
- 1727, 1731, 1735, 1736, 1742, 1743, 1744, 1745, 1746, 1750,
- 1751, 1751, 1751, 1761, 1762, 1766, 1766, 1767, 1767, 1772,
- 1775, 1785, 1788, 1794, 1795, 1799, 1807, 1811, 1821, 1826,
- 1843, 1843, 1848, 1848, 1855, 1855, 1863, 1866, 1872, 1875,
- 1881, 1885, 1892, 1899, 1906, 1913, 1924, 1933, 1937, 1944,
- 1947, 1953, 1953
+ 0, 187, 187, 188, 191, 234, 237, 250, 255, 260,
+ 266, 269, 356, 359, 460, 470, 483, 491, 591, 594,
+ 602, 605, 611, 615, 622, 628, 637, 645, 700, 710,
+ 713, 723, 733, 754, 755, 756, 761, 762, 771, 783,
+ 784, 792, 803, 807, 808, 818, 828, 838, 851, 852,
+ 862, 875, 879, 883, 887, 888, 901, 902, 915, 916,
+ 929, 930, 947, 948, 961, 962, 963, 964, 965, 969,
+ 972, 983, 991, 1018, 1023, 1037, 1074, 1077, 1084, 1092,
+ 1113, 1134, 1144, 1172, 1177, 1187, 1192, 1202, 1205, 1208,
+ 1211, 1217, 1224, 1227, 1249, 1267, 1291, 1314, 1318, 1336,
+ 1344, 1376, 1396, 1485, 1494, 1517, 1520, 1526, 1534, 1542,
+ 1550, 1560, 1567, 1570, 1573, 1579, 1582, 1597, 1601, 1605,
+ 1609, 1618, 1623, 1628, 1633, 1638, 1643, 1648, 1653, 1658,
+ 1663, 1669, 1675, 1681, 1686, 1691, 1700, 1709, 1714, 1727,
+ 1727, 1741, 1741, 1750, 1753, 1769, 1805, 1809, 1815, 1822,
+ 1837, 1841, 1845, 1846, 1852, 1853, 1854, 1855, 1856, 1860,
+ 1861, 1861, 1861, 1871, 1872, 1876, 1876, 1877, 1877, 1882,
+ 1885, 1895, 1898, 1904, 1905, 1909, 1917, 1921, 1931, 1936,
+ 1953, 1953, 1958, 1958, 1965, 1965, 1973, 1976, 1982, 1985,
+ 1991, 1995, 2002, 2009, 2016, 2023, 2034, 2043, 2047, 2054,
+ 2057, 2063, 2063
};
#endif
@@ -2262,7 +2270,14 @@
context->error((yylsp[(1) - (1)]), "variable expected", (yyvsp[(1) - (1)].lex).string->c_str());
context->recover();
}
+
variable = static_cast<const TVariable*>(symbol);
+
+ if (context->isVariableBuiltIn(variable) &&
+ !variable->getExtension().empty() &&
+ context->extensionErrorCheck((yylsp[(1) - (1)]), variable->getExtension())) {
+ context->recover();
+ }
}
// don't delete $1.string, it's used by error recovery, and the pool
@@ -2369,7 +2384,15 @@
}
} else {
if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray()) {
- if (index >= (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize()) {
+ if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) {
+ if ((yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getMaxArraySize() <= index) {
+ if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), index, true, (yylsp[(2) - (4)])))
+ context->recover();
+ } else {
+ if (context->arraySetMaxSize((yyvsp[(1) - (4)].interm.intermTypedNode)->getAsSymbolNode(), (yyvsp[(1) - (4)].interm.intermTypedNode)->getTypePointer(), 0, false, (yylsp[(2) - (4)])))
+ context->recover();
+ }
+ } else if (index >= (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize()) {
std::stringstream extraInfoStream;
extraInfoStream << "array index out of range '" << index << "'";
std::string extraInfo = extraInfoStream.str();
@@ -2389,6 +2412,10 @@
(yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yylsp[(2) - (4)]));
}
} else {
+ if ((yyvsp[(1) - (4)].interm.intermTypedNode)->isArray() && (yyvsp[(1) - (4)].interm.intermTypedNode)->getType().getArraySize() == 0) {
+ context->error((yylsp[(2) - (4)]), "", "[", "array must be redeclared with a size before being indexed with a variable");
+ context->recover();
+ }
(yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexIndirect, (yyvsp[(1) - (4)].interm.intermTypedNode), (yyvsp[(3) - (4)].interm.intermTypedNode), (yylsp[(2) - (4)]));
}
if ((yyval.interm.intermTypedNode) == 0) {
@@ -2752,33 +2779,33 @@
case EbtFloat:
if ((yyvsp[(1) - (1)].interm.type).matrix) {
switch((yyvsp[(1) - (1)].interm.type).size) {
- case 2: op = EOpConstructMat2; break;
- case 3: op = EOpConstructMat3; break;
- case 4: op = EOpConstructMat4; break;
+ case 2: op = EOpConstructMat2; break;
+ case 3: op = EOpConstructMat3; break;
+ case 4: op = EOpConstructMat4; break;
}
} else {
switch((yyvsp[(1) - (1)].interm.type).size) {
- case 1: op = EOpConstructFloat; break;
- case 2: op = EOpConstructVec2; break;
- case 3: op = EOpConstructVec3; break;
- case 4: op = EOpConstructVec4; break;
+ case 1: op = EOpConstructFloat; break;
+ case 2: op = EOpConstructVec2; break;
+ case 3: op = EOpConstructVec3; break;
+ case 4: op = EOpConstructVec4; break;
}
}
break;
case EbtInt:
switch((yyvsp[(1) - (1)].interm.type).size) {
- case 1: op = EOpConstructInt; break;
- case 2: op = EOpConstructIVec2; break;
- case 3: op = EOpConstructIVec3; break;
- case 4: op = EOpConstructIVec4; break;
+ case 1: op = EOpConstructInt; break;
+ case 2: FRAG_VERT_ONLY("ivec2", (yylsp[(1) - (1)])); op = EOpConstructIVec2; break;
+ case 3: FRAG_VERT_ONLY("ivec3", (yylsp[(1) - (1)])); op = EOpConstructIVec3; break;
+ case 4: FRAG_VERT_ONLY("ivec4", (yylsp[(1) - (1)])); op = EOpConstructIVec4; break;
}
break;
case EbtBool:
switch((yyvsp[(1) - (1)].interm.type).size) {
- case 1: op = EOpConstructBool; break;
- case 2: op = EOpConstructBVec2; break;
- case 3: op = EOpConstructBVec3; break;
- case 4: op = EOpConstructBVec4; break;
+ case 1: op = EOpConstructBool; break;
+ case 2: FRAG_VERT_ONLY("bvec2", (yylsp[(1) - (1)])); op = EOpConstructBVec2; break;
+ case 3: FRAG_VERT_ONLY("bvec3", (yylsp[(1) - (1)])); op = EOpConstructBVec3; break;
+ case 4: FRAG_VERT_ONLY("bvec4", (yylsp[(1) - (1)])); op = EOpConstructBVec4; break;
}
break;
default: break;
@@ -2887,6 +2914,7 @@
case 37:
{
+ FRAG_VERT_ONLY("*", (yylsp[(2) - (3)]));
(yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
if ((yyval.interm.intermTypedNode) == 0) {
context->binaryOpError((yylsp[(2) - (3)]), "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
@@ -2899,6 +2927,7 @@
case 38:
{
+ FRAG_VERT_ONLY("/", (yylsp[(2) - (3)]));
(yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
if ((yyval.interm.intermTypedNode) == 0) {
context->binaryOpError((yylsp[(2) - (3)]), "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
@@ -3152,27 +3181,27 @@
case 64:
- { (yyval.interm).op = EOpAssign; }
+ { (yyval.interm).op = EOpAssign; }
break;
case 65:
- { (yyval.interm).op = EOpMulAssign; }
+ { FRAG_VERT_ONLY("*=", (yylsp[(1) - (1)])); (yyval.interm).op = EOpMulAssign; }
break;
case 66:
- { (yyval.interm).op = EOpDivAssign; }
+ { FRAG_VERT_ONLY("/=", (yylsp[(1) - (1)])); (yyval.interm).op = EOpDivAssign; }
break;
case 67:
- { (yyval.interm).op = EOpAddAssign; }
+ { (yyval.interm).op = EOpAddAssign; }
break;
case 68:
- { (yyval.interm).op = EOpSubAssign; }
+ { (yyval.interm).op = EOpSubAssign; }
break;
case 69:
@@ -3976,6 +4005,7 @@
case 130:
{
+ FRAG_VERT_ONLY("mat2", (yylsp[(1) - (1)]));
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
(yyval.interm.type).setAggregate(2, true);
@@ -3985,6 +4015,7 @@
case 131:
{
+ FRAG_VERT_ONLY("mat3", (yylsp[(1) - (1)]));
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
(yyval.interm.type).setAggregate(3, true);
@@ -3994,6 +4025,7 @@
case 132:
{
+ FRAG_VERT_ONLY("mat4", (yylsp[(1) - (1)]));
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
(yyval.interm.type).setAggregate(4, true);
@@ -4003,6 +4035,7 @@
case 133:
{
+ FRAG_VERT_ONLY("sampler2D", (yylsp[(1) - (1)]));
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtSampler2D, qual, (yylsp[(1) - (1)]));
}
@@ -4011,6 +4044,7 @@
case 134:
{
+ FRAG_VERT_ONLY("samplerCube", (yylsp[(1) - (1)]));
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtSamplerCube, qual, (yylsp[(1) - (1)]));
}
@@ -4023,6 +4057,7 @@
context->error((yylsp[(1) - (1)]), "unsupported type", "samplerExternalOES");
context->recover();
}
+ FRAG_VERT_ONLY("samplerExternalOES", (yylsp[(1) - (1)]));
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtSamplerExternalOES, qual, (yylsp[(1) - (1)]));
}
@@ -4035,6 +4070,7 @@
context->error((yylsp[(1) - (1)]), "unsupported type", "sampler2DRect");
context->recover();
}
+ FRAG_VERT_ONLY("sampler2DRect", (yylsp[(1) - (1)]));
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
(yyval.interm.type).setBasic(EbtSampler2DRect, qual, (yylsp[(1) - (1)]));
}
@@ -4043,6 +4079,7 @@
case 137:
{
+ FRAG_VERT_ONLY("struct", (yylsp[(1) - (1)]));
(yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
(yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
}
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 3dd2cd8..f6ce667 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -3964,6 +3964,7 @@
extensionString += "GL_EXT_texture_format_BGRA8888 ";
extensionString += "GL_EXT_texture_storage ";
+ extensionString += "GL_EXT_frag_depth ";
// ANGLE-specific extensions
if (supportsDepthTextures())
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index 2c57c62..f68f6e5 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -1549,8 +1549,14 @@
"\n"
"struct PS_OUTPUT\n"
"{\n"
- " float4 gl_Color[1] : COLOR;\n"
- "};\n"
+ " float4 gl_Color[1] : COLOR;\n";
+
+ if (fragmentShader->mUsesFragDepth)
+ {
+ pixelHLSL += " float gl_Depth : DEPTH;\n";
+ }
+
+ pixelHLSL += "};\n"
"\n"
"PS_OUTPUT main(PS_INPUT input)\n"
"{\n";
@@ -1625,9 +1631,15 @@
pixelHLSL += "\n"
" gl_main();\n"
"\n"
- " PS_OUTPUT output;\n"
- " output.gl_Color[0] = gl_Color[0];\n"
- "\n"
+ " PS_OUTPUT output;\n"
+ " output.gl_Color[0] = gl_Color[0];\n";
+
+ if (fragmentShader->mUsesFragDepth)
+ {
+ pixelHLSL += " output.gl_Depth = gl_Depth;\n";
+ }
+
+ pixelHLSL += "\n"
" return output;\n"
"}\n";
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index e3e02d5..c3ee644 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -238,6 +238,7 @@
resources.OES_standard_derivatives = context->supportsDerivativeInstructions() ? 1 : 0;
// resources.OES_EGL_image_external = getDisplay()->isD3d9ExDevice() ? 1 : 0; // TODO: commented out until the extension is actually supported.
resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
+ resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
@@ -292,6 +293,7 @@
mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
+ mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL;
}
}
@@ -311,6 +313,7 @@
mUsesFrontFacing = false;
mUsesPointSize = false;
mUsesPointCoord = false;
+ mUsesFragDepth = false;
}
void Shader::compileToHLSL(void *compiler)
diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h
index b73fc28..e6ca03d 100644
--- a/src/libGLESv2/Shader.h
+++ b/src/libGLESv2/Shader.h
@@ -90,6 +90,7 @@
bool mUsesFrontFacing;
bool mUsesPointSize;
bool mUsesPointCoord;
+ bool mUsesFragDepth;
static void *mFragmentCompiler;
static void *mVertexCompiler;