Commit 37ad4744 by Olli Etuaho

Add support for parsing ESSL3 invariant qualifiers

The parser recognizes ESSL3 invariant variable declaration syntax and marks the variables as invariant. In ESSL3, invariant out variables can be linked to non-invariant in variables, so linking checks should now be different depending on shading language version. A shading language version dependent varying matching check is added to the translator API to facilitate this. Tested by deqp/data/gles3/shaders/qualification_order.html after patching Chrome to use the new linking check API. A previous revision of this change that broke API compatibility was reverted since it broke Chromium FYI bots. This revision keeps deprecated API functionality around for now so that changes can be rolled step-by-step to Chromium without breakage. TEST=WebGL 2 conformance tests, angle_unittests BUG=angleproject:987 Change-Id: Iecb64e3afd23e267ba999bc17f44390affcdfc13 Reviewed-on: https://chromium-review.googlesource.com/269940Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent 9e64edce
...@@ -48,7 +48,7 @@ typedef unsigned int GLenum; ...@@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 135 #define ANGLE_SH_VERSION 136
typedef enum { typedef enum {
SH_GLES2_SPEC = 0x8B40, SH_GLES2_SPEC = 0x8B40,
......
...@@ -161,7 +161,12 @@ struct COMPILER_EXPORT Varying : public ShaderVariable ...@@ -161,7 +161,12 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
// Decide whether two varyings are the same at shader link time, // Decide whether two varyings are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader. // assuming one from vertex shader and the other from fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.9. // Invariance needs to match only in ESSL1. Relevant spec sections:
// GLSL ES 3.00.4, sections 4.6.1 and 4.3.9.
// GLSL ES 1.00.17, section 4.6.4.
bool isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const;
// Deprecated version of isSameVaryingAtLinkTime, which assumes ESSL1.
bool isSameVaryingAtLinkTime(const Varying &other) const; bool isSameVaryingAtLinkTime(const Varying &other) const;
InterpolationType interpolation; InterpolationType interpolation;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "compiler/preprocessor/SourceLocation.h" #include "compiler/preprocessor/SourceLocation.h"
#include "compiler/translator/glslang.h" #include "compiler/translator/glslang.h"
#include "compiler/translator/ValidateSwitch.h" #include "compiler/translator/ValidateSwitch.h"
#include "compiler/translator/util.h"
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
...@@ -969,6 +970,15 @@ bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, T ...@@ -969,6 +970,15 @@ bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, T
return false; return false;
} }
void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation)
{
if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
{
error(invariantLocation, "Only out variables can be invariant.", "invariant");
recover();
}
}
bool TParseContext::supportsExtension(const char* extension) bool TParseContext::supportsExtension(const char* extension)
{ {
const TExtensionBehavior& extbehavior = extensionBehavior(); const TExtensionBehavior& extbehavior = extensionBehavior();
......
...@@ -110,6 +110,7 @@ struct TParseContext { ...@@ -110,6 +110,7 @@ struct TParseContext {
bool singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc &identifierLocation); bool singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc &identifierLocation);
bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation);
const TPragma& pragma() const { return directiveHandler.pragma(); } const TPragma& pragma() const { return directiveHandler.pragma(); }
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
......
...@@ -305,9 +305,14 @@ bool Varying::operator==(const Varying &other) const ...@@ -305,9 +305,14 @@ bool Varying::operator==(const Varying &other) const
bool Varying::isSameVaryingAtLinkTime(const Varying &other) const bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
{ {
return isSameVaryingAtLinkTime(other, 100);
}
bool Varying::isSameVaryingAtLinkTime(const Varying &other, int shaderVersion) const
{
return (ShaderVariable::isSameVariableAtLinkTime(other, false) && return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
interpolation == other.interpolation && interpolation == other.interpolation &&
isInvariant == other.isInvariant); (shaderVersion >= 300 || isInvariant == other.isInvariant));
} }
InterfaceBlock::InterfaceBlock() InterfaceBlock::InterfaceBlock()
......
...@@ -1012,6 +1012,16 @@ type_qualifier ...@@ -1012,6 +1012,16 @@ type_qualifier
$$.setBasic(EbtVoid, $2.qualifier, @2); $$.setBasic(EbtVoid, $2.qualifier, @2);
$$.layoutQualifier = $1; $$.layoutQualifier = $1;
} }
| INVARIANT storage_qualifier {
context->es3InvariantErrorCheck($2.qualifier, @1);
$$.setBasic(EbtVoid, $2.qualifier, @2);
$$.invariant = true;
}
| INVARIANT interpolation_qualifier storage_qualifier {
context->es3InvariantErrorCheck($3.qualifier, @1);
$$ = context->joinInterpolationQualifiers(@2, $2.qualifier, @3, $3.qualifier);
$$.invariant = true;
}
; ;
storage_qualifier storage_qualifier
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -299,6 +299,10 @@ void GetVariableTraverser::setTypeSpecificInfo( ...@@ -299,6 +299,10 @@ void GetVariableTraverser::setTypeSpecificInfo(
{ {
case EvqVaryingIn: case EvqVaryingIn:
case EvqVaryingOut: case EvqVaryingOut:
case EvqVertexOut:
case EvqSmoothOut:
case EvqFlatOut:
case EvqCentroidOut:
if (mSymbolTable.isVaryingInvariant(std::string(name.c_str())) || type.isInvariant()) if (mSymbolTable.isVaryingInvariant(std::string(name.c_str())) || type.isInvariant())
{ {
variable->isInvariant = true; variable->isInvariant = true;
......
...@@ -211,11 +211,17 @@ TEST(ShaderVariableTest, IsSameVaryingWithDifferentInvariance) ...@@ -211,11 +211,17 @@ TEST(ShaderVariableTest, IsSameVaryingWithDifferentInvariance)
fx.staticUse = true; fx.staticUse = true;
fx.isInvariant = false; fx.isInvariant = false;
// Default to ESSL1 behavior: invariance must match
EXPECT_FALSE(vx.isSameVaryingAtLinkTime(fx)); EXPECT_FALSE(vx.isSameVaryingAtLinkTime(fx));
EXPECT_FALSE(vx.isSameVaryingAtLinkTime(fx, 100));
// ESSL3 behavior: invariance doesn't need to match
EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx, 300));
// invariant varying float vary; // invariant varying float vary;
fx.isInvariant = true; fx.isInvariant = true;
EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx)); EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx));
EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx, 100));
EXPECT_TRUE(vx.isSameVaryingAtLinkTime(fx, 300));
} }
// Test that using invariant varyings doesn't trigger a double delete. // Test that using invariant varyings doesn't trigger a double delete.
......
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