Commit 70866b89 by Martin Radev Committed by Commit Bot

Change grammar to support features from es31

The grammar has been changed so that ES31 grammar is followed more closely. The ES31 grammar is not fully supported, only functionality related to qualifier enumeration is added. The ParseContext is changed so that type qualifiers can be now joined together (i.e. like layout qualifiers). This will allow enumeration of multiple storage qualifiers (i.e. uniform readonly coherent) which is essential for support of ES31 features. Some of the error checks had to be moved closer to the root of the parse tree since some of the information about the expression might be missing. Unfortunately, as there is no explicit ordering imposed by the grammar, additional checks for proper order of qualifiers had to be added. I also included unit tests which test against malformed shaders. BUG=angleproject:1442 TEST=angle_end2end_tests TEST=angle_unittests TEST=dEQP-GLES3.functional.shaders.*precision* TEST=dEQP-GLES3.functional.shaders.*function* TEST=dEQP-GLES2.functional.shaders.* Change-Id: Ib3653a1ed1bfced099a6b2cbf35a7cd480c9100d Reviewed-on: https://chromium-review.googlesource.com/362940 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent b962aab6
...@@ -81,6 +81,8 @@ ...@@ -81,6 +81,8 @@
'compiler/translator/Pragma.h', 'compiler/translator/Pragma.h',
'compiler/translator/PruneEmptyDeclarations.cpp', 'compiler/translator/PruneEmptyDeclarations.cpp',
'compiler/translator/PruneEmptyDeclarations.h', 'compiler/translator/PruneEmptyDeclarations.h',
'compiler/translator/QualifierTypes.h',
'compiler/translator/QualifierTypes.cpp',
'compiler/translator/RecordConstantPrecision.cpp', 'compiler/translator/RecordConstantPrecision.cpp',
'compiler/translator/RecordConstantPrecision.h', 'compiler/translator/RecordConstantPrecision.h',
'compiler/translator/RegenerateStructNames.cpp', 'compiler/translator/RegenerateStructNames.cpp',
......
...@@ -341,10 +341,11 @@ enum TQualifier ...@@ -341,10 +341,11 @@ enum TQualifier
EvqLastFragData, EvqLastFragData,
// GLSL ES 3.0 vertex output and fragment input // GLSL ES 3.0 vertex output and fragment input
EvqSmooth, // Incomplete qualifier, smooth is the default EvqSmooth, // Incomplete qualifier, smooth is the default
EvqFlat, // Incomplete qualifier EvqFlat, // Incomplete qualifier
EvqSmoothOut = EvqSmooth, EvqCentroid, // Incomplete qualifier
EvqFlatOut = EvqFlat, EvqSmoothOut,
EvqFlatOut,
EvqCentroidOut, // Implies smooth EvqCentroidOut, // Implies smooth
EvqSmoothIn, EvqSmoothIn,
EvqFlatIn, EvqFlatIn,
...@@ -363,6 +364,11 @@ enum TQualifier ...@@ -363,6 +364,11 @@ enum TQualifier
EvqLast EvqLast
}; };
inline bool IsQualifierUnspecified(TQualifier qualifier)
{
return (qualifier == EvqTemporary || qualifier == EvqGlobal);
}
enum TLayoutMatrixPacking enum TLayoutMatrixPacking
{ {
EmpUnspecified, EmpUnspecified,
...@@ -482,6 +488,9 @@ inline const char* getQualifierString(TQualifier q) ...@@ -482,6 +488,9 @@ inline const char* getQualifierString(TQualifier q)
case EvqSmoothIn: return "smooth in"; case EvqSmoothIn: return "smooth in";
case EvqFlatIn: return "flat in"; case EvqFlatIn: return "flat in";
case EvqCentroidIn: return "smooth centroid in"; case EvqCentroidIn: return "smooth centroid in";
case EvqCentroid: return "centroid";
case EvqFlat: return "flat";
case EvqSmooth: return "smooth";
case EvqComputeIn: return "in"; case EvqComputeIn: return "in";
case EvqNumWorkGroups: return "NumWorkGroups"; case EvqNumWorkGroups: return "NumWorkGroups";
case EvqWorkGroupSize: return "WorkGroupSize"; case EvqWorkGroupSize: return "WorkGroupSize";
......
...@@ -532,6 +532,7 @@ class TIntermAggregate : public TIntermOperator ...@@ -532,6 +532,7 @@ class TIntermAggregate : public TIntermOperator
TIntermTyped *fold(TInfoSink &infoSink); TIntermTyped *fold(TInfoSink &infoSink);
TIntermSequence *getSequence() { return &mSequence; } TIntermSequence *getSequence() { return &mSequence; }
const TIntermSequence *getSequence() const { return &mSequence; }
void setNameObj(const TName &name) { mName = name; } void setNameObj(const TName &name) { mName = name; }
const TName &getNameObj() const { return mName; } const TName &getNameObj() const { return mName; }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "compiler/translator/DirectiveHandler.h" #include "compiler/translator/DirectiveHandler.h"
#include "compiler/translator/Intermediate.h" #include "compiler/translator/Intermediate.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "compiler/translator/QualifierTypes.h"
#include "compiler/preprocessor/Preprocessor.h" #include "compiler/preprocessor/Preprocessor.h"
struct TMatrixFields struct TMatrixFields
...@@ -67,7 +68,8 @@ class TParseContext : angle::NonCopyable ...@@ -67,7 +68,8 @@ class TParseContext : angle::NonCopyable
mUsesSecondaryOutputs(false), mUsesSecondaryOutputs(false),
mMinProgramTexelOffset(resources.MinProgramTexelOffset), mMinProgramTexelOffset(resources.MinProgramTexelOffset),
mMaxProgramTexelOffset(resources.MaxProgramTexelOffset), mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
mComputeShaderLocalSizeDeclared(false) mComputeShaderLocalSizeDeclared(false),
mDeclaringFunction(false)
{ {
mComputeShaderLocalSize.fill(-1); mComputeShaderLocalSize.fill(-1);
} }
...@@ -119,6 +121,12 @@ class TParseContext : angle::NonCopyable ...@@ -119,6 +121,12 @@ class TParseContext : angle::NonCopyable
bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
sh::WorkGroupSize getComputeShaderLocalSize() const; sh::WorkGroupSize getComputeShaderLocalSize() const;
void enterFunctionDeclaration() { mDeclaringFunction = true; }
void exitFunctionDeclaration() { mDeclaringFunction = false; }
bool declaringFunction() const { return mDeclaringFunction; }
// This method is guaranteed to succeed, even if no variable with 'name' exists. // This method is guaranteed to succeed, even if no variable with 'name' exists.
const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol);
TIntermTyped *parseVariableIdentifier(const TSourceLoc &location, TIntermTyped *parseVariableIdentifier(const TSourceLoc &location,
...@@ -160,8 +168,7 @@ class TParseContext : angle::NonCopyable ...@@ -160,8 +168,7 @@ class TParseContext : angle::NonCopyable
TQualifier qualifier, TQualifier qualifier,
const TType &type); const TType &type);
void checkIsParameterQualifierValid(const TSourceLoc &line, void checkIsParameterQualifierValid(const TSourceLoc &line,
TQualifier qualifier, const TTypeQualifierBuilder &typeQualifierBuilder,
TQualifier paramQualifier,
TType *type); TType *type);
bool checkCanUseExtension(const TSourceLoc &line, const TString &extension); bool checkCanUseExtension(const TSourceLoc &line, const TString &extension);
void singleDeclarationErrorCheck(const TPublicType &publicType, void singleDeclarationErrorCheck(const TPublicType &publicType,
...@@ -173,8 +180,9 @@ class TParseContext : angle::NonCopyable ...@@ -173,8 +180,9 @@ class TParseContext : angle::NonCopyable
const TLayoutQualifier &layoutQualifier); const TLayoutQualifier &layoutQualifier);
void functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall); void functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);
void checkInvariantIsOutVariableES3(const TQualifier qualifier, void checkInvariantVariableQualifier(bool invariant,
const TSourceLoc &invariantLocation); const TQualifier qualifier,
const TSourceLoc &invariantLocation);
void checkInputOutputTypeIsValidES3(const TQualifier qualifier, void checkInputOutputTypeIsValidES3(const TQualifier qualifier,
const TPublicType &type, const TPublicType &type,
const TSourceLoc &qualifierLocation); const TSourceLoc &qualifierLocation);
...@@ -195,9 +203,7 @@ class TParseContext : angle::NonCopyable ...@@ -195,9 +203,7 @@ class TParseContext : angle::NonCopyable
TIntermTyped *initializer, TIntermTyped *initializer,
TIntermNode **intermNode); TIntermNode **intermNode);
TPublicType addFullySpecifiedType(TQualifier qualifier, TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
bool invariant,
TLayoutQualifier layoutQualifier,
const TPublicType &typeSpecifier); const TPublicType &typeSpecifier);
TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, TIntermAggregate *parseSingleDeclaration(TPublicType &publicType,
...@@ -224,7 +230,7 @@ class TParseContext : angle::NonCopyable ...@@ -224,7 +230,7 @@ class TParseContext : angle::NonCopyable
const TSourceLoc &initLocation, const TSourceLoc &initLocation,
TIntermTyped *initializer); TIntermTyped *initializer);
TIntermAggregate *parseInvariantDeclaration(const TSourceLoc &invariantLoc, TIntermAggregate *parseInvariantDeclaration(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &identifierLoc, const TSourceLoc &identifierLoc,
const TString *identifier, const TString *identifier,
const TSymbol *symbol); const TSymbol *symbol);
...@@ -256,7 +262,7 @@ class TParseContext : angle::NonCopyable ...@@ -256,7 +262,7 @@ class TParseContext : angle::NonCopyable
const TSourceLoc &initLocation, const TSourceLoc &initLocation,
TIntermTyped *initializer); TIntermTyped *initializer);
void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function, TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &function,
const TSourceLoc &location); const TSourceLoc &location);
TIntermAggregate *addFunctionDefinition(const TFunction &function, TIntermAggregate *addFunctionDefinition(const TFunction &function,
...@@ -287,20 +293,24 @@ class TParseContext : angle::NonCopyable ...@@ -287,20 +293,24 @@ class TParseContext : angle::NonCopyable
const TString &fieldString, const TString &fieldString,
const TSourceLoc &fieldLocation); const TSourceLoc &fieldLocation);
TFieldList *addStructDeclaratorListWithQualifiers(
const TTypeQualifierBuilder &typeQualifierBuilder,
TPublicType *typeSpecifier,
TFieldList *fieldList);
TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList); TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
TPublicType addStructure(const TSourceLoc &structLine, TPublicType addStructure(const TSourceLoc &structLine,
const TSourceLoc &nameLine, const TSourceLoc &nameLine,
const TString *structName, const TString *structName,
TFieldList *fieldList); TFieldList *fieldList);
TIntermAggregate* addInterfaceBlock(const TPublicType &typeQualifier, TIntermAggregate *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &nameLine, const TSourceLoc &nameLine,
const TString &blockName, const TString &blockName,
TFieldList *fieldList, TFieldList *fieldList,
const TString *instanceName, const TString *instanceName,
const TSourceLoc &instanceLine, const TSourceLoc &instanceLine,
TIntermTyped *arrayIndex, TIntermTyped *arrayIndex,
const TSourceLoc& arrayIndexLine); const TSourceLoc &arrayIndexLine);
void parseLocalSize(const TString &qualifierType, void parseLocalSize(const TString &qualifierType,
const TSourceLoc &qualifierTypeLine, const TSourceLoc &qualifierTypeLine,
...@@ -318,8 +328,6 @@ class TParseContext : angle::NonCopyable ...@@ -318,8 +328,6 @@ class TParseContext : angle::NonCopyable
TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier,
TLayoutQualifier rightQualifier, TLayoutQualifier rightQualifier,
const TSourceLoc &rightQualifierLocation); const TSourceLoc &rightQualifierLocation);
TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
const TSourceLoc &storageLoc, TQualifier storageQualifier);
// Performs an error check for embedded struct declarations. // Performs an error check for embedded struct declarations.
void enterStructDeclaration(const TSourceLoc &line, const TString &identifier); void enterStructDeclaration(const TSourceLoc &line, const TString &identifier);
...@@ -438,6 +446,8 @@ class TParseContext : angle::NonCopyable ...@@ -438,6 +446,8 @@ class TParseContext : angle::NonCopyable
// keep track of local group size declared in layout. It should be declared only once. // keep track of local group size declared in layout. It should be declared only once.
bool mComputeShaderLocalSizeDeclared; bool mComputeShaderLocalSizeDeclared;
sh::WorkGroupSize mComputeShaderLocalSize; sh::WorkGroupSize mComputeShaderLocalSize;
// keeps track whether we are declaring / defining a function
bool mDeclaringFunction;
}; };
int PaParseStrings( int PaParseStrings(
......
//
// Copyright (c) 2002-2016 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.
//
#ifndef COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
#define COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
#include "BaseTypes.h"
#include "common/angleutils.h"
#include "Types.h"
#include <vector>
class TDiagnostics;
enum TQualifierType
{
QtInvariant,
QtInterpolation,
QtLayout,
QtStorage,
QtPrecision
};
class TQualifierWrapperBase : angle::NonCopyable
{
public:
TQualifierWrapperBase(const TSourceLoc &line) : mLine(line) {}
virtual ~TQualifierWrapperBase(){};
virtual TQualifierType getType() const = 0;
virtual TString getQualifierString() const = 0;
const TSourceLoc &getLine() const { return mLine; }
private:
TSourceLoc mLine;
};
class TInvariantQualifierWrapper final : public TQualifierWrapperBase
{
public:
TInvariantQualifierWrapper(const TSourceLoc &line) : TQualifierWrapperBase(line) {}
~TInvariantQualifierWrapper() {}
TQualifierType getType() const { return QtInvariant; }
TString getQualifierString() const { return "invariant"; }
};
class TInterpolationQualifierWrapper final : public TQualifierWrapperBase
{
public:
TInterpolationQualifierWrapper(TQualifier interpolationQualifier, const TSourceLoc &line)
: TQualifierWrapperBase(line), mInterpolationQualifier(interpolationQualifier)
{
}
~TInterpolationQualifierWrapper() {}
TQualifierType getType() const { return QtInterpolation; }
TString getQualifierString() const { return ::getQualifierString(mInterpolationQualifier); }
TQualifier getQualifier() const { return mInterpolationQualifier; }
private:
TQualifier mInterpolationQualifier;
};
class TLayoutQualifierWrapper final : public TQualifierWrapperBase
{
public:
TLayoutQualifierWrapper(TLayoutQualifier layoutQualifier, const TSourceLoc &line)
: TQualifierWrapperBase(line), mLayoutQualifier(layoutQualifier)
{
}
~TLayoutQualifierWrapper() {}
TQualifierType getType() const { return QtLayout; }
TString getQualifierString() const { return "layout"; }
const TLayoutQualifier &getQualifier() const { return mLayoutQualifier; }
private:
TLayoutQualifier mLayoutQualifier;
};
class TStorageQualifierWrapper final : public TQualifierWrapperBase
{
public:
TStorageQualifierWrapper(TQualifier storageQualifier, const TSourceLoc &line)
: TQualifierWrapperBase(line), mStorageQualifier(storageQualifier)
{
}
~TStorageQualifierWrapper() {}
TQualifierType getType() const { return QtStorage; }
TString getQualifierString() const { return ::getQualifierString(mStorageQualifier); }
TQualifier getQualifier() const { return mStorageQualifier; }
private:
TQualifier mStorageQualifier;
};
class TPrecisionQualifierWrapper final : public TQualifierWrapperBase
{
public:
TPrecisionQualifierWrapper(TPrecision precisionQualifier, const TSourceLoc &line)
: TQualifierWrapperBase(line), mPrecisionQualifier(precisionQualifier)
{
}
~TPrecisionQualifierWrapper() {}
TQualifierType getType() const { return QtPrecision; }
TString getQualifierString() const { return ::getPrecisionString(mPrecisionQualifier); }
TPrecision getQualifier() const { return mPrecisionQualifier; }
private:
TPrecision mPrecisionQualifier;
};
// TTypeQualifier tightly covers type_qualifier from the grammar
struct TTypeQualifier
{
// initializes all of the qualifiers and sets the scope
TTypeQualifier(TQualifier scope, const TSourceLoc &loc);
TLayoutQualifier layoutQualifier;
TPrecision precision;
TQualifier qualifier;
bool invariant;
TSourceLoc line;
};
// TTypeQualifierBuilder contains all of the qualifiers when type_qualifier gets parsed.
// It is to be used to validate the qualifier sequence and build a TTypeQualifier from it.
class TTypeQualifierBuilder : angle::NonCopyable
{
public:
TTypeQualifierBuilder(const TStorageQualifierWrapper *scope);
// Adds the passed qualifier to the end of the sequence.
void appendQualifier(const TQualifierWrapperBase *qualifier);
// Checks for the order of qualification and repeating qualifiers.
bool checkOrderIsValid(TDiagnostics *diagnostics) const;
// Goes over the qualifier sequence and parses it to form a type qualifier for a function
// parameter.
// The returned object is initialized even if the parsing fails.
TTypeQualifier getParameterTypeQualifier(TDiagnostics *diagnostics) const;
// Goes over the qualifier sequence and parses it to form a type qualifier for a variable.
// The returned object is initialized even if the parsing fails.
TTypeQualifier getVariableTypeQualifier(TDiagnostics *diagnostics) const;
private:
// Handles the joining of storage qualifiers for a parameter in a function.
bool joinParameterStorageQualifier(TQualifier *joinedQualifier,
TQualifier storageQualifier) const;
// Handles the joining of storage qualifiers for variables.
bool joinVariableStorageQualifier(TQualifier *joinedQualifier,
TQualifier storageQualifier) const;
std::vector<const TQualifierWrapperBase *> mQualifiers;
};
#endif // COMPILER_TRANSLATOR_QUALIFIER_TYPES_H_
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -216,6 +216,8 @@ union YYSTYPE ...@@ -216,6 +216,8 @@ union YYSTYPE
TParameter param; TParameter param;
TField* field; TField* field;
TFieldList* fieldList; TFieldList* fieldList;
TQualifierWrapperBase *qualifierWrapper;
TTypeQualifierBuilder *typeQualifierBuilder;
}; };
} interm; } interm;
......
...@@ -537,4 +537,52 @@ template void GetVariableTraverser::traverse(const TType &, const TString &, std ...@@ -537,4 +537,52 @@ template void GetVariableTraverser::traverse(const TType &, const TString &, std
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *); template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *); template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
// GLSL ES 1.0.17 4.6.1 The Invariant Qualifier
bool CanBeInvariantESSL1(TQualifier qualifier)
{
return IsVaryingIn(qualifier) || IsVaryingOut(qualifier) ||
IsBuiltinOutputVariable(qualifier) ||
(IsBuiltinFragmentInputVariable(qualifier) && qualifier != EvqFrontFacing);
}
// GLSL ES 3.00 Revision 6, 4.6.1 The Invariant Qualifier
// GLSL ES 3.10 Revision 4, 4.8.1 The Invariant Qualifier
bool CanBeInvariantESSL3OrGreater(TQualifier qualifier)
{
return IsVaryingOut(qualifier) || qualifier == EvqFragmentOut ||
IsBuiltinOutputVariable(qualifier);
}
bool IsBuiltinOutputVariable(TQualifier qualifier)
{
switch (qualifier)
{
case EvqPosition:
case EvqPointSize:
case EvqFragDepth:
case EvqFragDepthEXT:
case EvqFragColor:
case EvqSecondaryFragColorEXT:
case EvqFragData:
case EvqSecondaryFragDataEXT:
return true;
default:
break;
}
return false;
}
bool IsBuiltinFragmentInputVariable(TQualifier qualifier)
{
switch (qualifier)
{
case EvqFragCoord:
case EvqPointCoord:
case EvqFrontFacing:
return true;
default:
break;
}
return false;
} }
} // namespace sh
...@@ -65,6 +65,10 @@ class GetVariableTraverser : angle::NonCopyable ...@@ -65,6 +65,10 @@ class GetVariableTraverser : angle::NonCopyable
const TSymbolTable &mSymbolTable; const TSymbolTable &mSymbolTable;
}; };
bool IsBuiltinOutputVariable(TQualifier qualifier);
bool IsBuiltinFragmentInputVariable(TQualifier qualifier);
bool CanBeInvariantESSL1(TQualifier qualifier);
bool CanBeInvariantESSL3OrGreater(TQualifier qualifier);
} }
#endif // COMPILER_TRANSLATOR_UTIL_H_ #endif // COMPILER_TRANSLATOR_UTIL_H_
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
'<(angle_path)/src/tests/compiler_tests/Pack_Unpack_test.cpp', '<(angle_path)/src/tests/compiler_tests/Pack_Unpack_test.cpp',
'<(angle_path)/src/tests/compiler_tests/PruneEmptyDeclarations_test.cpp', '<(angle_path)/src/tests/compiler_tests/PruneEmptyDeclarations_test.cpp',
'<(angle_path)/src/tests/compiler_tests/PruneUnusedFunctions_test.cpp', '<(angle_path)/src/tests/compiler_tests/PruneUnusedFunctions_test.cpp',
'<(angle_path)/src/tests/compiler_tests/QualificationOrder_test.cpp',
'<(angle_path)/src/tests/compiler_tests/RecordConstantPrecision_test.cpp', '<(angle_path)/src/tests/compiler_tests/RecordConstantPrecision_test.cpp',
'<(angle_path)/src/tests/compiler_tests/RemovePow_test.cpp', '<(angle_path)/src/tests/compiler_tests/RemovePow_test.cpp',
'<(angle_path)/src/tests/compiler_tests/ShaderExtension_test.cpp', '<(angle_path)/src/tests/compiler_tests/ShaderExtension_test.cpp',
......
...@@ -2323,7 +2323,7 @@ TEST_F(MalformedComputeShaderTest, CorrectUsageOfComputeBuiltins) ...@@ -2323,7 +2323,7 @@ TEST_F(MalformedComputeShaderTest, CorrectUsageOfComputeBuiltins)
} }
} }
// It is illegal to write to a special variable // It is illegal to write to a special variable.
TEST_F(MalformedComputeShaderTest, SpecialVariableNumWorkGroups) TEST_F(MalformedComputeShaderTest, SpecialVariableNumWorkGroups)
{ {
const std::string &shaderString = const std::string &shaderString =
...@@ -2339,7 +2339,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableNumWorkGroups) ...@@ -2339,7 +2339,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableNumWorkGroups)
} }
} }
// It is illegal to write to a special variable // It is illegal to write to a special variable.
TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupID) TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupID)
{ {
const std::string &shaderString = const std::string &shaderString =
...@@ -2355,7 +2355,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupID) ...@@ -2355,7 +2355,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupID)
} }
} }
// It is illegal to write to a special variable // It is illegal to write to a special variable.
TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationID) TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationID)
{ {
const std::string &shaderString = const std::string &shaderString =
...@@ -2371,7 +2371,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationID) ...@@ -2371,7 +2371,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationID)
} }
} }
// It is illegal to write to a special variable // It is illegal to write to a special variable.
TEST_F(MalformedComputeShaderTest, SpecialVariableGlobalInvocationID) TEST_F(MalformedComputeShaderTest, SpecialVariableGlobalInvocationID)
{ {
const std::string &shaderString = const std::string &shaderString =
...@@ -2387,7 +2387,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableGlobalInvocationID) ...@@ -2387,7 +2387,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableGlobalInvocationID)
} }
} }
// It is illegal to write to a special variable // It is illegal to write to a special variable.
TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationIndex) TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationIndex)
{ {
const std::string &shaderString = const std::string &shaderString =
...@@ -2403,7 +2403,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationIndex) ...@@ -2403,7 +2403,7 @@ TEST_F(MalformedComputeShaderTest, SpecialVariableLocalInvocationIndex)
} }
} }
// It is illegal to write to a special variable // It is illegal to write to a special variable.
TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupSize) TEST_F(MalformedComputeShaderTest, SpecialVariableWorkGroupSize)
{ {
const std::string &shaderString = const std::string &shaderString =
...@@ -2435,3 +2435,84 @@ TEST_F(MalformedShaderTest, SamplerUnaryOperator) ...@@ -2435,3 +2435,84 @@ TEST_F(MalformedShaderTest, SamplerUnaryOperator)
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
} }
} }
// Invariant cannot be used with a work group size declaration.
TEST_F(MalformedComputeShaderTest, InvariantBlockSize)
{
const std::string &shaderString =
"#version 310 es\n"
"invariant layout(local_size_x = 15) in;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Invariant cannot be used with a non-output variable in ESSL3.
TEST_F(MalformedShaderTest, InvariantNonOuput)
{
const std::string &shaderString =
"#version 300 es\n"
"invariant int value;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Invariant declaration should follow the following format "invariant <out variable name>".
// Test having an incorrect qualifier in the invariant declaration.
TEST_F(MalformedShaderTest, InvariantDeclarationWithStorageQualifier)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 foo;\n"
"invariant centroid foo;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Invariant declaration should follow the following format "invariant <out variable name>".
// Test having an incorrect precision qualifier in the invariant declaration.
TEST_F(MalformedShaderTest, InvariantDeclarationWithPrecisionQualifier)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 foo;\n"
"invariant highp foo;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Invariant declaration should follow the following format "invariant <out variable name>".
// Test having an incorrect layout qualifier in the invariant declaration.
TEST_F(MalformedShaderTest, InvariantDeclarationWithLayoutQualifier)
{
const std::string &shaderString =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 foo;\n"
"invariant layout(location=0) foo;\n"
"void main() {\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