Commit ff699005 by Olli Etuaho

Disallow operations on structs containing samplers

ESSL 1.00 spec section 5.9 says that equality operators don't operate on structs containing sampler types. Section 5.7 also suggests this. ESSL 3.00 doesn't have a similar restriction. ESSL 1.00 spec section 4.1.7 says that structs containing samplers can't be used as l-values. This is interpreted to apply also in the case of ESSL 3.00, which similarly disallows samplers as l-values, but doesn't explicitly mention structs. BUG=angleproject:954 TEST=angle_unittests, WebGL conformance tests Change-Id: I73f74962a192e8d9449990ffa5f3d8c851491601 Reviewed-on: https://chromium-review.googlesource.com/261822Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent ae37a5c8
...@@ -2792,7 +2792,7 @@ bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TInter ...@@ -2792,7 +2792,7 @@ bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TInter
} }
// Check that type sizes match exactly on ops that require that. // Check that type sizes match exactly on ops that require that.
// Also check restrictions for structs that contain arrays. // Also check restrictions for structs that contain arrays or samplers.
switch(op) switch(op)
{ {
case EOpAssign: case EOpAssign:
...@@ -2805,6 +2805,15 @@ bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TInter ...@@ -2805,6 +2805,15 @@ bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TInter
error(loc, "undefined operation for structs containing arrays", GetOperatorString(op)); error(loc, "undefined operation for structs containing arrays", GetOperatorString(op));
return false; return false;
} }
// Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
// we interpret the spec so that this extends to structs containing samplers,
// similarly to ESSL 1.00 spec.
if ((shaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
left->getType().isStructureContainingSamplers())
{
error(loc, "undefined operation for structs containing samplers", GetOperatorString(op));
return false;
}
case EOpLessThan: case EOpLessThan:
case EOpGreaterThan: case EOpGreaterThan:
case EOpLessThanEqual: case EOpLessThanEqual:
......
...@@ -200,6 +200,17 @@ bool TStructure::containsArrays() const ...@@ -200,6 +200,17 @@ bool TStructure::containsArrays() const
return false; return false;
} }
bool TStructure::containsSamplers() const
{
for (size_t i = 0; i < mFields->size(); ++i)
{
const TType *fieldType = (*mFields)[i]->type();
if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
return true;
}
return false;
}
TString TFieldListCollection::buildMangledName() const TString TFieldListCollection::buildMangledName() const
{ {
TString mangledName(mangledNamePrefix()); TString mangledName(mangledNamePrefix());
......
...@@ -125,6 +125,7 @@ class TStructure : public TFieldListCollection ...@@ -125,6 +125,7 @@ class TStructure : public TFieldListCollection
return mDeepestNesting; return mDeepestNesting;
} }
bool containsArrays() const; bool containsArrays() const;
bool containsSamplers() const;
bool equals(const TStructure &other) const; bool equals(const TStructure &other) const;
...@@ -480,6 +481,11 @@ class TType ...@@ -480,6 +481,11 @@ class TType
return structure ? structure->containsArrays() : false; return structure ? structure->containsArrays() : false;
} }
bool isStructureContainingSamplers() const
{
return structure ? structure->containsSamplers() : false;
}
protected: protected:
TString buildMangledName() const; TString buildMangledName() const;
size_t getStructSize() const; size_t getStructSize() const;
......
...@@ -158,3 +158,42 @@ TEST_F(MalformedShaderTest, AssignStructsContainingArrays) ...@@ -158,3 +158,42 @@ TEST_F(MalformedShaderTest, AssignStructsContainingArrays)
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
} }
} }
// Assignment and equality are undefined for structures containing samplers (ESSL 1.00 sections 5.7 and 5.9)
TEST_F(MalformedShaderTest, CompareStructsContainingSamplers)
{
const std::string &shaderString =
"precision mediump float;\n"
"struct s { sampler2D foo; };\n"
"uniform s a;\n"
"uniform s b;\n"
"void main() {\n"
" bool c = (a == b);\n"
" gl_FragColor = vec4(c ? 1.0 : 0.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Samplers are not allowed as l-values (ESSL 3.00 section 4.1.7), our interpretation is that this
// extends to structs containing samplers. ESSL 1.00 spec is clearer about this.
TEST_F(MalformedShaderTest, AssignStructsContainingSamplers)
{
const std::string &shaderString =
"#version 300 es;\n"
"precision mediump float;\n"
"struct s { sampler2D foo; };\n"
"uniform s a;\n"
"out vec4 my_FragColor;\n"
"void main() {\n"
" s b;\n"
" b = a;\n"
" my_FragColor = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
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