Commit 4cdac9eb by jchen10 Committed by Commit Bot

ES31: Add atomic counter for GLSL parsing

This makes shader compiler support the new basic type 'atomic_uint' and validate its layout qualifiers properly. BUG=angleproject:1729 TEST=angle_unittests:AtomicCounterTest angle_deqp_gles31_tests:dEQP-GLES31.functional.atomic_counter.layout.invalid* angle_deqp_gles31_tests:dEQP-GLES31.functional.debug.negative_coverage.*.atomic* Change-Id: Ia237eadf6ea72314f436a0abbb93a05598e71eba Reviewed-on: https://chromium-review.googlesource.com/500088 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 2cd45629
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// 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 175 #define ANGLE_SH_VERSION 176
enum ShShaderSpec enum ShShaderSpec
{ {
......
...@@ -121,6 +121,7 @@ struct Uniform : public VariableWithLocation ...@@ -121,6 +121,7 @@ struct Uniform : public VariableWithLocation
} }
int binding; int binding;
int offset;
// Decide whether two uniforms are the same at shader link time, // Decide whether two uniforms 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.
......
...@@ -157,6 +157,7 @@ GLenum VariableComponentType(GLenum type) ...@@ -157,6 +157,7 @@ GLenum VariableComponentType(GLenum type)
case GL_IMAGE_CUBE: case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE: case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE: case GL_UNSIGNED_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return GL_INT; return GL_INT;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_VEC2: case GL_UNSIGNED_INT_VEC2:
...@@ -277,6 +278,7 @@ int VariableRowCount(GLenum type) ...@@ -277,6 +278,7 @@ int VariableRowCount(GLenum type)
case GL_IMAGE_CUBE: case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE: case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE: case GL_UNSIGNED_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return 1; return 1;
case GL_FLOAT_MAT2: case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3x2: case GL_FLOAT_MAT3x2:
...@@ -340,6 +342,7 @@ int VariableColumnCount(GLenum type) ...@@ -340,6 +342,7 @@ int VariableColumnCount(GLenum type)
case GL_IMAGE_CUBE: case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE: case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE: case GL_UNSIGNED_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return 1; return 1;
case GL_BOOL_VEC2: case GL_BOOL_VEC2:
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
...@@ -422,11 +425,15 @@ bool IsImageType(GLenum type) ...@@ -422,11 +425,15 @@ bool IsImageType(GLenum type)
return false; return false;
} }
bool IsAtomicCounterType(GLenum type)
{
return type == GL_UNSIGNED_INT_ATOMIC_COUNTER;
}
bool IsOpaqueType(GLenum type) bool IsOpaqueType(GLenum type)
{ {
// ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters. // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
// TODO(oetuaho): add atomic types return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
return IsImageType(type) || IsSamplerType(type);
} }
GLenum SamplerTypeToTextureType(GLenum samplerType) GLenum SamplerTypeToTextureType(GLenum samplerType)
......
...@@ -31,6 +31,7 @@ int VariableRowCount(GLenum type); ...@@ -31,6 +31,7 @@ int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type); int VariableColumnCount(GLenum type);
bool IsSamplerType(GLenum type); bool IsSamplerType(GLenum type);
bool IsImageType(GLenum type); bool IsImageType(GLenum type);
bool IsAtomicCounterType(GLenum type);
bool IsOpaqueType(GLenum type); bool IsOpaqueType(GLenum type);
GLenum SamplerTypeToTextureType(GLenum samplerType); GLenum SamplerTypeToTextureType(GLenum samplerType);
bool IsMatrixType(GLenum type); bool IsMatrixType(GLenum type);
......
...@@ -123,6 +123,8 @@ enum TBasicType ...@@ -123,6 +123,8 @@ enum TBasicType
EbtInterfaceBlock, EbtInterfaceBlock,
EbtAddress, // should be deprecated?? EbtAddress, // should be deprecated??
EbtAtomicCounter,
// end of list // end of list
EbtLast EbtLast
}; };
...@@ -198,10 +200,14 @@ inline bool IsGImage(TBasicType type) ...@@ -198,10 +200,14 @@ inline bool IsGImage(TBasicType type)
return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd; return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
} }
inline bool IsAtomicCounter(TBasicType type)
{
return type == EbtAtomicCounter;
}
inline bool IsOpaqueType(TBasicType type) inline bool IsOpaqueType(TBasicType type)
{ {
// TODO (mradev): add atomic types as opaque. return IsSampler(type) || IsImage(type) || IsAtomicCounter(type);
return IsSampler(type) || IsImage(type);
} }
inline bool IsIntegerSampler(TBasicType type) inline bool IsIntegerSampler(TBasicType type)
...@@ -626,6 +632,7 @@ struct TLayoutQualifier ...@@ -626,6 +632,7 @@ struct TLayoutQualifier
sh::WorkGroupSize localSize; sh::WorkGroupSize localSize;
int binding; int binding;
int offset;
// Image format layout qualifier // Image format layout qualifier
TLayoutImageInternalFormat imageInternalFormat; TLayoutImageInternalFormat imageInternalFormat;
...@@ -647,6 +654,7 @@ struct TLayoutQualifier ...@@ -647,6 +654,7 @@ struct TLayoutQualifier
layoutQualifier.localSize.fill(-1); layoutQualifier.localSize.fill(-1);
layoutQualifier.binding = -1; layoutQualifier.binding = -1;
layoutQualifier.offset = -1;
layoutQualifier.numViews = -1; layoutQualifier.numViews = -1;
layoutQualifier.yuv = false; layoutQualifier.yuv = false;
...@@ -656,7 +664,7 @@ struct TLayoutQualifier ...@@ -656,7 +664,7 @@ struct TLayoutQualifier
bool isEmpty() const bool isEmpty() const
{ {
return location == -1 && binding == -1 && numViews == -1 && yuv == false && return location == -1 && binding == -1 && offset == -1 && numViews == -1 && yuv == false &&
matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified && matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified &&
!localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified; !localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified;
} }
......
...@@ -600,6 +600,10 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) ...@@ -600,6 +600,10 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
// It isn't specified whether Sampler2DRect has default precision. // It isn't specified whether Sampler2DRect has default precision.
initSamplerDefaultPrecision(EbtSampler2DRect); initSamplerDefaultPrecision(EbtSampler2DRect);
TPublicType atomicCounter;
atomicCounter.initializeBasicType(EbtAtomicCounter);
symbolTable.setDefaultPrecision(atomicCounter, EbpHigh);
InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable); InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable); IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
......
...@@ -630,6 +630,11 @@ void InsertBuiltInFunctions(sh::GLenum type, ...@@ -630,6 +630,11 @@ void InsertBuiltInFunctions(sh::GLenum type,
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow,
float4, float2, float2, int2); float4, float2, float2, int2);
const TType *atomicCounter = TCache::getType(EbtAtomicCounter);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounter", atomicCounter);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterIncrement", atomicCounter);
symbolTable.insertBuiltIn(ESSL3_1_BUILTINS, uint1, "atomicCounterDecrement", atomicCounter);
const TType *gimage2D = TCache::getType(EbtGImage2D); const TType *gimage2D = TCache::getType(EbtGImage2D);
const TType *gimage3D = TCache::getType(EbtGImage3D); const TType *gimage3D = TCache::getType(EbtGImage3D);
const TType *gimage2DArray = TCache::getType(EbtGImage2DArray); const TType *gimage2DArray = TCache::getType(EbtGImage2DArray);
......
...@@ -40,6 +40,7 @@ class TParseContext : angle::NonCopyable ...@@ -40,6 +40,7 @@ class TParseContext : angle::NonCopyable
bool checksPrecErrors, bool checksPrecErrors,
TDiagnostics *diagnostics, TDiagnostics *diagnostics,
const ShBuiltInResources &resources); const ShBuiltInResources &resources);
~TParseContext();
const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; } const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
pp::Preprocessor &getPreprocessor() { return mPreprocessor; } pp::Preprocessor &getPreprocessor() { return mPreprocessor; }
...@@ -363,6 +364,16 @@ class TParseContext : angle::NonCopyable ...@@ -363,6 +364,16 @@ class TParseContext : angle::NonCopyable
TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed
private: private:
class AtomicCounterBindingState;
constexpr static size_t kAtomicCounterSize = 4;
// UNIFORM_ARRAY_STRIDE for atomic counter arrays is an implementation-dependent value which
// can be queried after a program is linked according to ES 3.10 section 7.7.1. This is
// controversial with the offset inheritance as described in ESSL 3.10 section 4.4.6. Currently
// we treat it as always 4 in favour of the original interpretation in
// "ARB_shader_atomic_counters".
// TODO(jie.a.chen@intel.com): Double check this once the spec vagueness is resolved.
constexpr static size_t kAtomicCounterArrayStride = 4;
// Returns a clamped index. If it prints out an error message, the token is "[]". // Returns a clamped index. If it prints out an error message, the token is "[]".
int checkIndexOutOfRange(bool outOfRangeIndexIsError, int checkIndexOutOfRange(bool outOfRangeIndexIsError,
const TSourceLoc &location, const TSourceLoc &location,
...@@ -381,6 +392,9 @@ class TParseContext : angle::NonCopyable ...@@ -381,6 +392,9 @@ class TParseContext : angle::NonCopyable
bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation, bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
const TPublicType &elementType); const TPublicType &elementType);
// Done for all atomic counter declarations, whether empty or not.
void atomicCounterQualifierErrorCheck(const TPublicType &publicType,
const TSourceLoc &location);
// Assumes that multiplication op has already been set based on the types. // Assumes that multiplication op has already been set based on the types.
bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right); bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right);
...@@ -393,11 +407,18 @@ class TParseContext : angle::NonCopyable ...@@ -393,11 +407,18 @@ class TParseContext : angle::NonCopyable
TLayoutImageInternalFormat internalFormat); TLayoutImageInternalFormat internalFormat);
void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier, void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
const TSourceLoc &location); const TSourceLoc &location);
void checkAtomicCounterOffsetIsNotOverlapped(TPublicType &publicType,
size_t size,
bool forceAppend,
const TSourceLoc &loc,
TType &type);
void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type); void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type);
void checkBindingIsNotSpecified(const TSourceLoc &location, int binding); void checkBindingIsNotSpecified(const TSourceLoc &location, int binding);
void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset);
void checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize); void checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize);
void checkSamplerBindingIsValid(const TSourceLoc &location, int binding, int arraySize); void checkSamplerBindingIsValid(const TSourceLoc &location, int binding, int arraySize);
void checkBlockBindingIsValid(const TSourceLoc &location, int binding, int arraySize); void checkBlockBindingIsValid(const TSourceLoc &location, int binding, int arraySize);
void checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding);
void checkUniformLocationInRange(const TSourceLoc &location, void checkUniformLocationInRange(const TSourceLoc &location,
int objectLocationCount, int objectLocationCount,
...@@ -436,6 +457,9 @@ class TParseContext : angle::NonCopyable ...@@ -436,6 +457,9 @@ class TParseContext : angle::NonCopyable
const TSourceLoc &location, const TSourceLoc &location,
bool insertParametersToSymbolTable); bool insertParametersToSymbolTable);
void setAtomicCounterBindingDefaultOffset(const TPublicType &declaration,
const TSourceLoc &location);
// Set to true when the last/current declarator list was started with an empty declaration. The // Set to true when the last/current declarator list was started with an empty declaration. The
// non-empty declaration error check will need to be performed if the empty declaration is // non-empty declaration error check will need to be performed if the empty declaration is
// followed by a declarator. // followed by a declarator.
...@@ -482,8 +506,13 @@ class TParseContext : angle::NonCopyable ...@@ -482,8 +506,13 @@ class TParseContext : angle::NonCopyable
int mMaxCombinedTextureImageUnits; int mMaxCombinedTextureImageUnits;
int mMaxUniformLocations; int mMaxUniformLocations;
int mMaxUniformBufferBindings; int mMaxUniformBufferBindings;
int mMaxAtomicCounterBindings;
// keeps track whether we are declaring / defining a function // keeps track whether we are declaring / defining a function
bool mDeclaringFunction; bool mDeclaringFunction;
// Track the state of each atomic counter binding.
std::map<int, AtomicCounterBindingState> mAtomicCounterBindingStates;
}; };
int PaParseStrings(size_t count, int PaParseStrings(size_t count,
......
...@@ -568,6 +568,10 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier, ...@@ -568,6 +568,10 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
{ {
joinedQualifier.binding = rightQualifier.binding; joinedQualifier.binding = rightQualifier.binding;
} }
if (rightQualifier.offset != -1)
{
joinedQualifier.offset = rightQualifier.offset;
}
if (rightQualifier.matrixPacking != EmpUnspecified) if (rightQualifier.matrixPacking != EmpUnspecified)
{ {
joinedQualifier.matrixPacking = rightQualifier.matrixPacking; joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
......
...@@ -181,7 +181,7 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other, ...@@ -181,7 +181,7 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
return true; return true;
} }
Uniform::Uniform() : binding(-1) Uniform::Uniform() : binding(-1), offset(-1)
{ {
} }
...@@ -189,7 +189,8 @@ Uniform::~Uniform() ...@@ -189,7 +189,8 @@ Uniform::~Uniform()
{ {
} }
Uniform::Uniform(const Uniform &other) : VariableWithLocation(other), binding(other.binding) Uniform::Uniform(const Uniform &other)
: VariableWithLocation(other), binding(other.binding), offset(other.offset)
{ {
} }
...@@ -197,17 +198,19 @@ Uniform &Uniform::operator=(const Uniform &other) ...@@ -197,17 +198,19 @@ Uniform &Uniform::operator=(const Uniform &other)
{ {
VariableWithLocation::operator=(other); VariableWithLocation::operator=(other);
binding = other.binding; binding = other.binding;
offset = other.offset;
return *this; return *this;
} }
bool Uniform::operator==(const Uniform &other) const bool Uniform::operator==(const Uniform &other) const
{ {
return VariableWithLocation::operator==(other) && binding == other.binding; return VariableWithLocation::operator==(other) && binding == other.binding &&
offset == other.offset;
} }
bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{ {
if (binding != -1 && other.binding != -1 && binding != other.binding) if (binding != other.binding)
{ {
return false; return false;
} }
...@@ -215,6 +218,11 @@ bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const ...@@ -215,6 +218,11 @@ bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{ {
return false; return false;
} }
// TODO(jie.a.chen@intel.com): Add a test case to cover this.
if (offset != other.offset)
{
return false;
}
return VariableWithLocation::isSameVariableAtLinkTime(other, true); return VariableWithLocation::isSameVariableAtLinkTime(other, true);
} }
......
...@@ -105,6 +105,8 @@ const char *getBasicString(TBasicType t) ...@@ -105,6 +105,8 @@ const char *getBasicString(TBasicType t)
return "iimageCube"; return "iimageCube";
case EbtUImageCube: case EbtUImageCube:
return "uimageCube"; return "uimageCube";
case EbtAtomicCounter:
return "atomic_uint";
default: default:
UNREACHABLE(); UNREACHABLE();
return "unknown type"; return "unknown type";
......
...@@ -329,6 +329,8 @@ TString TypeString(const TType &type) ...@@ -329,6 +329,8 @@ TString TypeString(const TType &type)
return "samplerCUBE"; return "samplerCUBE";
case EbtSamplerExternalOES: case EbtSamplerExternalOES:
return "sampler2D"; return "sampler2D";
case EbtAtomicCounter:
return "atomic_uint";
default: default:
break; break;
} }
......
...@@ -572,6 +572,7 @@ Uniform CollectVariables::recordUniform(const TIntermSymbol &variable) const ...@@ -572,6 +572,7 @@ Uniform CollectVariables::recordUniform(const TIntermSymbol &variable) const
setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform); setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform);
uniform.binding = variable.getType().getLayoutQualifier().binding; uniform.binding = variable.getType().getLayoutQualifier().binding;
uniform.location = variable.getType().getLayoutQualifier().location; uniform.location = variable.getType().getLayoutQualifier().location;
uniform.offset = variable.getType().getLayoutQualifier().offset;
return uniform; return uniform;
} }
......
File mode changed from 100644 to 100755
...@@ -225,10 +225,10 @@ O [0-7] ...@@ -225,10 +225,10 @@ O [0-7]
"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); } "coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); }
"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); } "restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); }
"volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); } "volatile" { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); }
"atomic_uint" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, ATOMICUINT); }
/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
"resource" | "resource" |
"atomic_uint" |
"noperspective" | "noperspective" |
"patch" | "patch" |
"sample" | "sample" |
......
...@@ -187,6 +187,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons ...@@ -187,6 +187,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%token <lex> SAMPLEREXTERNAL2DY2YEXT %token <lex> SAMPLEREXTERNAL2DY2YEXT
%token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY %token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE %token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
%token <lex> ATOMICUINT
%token <lex> LAYOUT %token <lex> LAYOUT
%token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT %token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT
...@@ -1264,6 +1265,9 @@ type_specifier_nonarray ...@@ -1264,6 +1265,9 @@ type_specifier_nonarray
| UIMAGECUBE { | UIMAGECUBE {
$$.initialize(EbtUImageCube, @1); $$.initialize(EbtUImageCube, @1);
} }
| ATOMICUINT {
$$.initialize(EbtAtomicCounter, @1);
}
| TYPE_NAME { | TYPE_NAME {
// //
// This is for user defined type names. The lexical phase looked up the // This is for user defined type names. The lexical phase looked up the
......
...@@ -588,7 +588,7 @@ static const flex_int16_t yy_accept[886] = ...@@ -588,7 +588,7 @@ static const flex_int16_t yy_accept[886] =
183, 183, 183, 183, 8, 183, 183, 9, 183, 183, 183, 183, 183, 183, 8, 183, 183, 9, 183, 183,
183, 183, 183, 183, 20, 102, 11, 156, 116, 89, 183, 183, 183, 183, 20, 102, 11, 156, 116, 89,
96, 183, 183, 183, 183, 183, 183, 183, 183, 183, 96, 183, 183, 183, 183, 183, 183, 183, 183, 183,
183, 183, 183, 183, 152, 183, 183, 183, 100, 105, 183, 183, 183, 183, 152, 183, 183, 183, 100, 106,
103, 183, 183, 183, 183, 183, 183, 183, 148, 117, 103, 183, 183, 183, 183, 183, 183, 183, 148, 117,
90, 95, 183, 183, 163, 183, 104, 183, 183, 183, 90, 95, 183, 183, 163, 183, 104, 183, 183, 183,
...@@ -600,7 +600,7 @@ static const flex_int16_t yy_accept[886] = ...@@ -600,7 +600,7 @@ static const flex_int16_t yy_accept[886] =
183, 183, 183, 130, 68, 69, 183, 183, 183, 183, 183, 183, 183, 130, 68, 69, 183, 183, 183, 183,
183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183,
110, 183, 183, 183, 98, 132, 73, 74, 183, 183, 110, 183, 183, 183, 98, 132, 73, 74, 183, 183,
183, 183, 106, 183, 183, 183, 183, 183, 183, 183, 183, 183, 105, 183, 183, 183, 183, 183, 183, 183,
125, 183, 183, 183, 183, 183, 183, 183, 183, 183, 125, 183, 183, 183, 183, 183, 183, 183, 183, 183,
183, 183, 67, 183, 183, 183, 183, 61, 183, 183, 183, 183, 67, 183, 183, 183, 183, 61, 183, 183,
...@@ -2107,8 +2107,11 @@ case 104: ...@@ -2107,8 +2107,11 @@ case 104:
YY_RULE_SETUP YY_RULE_SETUP
{ return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); } { return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); }
YY_BREAK YY_BREAK
/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
case 105: case 105:
YY_RULE_SETUP
{ return ES2_ident_ES3_reserved_ES3_1_keyword(context, ATOMICUINT); }
YY_BREAK
/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
case 106: case 106:
case 107: case 107:
case 108: case 108:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -50,158 +50,159 @@ extern int yydebug; ...@@ -50,158 +50,159 @@ extern int yydebug;
/* Token type. */ /* Token type. */
#ifndef YYTOKENTYPE #ifndef YYTOKENTYPE
# define YYTOKENTYPE # define YYTOKENTYPE
enum yytokentype enum yytokentype
{ {
INVARIANT = 258, INVARIANT = 258,
HIGH_PRECISION = 259, HIGH_PRECISION = 259,
MEDIUM_PRECISION = 260, MEDIUM_PRECISION = 260,
LOW_PRECISION = 261, LOW_PRECISION = 261,
PRECISION = 262, PRECISION = 262,
ATTRIBUTE = 263, ATTRIBUTE = 263,
CONST_QUAL = 264, CONST_QUAL = 264,
BOOL_TYPE = 265, BOOL_TYPE = 265,
FLOAT_TYPE = 266, FLOAT_TYPE = 266,
INT_TYPE = 267, INT_TYPE = 267,
UINT_TYPE = 268, UINT_TYPE = 268,
BREAK = 269, BREAK = 269,
CONTINUE = 270, CONTINUE = 270,
DO = 271, DO = 271,
ELSE = 272, ELSE = 272,
FOR = 273, FOR = 273,
IF = 274, IF = 274,
DISCARD = 275, DISCARD = 275,
RETURN = 276, RETURN = 276,
SWITCH = 277, SWITCH = 277,
CASE = 278, CASE = 278,
DEFAULT = 279, DEFAULT = 279,
BVEC2 = 280, BVEC2 = 280,
BVEC3 = 281, BVEC3 = 281,
BVEC4 = 282, BVEC4 = 282,
IVEC2 = 283, IVEC2 = 283,
IVEC3 = 284, IVEC3 = 284,
IVEC4 = 285, IVEC4 = 285,
VEC2 = 286, VEC2 = 286,
VEC3 = 287, VEC3 = 287,
VEC4 = 288, VEC4 = 288,
UVEC2 = 289, UVEC2 = 289,
UVEC3 = 290, UVEC3 = 290,
UVEC4 = 291, UVEC4 = 291,
MATRIX2 = 292, MATRIX2 = 292,
MATRIX3 = 293, MATRIX3 = 293,
MATRIX4 = 294, MATRIX4 = 294,
IN_QUAL = 295, IN_QUAL = 295,
OUT_QUAL = 296, OUT_QUAL = 296,
INOUT_QUAL = 297, INOUT_QUAL = 297,
UNIFORM = 298, UNIFORM = 298,
VARYING = 299, VARYING = 299,
MATRIX2x3 = 300, MATRIX2x3 = 300,
MATRIX3x2 = 301, MATRIX3x2 = 301,
MATRIX2x4 = 302, MATRIX2x4 = 302,
MATRIX4x2 = 303, MATRIX4x2 = 303,
MATRIX3x4 = 304, MATRIX3x4 = 304,
MATRIX4x3 = 305, MATRIX4x3 = 305,
CENTROID = 306, CENTROID = 306,
FLAT = 307, FLAT = 307,
SMOOTH = 308, SMOOTH = 308,
READONLY = 309, READONLY = 309,
WRITEONLY = 310, WRITEONLY = 310,
COHERENT = 311, COHERENT = 311,
RESTRICT = 312, RESTRICT = 312,
VOLATILE = 313, VOLATILE = 313,
SHARED = 314, SHARED = 314,
STRUCT = 315, STRUCT = 315,
VOID_TYPE = 316, VOID_TYPE = 316,
WHILE = 317, WHILE = 317,
SAMPLER2D = 318, SAMPLER2D = 318,
SAMPLERCUBE = 319, SAMPLERCUBE = 319,
SAMPLER_EXTERNAL_OES = 320, SAMPLER_EXTERNAL_OES = 320,
SAMPLER2DRECT = 321, SAMPLER2DRECT = 321,
SAMPLER2DARRAY = 322, SAMPLER2DARRAY = 322,
ISAMPLER2D = 323, ISAMPLER2D = 323,
ISAMPLER3D = 324, ISAMPLER3D = 324,
ISAMPLERCUBE = 325, ISAMPLERCUBE = 325,
ISAMPLER2DARRAY = 326, ISAMPLER2DARRAY = 326,
USAMPLER2D = 327, USAMPLER2D = 327,
USAMPLER3D = 328, USAMPLER3D = 328,
USAMPLERCUBE = 329, USAMPLERCUBE = 329,
USAMPLER2DARRAY = 330, USAMPLER2DARRAY = 330,
SAMPLER2DMS = 331, SAMPLER2DMS = 331,
ISAMPLER2DMS = 332, ISAMPLER2DMS = 332,
USAMPLER2DMS = 333, USAMPLER2DMS = 333,
SAMPLER3D = 334, SAMPLER3D = 334,
SAMPLER3DRECT = 335, SAMPLER3DRECT = 335,
SAMPLER2DSHADOW = 336, SAMPLER2DSHADOW = 336,
SAMPLERCUBESHADOW = 337, SAMPLERCUBESHADOW = 337,
SAMPLER2DARRAYSHADOW = 338, SAMPLER2DARRAYSHADOW = 338,
SAMPLEREXTERNAL2DY2YEXT = 339, SAMPLEREXTERNAL2DY2YEXT = 339,
IMAGE2D = 340, IMAGE2D = 340,
IIMAGE2D = 341, IIMAGE2D = 341,
UIMAGE2D = 342, UIMAGE2D = 342,
IMAGE3D = 343, IMAGE3D = 343,
IIMAGE3D = 344, IIMAGE3D = 344,
UIMAGE3D = 345, UIMAGE3D = 345,
IMAGE2DARRAY = 346, IMAGE2DARRAY = 346,
IIMAGE2DARRAY = 347, IIMAGE2DARRAY = 347,
UIMAGE2DARRAY = 348, UIMAGE2DARRAY = 348,
IMAGECUBE = 349, IMAGECUBE = 349,
IIMAGECUBE = 350, IIMAGECUBE = 350,
UIMAGECUBE = 351, UIMAGECUBE = 351,
LAYOUT = 352, ATOMICUINT = 352,
YUVCSCSTANDARDEXT = 353, LAYOUT = 353,
YUVCSCSTANDARDEXTCONSTANT = 354, YUVCSCSTANDARDEXT = 354,
IDENTIFIER = 355, YUVCSCSTANDARDEXTCONSTANT = 355,
TYPE_NAME = 356, IDENTIFIER = 356,
FLOATCONSTANT = 357, TYPE_NAME = 357,
INTCONSTANT = 358, FLOATCONSTANT = 358,
UINTCONSTANT = 359, INTCONSTANT = 359,
BOOLCONSTANT = 360, UINTCONSTANT = 360,
FIELD_SELECTION = 361, BOOLCONSTANT = 361,
LEFT_OP = 362, FIELD_SELECTION = 362,
RIGHT_OP = 363, LEFT_OP = 363,
INC_OP = 364, RIGHT_OP = 364,
DEC_OP = 365, INC_OP = 365,
LE_OP = 366, DEC_OP = 366,
GE_OP = 367, LE_OP = 367,
EQ_OP = 368, GE_OP = 368,
NE_OP = 369, EQ_OP = 369,
AND_OP = 370, NE_OP = 370,
OR_OP = 371, AND_OP = 371,
XOR_OP = 372, OR_OP = 372,
MUL_ASSIGN = 373, XOR_OP = 373,
DIV_ASSIGN = 374, MUL_ASSIGN = 374,
ADD_ASSIGN = 375, DIV_ASSIGN = 375,
MOD_ASSIGN = 376, ADD_ASSIGN = 376,
LEFT_ASSIGN = 377, MOD_ASSIGN = 377,
RIGHT_ASSIGN = 378, LEFT_ASSIGN = 378,
AND_ASSIGN = 379, RIGHT_ASSIGN = 379,
XOR_ASSIGN = 380, AND_ASSIGN = 380,
OR_ASSIGN = 381, XOR_ASSIGN = 381,
SUB_ASSIGN = 382, OR_ASSIGN = 382,
LEFT_PAREN = 383, SUB_ASSIGN = 383,
RIGHT_PAREN = 384, LEFT_PAREN = 384,
LEFT_BRACKET = 385, RIGHT_PAREN = 385,
RIGHT_BRACKET = 386, LEFT_BRACKET = 386,
LEFT_BRACE = 387, RIGHT_BRACKET = 387,
RIGHT_BRACE = 388, LEFT_BRACE = 388,
DOT = 389, RIGHT_BRACE = 389,
COMMA = 390, DOT = 390,
COLON = 391, COMMA = 391,
EQUAL = 392, COLON = 392,
SEMICOLON = 393, EQUAL = 393,
BANG = 394, SEMICOLON = 394,
DASH = 395, BANG = 395,
TILDE = 396, DASH = 396,
PLUS = 397, TILDE = 397,
STAR = 398, PLUS = 398,
SLASH = 399, STAR = 399,
PERCENT = 400, SLASH = 400,
LEFT_ANGLE = 401, PERCENT = 401,
RIGHT_ANGLE = 402, LEFT_ANGLE = 402,
VERTICAL_BAR = 403, RIGHT_ANGLE = 403,
CARET = 404, VERTICAL_BAR = 404,
AMPERSAND = 405, CARET = 405,
QUESTION = 406 AMPERSAND = 406,
}; QUESTION = 407
};
#endif #endif
/* Value type. */ /* Value type. */
......
...@@ -392,6 +392,8 @@ GLenum GLVariableType(const TType &type) ...@@ -392,6 +392,8 @@ GLenum GLVariableType(const TType &type)
return GL_INT_IMAGE_CUBE; return GL_INT_IMAGE_CUBE;
case EbtUImageCube: case EbtUImageCube:
return GL_UNSIGNED_INT_IMAGE_CUBE; return GL_UNSIGNED_INT_IMAGE_CUBE;
case EbtAtomicCounter:
return GL_UNSIGNED_INT_ATOMIC_COUNTER;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
'<(angle_path)/src/tests/angle_unittests_utils.h', '<(angle_path)/src/tests/angle_unittests_utils.h',
'<(angle_path)/src/tests/compiler_tests/API_test.cpp', '<(angle_path)/src/tests/compiler_tests/API_test.cpp',
'<(angle_path)/src/tests/compiler_tests/AppendixALimitations_test.cpp', '<(angle_path)/src/tests/compiler_tests/AppendixALimitations_test.cpp',
'<(angle_path)/src/tests/compiler_tests/AtomicCounter_test.cpp',
'<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp', '<(angle_path)/src/tests/compiler_tests/CollectVariables_test.cpp',
'<(angle_path)/src/tests/compiler_tests/ConstantFolding_test.cpp', '<(angle_path)/src/tests/compiler_tests/ConstantFolding_test.cpp',
'<(angle_path)/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp', '<(angle_path)/src/tests/compiler_tests/ConstantFoldingNaN_test.cpp',
......
//
// Copyright (c) 2017 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.
//
// AtomicCounter_test.cpp:
// Tests for validating ESSL 3.10 section 4.4.6.
//
#include "gtest/gtest.h"
#include "GLSLANG/ShaderLang.h"
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "tests/test_utils/ShaderCompileTreeTest.h"
using namespace sh;
class AtomicCounterTest : public ShaderCompileTreeTest
{
public:
AtomicCounterTest() {}
protected:
::GLenum getShaderType() const override { return GL_VERTEX_SHADER; }
ShShaderSpec getShaderSpec() const override { return SH_GLES3_1_SPEC; }
void initResources(ShBuiltInResources *resources) override
{
resources->MaxAtomicCounterBindings = 8;
}
};
// Test that layout qualifiers described in ESSL 3.10 section 4.4.6 can be successfully compiled,
// and the values of offset are properly assigned to counter variables.
TEST_F(AtomicCounterTest, BasicAtomicCounterDeclaration)
{
mExtraCompileOptions |= SH_VARIABLES;
const std::string &source =
"#version 310 es\n"
"layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
"layout(binding = 2) uniform atomic_uint b;\n"
"layout(binding = 2, offset = 12) uniform atomic_uint c, d;\n"
"layout(binding = 1, offset = 4) uniform atomic_uint e;\n"
"void main()\n"
"{\n"
"}\n";
if (!compile(source))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
std::vector<sh::Uniform> counters = getUniforms();
EXPECT_EQ(std::string("a"), counters[0].name);
EXPECT_EQ(2, counters[0].binding);
EXPECT_EQ(4, counters[0].offset);
EXPECT_EQ(std::string("b"), counters[1].name);
EXPECT_EQ(2, counters[1].binding);
EXPECT_EQ(8, counters[1].offset);
EXPECT_EQ(std::string("c"), counters[2].name);
EXPECT_EQ(2, counters[2].binding);
EXPECT_EQ(12, counters[2].offset);
EXPECT_EQ(std::string("d"), counters[3].name);
EXPECT_EQ(2, counters[3].binding);
EXPECT_EQ(16, counters[3].offset);
EXPECT_EQ(std::string("e"), counters[4].name);
EXPECT_EQ(1, counters[4].binding);
EXPECT_EQ(4, counters[4].offset);
}
// Test that ESSL 3.00 doesn't support atomic_uint.
TEST_F(AtomicCounterTest, InvalidShaderVersion)
{
const std::string &source =
"#version 300 es\n"
"layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that any qualifier other than uniform leads to compile-time error.
TEST_F(AtomicCounterTest, InvalidQualifier)
{
const std::string &source =
"#version 310 es\n"
"layout(binding = 2, offset = 4) in atomic_uint a;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that uniform must be specified for declaration.
TEST_F(AtomicCounterTest, UniformMustSpecifiedForDeclaration)
{
const std::string &source =
"#version 310 es\n"
"atomic_uint a;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that offset overlapping leads to compile-time error(ESSL 3.10 section 4.4.6).
TEST_F(AtomicCounterTest, BindingOffsetOverlapping)
{
const std::string &source =
"#version 310 es\n"
"layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
"layout(binding = 2, offset = 6) uniform atomic_uint b;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test offset inheritance for multiple variables in one same declaration.
TEST_F(AtomicCounterTest, MultipleVariablesDeclaration)
{
const std::string &source =
"#version 310 es\n"
"layout(binding = 2, offset = 4) uniform atomic_uint a, b;\n"
"layout(binding = 2, offset = 8) uniform atomic_uint c;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that subsequent declarations inherit the globally specified offset.
TEST_F(AtomicCounterTest, GlobalBindingOffsetOverlapping)
{
const std::string &source =
"#version 310 es\n"
"layout(binding = 2, offset = 4) uniform atomic_uint;\n"
"layout(binding = 2) uniform atomic_uint b;\n"
"layout(binding = 2, offset = 4) uniform atomic_uint c;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// The spec only demands offset unique and non-overlapping. So this should be allowed.
TEST_F(AtomicCounterTest, DeclarationSequenceWithDecrementalOffsetsSpecified)
{
const std::string &source =
"#version 310 es\n"
"layout(binding = 2, offset = 4) uniform atomic_uint a;\n"
"layout(binding = 2, offset = 0) uniform atomic_uint b;\n"
"void main()\n"
"{\n"
"}\n";
if (!compile(source))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Test that image format qualifiers are not allowed for atomic counters.
TEST_F(AtomicCounterTest, ImageFormatMustNotSpecified)
{
const std::string &source =
"#version 310 es\n"
"layout(binding = 2, offset = 4, rgba32f) uniform atomic_uint a;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
// Test that global layout qualifiers must not use 'offset'.
TEST_F(AtomicCounterTest, OffsetMustNotSpecifiedForGlobalLayoutQualifier)
{
const std::string &source =
"#version 310 es\n"
"layout(offset = 4) in;\n"
"void main()\n"
"{\n"
"}\n";
if (compile(source))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << 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