Commit b8b0122f by Martin Radev Committed by Commit Bot

Add compiler support for shared memory

The patch adds handling of the 'shared' qualifier in the shader compiler. BUG=angleproject:1442 TEST=angle_unittests Change-Id: Iaa288026af0faf2a30e40495faa6ea1f5ff02323 Reviewed-on: https://chromium-review.googlesource.com/413200 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent c31b7411
......@@ -504,6 +504,7 @@ enum TQualifier
EvqCentroidIn, // Implies smooth
// GLSL ES 3.1 compute shader special variables
EvqShared,
EvqComputeIn,
EvqNumWorkGroups,
EvqWorkGroupSize,
......@@ -707,6 +708,7 @@ inline const char *getQualifierString(TQualifier q)
case EvqCentroid: return "centroid";
case EvqFlat: return "flat";
case EvqSmooth: return "smooth";
case EvqShared: return "shared";
case EvqComputeIn: return "in";
case EvqNumWorkGroups: return "NumWorkGroups";
case EvqWorkGroupSize: return "WorkGroupSize";
......
......@@ -1099,6 +1099,21 @@ bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &
return true;
}
void TParseContext::emptyDeclarationErrorCheck(const TPublicType &publicType,
const TSourceLoc &location)
{
if (publicType.isUnsizedArray())
{
// ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
// error. It is assumed that this applies to empty declarations as well.
error(location, "empty array declaration needs to specify a size", "");
}
if (publicType.qualifier == EvqShared && !publicType.layoutQualifier.isEmpty())
{
error(location, "Shared memory declarations cannot have layout specified", "layout");
}
}
// These checks are common for all declarations starting a declarator list, and declarators that
// follow an empty declaration.
void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
......@@ -1900,13 +1915,7 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration(
if (emptyDeclaration)
{
if (publicType.isUnsizedArray())
{
// ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
// error. It is assumed that this applies to empty declarations as well.
error(identifierOrTypeLocation, "empty array declaration needs to specify a size",
identifier.c_str());
}
emptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
}
else
{
......
......@@ -145,6 +145,7 @@ class TParseContext : angle::NonCopyable
bool checkCanUseExtension(const TSourceLoc &line, const TString &extension);
void singleDeclarationErrorCheck(const TPublicType &publicType,
const TSourceLoc &identifierLocation);
void emptyDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &location);
void checkLayoutQualifierSupported(const TSourceLoc &location,
const TString &layoutQualifierName,
int versionRequired);
......
......@@ -78,6 +78,7 @@ static int ES2_keyword_ES3_reserved(TParseContext *context, int token);
static int ES2_ident_ES3_keyword(TParseContext *context, int token);
static int ES2_ident_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
static int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token);
static int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token);
static int uint_constant(TParseContext *context);
static int int_constant(TParseContext *context);
static int float_constant(yyscan_t yyscanner);
......@@ -131,6 +132,7 @@ O [0-7]
"in" { return IN_QUAL; }
"out" { return OUT_QUAL; }
"inout" { return INOUT_QUAL; }
"shared" { return ES2_and_ES3_ident_ES3_1_keyword(context, SHARED); }
"float" { return FLOAT_TYPE; }
"int" { return INT_TYPE; }
......@@ -516,6 +518,21 @@ int ES2_and_ES3_reserved_ES3_1_keyword(TParseContext *context, int token)
return token;
}
int ES2_and_ES3_ident_ES3_1_keyword(TParseContext *context, int token)
{
struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
yyscan_t yyscanner = (yyscan_t) context->getScanner();
// not a reserved word in GLSL ES 1.00 and GLSL ES 3.00, so could be used as an identifier/type name
if (context->getShaderVersion() < 310)
{
yylval->lex.string = NewPoolTString(yytext);
return check_type(yyscanner);
}
return token;
}
int uint_constant(TParseContext *context)
{
struct yyguts_t* yyg = (struct yyguts_t*) context->getScanner();
......
......@@ -169,7 +169,7 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, cons
%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
%token <lex> MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3
%token <lex> CENTROID FLAT SMOOTH
%token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE
%token <lex> READONLY WRITEONLY COHERENT RESTRICT VOLATILE SHARED
%token <lex> STRUCT VOID_TYPE WHILE
%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY
%token <lex> ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY
......@@ -959,6 +959,11 @@ storage_qualifier
| VOLATILE {
$$ = new TMemoryQualifierWrapper(EvqVolatile, @1);
}
| SHARED {
context->checkIsAtGlobalLevel(@1, "shared");
COMPUTE_ONLY("shared", @1);
$$ = new TStorageQualifierWrapper(EvqShared, @1);
}
;
type_specifier
......@@ -1006,6 +1011,9 @@ layout_qualifier_id
| IDENTIFIER EQUAL UINTCONSTANT {
$$ = context->parseLayoutQualifier(*$1.string, @1, $3.i, @3);
}
| SHARED {
$$ = context->parseLayoutQualifier("shared", @1);
}
;
type_specifier_no_prec
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -105,92 +105,93 @@ enum yytokentype
COHERENT = 311,
RESTRICT = 312,
VOLATILE = 313,
STRUCT = 314,
VOID_TYPE = 315,
WHILE = 316,
SAMPLER2D = 317,
SAMPLERCUBE = 318,
SAMPLER_EXTERNAL_OES = 319,
SAMPLER2DRECT = 320,
SAMPLER2DARRAY = 321,
ISAMPLER2D = 322,
ISAMPLER3D = 323,
ISAMPLERCUBE = 324,
ISAMPLER2DARRAY = 325,
USAMPLER2D = 326,
USAMPLER3D = 327,
USAMPLERCUBE = 328,
USAMPLER2DARRAY = 329,
SAMPLER3D = 330,
SAMPLER3DRECT = 331,
SAMPLER2DSHADOW = 332,
SAMPLERCUBESHADOW = 333,
SAMPLER2DARRAYSHADOW = 334,
IMAGE2D = 335,
IIMAGE2D = 336,
UIMAGE2D = 337,
IMAGE3D = 338,
IIMAGE3D = 339,
UIMAGE3D = 340,
IMAGE2DARRAY = 341,
IIMAGE2DARRAY = 342,
UIMAGE2DARRAY = 343,
IMAGECUBE = 344,
IIMAGECUBE = 345,
UIMAGECUBE = 346,
LAYOUT = 347,
IDENTIFIER = 348,
TYPE_NAME = 349,
FLOATCONSTANT = 350,
INTCONSTANT = 351,
UINTCONSTANT = 352,
BOOLCONSTANT = 353,
FIELD_SELECTION = 354,
LEFT_OP = 355,
RIGHT_OP = 356,
INC_OP = 357,
DEC_OP = 358,
LE_OP = 359,
GE_OP = 360,
EQ_OP = 361,
NE_OP = 362,
AND_OP = 363,
OR_OP = 364,
XOR_OP = 365,
MUL_ASSIGN = 366,
DIV_ASSIGN = 367,
ADD_ASSIGN = 368,
MOD_ASSIGN = 369,
LEFT_ASSIGN = 370,
RIGHT_ASSIGN = 371,
AND_ASSIGN = 372,
XOR_ASSIGN = 373,
OR_ASSIGN = 374,
SUB_ASSIGN = 375,
LEFT_PAREN = 376,
RIGHT_PAREN = 377,
LEFT_BRACKET = 378,
RIGHT_BRACKET = 379,
LEFT_BRACE = 380,
RIGHT_BRACE = 381,
DOT = 382,
COMMA = 383,
COLON = 384,
EQUAL = 385,
SEMICOLON = 386,
BANG = 387,
DASH = 388,
TILDE = 389,
PLUS = 390,
STAR = 391,
SLASH = 392,
PERCENT = 393,
LEFT_ANGLE = 394,
RIGHT_ANGLE = 395,
VERTICAL_BAR = 396,
CARET = 397,
AMPERSAND = 398,
QUESTION = 399
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,
SAMPLER3D = 331,
SAMPLER3DRECT = 332,
SAMPLER2DSHADOW = 333,
SAMPLERCUBESHADOW = 334,
SAMPLER2DARRAYSHADOW = 335,
IMAGE2D = 336,
IIMAGE2D = 337,
UIMAGE2D = 338,
IMAGE3D = 339,
IIMAGE3D = 340,
UIMAGE3D = 341,
IMAGE2DARRAY = 342,
IIMAGE2DARRAY = 343,
UIMAGE2DARRAY = 344,
IMAGECUBE = 345,
IIMAGECUBE = 346,
UIMAGECUBE = 347,
LAYOUT = 348,
IDENTIFIER = 349,
TYPE_NAME = 350,
FLOATCONSTANT = 351,
INTCONSTANT = 352,
UINTCONSTANT = 353,
BOOLCONSTANT = 354,
FIELD_SELECTION = 355,
LEFT_OP = 356,
RIGHT_OP = 357,
INC_OP = 358,
DEC_OP = 359,
LE_OP = 360,
GE_OP = 361,
EQ_OP = 362,
NE_OP = 363,
AND_OP = 364,
OR_OP = 365,
XOR_OP = 366,
MUL_ASSIGN = 367,
DIV_ASSIGN = 368,
ADD_ASSIGN = 369,
MOD_ASSIGN = 370,
LEFT_ASSIGN = 371,
RIGHT_ASSIGN = 372,
AND_ASSIGN = 373,
XOR_ASSIGN = 374,
OR_ASSIGN = 375,
SUB_ASSIGN = 376,
LEFT_PAREN = 377,
RIGHT_PAREN = 378,
LEFT_BRACKET = 379,
RIGHT_BRACKET = 380,
LEFT_BRACE = 381,
RIGHT_BRACE = 382,
DOT = 383,
COMMA = 384,
COLON = 385,
EQUAL = 386,
SEMICOLON = 387,
BANG = 388,
DASH = 389,
TILDE = 390,
PLUS = 391,
STAR = 392,
SLASH = 393,
PERCENT = 394,
LEFT_ANGLE = 395,
RIGHT_ANGLE = 396,
VERTICAL_BAR = 397,
CARET = 398,
AMPERSAND = 399,
QUESTION = 400
};
#endif
......
......@@ -3130,3 +3130,202 @@ TEST_F(MalformedComputeShaderTest, WorkGroupSizeAsArraySize)
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Shared memory variables cannot be used inside a vertex shader.
// GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
TEST_F(MalformedVertexShaderGLES31Test, VertexShaderSharedMemory)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"in vec4 i;\n"
"shared float myShared[10];\n"
"void main() {\n"
" gl_Position = i;\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Shared memory variables cannot be used inside a fragment shader.
// GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
TEST_F(MalformedFragmentShaderGLES31Test, FragmentShaderSharedMemory)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"shared float myShared[10];\n"
"out vec4 color;\n"
"void main() {\n"
" color = vec4(1.0);\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Shared memory cannot be combined with any other storage qualifier.
TEST_F(MalformedComputeShaderTest, UniformSharedMemory)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"uniform shared float myShared[100];\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Correct usage of shared memory variables.
TEST_F(MalformedComputeShaderTest, CorrectUsageOfSharedMemory)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"shared float myShared[100];\n"
"void main() {\n"
" myShared[gl_LocalInvocationID.x] = 1.0;\n"
"}\n";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success " << mInfoLog;
}
}
// Shared memory variables cannot be initialized.
// GLSL ES 3.10 Revision 4, 4.3.8 Shared Variables
TEST_F(MalformedComputeShaderTest, SharedVariableInitialization)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"shared int myShared = 0;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Local variables cannot be qualified as shared.
// GLSL ES 3.10 Revision 4, 4.3 Storage Qualifiers
TEST_F(MalformedComputeShaderTest, SharedMemoryInFunctionBody)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"void func() {\n"
" shared int myShared;\n"
"}\n"
"void main() {\n"
" func();\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Struct members cannot be qualified as shared.
TEST_F(MalformedComputeShaderTest, SharedMemoryInStruct)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"struct MyStruct {\n"
" shared int myShared;\n"
"};\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// Interface block members cannot be qualified as shared.
TEST_F(MalformedComputeShaderTest, SharedMemoryInInterfaceBlock)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"uniform Myblock {\n"
" shared int myShared;\n"
"};\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// The shared qualifier cannot be used with any other qualifier.
TEST_F(MalformedComputeShaderTest, SharedWithInvariant)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"invariant shared int myShared;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// The shared qualifier cannot be used with any other qualifier.
TEST_F(MalformedComputeShaderTest, SharedWithMemoryQualifier)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"readonly shared int myShared;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
// The shared qualifier cannot be used with any other qualifier.
TEST_F(MalformedComputeShaderTest, SharedGlobalLayoutDeclaration)
{
const std::string &shaderString =
"#version 310 es\n"
"precision mediump float;\n"
"layout(local_size_x = 5) in;\n"
"layout(row_major) shared mat4;\n"
"void main() {\n"
"}\n";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
}
}
\ No newline at end of file
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