Commit 703671e9 by Olli Etuaho Committed by Commit Bot

Unify extension behavior checks

Some supportsExtension and isExtensionEnabled checks are now turned into checkCanUseExtension checks. Using checkCanUseExtension is preferable so that warnings are generated correctly when an extension is used and a warn directive is present. isExtensionEnabled is still used in some places where an error message about the extension could be confusing, particularly when a core spec version adds support for something that is also present in an extension. Also make it possible to disable ARB_texture_rectangle extension using an extension directive. ARB_texture_rectangle extension functionality is enabled by default in GLSL when the extension is supported. BUG=angleproject:2238 TEST=angle_unittests Change-Id: I7455293412ff469f54bc7da79df146e7bc127379 Reviewed-on: https://chromium-review.googlesource.com/760737 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent bb0775da
...@@ -89,7 +89,8 @@ bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extens ...@@ -89,7 +89,8 @@ bool IsExtensionEnabled(const TExtensionBehavior &extBehavior, TExtension extens
{ {
ASSERT(extension != TExtension::UNDEFINED); ASSERT(extension != TExtension::UNDEFINED);
auto iter = extBehavior.find(extension); auto iter = extBehavior.find(extension);
return iter != extBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire); return iter != extBehavior.end() &&
(iter->second == EBhEnable || iter->second == EBhRequire || iter->second == EBhWarn);
} }
} // namespace sh } // namespace sh
...@@ -1050,7 +1050,9 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi ...@@ -1050,7 +1050,9 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
} }
if (resources.ARB_texture_rectangle) if (resources.ARB_texture_rectangle)
{ {
extBehavior[TExtension::ARB_texture_rectangle] = EBhUndefined; // Special: ARB_texture_rectangle extension does not follow the standard for #extension
// directives - it is enabled by default. An extension directive may still disable it.
extBehavior[TExtension::ARB_texture_rectangle] = EBhEnable;
} }
if (resources.EXT_blend_func_extended) if (resources.EXT_blend_func_extended)
{ {
...@@ -1097,9 +1099,16 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi ...@@ -1097,9 +1099,16 @@ void InitExtensionBehavior(const ShBuiltInResources &resources, TExtensionBehavi
void ResetExtensionBehavior(TExtensionBehavior &extBehavior) void ResetExtensionBehavior(TExtensionBehavior &extBehavior)
{ {
for (auto ext_iter = extBehavior.begin(); ext_iter != extBehavior.end(); ++ext_iter) for (auto &ext : extBehavior)
{ {
ext_iter->second = EBhUndefined; if (ext.first == TExtension::ARB_texture_rectangle)
{
ext.second = EBhEnable;
}
else
{
ext.second = EBhUndefined;
}
} }
} }
......
...@@ -1156,72 +1156,95 @@ void TParseContext::checkIsParameterQualifierValid( ...@@ -1156,72 +1156,95 @@ void TParseContext::checkIsParameterQualifierValid(
} }
} }
bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension) template <size_t size>
bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
const std::array<TExtension, size> &extensions)
{ {
ASSERT(extension != TExtension::UNDEFINED); ASSERT(!extensions.empty());
ASSERT(extension != TExtension::EXT_geometry_shader); const TExtensionBehavior &extBehavior = extensionBehavior();
const TExtensionBehavior &extBehavior = extensionBehavior();
TExtensionBehavior::const_iterator iter = extBehavior.find(extension); bool canUseWithWarning = false;
if (iter == extBehavior.end()) bool canUseWithoutWarning = false;
{
error(line, "extension is not supported", GetExtensionNameString(extension)); const char *errorMsgString = "";
return false; TExtension errorMsgExtension = TExtension::UNDEFINED;
}
// In GLSL ES, an extension's default behavior is "disable". for (TExtension extension : extensions)
if (iter->second == EBhDisable || iter->second == EBhUndefined)
{ {
// We also need to check EXT_geometry_shader because internally we always use auto extIter = extBehavior.find(extension);
// TExtension::OES_geometry_shader to represent both OES_geometry_shader and if (canUseWithWarning)
// EXT_geometry_shader.
if (extension == TExtension::OES_geometry_shader)
{ {
TExtensionBehavior::const_iterator iterExt = // We already have an extension that we can use, but with a warning.
extBehavior.find(TExtension::EXT_geometry_shader); // See if we can use the alternative extension without a warning.
ASSERT(iterExt != extBehavior.end()); if (extIter == extBehavior.end())
if (iterExt->second == EBhUndefined)
{ {
error(line, "extension is disabled", continue;
GetExtensionNameString(TExtension::OES_geometry_shader));
return false;
} }
if (iterExt->second == EBhDisable) if (extIter->second == EBhEnable || extIter->second == EBhRequire)
{ {
error(line, "extension is disabled", canUseWithoutWarning = true;
GetExtensionNameString(TExtension::EXT_geometry_shader)); break;
return false;
}
if (iterExt->second == EBhWarn)
{
warning(line, "extension is being used",
GetExtensionNameString(TExtension::EXT_geometry_shader));
} }
continue;
return true;
} }
if (extIter == extBehavior.end())
error(line, "extension is disabled", GetExtensionNameString(extension));
return false;
}
if (iter->second == EBhWarn)
{
if (extension == TExtension::OES_geometry_shader)
{ {
TExtensionBehavior::const_iterator iterExt = errorMsgString = "extension is not supported";
extBehavior.find(TExtension::EXT_geometry_shader); errorMsgExtension = extension;
ASSERT(iterExt != extBehavior.end()); }
// We should output no warnings when OES_geometry_shader is declared as "warn" and else if (extIter->second == EBhUndefined || extIter->second == EBhDisable)
// EXT_geometry_shader is declared as "require" or "enable". {
if (iterExt->second == EBhRequire || iterExt->second == EBhEnable) errorMsgString = "extension is disabled";
{ errorMsgExtension = extension;
return true; }
} else if (extIter->second == EBhWarn)
{
errorMsgExtension = extension;
canUseWithWarning = true;
}
else
{
ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire);
canUseWithoutWarning = true;
break;
} }
}
warning(line, "extension is being used", GetExtensionNameString(extension)); if (canUseWithoutWarning)
{
return true;
}
if (canUseWithWarning)
{
warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension));
return true; return true;
} }
error(line, errorMsgString, GetExtensionNameString(errorMsgExtension));
return false;
}
return true; template bool TParseContext::checkCanUseOneOfExtensions(
const TSourceLoc &line,
const std::array<TExtension, 1> &extensions);
template bool TParseContext::checkCanUseOneOfExtensions(
const TSourceLoc &line,
const std::array<TExtension, 2> &extensions);
template bool TParseContext::checkCanUseOneOfExtensions(
const TSourceLoc &line,
const std::array<TExtension, 3> &extensions);
bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
{
ASSERT(extension != TExtension::UNDEFINED);
ASSERT(extension != TExtension::EXT_geometry_shader);
if (extension == TExtension::OES_geometry_shader)
{
// OES_geometry_shader and EXT_geometry_shader are always interchangeable.
constexpr std::array<TExtension, 2u> extensions{
{TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}};
return checkCanUseOneOfExtensions(line, extensions);
}
return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{extension});
} }
// ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause // ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
...@@ -1680,13 +1703,6 @@ void TParseContext::checkInvariantVariableQualifier(bool invariant, ...@@ -1680,13 +1703,6 @@ void TParseContext::checkInvariantVariableQualifier(bool invariant,
} }
} }
bool TParseContext::supportsExtension(TExtension extension)
{
const TExtensionBehavior &extbehavior = extensionBehavior();
TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
return (iter != extbehavior.end());
}
bool TParseContext::isExtensionEnabled(TExtension extension) const bool TParseContext::isExtensionEnabled(TExtension extension) const
{ {
return IsExtensionEnabled(extensionBehavior(), extension); return IsExtensionEnabled(extensionBehavior(), extension);
...@@ -4206,10 +4222,12 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp ...@@ -4206,10 +4222,12 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp
error(qualifierTypeLine, "invalid layout qualifier: location requires an argument", error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
qualifierType.c_str()); qualifierType.c_str());
} }
else if (qualifierType == "yuv" && isExtensionEnabled(TExtension::EXT_YUV_target) && else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
mShaderType == GL_FRAGMENT_SHADER)
{ {
qualifier.yuv = true; if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
{
qualifier.yuv = true;
}
} }
else if (qualifierType == "rgba32f") else if (qualifierType == "rgba32f")
{ {
...@@ -4464,10 +4482,12 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp ...@@ -4464,10 +4482,12 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp
parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u, parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
&qualifier.localSize); &qualifier.localSize);
} }
else if (qualifierType == "num_views" && isExtensionEnabled(TExtension::OVR_multiview) && else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
mShaderType == GL_VERTEX_SHADER)
{ {
parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews); if (checkCanUseExtension(qualifierTypeLine, TExtension::OVR_multiview))
{
parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
}
} }
else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_OES && else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_OES &&
checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader)) checkCanUseExtension(qualifierTypeLine, TExtension::OES_geometry_shader))
......
...@@ -141,6 +141,15 @@ class TParseContext : angle::NonCopyable ...@@ -141,6 +141,15 @@ class TParseContext : angle::NonCopyable
void checkIsParameterQualifierValid(const TSourceLoc &line, void checkIsParameterQualifierValid(const TSourceLoc &line,
const TTypeQualifierBuilder &typeQualifierBuilder, const TTypeQualifierBuilder &typeQualifierBuilder,
TType *type); TType *type);
// Check if at least one of the specified extensions can be used, and generate error/warning as
// appropriate according to the spec.
// This function is only needed for a few different small constant sizes of extension array, and
// we want to avoid unnecessary dynamic allocations. That's why checkCanUseOneOfExtensions is a
// template function rather than one taking a vector.
template <size_t size>
bool checkCanUseOneOfExtensions(const TSourceLoc &line,
const std::array<TExtension, size> &extensions);
bool checkCanUseExtension(const TSourceLoc &line, TExtension extension); bool checkCanUseExtension(const TSourceLoc &line, TExtension extension);
// Done for all declarations, whether empty or not. // Done for all declarations, whether empty or not.
...@@ -171,7 +180,7 @@ class TParseContext : angle::NonCopyable ...@@ -171,7 +180,7 @@ class TParseContext : angle::NonCopyable
{ {
return mDirectiveHandler.extensionBehavior(); return mDirectiveHandler.extensionBehavior();
} }
bool supportsExtension(TExtension extension);
bool isExtensionEnabled(TExtension extension) const; bool isExtensionEnabled(TExtension extension) const;
void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior); void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior);
void handlePragmaDirective(const TSourceLoc &loc, void handlePragmaDirective(const TSourceLoc &loc,
......
...@@ -282,7 +282,8 @@ primary_expression ...@@ -282,7 +282,8 @@ primary_expression
$$ = context->addScalarLiteral(unionArray, @1); $$ = context->addScalarLiteral(unionArray, @1);
} }
| YUVCSCSTANDARDEXTCONSTANT { | YUVCSCSTANDARDEXTCONSTANT {
if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) { if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
{
context->error(@1, "unsupported value", $1.string->c_str()); context->error(@1, "unsupported value", $1.string->c_str());
} }
TConstantUnion *unionArray = new TConstantUnion[1]; TConstantUnion *unionArray = new TConstantUnion[1];
...@@ -1049,7 +1050,8 @@ type_specifier_nonarray ...@@ -1049,7 +1050,8 @@ type_specifier_nonarray
$$.setMatrix(4, 3); $$.setMatrix(4, 3);
} }
| YUVCSCSTANDARDEXT { | YUVCSCSTANDARDEXT {
if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) { if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
{
context->error(@1, "unsupported type", "yuvCscStandardEXT"); context->error(@1, "unsupported type", "yuvCscStandardEXT");
} }
$$.initialize(EbtYuvCscStandardEXT, @1); $$.initialize(EbtYuvCscStandardEXT, @1);
...@@ -1109,20 +1111,25 @@ type_specifier_nonarray ...@@ -1109,20 +1111,25 @@ type_specifier_nonarray
$$.initialize(EbtSampler2DArrayShadow, @1); $$.initialize(EbtSampler2DArrayShadow, @1);
} }
| SAMPLER_EXTERNAL_OES { | SAMPLER_EXTERNAL_OES {
if (!context->supportsExtension(TExtension::OES_EGL_image_external) && constexpr std::array<TExtension, 3u> extensions{ { TExtension::NV_EGL_stream_consumer_external,
!context->supportsExtension(TExtension::NV_EGL_stream_consumer_external)) { TExtension::OES_EGL_image_external_essl3,
TExtension::OES_EGL_image_external } };
if (!context->checkCanUseOneOfExtensions(@1, extensions))
{
context->error(@1, "unsupported type", "samplerExternalOES"); context->error(@1, "unsupported type", "samplerExternalOES");
} }
$$.initialize(EbtSamplerExternalOES, @1); $$.initialize(EbtSamplerExternalOES, @1);
} }
| SAMPLEREXTERNAL2DY2YEXT { | SAMPLEREXTERNAL2DY2YEXT {
if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) { if (!context->checkCanUseExtension(@1, TExtension::EXT_YUV_target))
{
context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT"); context->error(@1, "unsupported type", "__samplerExternal2DY2YEXT");
} }
$$.initialize(EbtSamplerExternal2DY2YEXT, @1); $$.initialize(EbtSamplerExternal2DY2YEXT, @1);
} }
| SAMPLER2DRECT { | SAMPLER2DRECT {
if (!context->supportsExtension(TExtension::ARB_texture_rectangle)) { if (!context->checkCanUseExtension(@1, TExtension::ARB_texture_rectangle))
{
context->error(@1, "unsupported type", "sampler2DRect"); context->error(@1, "unsupported type", "sampler2DRect");
} }
$$.initialize(EbtSampler2DRect, @1); $$.initialize(EbtSampler2DRect, @1);
......
...@@ -743,35 +743,35 @@ static const yytype_uint8 yytranslate[] = ...@@ -743,35 +743,35 @@ static const yytype_uint8 yytranslate[] =
static const yytype_uint16 yyrline[] = static const yytype_uint16 yyrline[] =
{ {
0, 247, 247, 248, 251, 261, 264, 269, 274, 279, 0, 247, 247, 248, 251, 261, 264, 269, 274, 279,
284, 292, 298, 301, 304, 307, 310, 313, 319, 326, 284, 293, 299, 302, 305, 308, 311, 314, 320, 327,
332, 336, 344, 347, 353, 357, 364, 369, 376, 384, 333, 337, 345, 348, 354, 358, 365, 370, 377, 385,
387, 390, 396, 399, 402, 405, 412, 413, 414, 415, 388, 391, 397, 400, 403, 406, 413, 414, 415, 416,
423, 424, 427, 430, 437, 438, 441, 447, 448, 452, 424, 425, 428, 431, 438, 439, 442, 448, 449, 453,
459, 460, 463, 466, 469, 475, 476, 479, 485, 486, 460, 461, 464, 467, 470, 476, 477, 480, 486, 487,
493, 494, 501, 502, 509, 510, 516, 517, 523, 524, 494, 495, 502, 503, 510, 511, 517, 518, 524, 525,
530, 531, 537, 538, 544, 545, 546, 547, 551, 552, 531, 532, 538, 539, 545, 546, 547, 548, 552, 553,
553, 557, 561, 565, 569, 576, 579, 585, 592, 599, 554, 558, 562, 566, 570, 577, 580, 586, 593, 600,
602, 605, 609, 613, 617, 621, 625, 632, 639, 642, 603, 606, 610, 614, 618, 622, 626, 633, 640, 643,
649, 657, 674, 684, 687, 693, 697, 701, 705, 712, 650, 658, 675, 685, 688, 694, 698, 702, 706, 713,
719, 722, 726, 730, 735, 742, 746, 750, 754, 759, 720, 723, 727, 731, 736, 743, 747, 751, 755, 760,
766, 770, 776, 779, 785, 789, 796, 802, 806, 810, 767, 771, 777, 780, 786, 790, 797, 803, 807, 811,
813, 816, 825, 830, 834, 837, 840, 843, 846, 850, 814, 817, 826, 831, 835, 838, 841, 844, 847, 851,
853, 857, 860, 863, 866, 869, 872, 879, 886, 889, 854, 858, 861, 864, 867, 870, 873, 880, 887, 890,
892, 898, 905, 908, 914, 917, 920, 923, 929, 932, 893, 899, 906, 909, 915, 918, 921, 924, 930, 933,
939, 943, 952, 955, 958, 961, 964, 967, 971, 975, 940, 944, 953, 956, 959, 962, 965, 968, 972, 976,
979, 983, 987, 991, 995, 999, 1003, 1007, 1011, 1015, 980, 984, 988, 992, 996, 1000, 1004, 1008, 1012, 1016,
1019, 1023, 1027, 1031, 1035, 1039, 1043, 1047, 1051, 1057, 1020, 1024, 1028, 1032, 1036, 1040, 1044, 1048, 1052, 1059,
1060, 1063, 1066, 1069, 1072, 1075, 1078, 1081, 1084, 1087, 1062, 1065, 1068, 1071, 1074, 1077, 1080, 1083, 1086, 1089,
1090, 1093, 1096, 1099, 1102, 1105, 1108, 1111, 1118, 1124, 1092, 1095, 1098, 1101, 1104, 1107, 1110, 1113, 1123, 1130,
1130, 1133, 1136, 1139, 1142, 1145, 1148, 1151, 1154, 1157, 1137, 1140, 1143, 1146, 1149, 1152, 1155, 1158, 1161, 1164,
1160, 1163, 1166, 1169, 1172, 1180, 1180, 1183, 1183, 1189, 1167, 1170, 1173, 1176, 1179, 1187, 1187, 1190, 1190, 1196,
1192, 1198, 1201, 1208, 1212, 1218, 1221, 1227, 1231, 1235, 1199, 1205, 1208, 1215, 1219, 1225, 1228, 1234, 1238, 1242,
1236, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1252, 1256, 1243, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1259, 1263,
1256, 1256, 1263, 1264, 1268, 1268, 1269, 1269, 1274, 1278, 1263, 1263, 1270, 1271, 1275, 1275, 1276, 1276, 1281, 1285,
1285, 1289, 1296, 1297, 1301, 1307, 1311, 1320, 1320, 1327, 1292, 1296, 1303, 1304, 1308, 1314, 1318, 1327, 1327, 1334,
1330, 1336, 1340, 1346, 1346, 1351, 1351, 1355, 1355, 1363, 1337, 1343, 1347, 1353, 1353, 1358, 1358, 1362, 1362, 1370,
1366, 1372, 1375, 1381, 1385, 1392, 1395, 1398, 1401, 1404, 1373, 1379, 1382, 1388, 1392, 1399, 1402, 1405, 1408, 1411,
1412, 1418, 1424, 1427, 1433, 1433 1419, 1425, 1431, 1434, 1440, 1440
}; };
#endif #endif
...@@ -2527,7 +2527,8 @@ yyreduce: ...@@ -2527,7 +2527,8 @@ yyreduce:
case 10: case 10:
{ {
if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) { if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target))
{
context->error((yylsp[0]), "unsupported value", (yyvsp[0].lex).string->c_str()); context->error((yylsp[0]), "unsupported value", (yyvsp[0].lex).string->c_str());
} }
TConstantUnion *unionArray = new TConstantUnion[1]; TConstantUnion *unionArray = new TConstantUnion[1];
...@@ -4019,7 +4020,8 @@ yyreduce: ...@@ -4019,7 +4020,8 @@ yyreduce:
case 188: case 188:
{ {
if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) { if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target))
{
context->error((yylsp[0]), "unsupported type", "yuvCscStandardEXT"); context->error((yylsp[0]), "unsupported type", "yuvCscStandardEXT");
} }
(yyval.interm.typeSpecifierNonArray).initialize(EbtYuvCscStandardEXT, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).initialize(EbtYuvCscStandardEXT, (yylsp[0]));
...@@ -4174,8 +4176,11 @@ yyreduce: ...@@ -4174,8 +4176,11 @@ yyreduce:
case 207: case 207:
{ {
if (!context->supportsExtension(TExtension::OES_EGL_image_external) && constexpr std::array<TExtension, 3u> extensions{ { TExtension::NV_EGL_stream_consumer_external,
!context->supportsExtension(TExtension::NV_EGL_stream_consumer_external)) { TExtension::OES_EGL_image_external_essl3,
TExtension::OES_EGL_image_external } };
if (!context->checkCanUseOneOfExtensions((yylsp[0]), extensions))
{
context->error((yylsp[0]), "unsupported type", "samplerExternalOES"); context->error((yylsp[0]), "unsupported type", "samplerExternalOES");
} }
(yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternalOES, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternalOES, (yylsp[0]));
...@@ -4186,7 +4191,8 @@ yyreduce: ...@@ -4186,7 +4191,8 @@ yyreduce:
case 208: case 208:
{ {
if (!context->isExtensionEnabled(TExtension::EXT_YUV_target)) { if (!context->checkCanUseExtension((yylsp[0]), TExtension::EXT_YUV_target))
{
context->error((yylsp[0]), "unsupported type", "__samplerExternal2DY2YEXT"); context->error((yylsp[0]), "unsupported type", "__samplerExternal2DY2YEXT");
} }
(yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternal2DY2YEXT, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).initialize(EbtSamplerExternal2DY2YEXT, (yylsp[0]));
...@@ -4197,7 +4203,8 @@ yyreduce: ...@@ -4197,7 +4203,8 @@ yyreduce:
case 209: case 209:
{ {
if (!context->supportsExtension(TExtension::ARB_texture_rectangle)) { if (!context->checkCanUseExtension((yylsp[0]), TExtension::ARB_texture_rectangle))
{
context->error((yylsp[0]), "unsupported type", "sampler2DRect"); context->error((yylsp[0]), "unsupported type", "sampler2DRect");
} }
(yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DRect, (yylsp[0])); (yyval.interm.typeSpecifierNonArray).initialize(EbtSampler2DRect, (yylsp[0]));
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
'<(angle_path)/src/tests/compiler_tests/ExpressionLimit_test.cpp', '<(angle_path)/src/tests/compiler_tests/ExpressionLimit_test.cpp',
'<(angle_path)/src/tests/compiler_tests/EXT_YUV_target_test.cpp', '<(angle_path)/src/tests/compiler_tests/EXT_YUV_target_test.cpp',
'<(angle_path)/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp', '<(angle_path)/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp',
'<(angle_path)/src/tests/compiler_tests/ExtensionDirective_test.cpp',
'<(angle_path)/src/tests/compiler_tests/FloatLex_test.cpp', '<(angle_path)/src/tests/compiler_tests/FloatLex_test.cpp',
'<(angle_path)/src/tests/compiler_tests/FragDepth_test.cpp', '<(angle_path)/src/tests/compiler_tests/FragDepth_test.cpp',
'<(angle_path)/src/tests/compiler_tests/GLSLCompatibilityOutput_test.cpp', '<(angle_path)/src/tests/compiler_tests/GLSLCompatibilityOutput_test.cpp',
......
...@@ -30,19 +30,6 @@ class ARBTextureRectangleTest : public ARBTextureRectangleTestNoExt ...@@ -30,19 +30,6 @@ class ARBTextureRectangleTest : public ARBTextureRectangleTestNoExt
} }
}; };
// Check that new types and builtins are disallowed if the extension isn't present in the translator
// resources
TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltinsWithoutTranslatorResourceExtension)
{
// The new builtins require Sampler2DRect so we can't test them independently.
const std::string &shaderString =
"precision mediump float;\n"
"uniform sampler2DRect tex;\n"
"void main() {\n"
"}\n";
ASSERT_TRUE(compile(shaderString));
}
// Check that new types and builtins are usable even with the #extension directive // Check that new types and builtins are usable even with the #extension directive
// Issue #15 of ARB_texture_rectangle explains that the extension was specified before the // Issue #15 of ARB_texture_rectangle explains that the extension was specified before the
// #extension mechanism was in place so it doesn't require explicit enabling. // #extension mechanism was in place so it doesn't require explicit enabling.
...@@ -56,7 +43,10 @@ TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltinsWithoutExtensionDirective) ...@@ -56,7 +43,10 @@ TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltinsWithoutExtensionDirective)
" color = texture2DRectProj(tex, vec3(1.0));" " color = texture2DRectProj(tex, vec3(1.0));"
" color = texture2DRectProj(tex, vec4(1.0));" " color = texture2DRectProj(tex, vec4(1.0));"
"}\n"; "}\n";
ASSERT_TRUE(compile(shaderString)); if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
} }
// Test valid usage of the new types and builtins // Test valid usage of the new types and builtins
...@@ -71,7 +61,10 @@ TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltingsWithExtensionDirective) ...@@ -71,7 +61,10 @@ TEST_F(ARBTextureRectangleTest, NewTypeAndBuiltingsWithExtensionDirective)
" color = texture2DRectProj(tex, vec3(1.0));" " color = texture2DRectProj(tex, vec3(1.0));"
" color = texture2DRectProj(tex, vec4(1.0));" " color = texture2DRectProj(tex, vec4(1.0));"
"}\n"; "}\n";
ASSERT_TRUE(compile(shaderString)); if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
} }
// Check that it is not possible to pass a sampler2DRect where sampler2D is expected, and vice versa // Check that it is not possible to pass a sampler2DRect where sampler2D is expected, and vice versa
...@@ -84,7 +77,10 @@ TEST_F(ARBTextureRectangleTest, Rect2DVs2DMismatch) ...@@ -84,7 +77,10 @@ TEST_F(ARBTextureRectangleTest, Rect2DVs2DMismatch)
"void main() {\n" "void main() {\n"
" vec4 color = texture2D(tex, vec2(1.0));" " vec4 color = texture2D(tex, vec2(1.0));"
"}\n"; "}\n";
ASSERT_FALSE(compile(shaderString1)); if (compile(shaderString1))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
const std::string &shaderString2 = const std::string &shaderString2 =
"#extension GL_ARB_texture_rectangle : require\n" "#extension GL_ARB_texture_rectangle : require\n"
...@@ -93,5 +89,28 @@ TEST_F(ARBTextureRectangleTest, Rect2DVs2DMismatch) ...@@ -93,5 +89,28 @@ TEST_F(ARBTextureRectangleTest, Rect2DVs2DMismatch)
"void main() {\n" "void main() {\n"
" vec4 color = texture2DRect(tex, vec2(1.0));" " vec4 color = texture2DRect(tex, vec2(1.0));"
"}\n"; "}\n";
ASSERT_FALSE(compile(shaderString2)); if (compile(shaderString2))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Disabling ARB_texture_rectangle in GLSL should work, even if it is enabled by default.
// See ARB_texture_rectangle spec: "a shader can still include all variations of #extension
// GL_ARB_texture_rectangle in its source code"
TEST_F(ARBTextureRectangleTest, DisableARBTextureRectangle)
{
const std::string &shaderString =
R"(
#extension GL_ARB_texture_rectangle : disable
precision mediump float;
uniform sampler2DRect s;
void main()
{})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
} }
//
// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ExtensionDirective_test.cpp:
// Miscellaneous tests for extension directives toggling functionality correctly.
//
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "compiler/translator/ExtensionBehavior.h"
#include "gtest/gtest.h"
#include "tests/test_utils/ShaderCompileTreeTest.h"
using namespace sh;
class FragmentShaderExtensionDirectiveTest : public ShaderCompileTreeTest
{
public:
FragmentShaderExtensionDirectiveTest() {}
protected:
::GLenum getShaderType() const override { return GL_FRAGMENT_SHADER; }
ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
void testCompileNeedsExtensionDirective(const std::string &shader, const std::string &extension)
{
testCompileNeedsExtensionDirective(shader, extension, "");
}
void testCompileNeedsExtensionDirective(const std::string &shader,
const std::string &extension,
const std::string &versionDirective)
{
if (compile(versionDirective + shader))
{
FAIL()
<< "Shader compilation without extension directive succeeded, expecting failure:\n"
<< mInfoLog;
}
if (compile(versionDirective + getExtensionDirective(extension, sh::EBhDisable) + shader))
{
FAIL() << "Shader compilation with extension disable directive succeeded, expecting "
"failure:\n"
<< mInfoLog;
}
if (!compile(versionDirective + getExtensionDirective(extension, sh::EBhEnable) + shader))
{
FAIL()
<< "Shader compilation with extension enable directive failed, expecting success:\n"
<< mInfoLog;
}
if (!compile(versionDirective + getExtensionDirective(extension, sh::EBhWarn) + shader))
{
FAIL()
<< "Shader compilation with extension warn directive failed, expecting success:\n"
<< mInfoLog;
}
else if (!hasWarning())
{
FAIL() << "Expected compilation to succeed with warning, but warning not present:\n"
<< mInfoLog;
}
}
private:
std::string getExtensionDirective(const std::string &extension, sh::TBehavior behavior)
{
std::string extensionDirective("#extension ");
extensionDirective += extension + " : ";
switch (behavior)
{
case EBhRequire:
extensionDirective += "require";
break;
case EBhEnable:
extensionDirective += "enable";
break;
case EBhWarn:
extensionDirective += "warn";
break;
case EBhDisable:
extensionDirective += "disable";
break;
default:
break;
}
extensionDirective += "\n";
return extensionDirective;
}
};
class OESEGLImageExternalTest : public FragmentShaderExtensionDirectiveTest
{
public:
OESEGLImageExternalTest() {}
protected:
void initResources(ShBuiltInResources *resources) override
{
resources->OES_EGL_image_external = 1;
}
};
// OES_EGL_image_external needs to be enabled in GLSL to be able to use samplerExternalOES.
TEST_F(OESEGLImageExternalTest, SamplerExternalOESUsageNeedsExtensionDirective)
{
const std::string &shaderString =
R"(
precision mediump float;
uniform samplerExternalOES s;
void main()
{})";
testCompileNeedsExtensionDirective(shaderString, "GL_OES_EGL_image_external");
}
class NVEGLStreamConsumerExternalTest : public FragmentShaderExtensionDirectiveTest
{
public:
NVEGLStreamConsumerExternalTest() {}
protected:
void initResources(ShBuiltInResources *resources) override
{
resources->NV_EGL_stream_consumer_external = 1;
}
};
// NV_EGL_stream_consumer_external needs to be enabled in GLSL to be able to use samplerExternalOES.
TEST_F(NVEGLStreamConsumerExternalTest, SamplerExternalOESUsageNeedsExtensionDirective)
{
const std::string &shaderString =
R"(
precision mediump float;
uniform samplerExternalOES s;
void main()
{})";
testCompileNeedsExtensionDirective(shaderString, "GL_NV_EGL_stream_consumer_external");
}
class EXTYUVTargetTest : public FragmentShaderExtensionDirectiveTest
{
public:
EXTYUVTargetTest() {}
protected:
void initResources(ShBuiltInResources *resources) override { resources->EXT_YUV_target = 1; }
};
// GL_EXT_YUV_target needs to be enabled in GLSL to be able to use samplerExternal2DY2YEXT.
TEST_F(EXTYUVTargetTest, SamplerExternal2DY2YEXTUsageNeedsExtensionDirective)
{
const std::string &shaderString =
R"(
precision mediump float;
uniform __samplerExternal2DY2YEXT s;
void main()
{})";
testCompileNeedsExtensionDirective(shaderString, "GL_EXT_YUV_target", "#version 300 es\n");
}
// GL_EXT_YUV_target needs to be enabled in GLSL to be able to use samplerExternal2DY2YEXT.
TEST_F(EXTYUVTargetTest, YUVLayoutNeedsExtensionDirective)
{
const std::string &shaderString =
R"(
precision mediump float;
layout(yuv) out vec4 color;
void main()
{})";
testCompileNeedsExtensionDirective(shaderString, "GL_EXT_YUV_target", "#version 300 es\n");
}
...@@ -2409,14 +2409,16 @@ TEST_P(GLSLTest, ExternalAnd2DSampler) ...@@ -2409,14 +2409,16 @@ TEST_P(GLSLTest, ExternalAnd2DSampler)
} }
const std::string fragmentShader = const std::string fragmentShader =
"precision mediump float;\n" R"(
"uniform samplerExternalOES tex0;\n" #extension GL_OES_EGL_image_external : enable
"uniform sampler2D tex1;\n" precision mediump float;
"void main(void)\n" uniform samplerExternalOES tex0;
"{\n" uniform sampler2D tex1;
" vec2 uv = vec2(0.0, 0.0);" void main(void)
" gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);\n" {
"}\n"; vec2 uv = vec2(0.0, 0.0);
gl_FragColor = texture2D(tex0, uv) + texture2D(tex1, uv);
})";
ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader); ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShader);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment