Redesign layout qualifier parsing to be simpler and more storage efficient.
TRAC #23268
Signed-off-by: Geoff Lang
Signed-off-by: Nicolas Capens
Authored-by: Jamie Madill
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index f79bbb8..ace297c 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -965,6 +965,45 @@
return false;
}
+bool TParseContext::singleDeclarationErrorCheck(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier)
+{
+ if (structQualifierErrorCheck(identifierLocation, publicType))
+ return true;
+
+ // check for layout qualifier issues
+ const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
+
+ if (layoutQualifier.matrixPacking != EmpUnspecified)
+ {
+ error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking), "only valid for interface blocks");
+ return false;
+ }
+
+ if (layoutQualifier.blockStorage != EbsUnspecified)
+ {
+ error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage), "only valid for interface blocks");
+ return false;
+ }
+
+ if (publicType.qualifier != EvqVertexInput && publicType.qualifier != EvqFragmentOutput && layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
+ {
+ return false;
+ }
+
+ return false;
+}
+
+bool TParseContext::layoutLocationErrorCheck(TSourceLoc location, const TLayoutQualifier &layoutQualifier)
+{
+ if (layoutQualifier.location != -1)
+ {
+ error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");
+ return true;
+ }
+
+ return false;
+}
+
bool TParseContext::supportsExtension(const char* extension)
{
const TExtensionBehavior& extbehavior = extensionBehavior();
@@ -1130,10 +1169,11 @@
return allConstant;
}
-TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, const TPublicType& typeSpecifier)
+TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQualifier layoutQualifier, const TPublicType& typeSpecifier)
{
TPublicType returnType = typeSpecifier;
returnType.qualifier = qualifier;
+ returnType.layoutQualifier = layoutQualifier;
if (typeSpecifier.array)
{
@@ -1250,7 +1290,7 @@
TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc initLocation, TIntermTyped *initializer)
{
- if (structQualifierErrorCheck(identifierLocation, publicType))
+ if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier))
recover();
TIntermNode* intermNode;
@@ -1719,6 +1759,12 @@
recover();
}
+ const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
+ if (layoutLocationErrorCheck(typeQualifier.line, layoutQualifier))
+ {
+ recover();
+ }
+
TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName);
if (!symbolTable.declare(*blockNameSymbol)) {
error(nameLine, "redefinition", blockName.c_str(), "interface block name");
@@ -1745,11 +1791,18 @@
recover();
break;
}
+
+ // check layout qualifiers
+ if (layoutLocationErrorCheck(memberTypeLine.line, memberType->getLayoutQualifier()))
+ {
+ recover();
+ }
}
TType* interfaceBlock = new TType(typeList, blockName);
interfaceBlock->setBasicType(EbtInterfaceBlock);
interfaceBlock->setQualifier(typeQualifier.qualifier);
+ interfaceBlock->setLayoutQualifier(layoutQualifier);
TString symbolName = "";
int symbolId = 0;
@@ -2182,32 +2235,33 @@
return indexedExpression;
}
-TLayoutQualifierId TParseContext::addLayoutQualifierId(const TString &qualifierType, TSourceLoc qualifierTypeLine)
+TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, TSourceLoc qualifierTypeLine)
{
- TLayoutQualifierId qualifierId;
+ TLayoutQualifier qualifier;
- qualifierId.type = ElqError;
- qualifierId.location = -1;
+ qualifier.location = -1;
+ qualifier.matrixPacking = EmpUnspecified;
+ qualifier.blockStorage = EbsUnspecified;
if (qualifierType == "shared")
{
- qualifierId.type = ElqShared;
+ qualifier.blockStorage = EbsShared;
}
else if (qualifierType == "packed")
{
- qualifierId.type = ElqPacked;
+ qualifier.blockStorage = EbsPacked;
}
else if (qualifierType == "std140")
{
- qualifierId.type = ElqStd140;
+ qualifier.blockStorage = EbsStd140;
}
else if (qualifierType == "row_major")
{
- qualifierId.type = ElqRowMajor;
+ qualifier.matrixPacking = EmpRowMajor;
}
else if (qualifierType == "column_major")
{
- qualifierId.type = ElqColumnMajor;
+ qualifier.matrixPacking = EmpColumnMajor;
}
else if (qualifierType == "location")
{
@@ -2220,15 +2274,16 @@
recover();
}
- return qualifierId;
+ return qualifier;
}
-TLayoutQualifierId TParseContext::addLayoutQualifierId(const TString &qualifierType, TSourceLoc qualifierTypeLine, const TString &intValueString, int intValue, TSourceLoc intValueLine)
+TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, TSourceLoc qualifierTypeLine, const TString &intValueString, int intValue, TSourceLoc intValueLine)
{
- TLayoutQualifierId qualifierId;
+ TLayoutQualifier qualifier;
- qualifierId.type = ElqError;
- qualifierId.location = -1;
+ qualifier.location = -1;
+ qualifier.matrixPacking = EmpUnspecified;
+ qualifier.blockStorage = EbsUnspecified;
if (qualifierType != "location")
{
@@ -2244,23 +2299,33 @@
}
else
{
- qualifierId.location = intValue;
+ qualifier.location = intValue;
}
// TODO: must check that location is < MAX_DRAW_BUFFERS
}
- return qualifierId;
+ return qualifier;
}
-TLayoutQualifier* TParseContext::makeLayoutQualifierFromId(TLayoutQualifierId layoutQualifierId)
+TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
{
- return NULL;
-}
+ TLayoutQualifier joinedQualifier = leftQualifier;
-TLayoutQualifier* TParseContext::extendLayoutQualifier(TLayoutQualifier *layoutQualifier, TLayoutQualifierId layoutQualifierId)
-{
- return NULL;
+ if (rightQualifier.location != -1)
+ {
+ joinedQualifier.location = rightQualifier.location;
+ }
+ if (rightQualifier.matrixPacking != EmpUnspecified)
+ {
+ joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
+ }
+ if (rightQualifier.blockStorage != EbsUnspecified)
+ {
+ joinedQualifier.blockStorage = rightQualifier.blockStorage;
+ }
+
+ return joinedQualifier;
}
TTypeList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TTypeList *typeList)
@@ -2279,6 +2344,7 @@
type->setSecondarySize(typeSpecifier.secondarySize);
type->setPrecision(typeSpecifier.precision);
type->setQualifier(typeSpecifier.qualifier);
+ type->setLayoutQualifier(typeSpecifier.layoutQualifier);
// don't allow arrays of arrays
if (type->isArray()) {