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 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 175
#define ANGLE_SH_VERSION 176
enum ShShaderSpec
{
......
......@@ -121,6 +121,7 @@ struct Uniform : public VariableWithLocation
}
int binding;
int offset;
// Decide whether two uniforms are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
......
......@@ -157,6 +157,7 @@ GLenum VariableComponentType(GLenum type)
case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return GL_INT;
case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_VEC2:
......@@ -277,6 +278,7 @@ int VariableRowCount(GLenum type)
case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return 1;
case GL_FLOAT_MAT2:
case GL_FLOAT_MAT3x2:
......@@ -340,6 +342,7 @@ int VariableColumnCount(GLenum type)
case GL_IMAGE_CUBE:
case GL_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_IMAGE_CUBE:
case GL_UNSIGNED_INT_ATOMIC_COUNTER:
return 1;
case GL_BOOL_VEC2:
case GL_FLOAT_VEC2:
......@@ -422,11 +425,15 @@ bool IsImageType(GLenum type)
return false;
}
bool IsAtomicCounterType(GLenum type)
{
return type == GL_UNSIGNED_INT_ATOMIC_COUNTER;
}
bool IsOpaqueType(GLenum type)
{
// 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);
return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
}
GLenum SamplerTypeToTextureType(GLenum samplerType)
......
......@@ -31,6 +31,7 @@ int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
bool IsSamplerType(GLenum type);
bool IsImageType(GLenum type);
bool IsAtomicCounterType(GLenum type);
bool IsOpaqueType(GLenum type);
GLenum SamplerTypeToTextureType(GLenum samplerType);
bool IsMatrixType(GLenum type);
......
......@@ -123,6 +123,8 @@ enum TBasicType
EbtInterfaceBlock,
EbtAddress, // should be deprecated??
EbtAtomicCounter,
// end of list
EbtLast
};
......@@ -198,10 +200,14 @@ inline bool IsGImage(TBasicType type)
return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
}
inline bool IsAtomicCounter(TBasicType type)
{
return type == EbtAtomicCounter;
}
inline bool IsOpaqueType(TBasicType type)
{
// TODO (mradev): add atomic types as opaque.
return IsSampler(type) || IsImage(type);
return IsSampler(type) || IsImage(type) || IsAtomicCounter(type);
}
inline bool IsIntegerSampler(TBasicType type)
......@@ -626,6 +632,7 @@ struct TLayoutQualifier
sh::WorkGroupSize localSize;
int binding;
int offset;
// Image format layout qualifier
TLayoutImageInternalFormat imageInternalFormat;
......@@ -647,6 +654,7 @@ struct TLayoutQualifier
layoutQualifier.localSize.fill(-1);
layoutQualifier.binding = -1;
layoutQualifier.offset = -1;
layoutQualifier.numViews = -1;
layoutQualifier.yuv = false;
......@@ -656,7 +664,7 @@ struct TLayoutQualifier
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 &&
!localSize.isAnyValueSet() && imageInternalFormat == EiifUnspecified;
}
......
......@@ -600,6 +600,10 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
// It isn't specified whether Sampler2DRect has default precision.
initSamplerDefaultPrecision(EbtSampler2DRect);
TPublicType atomicCounter;
atomicCounter.initializeBasicType(EbtAtomicCounter);
symbolTable.setDefaultPrecision(atomicCounter, EbpHigh);
InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
......
......@@ -630,6 +630,11 @@ void InsertBuiltInFunctions(sh::GLenum type,
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow,
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 *gimage3D = TCache::getType(EbtGImage3D);
const TType *gimage2DArray = TCache::getType(EbtGImage2DArray);
......
......@@ -40,6 +40,7 @@ class TParseContext : angle::NonCopyable
bool checksPrecErrors,
TDiagnostics *diagnostics,
const ShBuiltInResources &resources);
~TParseContext();
const pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
pp::Preprocessor &getPreprocessor() { return mPreprocessor; }
......@@ -363,6 +364,16 @@ class TParseContext : angle::NonCopyable
TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed
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 "[]".
int checkIndexOutOfRange(bool outOfRangeIndexIsError,
const TSourceLoc &location,
......@@ -381,6 +392,9 @@ class TParseContext : angle::NonCopyable
bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
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.
bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right);
......@@ -393,11 +407,18 @@ class TParseContext : angle::NonCopyable
TLayoutImageInternalFormat internalFormat);
void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
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 checkBindingIsNotSpecified(const TSourceLoc &location, int binding);
void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset);
void checkImageBindingIsValid(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 checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding);
void checkUniformLocationInRange(const TSourceLoc &location,
int objectLocationCount,
......@@ -436,6 +457,9 @@ class TParseContext : angle::NonCopyable
const TSourceLoc &location,
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
// non-empty declaration error check will need to be performed if the empty declaration is
// followed by a declarator.
......@@ -482,8 +506,13 @@ class TParseContext : angle::NonCopyable
int mMaxCombinedTextureImageUnits;
int mMaxUniformLocations;
int mMaxUniformBufferBindings;
int mMaxAtomicCounterBindings;
// keeps track whether we are declaring / defining a function
bool mDeclaringFunction;
// Track the state of each atomic counter binding.
std::map<int, AtomicCounterBindingState> mAtomicCounterBindingStates;
};
int PaParseStrings(size_t count,
......
......@@ -568,6 +568,10 @@ TLayoutQualifier JoinLayoutQualifiers(TLayoutQualifier leftQualifier,
{
joinedQualifier.binding = rightQualifier.binding;
}
if (rightQualifier.offset != -1)
{
joinedQualifier.offset = rightQualifier.offset;
}
if (rightQualifier.matrixPacking != EmpUnspecified)
{
joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
......
......@@ -181,7 +181,7 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
return true;
}
Uniform::Uniform() : binding(-1)
Uniform::Uniform() : binding(-1), offset(-1)
{
}
......@@ -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)
{
VariableWithLocation::operator=(other);
binding = other.binding;
offset = other.offset;
return *this;
}
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
{
if (binding != -1 && other.binding != -1 && binding != other.binding)
if (binding != other.binding)
{
return false;
}
......@@ -215,6 +218,11 @@ bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{
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);
}
......
......@@ -105,6 +105,8 @@ const char *getBasicString(TBasicType t)
return "iimageCube";
case EbtUImageCube:
return "uimageCube";
case EbtAtomicCounter:
return "atomic_uint";
default:
UNREACHABLE();
return "unknown type";
......
......@@ -329,6 +329,8 @@ TString TypeString(const TType &type)
return "samplerCUBE";
case EbtSamplerExternalOES:
return "sampler2D";
case EbtAtomicCounter:
return "atomic_uint";
default:
break;
}
......
......@@ -572,6 +572,7 @@ Uniform CollectVariables::recordUniform(const TIntermSymbol &variable) const
setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform);
uniform.binding = variable.getType().getLayoutQualifier().binding;
uniform.location = variable.getType().getLayoutQualifier().location;
uniform.offset = variable.getType().getLayoutQualifier().offset;
return uniform;
}
......
File mode changed from 100644 to 100755
......@@ -225,10 +225,10 @@ O [0-7]
"coherent" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, COHERENT); }
"restrict" { return ES2_ident_ES3_reserved_ES3_1_keyword(context, RESTRICT); }
"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 */
"resource" |
"atomic_uint" |
"noperspective" |
"patch" |
"sample" |
......
......@@ -187,6 +187,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%token <lex> SAMPLEREXTERNAL2DY2YEXT
%token <lex> IMAGE2D IIMAGE2D UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY
%token <lex> IMAGECUBE IIMAGECUBE UIMAGECUBE
%token <lex> ATOMICUINT
%token <lex> LAYOUT
%token <lex> YUVCSCSTANDARDEXT YUVCSCSTANDARDEXTCONSTANT
......@@ -1264,6 +1265,9 @@ type_specifier_nonarray
| UIMAGECUBE {
$$.initialize(EbtUImageCube, @1);
}
| ATOMICUINT {
$$.initialize(EbtAtomicCounter, @1);
}
| TYPE_NAME {
//
// 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] =
183, 183, 183, 183, 8, 183, 183, 9, 183, 183,
183, 183, 183, 183, 20, 102, 11, 156, 116, 89,
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,
90, 95, 183, 183, 163, 183, 104, 183, 183, 183,
......@@ -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, 183, 183, 183, 183, 183, 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,
183, 183, 67, 183, 183, 183, 183, 61, 183, 183,
......@@ -2107,8 +2107,11 @@ case 104:
YY_RULE_SETUP
{ return ES2_and_ES3_reserved_ES3_1_keyword(context, VOLATILE); }
YY_BREAK
/* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */
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 107:
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;
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
enum yytokentype
{
INVARIANT = 258,
HIGH_PRECISION = 259,
MEDIUM_PRECISION = 260,
LOW_PRECISION = 261,
PRECISION = 262,
ATTRIBUTE = 263,
CONST_QUAL = 264,
BOOL_TYPE = 265,
FLOAT_TYPE = 266,
INT_TYPE = 267,
UINT_TYPE = 268,
BREAK = 269,
CONTINUE = 270,
DO = 271,
ELSE = 272,
FOR = 273,
IF = 274,
DISCARD = 275,
RETURN = 276,
SWITCH = 277,
CASE = 278,
DEFAULT = 279,
BVEC2 = 280,
BVEC3 = 281,
BVEC4 = 282,
IVEC2 = 283,
IVEC3 = 284,
IVEC4 = 285,
VEC2 = 286,
VEC3 = 287,
VEC4 = 288,
UVEC2 = 289,
UVEC3 = 290,
UVEC4 = 291,
MATRIX2 = 292,
MATRIX3 = 293,
MATRIX4 = 294,
IN_QUAL = 295,
OUT_QUAL = 296,
INOUT_QUAL = 297,
UNIFORM = 298,
VARYING = 299,
MATRIX2x3 = 300,
MATRIX3x2 = 301,
MATRIX2x4 = 302,
MATRIX4x2 = 303,
MATRIX3x4 = 304,
MATRIX4x3 = 305,
CENTROID = 306,
FLAT = 307,
SMOOTH = 308,
READONLY = 309,
WRITEONLY = 310,
COHERENT = 311,
RESTRICT = 312,
VOLATILE = 313,
SHARED = 314,
STRUCT = 315,
VOID_TYPE = 316,
WHILE = 317,
SAMPLER2D = 318,
SAMPLERCUBE = 319,
SAMPLER_EXTERNAL_OES = 320,
SAMPLER2DRECT = 321,
SAMPLER2DARRAY = 322,
ISAMPLER2D = 323,
ISAMPLER3D = 324,
ISAMPLERCUBE = 325,
ISAMPLER2DARRAY = 326,
USAMPLER2D = 327,
USAMPLER3D = 328,
USAMPLERCUBE = 329,
USAMPLER2DARRAY = 330,
SAMPLER2DMS = 331,
ISAMPLER2DMS = 332,
USAMPLER2DMS = 333,
SAMPLER3D = 334,
SAMPLER3DRECT = 335,
SAMPLER2DSHADOW = 336,
SAMPLERCUBESHADOW = 337,
SAMPLER2DARRAYSHADOW = 338,
SAMPLEREXTERNAL2DY2YEXT = 339,
IMAGE2D = 340,
IIMAGE2D = 341,
UIMAGE2D = 342,
IMAGE3D = 343,
IIMAGE3D = 344,
UIMAGE3D = 345,
IMAGE2DARRAY = 346,
IIMAGE2DARRAY = 347,
UIMAGE2DARRAY = 348,
IMAGECUBE = 349,
IIMAGECUBE = 350,
UIMAGECUBE = 351,
LAYOUT = 352,
YUVCSCSTANDARDEXT = 353,
YUVCSCSTANDARDEXTCONSTANT = 354,
IDENTIFIER = 355,
TYPE_NAME = 356,
FLOATCONSTANT = 357,
INTCONSTANT = 358,
UINTCONSTANT = 359,
BOOLCONSTANT = 360,
FIELD_SELECTION = 361,
LEFT_OP = 362,
RIGHT_OP = 363,
INC_OP = 364,
DEC_OP = 365,
LE_OP = 366,
GE_OP = 367,
EQ_OP = 368,
NE_OP = 369,
AND_OP = 370,
OR_OP = 371,
XOR_OP = 372,
MUL_ASSIGN = 373,
DIV_ASSIGN = 374,
ADD_ASSIGN = 375,
MOD_ASSIGN = 376,
LEFT_ASSIGN = 377,
RIGHT_ASSIGN = 378,
AND_ASSIGN = 379,
XOR_ASSIGN = 380,
OR_ASSIGN = 381,
SUB_ASSIGN = 382,
LEFT_PAREN = 383,
RIGHT_PAREN = 384,
LEFT_BRACKET = 385,
RIGHT_BRACKET = 386,
LEFT_BRACE = 387,
RIGHT_BRACE = 388,
DOT = 389,
COMMA = 390,
COLON = 391,
EQUAL = 392,
SEMICOLON = 393,
BANG = 394,
DASH = 395,
TILDE = 396,
PLUS = 397,
STAR = 398,
SLASH = 399,
PERCENT = 400,
LEFT_ANGLE = 401,
RIGHT_ANGLE = 402,
VERTICAL_BAR = 403,
CARET = 404,
AMPERSAND = 405,
QUESTION = 406
};
enum yytokentype
{
INVARIANT = 258,
HIGH_PRECISION = 259,
MEDIUM_PRECISION = 260,
LOW_PRECISION = 261,
PRECISION = 262,
ATTRIBUTE = 263,
CONST_QUAL = 264,
BOOL_TYPE = 265,
FLOAT_TYPE = 266,
INT_TYPE = 267,
UINT_TYPE = 268,
BREAK = 269,
CONTINUE = 270,
DO = 271,
ELSE = 272,
FOR = 273,
IF = 274,
DISCARD = 275,
RETURN = 276,
SWITCH = 277,
CASE = 278,
DEFAULT = 279,
BVEC2 = 280,
BVEC3 = 281,
BVEC4 = 282,
IVEC2 = 283,
IVEC3 = 284,
IVEC4 = 285,
VEC2 = 286,
VEC3 = 287,
VEC4 = 288,
UVEC2 = 289,
UVEC3 = 290,
UVEC4 = 291,
MATRIX2 = 292,
MATRIX3 = 293,
MATRIX4 = 294,
IN_QUAL = 295,
OUT_QUAL = 296,
INOUT_QUAL = 297,
UNIFORM = 298,
VARYING = 299,
MATRIX2x3 = 300,
MATRIX3x2 = 301,
MATRIX2x4 = 302,
MATRIX4x2 = 303,
MATRIX3x4 = 304,
MATRIX4x3 = 305,
CENTROID = 306,
FLAT = 307,
SMOOTH = 308,
READONLY = 309,
WRITEONLY = 310,
COHERENT = 311,
RESTRICT = 312,
VOLATILE = 313,
SHARED = 314,
STRUCT = 315,
VOID_TYPE = 316,
WHILE = 317,
SAMPLER2D = 318,
SAMPLERCUBE = 319,
SAMPLER_EXTERNAL_OES = 320,
SAMPLER2DRECT = 321,
SAMPLER2DARRAY = 322,
ISAMPLER2D = 323,
ISAMPLER3D = 324,
ISAMPLERCUBE = 325,
ISAMPLER2DARRAY = 326,
USAMPLER2D = 327,
USAMPLER3D = 328,
USAMPLERCUBE = 329,
USAMPLER2DARRAY = 330,
SAMPLER2DMS = 331,
ISAMPLER2DMS = 332,
USAMPLER2DMS = 333,
SAMPLER3D = 334,
SAMPLER3DRECT = 335,
SAMPLER2DSHADOW = 336,
SAMPLERCUBESHADOW = 337,
SAMPLER2DARRAYSHADOW = 338,
SAMPLEREXTERNAL2DY2YEXT = 339,
IMAGE2D = 340,
IIMAGE2D = 341,
UIMAGE2D = 342,
IMAGE3D = 343,
IIMAGE3D = 344,
UIMAGE3D = 345,
IMAGE2DARRAY = 346,
IIMAGE2DARRAY = 347,
UIMAGE2DARRAY = 348,
IMAGECUBE = 349,
IIMAGECUBE = 350,
UIMAGECUBE = 351,
ATOMICUINT = 352,
LAYOUT = 353,
YUVCSCSTANDARDEXT = 354,
YUVCSCSTANDARDEXTCONSTANT = 355,
IDENTIFIER = 356,
TYPE_NAME = 357,
FLOATCONSTANT = 358,
INTCONSTANT = 359,
UINTCONSTANT = 360,
BOOLCONSTANT = 361,
FIELD_SELECTION = 362,
LEFT_OP = 363,
RIGHT_OP = 364,
INC_OP = 365,
DEC_OP = 366,
LE_OP = 367,
GE_OP = 368,
EQ_OP = 369,
NE_OP = 370,
AND_OP = 371,
OR_OP = 372,
XOR_OP = 373,
MUL_ASSIGN = 374,
DIV_ASSIGN = 375,
ADD_ASSIGN = 376,
MOD_ASSIGN = 377,
LEFT_ASSIGN = 378,
RIGHT_ASSIGN = 379,
AND_ASSIGN = 380,
XOR_ASSIGN = 381,
OR_ASSIGN = 382,
SUB_ASSIGN = 383,
LEFT_PAREN = 384,
RIGHT_PAREN = 385,
LEFT_BRACKET = 386,
RIGHT_BRACKET = 387,
LEFT_BRACE = 388,
RIGHT_BRACE = 389,
DOT = 390,
COMMA = 391,
COLON = 392,
EQUAL = 393,
SEMICOLON = 394,
BANG = 395,
DASH = 396,
TILDE = 397,
PLUS = 398,
STAR = 399,
SLASH = 400,
PERCENT = 401,
LEFT_ANGLE = 402,
RIGHT_ANGLE = 403,
VERTICAL_BAR = 404,
CARET = 405,
AMPERSAND = 406,
QUESTION = 407
};
#endif
/* Value type. */
......
......@@ -392,6 +392,8 @@ GLenum GLVariableType(const TType &type)
return GL_INT_IMAGE_CUBE;
case EbtUImageCube:
return GL_UNSIGNED_INT_IMAGE_CUBE;
case EbtAtomicCounter:
return GL_UNSIGNED_INT_ATOMIC_COUNTER;
default:
UNREACHABLE();
}
......
......@@ -48,6 +48,7 @@
'<(angle_path)/src/tests/angle_unittests_utils.h',
'<(angle_path)/src/tests/compiler_tests/API_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/ConstantFolding_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