Add support for parsing interface blocks to the shader translator.
TRAC #22930
Signed-off-by: Nicolas Capens
Signed-off-by: Geoff Lang
Author: Jamie Madill
git-svn-id: https://angleproject.googlecode.com/svn/branches/es3proto@2341 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index e002cdf..6ae90c4 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -656,7 +656,7 @@
if (IsSampler(type.getBasicType()))
return true;
- if (type.getBasicType() == EbtStruct) {
+ if (type.getBasicType() == EbtStruct || type.getBasicType() == EbtInterfaceBlock) {
TTypeList& structure = *type.getStruct();
for (unsigned int i = 0; i < structure.size(); ++i) {
if (containsSampler(*structure[i].type))
@@ -1451,6 +1451,102 @@
return typedNode;
}
+//
+// Interface/uniform blocks
+//
+TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, TSourceLoc nameLine, const TString& blockName, TTypeList* typeList,
+ const TString& instanceName, TSourceLoc instanceLine, TIntermTyped* arrayIndex, TSourceLoc arrayIndexLine)
+{
+ if (reservedErrorCheck(nameLine, blockName))
+ recover();
+
+ if (typeQualifier.qualifier != EvqUniform)
+ {
+ error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform");
+ recover();
+ }
+
+ TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName);
+ if (!symbolTable.declare(*blockNameSymbol)) {
+ error(nameLine, "redefinition", blockName.c_str(), "interface block name");
+ recover();
+ }
+
+ // check for sampler types
+ for (size_t memberIndex = 0; memberIndex < typeList->size(); ++memberIndex) {
+ const TTypeLine& memberTypeLine = (*typeList)[memberIndex];
+ TType* memberType = memberTypeLine.type;
+ if (IsSampler(memberType->getBasicType())) {
+ error(memberTypeLine.line, "unsupported type", memberType->getBasicString(), "sampler types are not allowed in interface blocks");
+ recover();
+ }
+
+ const TQualifier qualifier = memberTypeLine.type->getQualifier();
+ switch (qualifier)
+ {
+ case EvqGlobal:
+ case EvqUniform:
+ break;
+ default:
+ error(memberTypeLine.line, "invalid qualifier on interface block member", getQualifierString(qualifier));
+ recover();
+ break;
+ }
+ }
+
+ TType* interfaceBlock = new TType(typeList, blockName);
+ interfaceBlock->setBasicType(EbtInterfaceBlock);
+ interfaceBlock->setQualifier(typeQualifier.qualifier);
+
+ TString symbolName = "";
+ int symbolId = 0;
+
+ if (instanceName == "")
+ {
+ // define symbols for the members of the interface block
+ for (size_t memberIndex = 0; memberIndex < typeList->size(); ++memberIndex) {
+ const TTypeLine& memberTypeLine = (*typeList)[memberIndex];
+ TType* memberType = memberTypeLine.type;
+ memberType->setInterfaceBlockType(interfaceBlock);
+ TVariable* memberVariable = new TVariable(&memberType->getFieldName(), *memberType);
+ memberVariable->setQualifier(typeQualifier.qualifier);
+ if (!symbolTable.declare(*memberVariable)) {
+ error(memberTypeLine.line, "redefinition", memberType->getFieldName().c_str(), "interface block member name");
+ recover();
+ }
+ }
+ }
+ else
+ {
+ interfaceBlock->setInstanceName(instanceName);
+
+ // add array index
+ if (arrayIndex != NULL)
+ {
+ int size;
+ if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, size))
+ recover();
+ interfaceBlock->setArraySize(size);
+ }
+
+ // add a symbol for this interface block
+ TVariable* instanceTypeDef = new TVariable(&instanceName, *interfaceBlock, false);
+ instanceTypeDef->setQualifier(typeQualifier.qualifier);
+ if (!symbolTable.declare(*instanceTypeDef)) {
+ error(instanceLine, "redefinition", instanceName.c_str(), "interface block instance name");
+ recover();
+ }
+
+ symbolId = instanceTypeDef->getUniqueId();
+ symbolName = instanceTypeDef->getName();
+ }
+
+ exitStructDeclaration();
+ TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, *interfaceBlock, typeQualifier.line), nameLine);
+ aggregate->setOp(EOpDeclaration);
+ return aggregate;
+}
+
bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
{
++structNestingLevel;
@@ -1768,9 +1864,53 @@
}
}
}
+ else if (baseExpression->getBasicType() == EbtInterfaceBlock)
+ {
+ bool fieldFound = false;
+ const TTypeList* fields = baseExpression->getType().getStruct();
+ if (fields == 0)
+ {
+ error(dotLocation, "interface block has no fields", "Internal Error");
+ recover();
+ indexedExpression = baseExpression;
+ }
+ else
+ {
+ unsigned int i;
+ for (i = 0; i < fields->size(); ++i)
+ {
+ if ((*fields)[i].type->getFieldName() == fieldString)
+ {
+ fieldFound = true;
+ break;
+ }
+ }
+ if (fieldFound)
+ {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(i);
+ TIntermTyped* index = intermediate.addConstantUnion(unionArray, *(*fields)[i].type, fieldLocation);
+ indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, dotLocation);
+ indexedExpression->setType(*(*fields)[i].type);
+ }
+ else
+ {
+ error(dotLocation, " no such field in interface block", fieldString.c_str());
+ recover();
+ indexedExpression = baseExpression;
+ }
+ }
+ }
else
{
- error(dotLocation, " field selection requires structure, vector, or matrix on left hand side", fieldString.c_str());
+ if (shaderVersion < 300)
+ {
+ error(dotLocation, " field selection requires structure, vector, or matrix on left hand side", fieldString.c_str());
+ }
+ else
+ {
+ error(dotLocation, " field selection requires structure, vector, matrix, or interface block on left hand side", fieldString.c_str());
+ }
recover();
indexedExpression = baseExpression;
}