Disallow multiple locations on output variables
GLSL ES specs from version 3.00 to 3.20 all mention that output layout
location qualifier may appear at most once within a declaration.
Enforce this rule when parsing shaders.
Also set max draw buffers to 8 when compiling GLSL ES >= 3.00 in the
qualification order tests and shader translator sample, so that
parsing locations > 0 will succeed.
BUG=angleproject:1505
TEST=angle_unittests
Change-Id: I50fe409041385f5e10e695f43dc3a572433e9772
Reviewed-on: https://chromium-review.googlesource.com/381211
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index 78e06b3..0919955 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -387,6 +387,7 @@
struct TLayoutQualifier
{
int location;
+ unsigned int locationsSpecified;
TLayoutMatrixPacking matrixPacking;
TLayoutBlockStorage blockStorage;
@@ -398,6 +399,7 @@
TLayoutQualifier layoutQualifier;
layoutQualifier.location = -1;
+ layoutQualifier.locationsSpecified = 0;
layoutQualifier.matrixPacking = EmpUnspecified;
layoutQualifier.blockStorage = EbsUnspecified;
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index fc3c2c5..9a08ddf 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -2935,6 +2935,7 @@
else
{
qualifier.location = intValue;
+ qualifier.locationsSpecified = 1;
}
}
else if (qualifierType == "local_size_x")
diff --git a/src/compiler/translator/QualifierTypes.cpp b/src/compiler/translator/QualifierTypes.cpp
index 27d73aa..b785627 100644
--- a/src/compiler/translator/QualifierTypes.cpp
+++ b/src/compiler/translator/QualifierTypes.cpp
@@ -22,6 +22,7 @@
if (rightQualifier.location != -1)
{
joinedQualifier.location = rightQualifier.location;
+ ++joinedQualifier.locationsSpecified;
}
if (rightQualifier.matrixPacking != EmpUnspecified)
{
@@ -98,6 +99,9 @@
bool layoutFound = false;
bool interpolationFound = false;
+ unsigned int locationsSpecified = 0;
+ bool isOut = false;
+
// The iteration starts from one since the first qualifier only reveals the scope of the
// expression. It is inserted first whenever the sequence gets created.
for (size_t i = 1; i < qualifiers.size(); ++i)
@@ -132,6 +136,9 @@
return true;
}
layoutFound = true;
+ const TLayoutQualifier ¤tQualifier =
+ static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier();
+ locationsSpecified += currentQualifier.locationsSpecified;
break;
}
case QtInterpolation:
@@ -153,6 +160,10 @@
// repetitions.
TQualifier currentQualifier =
static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier();
+ if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut)
+ {
+ isOut = true;
+ }
for (size_t j = 1; j < i; ++j)
{
if (qualifiers[j]->getType() == QtStorage)
@@ -175,6 +186,15 @@
}
}
+ if (locationsSpecified > 1 && isOut)
+ {
+ // GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers
+ // GLSL ES 3.10 section 4.4.2 Output Layout Qualifiers
+ // "The qualifier may appear at most once within a declaration."
+ *errorMessage = "Output layout location specified multiple times.";
+ return true;
+ }
+
return false;
}