@@ -3342,10 +3342,14 @@ void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &lo
33423342 const ImmutableString &token,
33433343 TType *type)
33443344{
3345- if (type->getQualifier () == EvqPerVertexIn)
3345+ if (type->getQualifier () == EvqPerVertexIn && mShaderType == GL_GEOMETRY_SHADER )
33463346 {
33473347 // This is a redeclaration of gl_in, which may be unsized.
3348- ASSERT (type->isArray ());
3348+ if (!type->isArray ())
3349+ {
3350+ error (location, " gl_in must be an array" , " gl_in" );
3351+ type->makeArray (0 );
3352+ }
33493353
33503354 // If the size is already determined, set the size / verify it:
33513355 if (mGeometryShaderInputPrimitiveType != EptUndefined)
@@ -3410,6 +3414,53 @@ void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSource
34103414 TType *type)
34113415{
34123416 TQualifier qualifier = type->getQualifier ();
3417+
3418+ if (qualifier == EvqPerVertexIn && type->isArray () &&
3419+ (mShaderType == GL_TESS_CONTROL_SHADER || mShaderType == GL_TESS_EVALUATION_SHADER ))
3420+ {
3421+ // gl_in in both tessellation stages should be sized as gl_MaxPatchVertices
3422+ if (type->getOutermostArraySize () == 0 )
3423+ {
3424+ ASSERT (mMaxPatchVertices > 0 );
3425+ type->sizeOutermostUnsizedArray (mMaxPatchVertices );
3426+ }
3427+ else if (type->getOutermostArraySize () != static_cast <unsigned int >(mMaxPatchVertices ))
3428+ {
3429+ error (location,
3430+ " If a size is specified for a tessellation control or evaluation gl_in "
3431+ " variable, it must match the maximum patch size (gl_MaxPatchVertices)." ,
3432+ token);
3433+ }
3434+ return ;
3435+ }
3436+ if (qualifier == EvqPerVertexOut && type->isArray () && mShaderType == GL_TESS_CONTROL_SHADER )
3437+ {
3438+ if (type->getOutermostArraySize () == 0 )
3439+ {
3440+ if (mTessControlShaderOutputVertices == 0 )
3441+ {
3442+ error (location,
3443+ " Missing a valid vertices declaration before declaring an unsized "
3444+ " gl_out array" ,
3445+ " gl_out" );
3446+ }
3447+ else
3448+ {
3449+ type->sizeOutermostUnsizedArray (mTessControlShaderOutputVertices );
3450+ }
3451+ }
3452+ else if (type->getOutermostArraySize () !=
3453+ static_cast <unsigned int >(mTessControlShaderOutputVertices ) &&
3454+ mTessControlShaderOutputVertices != 0 )
3455+ {
3456+ error (location,
3457+ " If a size is specified for a tessellation control gl_out "
3458+ " variable, it must match the the number of vertices in the output patch." ,
3459+ token);
3460+ }
3461+ return ;
3462+ }
3463+
34133464 if (!IsTessellationControlShaderOutput (mShaderType , qualifier) &&
34143465 !IsTessellationControlShaderInput (mShaderType , qualifier) &&
34153466 !IsTessellationEvaluationShaderInput (mShaderType , qualifier))
@@ -3577,15 +3628,15 @@ TIntermDeclaration *TParseContext::parseSingleDeclaration(
35773628 checkAtomicCounterOffsetIsValid (false , identifierOrTypeLocation, type);
35783629 }
35793630
3631+ adjustRedeclaredBuiltInType (identifierOrTypeLocation, identifier, type);
3632+
35803633 TVariable *variable = nullptr ;
35813634 if (declareVariable (identifierOrTypeLocation, identifier, type, &variable))
35823635 {
35833636 symbol = new TIntermSymbol (variable);
35843637 }
35853638 }
35863639
3587- adjustRedeclaredBuiltInType (identifierOrTypeLocation, identifier, type);
3588-
35893640 TIntermDeclaration *declaration = new TIntermDeclaration ();
35903641 declaration->setLine (identifierOrTypeLocation);
35913642 if (symbol)
@@ -5017,10 +5068,13 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
50175068
50185069 // Both inputs and outputs of tessellation control shaders must be arrays.
50195070 // For tessellation evaluation shaders, only inputs must necessarily be arrays.
5071+ // Inputs of geometry shaders must be arrays too.
50205072 const bool isTCS = mShaderType == GL_TESS_CONTROL_SHADER ;
50215073 const bool isTESIn =
50225074 mShaderType == GL_TESS_EVALUATION_SHADER && IsShaderIn (typeQualifier.qualifier );
5023- if (arraySizes == nullptr && (isTCS || isTESIn))
5075+ const bool isGSIn =
5076+ mShaderType == GL_GEOMETRY_SHADER && IsShaderIn (typeQualifier.qualifier );
5077+ if (arraySizes == nullptr && (isTCS || isTESIn || isGSIn))
50245078 {
50255079 error (typeQualifier.line , " type must be an array" , blockName);
50265080 }
@@ -5303,9 +5357,20 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
53035357 SymbolType instanceSymbolType = SymbolType::UserDefined;
53045358 if (isGLPerVertex)
53055359 {
5306- instanceSymbolType = SymbolType::BuiltIn;
5307- typeQualifier.qualifier =
5308- IsVaryingOut (typeQualifier.qualifier ) ? EvqPerVertexOut : EvqPerVertexIn;
5360+ // Mark gl_PerVertex as built-in if usage is not erroneous. If it is, there will be failure
5361+ // elsewhere that validates gl_PerVertex cannot be used when not a built-in.
5362+ if (IsVaryingOut (typeQualifier.qualifier ) && mShaderType != GL_FRAGMENT_SHADER &&
5363+ mShaderType != GL_COMPUTE_SHADER )
5364+ {
5365+ instanceSymbolType = SymbolType::BuiltIn;
5366+ typeQualifier.qualifier = EvqPerVertexOut;
5367+ }
5368+ else if (IsVaryingIn (typeQualifier.qualifier ) && mShaderType != GL_VERTEX_SHADER &&
5369+ mShaderType != GL_FRAGMENT_SHADER && mShaderType != GL_COMPUTE_SHADER )
5370+ {
5371+ instanceSymbolType = SymbolType::BuiltIn;
5372+ typeQualifier.qualifier = EvqPerVertexIn;
5373+ }
53095374 }
53105375 TInterfaceBlock *interfaceBlock = new TInterfaceBlock (&symbolTable, blockName, fieldList,
53115376 blockLayoutQualifier, instanceSymbolType);
@@ -5319,11 +5384,49 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
53195384 if (arraySizes)
53205385 {
53215386 interfaceBlockType->makeArrays (*arraySizes);
5322- checkGeometryShaderInputAndSetArraySize (instanceLine, instanceName, interfaceBlockType);
5323- checkTessellationShaderUnsizedArraysAndSetSize (instanceLine, instanceName,
5324- interfaceBlockType);
53255387 checkDeclarationIsValidArraySize (instanceLine, instanceName, interfaceBlockType);
53265388 }
5389+ checkGeometryShaderInputAndSetArraySize (instanceLine, instanceName, interfaceBlockType);
5390+ checkTessellationShaderUnsizedArraysAndSetSize (instanceLine, instanceName, interfaceBlockType);
5391+
5392+ // If this is gl_PerVertex, make sure the instance name is as expected.
5393+ if (interfaceBlockType->getQualifier () == EvqPerVertexOut)
5394+ {
5395+ switch (mShaderType )
5396+ {
5397+ case GL_VERTEX_SHADER :
5398+ case GL_TESS_EVALUATION_SHADER_EXT :
5399+ case GL_GEOMETRY_SHADER_EXT :
5400+ if (!instanceName.empty ())
5401+ {
5402+ error (instanceLine,
5403+ " out gl_PerVertex instance name must be empty in this shader" ,
5404+ instanceName);
5405+ instanceSymbolType = SymbolType::UserDefined;
5406+ }
5407+ break ;
5408+ case GL_TESS_CONTROL_SHADER_EXT :
5409+ if (instanceName != " gl_out" )
5410+ {
5411+ error (instanceLine,
5412+ " out gl_PerVertex instance name must be gl_out in this shader" ,
5413+ instanceName);
5414+ instanceSymbolType = SymbolType::UserDefined;
5415+ }
5416+ break ;
5417+ default :
5418+ UNREACHABLE ();
5419+ break ;
5420+ }
5421+ }
5422+ else if (interfaceBlockType->getQualifier () == EvqPerVertexIn)
5423+ {
5424+ if (instanceName != " gl_in" )
5425+ {
5426+ error (instanceLine, " in gl_PerVertex instance name must be gl_in" , instanceName);
5427+ instanceSymbolType = SymbolType::UserDefined;
5428+ }
5429+ }
53275430
53285431 // The instance variable gets created to refer to the interface block type from the AST
53295432 // regardless of if there's an instance name. It's created as an empty symbol if there is no
@@ -5351,7 +5454,8 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
53515454 {
53525455 // These builtins can be redefined only when used within a redefined gl_PerVertex
53535456 // block
5354- if (interfaceBlock->name () != " gl_PerVertex" )
5457+ if (interfaceBlockType->getQualifier () != EvqPerVertexIn &&
5458+ interfaceBlockType->getQualifier () != EvqPerVertexOut)
53555459 {
53565460 error (field->line (), " redefinition in an invalid interface block" ,
53575461 field->name ());
@@ -5369,12 +5473,17 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
53695473 }
53705474 else
53715475 {
5372- // gl_in is allowed to be redeclared
5373- if (interfaceBlockType->getQualifier () != EvqPerVertexIn)
5476+ // gl_in and gl_out are allowed to be redeclared
5477+ bool isGlIn =
5478+ interfaceBlockType->getQualifier () == EvqPerVertexIn && instanceName == " gl_in" ;
5479+ bool isGlOut = interfaceBlockType->getQualifier () == EvqPerVertexOut &&
5480+ instanceName == " gl_out" && mShaderType == GL_TESS_CONTROL_SHADER_EXT ;
5481+
5482+ if (!isGlIn && !isGlOut)
53745483 {
53755484 checkIsNotReserved (instanceLine, instanceName);
53765485 }
5377- else
5486+ else if (isGlIn)
53785487 {
53795488 symbolTable.onGlInVariableRedeclaration (instanceVariable);
53805489 }
0 commit comments