Commit 87d410c8 by Olli Etuaho Committed by Commit Bot

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/381211Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent a223430c
...@@ -222,6 +222,10 @@ int main(int argc, char *argv[]) ...@@ -222,6 +222,10 @@ int main(int argc, char *argv[])
} }
else else
{ {
if (spec != SH_GLES2_SPEC && spec != SH_WEBGL_SPEC)
{
resources.MaxDrawBuffers = 8;
}
ShHandle compiler = 0; ShHandle compiler = 0;
switch (FindShaderType(argv[0])) switch (FindShaderType(argv[0]))
{ {
......
...@@ -387,6 +387,7 @@ enum TLayoutBlockStorage ...@@ -387,6 +387,7 @@ enum TLayoutBlockStorage
struct TLayoutQualifier struct TLayoutQualifier
{ {
int location; int location;
unsigned int locationsSpecified;
TLayoutMatrixPacking matrixPacking; TLayoutMatrixPacking matrixPacking;
TLayoutBlockStorage blockStorage; TLayoutBlockStorage blockStorage;
...@@ -398,6 +399,7 @@ struct TLayoutQualifier ...@@ -398,6 +399,7 @@ struct TLayoutQualifier
TLayoutQualifier layoutQualifier; TLayoutQualifier layoutQualifier;
layoutQualifier.location = -1; layoutQualifier.location = -1;
layoutQualifier.locationsSpecified = 0;
layoutQualifier.matrixPacking = EmpUnspecified; layoutQualifier.matrixPacking = EmpUnspecified;
layoutQualifier.blockStorage = EbsUnspecified; layoutQualifier.blockStorage = EbsUnspecified;
......
...@@ -2935,6 +2935,7 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp ...@@ -2935,6 +2935,7 @@ TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierTyp
else else
{ {
qualifier.location = intValue; qualifier.location = intValue;
qualifier.locationsSpecified = 1;
} }
} }
else if (qualifierType == "local_size_x") else if (qualifierType == "local_size_x")
......
...@@ -22,6 +22,7 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, ...@@ -22,6 +22,7 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
if (rightQualifier.location != -1) if (rightQualifier.location != -1)
{ {
joinedQualifier.location = rightQualifier.location; joinedQualifier.location = rightQualifier.location;
++joinedQualifier.locationsSpecified;
} }
if (rightQualifier.matrixPacking != EmpUnspecified) if (rightQualifier.matrixPacking != EmpUnspecified)
{ {
...@@ -98,6 +99,9 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual ...@@ -98,6 +99,9 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual
bool layoutFound = false; bool layoutFound = false;
bool interpolationFound = 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 // 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. // expression. It is inserted first whenever the sequence gets created.
for (size_t i = 1; i < qualifiers.size(); ++i) for (size_t i = 1; i < qualifiers.size(); ++i)
...@@ -132,6 +136,9 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual ...@@ -132,6 +136,9 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual
return true; return true;
} }
layoutFound = true; layoutFound = true;
const TLayoutQualifier &currentQualifier =
static_cast<const TLayoutQualifierWrapper *>(qualifiers[i])->getQualifier();
locationsSpecified += currentQualifier.locationsSpecified;
break; break;
} }
case QtInterpolation: case QtInterpolation:
...@@ -153,6 +160,10 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual ...@@ -153,6 +160,10 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual
// repetitions. // repetitions.
TQualifier currentQualifier = TQualifier currentQualifier =
static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier(); static_cast<const TStorageQualifierWrapper *>(qualifiers[i])->getQualifier();
if (currentQualifier == EvqVertexOut || currentQualifier == EvqFragmentOut)
{
isOut = true;
}
for (size_t j = 1; j < i; ++j) for (size_t j = 1; j < i; ++j)
{ {
if (qualifiers[j]->getType() == QtStorage) if (qualifiers[j]->getType() == QtStorage)
...@@ -175,6 +186,15 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual ...@@ -175,6 +186,15 @@ bool HasRepeatingQualifiers(const TTypeQualifierBuilder::QualifierSequence &qual
} }
} }
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; return false;
} }
......
...@@ -27,6 +27,7 @@ class QualificationOrderShaderTest : public testing::Test ...@@ -27,6 +27,7 @@ class QualificationOrderShaderTest : public testing::Test
{ {
ShBuiltInResources resources; ShBuiltInResources resources;
ShInitBuiltInResources(&resources); ShInitBuiltInResources(&resources);
resources.MaxDrawBuffers = (spec == SH_GLES2_SPEC) ? 1 : 8;
TranslatorESSL *translator = new TranslatorESSL(shaderType, spec); TranslatorESSL *translator = new TranslatorESSL(shaderType, spec);
EXPECT_TRUE(translator->Init(resources)); EXPECT_TRUE(translator->Init(resources));
...@@ -549,3 +550,20 @@ TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersFlatIn) ...@@ -549,3 +550,20 @@ TEST_F(QualificationOrderShaderTest, InvalidFunctionParametersFlatIn)
FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure" << mInfoLog;
} }
} }
// Output layout location qualifier can't appear more than once within a declaration.
// GLSL ES 3.00.6 section 4.3.8.2 Output Layout Qualifiers.
TEST_F(QualificationOrderShaderTest, TwoOutputLocations)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"layout(location=1, location=2) out vec4 myColor;\n"
"void main() {\n"
"}\n";
if (compile(shaderString, GL_FRAGMENT_SHADER, SH_GLES3_SPEC))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
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