Commit 98493ddc by Jamie Madill Committed by Shannon Woods

Simplified TType class by carving out TStructure and TField.

R=kbr@chromium.org Review URL: https://codereview.appspot.com/9866043 git-svn-id: https://angleproject.googlecode.com/svn/trunk@2423 736b8ea6-26fd-11df-bfd4-992fa37f6226 TRAC #23415 Authored-by: alokp@chromium.org Signed-off-by: Shannon Woods Signed-off-by Nicolas Capens Merged-by: Jamie Madill
parent f386bf76
......@@ -55,11 +55,11 @@ bool FlagStd140Structs::isInStd140InterfaceBlock(TIntermTyped *node) const
const TType &type = node->getType();
if (type.isInterfaceBlockMember() || type.getBasicType() == EbtInterfaceBlock)
// determine if we are in the standard layout
const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
if (interfaceBlock)
{
// determine if we are in the standard layout
const TType &interfaceBlockType = (type.isInterfaceBlockMember() ? *type.getInterfaceBlockType() : type);
return (interfaceBlockType.getLayoutQualifier().blockStorage == EbsStd140);
return (interfaceBlock->blockStorage() == EbsStd140);
}
return false;
......
......@@ -447,19 +447,18 @@ void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltI
//
// Depth range in window coordinates
//
TTypeList *members = NewPoolTTypeList();
TTypeLine near = {new TType(EbtFloat, EbpHigh, EvqGlobal, 1), 0};
TTypeLine far = {new TType(EbtFloat, EbpHigh, EvqGlobal, 1), 0};
TTypeLine diff = {new TType(EbtFloat, EbpHigh, EvqGlobal, 1), 0};
near.type->setFieldName("near");
far.type->setFieldName("far");
diff.type->setFieldName("diff");
members->push_back(near);
members->push_back(far);
members->push_back(diff);
TVariable *depthRangeParameters = new TVariable(NewPoolTString("gl_DepthRangeParameters"), TType(members, "gl_DepthRangeParameters"), true);
TFieldList *fields = NewPoolTFieldList();
TSourceLoc zeroSourceLoc = {0};
TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"), zeroSourceLoc);
TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"), zeroSourceLoc);
TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"), zeroSourceLoc);
fields->push_back(near);
fields->push_back(far);
fields->push_back(diff);
TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
symbolTable.insert(COMMON_BUILTINS, *depthRangeParameters);
TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(members, "gl_DepthRangeParameters"));
TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
depthRange->setQualifier(EvqUniform);
symbolTable.insert(COMMON_BUILTINS, *depthRange);
......
......@@ -1142,16 +1142,16 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
{
const TTypeList* fields = leftNodeType.getStruct();
const TFieldList& fields = leftNodeType.getStruct()->fields();
size_t structSize = fields->size();
size_t structSize = fields.size();
size_t index = 0;
for (size_t j = 0; j < structSize; j++) {
size_t size = (*fields)[j].type->getObjectSize();
size_t size = fields[j]->type()->getObjectSize();
for (size_t i = 0; i < size; i++) {
if ((*fields)[j].type->getBasicType() == EbtStruct) {
if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
if (fields[j]->type()->getBasicType() == EbtStruct) {
if (!CompareStructure(*fields[j]->type(), &rightUnionArray[index], &leftUnionArray[index]))
return false;
} else {
if (leftUnionArray[index] != rightUnionArray[index])
......
......@@ -79,25 +79,9 @@ void TOutputGLSLBase::writeVariableType(const TType& type)
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
out << type.getQualifierString() << " ";
// Declare the struct if we have not done so already.
if ((type.getBasicType() == EbtStruct) &&
(mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
{
out << "struct " << hashName(type.getTypeName()) << "{\n";
const TTypeList* structure = type.getStruct();
ASSERT(structure != NULL);
for (size_t i = 0; i < structure->size(); ++i)
{
const TType* fieldType = (*structure)[i].type;
ASSERT(fieldType != NULL);
if (writeVariablePrecision(fieldType->getPrecision()))
out << " ";
out << getTypeName(*fieldType) << " " << hashName(fieldType->getFieldName());
if (fieldType->isArray())
out << arrayBrackets(*fieldType);
out << ";\n";
}
out << "}";
mDeclaredStructs.insert(type.getTypeName());
declareStruct(type.getStruct());
}
else
{
......@@ -138,15 +122,16 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
if (type.getBasicType() == EbtStruct)
{
out << hashName(type.getTypeName()) << "(";
const TTypeList* structure = type.getStruct();
ASSERT(structure != NULL);
for (size_t i = 0; i < structure->size(); ++i)
const TStructure* structure = type.getStruct();
out << hashName(structure->name()) << "(";
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TType* fieldType = (*structure)[i].type;
const TType* fieldType = fields[i]->type();
ASSERT(fieldType != NULL);
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
if (i != structure->size() - 1) out << ", ";
if (i != fields.size() - 1) out << ", ";
}
out << ")";
}
......@@ -260,12 +245,18 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
case EOpIndexDirectStruct:
if (visit == InVisit)
{
// Here we are writing out "foo.bar", where "foo" is struct
// and "bar" is field. In AST, it is represented as a binary
// node, where left child represents "foo" and right child "bar".
// The node itself represents ".". The struct field "bar" is
// actually stored as an index into TStructure::fields.
out << ".";
// TODO(alokp): ASSERT
TString fieldName = node->getType().getFieldName();
const TStructure* structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
const TField* field = structure->fields()[index->getIConst(0)];
const TType& structType = node->getLeft()->getType();
if (!mSymbolTable.findBuiltIn(structType.getTypeName()))
TString fieldName = field->name();
if (!mSymbolTable.findBuiltIn(structure->name()))
fieldName = hashName(fieldName);
out << fieldName;
......@@ -596,7 +587,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
{
const TType& type = node->getType();
ASSERT(type.getBasicType() == EbtStruct);
out << hashName(type.getTypeName()) << "(";
out << hashName(type.getStruct()->name()) << "(";
}
else if (visit == InVisit)
{
......@@ -765,7 +756,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type)
else
{
if (type.getBasicType() == EbtStruct)
out << hashName(type.getTypeName());
out << hashName(type.getStruct()->name());
else
out << type.getBasicString();
}
......@@ -798,3 +789,29 @@ TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
return name;
return hashName(name);
}
bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
{
return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
}
void TOutputGLSLBase::declareStruct(const TStructure* structure)
{
TInfoSinkBase& out = objSink();
out << "struct " << hashName(structure->name()) << "{\n";
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < fields.size(); ++i)
{
const TField* field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
out << getTypeName(*field->type()) << " " << hashName(field->name());
if (field->type()->isArray())
out << arrayBrackets(*field->type());
out << ";\n";
}
out << "}";
mDeclaredStructs.insert(structure->name());
}
......@@ -52,6 +52,9 @@ protected:
TString hashFunctionName(const TString& mangled_name);
private:
bool structDeclared(const TStructure* structure) const;
void declareStruct(const TStructure* structure);
TInfoSinkBase& mObjSink;
bool mDeclaringVariables;
......
......@@ -241,15 +241,15 @@ int OutputHLSL::vectorSize(const TType &type) const
return elementSize * arraySize;
}
TString OutputHLSL::interfaceBlockUniformName(const TType &interfaceBlockType, const TType &uniformType)
TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field)
{
if (interfaceBlockType.hasInstanceName())
if (interfaceBlock.hasInstanceName())
{
return interfaceBlockType.getTypeName() + "." + uniformType.getFieldName();
return interfaceBlock.name() + "." + field.name();
}
else
{
return uniformType.getFieldName();
return field.name();
}
}
......@@ -258,49 +258,115 @@ TString OutputHLSL::decoratePrivate(const TString &privateText)
return "dx_" + privateText;
}
TString OutputHLSL::interfaceBlockStructName(const TType &interfaceBlockType)
TString OutputHLSL::interfaceBlockStructNameString(const TInterfaceBlock &interfaceBlock)
{
return decoratePrivate(interfaceBlockType.getTypeName()) + "_type";
return decoratePrivate(interfaceBlock.name()) + "_type";
}
TString OutputHLSL::interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex)
TString OutputHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex)
{
if (!interfaceBlockType.hasInstanceName())
if (!interfaceBlock.hasInstanceName())
{
return "";
}
else if (interfaceBlockType.isArray())
else if (interfaceBlock.isArray())
{
return decoratePrivate(interfaceBlockType.getInstanceName()) + "_" + str(arrayIndex);
return decoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex);
}
else
{
return decorate(interfaceBlockType.getInstanceName());
return decorate(interfaceBlock.instanceName());
}
}
TString OutputHLSL::interfaceBlockMemberTypeString(const TType &memberType, TLayoutBlockStorage blockStorage)
TString OutputHLSL::interfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage)
{
const TLayoutMatrixPacking matrixPacking = memberType.getLayoutQualifier().matrixPacking;
const TType &fieldType = *field.type();
const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking;
ASSERT(matrixPacking != EmpUnspecified);
if (memberType.isMatrix())
if (fieldType.isMatrix())
{
// Use HLSL row-major packing for GLSL column-major matrices
const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major");
return matrixPackString + " " + typeString(memberType);
return matrixPackString + " " + typeString(fieldType);
}
else if (memberType.getBasicType() == EbtStruct)
else if (fieldType.getStruct())
{
// Use HLSL row-major packing for GLSL column-major matrices
return structureTypeName(memberType, matrixPacking == EmpColumnMajor, blockStorage == EbsStd140);
return structureTypeName(*fieldType.getStruct(), matrixPacking == EmpColumnMajor, blockStorage == EbsStd140);
}
else
{
return typeString(memberType);
return typeString(fieldType);
}
}
TString OutputHLSL::interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage)
{
TString hlsl;
int elementIndex = 0;
for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++)
{
const TField &field = *interfaceBlock.fields()[typeIndex];
const TType &fieldType = *field.type();
if (blockStorage == EbsStd140)
{
// 2 and 3 component vector types in some cases need pre-padding
hlsl += std140PrePaddingString(fieldType, &elementIndex);
}
hlsl += " " + interfaceBlockFieldTypeString(field, blockStorage) +
" " + decorate(field.name()) + arrayString(fieldType) + ";\n";
// must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
if (blockStorage == EbsStd140)
{
const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
hlsl += std140PostPaddingString(fieldType, useHLSLRowMajorPacking);
}
}
return hlsl;
}
TString OutputHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock)
{
const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
return "struct " + interfaceBlockStructNameString(interfaceBlock) + "\n"
"{\n" +
interfaceBlockFieldString(interfaceBlock, blockStorage) +
"};\n\n";
}
TString OutputHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex)
{
const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? decorate(str(arrayIndex)) : "");
const TString &blockName = interfaceBlock.name() + arrayIndexString;
TString hlsl;
hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
"{\n";
if (interfaceBlock.hasInstanceName())
{
hlsl += " " + interfaceBlockStructNameString(interfaceBlock) + " " + interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n";
}
else
{
const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage();
hlsl += interfaceBlockFieldString(interfaceBlock, blockStorage);
}
hlsl += "};\n\n";
return hlsl;
}
TString OutputHLSL::std140PrePaddingString(const TType &type, int *elementIndex)
{
if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray())
......@@ -370,9 +436,9 @@ TString OutputHLSL::std140PostPaddingString(const TType &type, bool useHLSLRowMa
const GLenum glType = glVariableType(type);
numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix);
}
else if (type.getBasicType() == EbtStruct)
else if (type.getStruct())
{
const TString &structName = structureTypeName(type, useHLSLRowMajorPacking, true);
const TString &structName = structureTypeName(*type.getStruct(), useHLSLRowMajorPacking, true);
numComponents = mStd140StructElementIndexes[structName];
if (numComponents == 0)
......@@ -394,72 +460,6 @@ TString OutputHLSL::std140PostPaddingString(const TType &type, bool useHLSLRowMa
return padding;
}
TString OutputHLSL::interfaceBlockMemberString(const TTypeList &typeList, TLayoutBlockStorage blockStorage)
{
TString hlsl;
int elementIndex = 0;
for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
{
const TType &memberType = *typeList[typeIndex].type;
if (blockStorage == EbsStd140)
{
// 2 and 3 component vector types in some cases need pre-padding
hlsl += std140PrePaddingString(memberType, &elementIndex);
}
hlsl += " " + interfaceBlockMemberTypeString(memberType, blockStorage) +
" " + decorate(memberType.getFieldName()) + arrayString(memberType) + ";\n";
// must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff
if (blockStorage == EbsStd140)
{
const bool useHLSLRowMajorPacking = (memberType.getLayoutQualifier().matrixPacking == EmpColumnMajor);
hlsl += std140PostPaddingString(memberType, useHLSLRowMajorPacking);
}
}
return hlsl;
}
TString OutputHLSL::interfaceBlockStructString(const TType &interfaceBlockType)
{
const TTypeList &typeList = *interfaceBlockType.getStruct();
const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
return "struct " + interfaceBlockStructName(interfaceBlockType) + "\n"
"{\n" +
interfaceBlockMemberString(typeList, blockStorage) +
"};\n\n";
}
TString OutputHLSL::interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex)
{
const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? decorate(str(arrayIndex)) : "");
const TString &blockName = interfaceBlockType.getTypeName() + arrayIndexString;
TString hlsl;
hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n"
"{\n";
if (interfaceBlockType.hasInstanceName())
{
hlsl += " " + interfaceBlockStructName(interfaceBlockType) + " " + interfaceBlockInstanceString(interfaceBlockType, arrayIndex) + ";\n";
}
else
{
const TTypeList &typeList = *interfaceBlockType.getStruct();
const TLayoutBlockStorage blockStorage = interfaceBlockType.getLayoutQualifier().blockStorage;
hlsl += interfaceBlockMemberString(typeList, blockStorage);
}
hlsl += "};\n\n";
return hlsl;
}
// Use the same layout for packed and shared
void setBlockLayout(InterfaceBlock *interfaceBlock, BlockLayoutType newLayout)
{
......@@ -502,7 +502,7 @@ BlockLayoutType convertBlockLayoutType(TLayoutBlockStorage blockStorage)
}
}
TString OutputHLSL::structInitializerString(int indent, const TTypeList &structMembers, const TString &structName)
TString OutputHLSL::structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName)
{
TString init;
......@@ -521,19 +521,20 @@ TString OutputHLSL::structInitializerString(int indent, const TTypeList &structM
init += preIndentString + "{\n";
for (unsigned int memberIndex = 0; memberIndex < structMembers.size(); memberIndex++)
const TFieldList &fields = structure.fields();
for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
{
const TType &memberType = *structMembers[memberIndex].type;
const TString &fieldName = decorate(memberType.getFieldName());
const TField &field = *fields[fieldIndex];
const TString &fieldName = rhsStructName + "." + decorate(field.name());
const TType &fieldType = *field.type();
if (memberType.getBasicType() == EbtStruct)
if (fieldType.getStruct())
{
const TTypeList &nestedStructMembers = *memberType.getStruct();
init += structInitializerString(indent + 1, nestedStructMembers, structName + "." + fieldName);
init += structInitializerString(indent + 1, *fieldType.getStruct(), fieldName);
}
else
{
init += fullIndentString + structName + "." + fieldName + ",\n";
init += fullIndentString + fieldName + ",\n";
}
}
......@@ -577,40 +578,39 @@ void OutputHLSL::header()
for (ReferencedSymbols::const_iterator interfaceBlockIt = mReferencedInterfaceBlocks.begin(); interfaceBlockIt != mReferencedInterfaceBlocks.end(); interfaceBlockIt++)
{
const TType &nodeType = interfaceBlockIt->second->getType();
const TType &interfaceBlockType = nodeType.isInterfaceBlockMember() ? *nodeType.getInterfaceBlockType() : nodeType;
const TString &blockName = interfaceBlockType.getTypeName();
const TTypeList &typeList = *interfaceBlockType.getStruct();
const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock();
const TFieldList &fieldList = interfaceBlock.fields();
const unsigned int arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getArraySize() : 0;
sh::InterfaceBlock interfaceBlock(blockName.c_str(), arraySize, mInterfaceBlockRegister);
for (unsigned int typeIndex = 0; typeIndex < typeList.size(); typeIndex++)
unsigned int arraySize = static_cast<unsigned int>(interfaceBlock.arraySize());
sh::InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize, mInterfaceBlockRegister);
for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++)
{
const TType &memberType = *typeList[typeIndex].type;
const TString &fullUniformName = interfaceBlockUniformName(interfaceBlockType, memberType);
declareUniformToList(memberType, fullUniformName, typeIndex, interfaceBlock.activeUniforms);
const TField &field = *fieldList[typeIndex];
const TString &fullUniformName = interfaceBlockFieldString(interfaceBlock, field);
declareUniformToList(*field.type(), fullUniformName, typeIndex, activeBlock.activeUniforms);
}
mInterfaceBlockRegister += std::max(1u, interfaceBlock.arraySize);
mInterfaceBlockRegister += std::max(1u, arraySize);
BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlockType.getLayoutQualifier().blockStorage);
setBlockLayout(&interfaceBlock, blockLayoutType);
mActiveInterfaceBlocks.push_back(interfaceBlock);
BlockLayoutType blockLayoutType = convertBlockLayoutType(interfaceBlock.blockStorage());
setBlockLayout(&activeBlock, blockLayoutType);
mActiveInterfaceBlocks.push_back(activeBlock);
if (interfaceBlockType.hasInstanceName())
if (interfaceBlock.hasInstanceName())
{
interfaceBlocks += interfaceBlockStructString(interfaceBlockType);
interfaceBlocks += interfaceBlockStructString(interfaceBlock);
}
if (arraySize > 0)
{
for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++)
{
interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex + arrayIndex, arrayIndex);
interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex + arrayIndex, arrayIndex);
}
}
else
{
interfaceBlocks += interfaceBlockString(interfaceBlockType, interfaceBlock.registerIndex, GL_INVALID_INDEX);
interfaceBlocks += interfaceBlockString(interfaceBlock, activeBlock.registerIndex, GL_INVALID_INDEX);
}
}
......@@ -618,12 +618,11 @@ void OutputHLSL::header()
{
TIntermTyped *structNode = flaggedStructIt->first;
const TString &mappedName = flaggedStructIt->second;
const TType &structType = structNode->getType();
const TTypeList &structMembers = *structType.getStruct();
const TStructure &structure = *structNode->getType().getStruct();
const TString &originalName = mFlaggedStructOriginalNames[structNode];
flaggedStructs += "static " + decorate(structType.getTypeName()) + " " + mappedName + " =\n";
flaggedStructs += structInitializerString(0, structMembers, originalName);
flaggedStructs += "static " + decorate(structure.name()) + " " + mappedName + " =\n";
flaggedStructs += structInitializerString(0, structure, originalName);
flaggedStructs += "\n";
}
......@@ -1463,23 +1462,19 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
if (qualifier == EvqUniform)
{
if (node->getType().isInterfaceBlockMember())
{
const TString& interfaceBlockTypeName = node->getType().getInterfaceBlockType()->getTypeName();
mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
out << decorateUniform(name, node->getType());
}
else if (node->getBasicType() == EbtInterfaceBlock)
const TType& nodeType = node->getType();
const TInterfaceBlock* interfaceBlock = nodeType.getInterfaceBlock();
if (interfaceBlock)
{
const TString& interfaceBlockTypeName = node->getType().getTypeName();
mReferencedInterfaceBlocks[interfaceBlockTypeName] = node;
out << decorateUniform(name, node->getType());
mReferencedInterfaceBlocks[interfaceBlock->name()] = node;
}
else
{
mReferencedUniforms[name] = node;
out << decorateUniform(name, node->getType());
}
out << decorateUniform(name, nodeType);
}
else if (qualifier == EvqAttribute || qualifier == EvqVertexInput)
{
......@@ -1624,19 +1619,25 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
break;
case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
case EOpIndexDirect:
if (node->getLeft()->getBasicType() == EbtInterfaceBlock)
{
if (visit == PreVisit)
const TType& leftType = node->getLeft()->getType();
if (leftType.isInterfaceBlock())
{
const TType &interfaceBlockType = node->getLeft()->getType();
mReferencedInterfaceBlocks[interfaceBlockType.getInstanceName()] = node->getLeft()->getAsSymbolNode();
out << interfaceBlockInstanceString(interfaceBlockType, node->getRight()->getAsConstantUnion()->getIConst(0));
return false;
if (visit == PreVisit)
{
TInterfaceBlock* interfaceBlock = leftType.getInterfaceBlock();
const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
mReferencedInterfaceBlocks[interfaceBlock->instanceName()] = node->getLeft()->getAsSymbolNode();
out << interfaceBlockInstanceString(*interfaceBlock, arrayIndex);
return false;
}
}
else
{
outputTriplet(visit, "", "[", "]");
}
}
else
{
outputTriplet(visit, "", "[", "]");
}
break;
case EOpIndexIndirect:
......@@ -1645,10 +1646,23 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
outputTriplet(visit, "", "[", "]");
break;
case EOpIndexDirectStruct:
if (visit == InVisit)
{
const TStructure* structure = node->getLeft()->getType().getStruct();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
const TField* field = structure->fields()[index->getIConst(0)];
out << "." + decorateField(field->name(), *structure);
return false;
}
break;
case EOpIndexDirectInterfaceBlock:
if (visit == InVisit)
{
out << "." + decorateField(node->getType().getFieldName(), node->getLeft()->getType());
const TInterfaceBlock* interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
const TField* field = interfaceBlock->fields()[index->getIConst(0)];
out << "." + decorate(field->name());
return false;
}
......@@ -1717,18 +1731,19 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
out << "!(";
}
const TTypeList *fields = node->getLeft()->getType().getStruct();
const TStructure &structure = *node->getLeft()->getType().getStruct();
const TFieldList &fields = structure.fields();
for (size_t i = 0; i < fields->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = (*fields)[i].type;
const TField *field = fields[i];
node->getLeft()->traverse(this);
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType()) + " == ";
out << "." + decorateField(field->name(), structure) + " == ";
node->getRight()->traverse(this);
out << "." + decorateField(fieldType->getFieldName(), node->getLeft()->getType());
out << "." + decorateField(field->name(), structure);
if (i < fields->size() - 1)
if (i < fields.size() - 1)
{
out << " && ";
}
......@@ -1996,7 +2011,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (variable->getType().getStruct())
{
addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
}
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
......@@ -2123,7 +2138,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
if (symbol->getType().getStruct())
{
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getTypeName()), NULL);
addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
}
out << argumentString(symbol);
......@@ -2319,8 +2334,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
outputTriplet(visit, "mat4(", ", ", ")");
break;
case EOpConstructStruct:
addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
break;
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
......@@ -2910,15 +2925,17 @@ TString OutputHLSL::qualifierString(TQualifier qualifier)
TString OutputHLSL::typeString(const TType &type)
{
if (type.getBasicType() == EbtStruct)
const TStructure* structure = type.getStruct();
if (structure)
{
if (type.getTypeName() != "")
const TString& typeName = structure->name();
if (typeName != "")
{
return structLookup(type.getTypeName());
return structLookup(typeName);
}
else // Nameless structure, define in place
{
return structureString(type, false, false);
return structureString(*structure, false, false);
}
}
else if (type.isMatrix())
......@@ -3038,42 +3055,41 @@ TString OutputHLSL::initializer(const TType &type)
return "{" + string + "}";
}
TString OutputHLSL::structureString(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing)
TString OutputHLSL::structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing)
{
ASSERT(structType.getStruct());
const TTypeList &fields = *structType.getStruct();
const bool isNameless = (structType.getTypeName() == "");
const TString &structName = structureTypeName(structType, useHLSLRowMajorPacking, useStd140Packing);
const TFieldList &fields = structure.fields();
const bool isNameless = (structure.name() == "");
const TString &structName = structureTypeName(structure, useHLSLRowMajorPacking, useStd140Packing);
const TString declareString = (isNameless ? "struct" : "struct " + structName);
TString structure;
structure += declareString + "\n"
"{\n";
TString string;
string += declareString + "\n"
"{\n";
int elementIndex = 0;
for (unsigned int i = 0; i < fields.size(); i++)
{
const TType &field = *fields[i].type;
const TField &field = *fields[i];
const TType &fieldType = *field.type();
const TStructure *fieldStruct = fieldType.getStruct();
const TString &fieldTypeString = fieldStruct ? structureTypeName(*fieldStruct, useHLSLRowMajorPacking, useStd140Packing) : typeString(fieldType);
if (useStd140Packing)
{
structure += std140PrePaddingString(field, &elementIndex);
string += std140PrePaddingString(*field.type(), &elementIndex);
}
structure += " " + structureTypeName(field, useHLSLRowMajorPacking, useStd140Packing) + " " +
decorateField(field.getFieldName(), structType) + arrayString(field) + ";\n";
string += " " + fieldTypeString + " " + decorateField(field.name(), structure) + arrayString(fieldType) + ";\n";
if (useStd140Packing)
{
structure += std140PostPaddingString(field, useHLSLRowMajorPacking);
string += std140PostPaddingString(*field.type(), useHLSLRowMajorPacking);
}
}
// Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable
structure += (isNameless ? "} " : "};\n");
string += (isNameless ? "} " : "};\n");
// Add remaining element index to the global map, for use with nested structs in standard layouts
if (useStd140Packing)
......@@ -3081,17 +3097,12 @@ TString OutputHLSL::structureString(const TType &structType, bool useHLSLRowMajo
mStd140StructElementIndexes[structName] = elementIndex;
}
return structure;
return string;
}
TString OutputHLSL::structureTypeName(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing)
TString OutputHLSL::structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing)
{
if (structType.getBasicType() != EbtStruct)
{
return typeString(structType);
}
if (structType.getTypeName() == "")
if (structure.name() == "")
{
return "";
}
......@@ -3112,7 +3123,7 @@ TString OutputHLSL::structureTypeName(const TType &structType, bool useHLSLRowMa
prefix += "rm";
}
return prefix + typeString(structType);
return prefix + structLookup(structure.name());
}
void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
......@@ -3137,37 +3148,38 @@ void OutputHLSL::addConstructor(const TType &type, const TString &name, const TI
typedef std::vector<TType> ParameterArray;
ParameterArray ctorParameters;
if (type.getStruct())
const TStructure* structure = type.getStruct();
if (structure)
{
mStructNames.insert(decorate(name));
const TString &structure = structureString(type, false, false);
const TString &structString = structureString(*structure, false, false);
if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end())
{
// Add row-major packed struct for interface blocks
TString rowMajorString = "#pragma pack_matrix(row_major)\n" +
structureString(type, true, false) +
structureString(*structure, true, false) +
"#pragma pack_matrix(column_major)\n";
const TString &std140Prefix = "std";
TString std140String = structureString(type, false, true);
TString std140String = structureString(*structure, false, true);
const TString &std140RowMajorPrefix = "std_rm";
TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" +
structureString(type, true, true) +
structureString(*structure, true, true) +
"#pragma pack_matrix(column_major)\n";
mStructDeclarations.push_back(structure);
mStructDeclarations.push_back(structString);
mStructDeclarations.push_back(rowMajorString);
mStructDeclarations.push_back(std140String);
mStructDeclarations.push_back(std140RowMajorString);
}
const TTypeList &fields = *type.getStruct();
const TFieldList &fields = structure->fields();
for (unsigned int i = 0; i < fields.size(); i++)
{
ctorParameters.push_back(*fields[i].type);
ctorParameters.push_back(*fields[i]->type());
}
}
else if (parameters)
......@@ -3338,19 +3350,20 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
{
TInfoSinkBase &out = mBody;
if (type.getBasicType() == EbtStruct)
const TStructure* structure = type.getStruct();
if (structure)
{
out << structLookup(type.getTypeName()) + "_ctor(";
out << structLookup(structure->name()) + "_ctor(";
const TTypeList *structure = type.getStruct();
const TFieldList& fields = structure->fields();
for (size_t i = 0; i < structure->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = (*structure)[i].type;
const TType *fieldType = fields[i]->type();
constUnion = writeConstantUnion(*fieldType, constUnion);
if (i != structure->size() - 1)
if (i != fields.size() - 1)
{
out << ", ";
}
......@@ -3456,9 +3469,9 @@ TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
return decorate(string);
}
TString OutputHLSL::decorateField(const TString &string, const TType &structure)
TString OutputHLSL::decorateField(const TString &string, const TStructure &structure)
{
if (structure.getTypeName().compare(0, 3, "gl_") != 0)
if (structure.name().compare(0, 3, "gl_") != 0)
{
return decorate(string);
}
......@@ -3504,31 +3517,32 @@ int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
return index;
}
void OutputHLSL::declareUniformToList(const TType &type, const TString &name, int index, ActiveUniforms& output)
void OutputHLSL::declareUniformToList(const TType &type, const TString &name, int registerIndex, ActiveUniforms& output)
{
const TTypeList *structure = type.getStruct();
const TStructure *structure = type.getStruct();
if (!structure)
{
const bool isRowMajorMatrix = (type.isMatrix() && type.getLayoutQualifier().matrixPacking == EmpRowMajor);
output.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index, isRowMajorMatrix));
output.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex, isRowMajorMatrix));
}
else
{
Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)index, false);
Uniform structUniform(GL_NONE, GL_NONE, name.c_str(), (unsigned int)type.getArraySize(), (unsigned int)registerIndex, false);
int fieldIndex = index;
int fieldRegister = registerIndex;
const TFieldList &fields = structure->fields();
for (size_t i = 0; i < structure->size(); i++)
for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
{
TType fieldType = *(*structure)[i].type;
const TString &fieldName = fieldType.getFieldName();
TField *field = fields[fieldIndex];
TType *fieldType = field->type();
// make sure to copy matrix packing information
fieldType.setLayoutQualifier(type.getLayoutQualifier());
fieldType->setLayoutQualifier(type.getLayoutQualifier());
declareUniformToList(fieldType, fieldName, fieldIndex, structUniform.fields);
fieldIndex += fieldType.totalRegisterCount();
declareUniformToList(*fieldType, field->name(), fieldRegister, structUniform.fields);
fieldRegister += fieldType->totalRegisterCount();
}
output.push_back(structUniform);
......
......@@ -40,14 +40,14 @@ class OutputHLSL : public TIntermTraverser
TString typeString(const TType &type);
TString textureString(const TType &type);
TString interpolationString(TQualifier qualifier);
TString structureString(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing);
TString structureTypeName(const TType &structType, bool useHLSLRowMajorPacking, bool useStd140Packing);
TString structureString(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing);
TString structureTypeName(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing);
static TString qualifierString(TQualifier qualifier);
static TString arrayString(const TType &type);
static TString initializer(const TType &type);
static TString decorate(const TString &string); // Prepends an underscore to avoid naming clashes
static TString decorateUniform(const TString &string, const TType &type);
static TString decorateField(const TString &string, const TType &structure);
static TString decorateField(const TString &string, const TStructure &structure);
protected:
void header();
......@@ -187,20 +187,20 @@ class OutputHLSL : public TIntermTraverser
TString registerString(TIntermSymbol *operand);
int samplerRegister(TIntermSymbol *sampler);
int uniformRegister(TIntermSymbol *uniform);
void declareUniformToList(const TType &type, const TString &name, int index, ActiveUniforms& output);
void declareUniformToList(const TType &type, const TString &name, int registerIndex, ActiveUniforms& output);
void declareUniform(const TType &type, const TString &name, int index);
TString interfaceBlockUniformName(const TType &interfaceBlockType, const TType &uniformType);
TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, const TField &field);
TString decoratePrivate(const TString &privateText);
TString interfaceBlockStructName(const TType &interfaceBlockType);
TString interfaceBlockInstanceString(const TType& interfaceBlockType, unsigned int arrayIndex);
TString interfaceBlockMemberTypeString(const TType &memberType, TLayoutBlockStorage blockStorage);
TString interfaceBlockMemberString(const TTypeList &typeList, TLayoutBlockStorage blockStorage);
TString interfaceBlockStructString(const TType &interfaceBlockType);
TString interfaceBlockString(const TType &interfaceBlockType, unsigned int registerIndex, unsigned int arrayIndex);
TString interfaceBlockStructNameString(const TInterfaceBlock &interfaceBlockType);
TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex);
TString interfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage);
TString interfaceBlockFieldString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage);
TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock);
TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex);
TString std140PrePaddingString(const TType &type, int *elementIndex);
TString std140PostPaddingString(const TType &type, bool useHLSLRowMajorPacking);
TString structInitializerString(int indent, const TTypeList &structMembers, const TString &structName);
TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName);
static GLenum glVariableType(const TType &type);
static GLenum glVariablePrecision(const TType &type);
......
......@@ -532,7 +532,7 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* n
return true;
}
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
return true;
}
......@@ -672,10 +672,10 @@ bool TParseContext::containsSampler(TType& type)
if (IsSampler(type.getBasicType()))
return true;
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))
if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
const TFieldList& fields = type.getStruct()->fields();
for (unsigned int i = 0; i < fields.size(); ++i) {
if (containsSampler(*fields[i]->type()))
return true;
}
}
......@@ -1503,9 +1503,9 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
TIntermAggregate* aggrNode = node->getAsAggregate();
TTypeList::const_iterator memberTypes;
TFieldList::const_iterator memberTypes;
if (op == EOpConstructStruct)
memberTypes = type->getStruct()->begin();
memberTypes = type->getStruct()->fields().begin();
TType elementType = *type;
if (type->isArray())
......@@ -1527,7 +1527,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
else if (op == EOpConstructStruct)
newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
newNode = constructStruct(node, (*memberTypes)->type(), 1, node->getLine(), false);
else
newNode = constructBuiltIn(type, op, node, node->getLine(), false);
......@@ -1558,7 +1558,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type
if (type->isArray())
newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
else if (op == EOpConstructStruct)
newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
newNode = constructStruct(*p, (memberTypes[paramCount])->type(), paramCount+1, node->getLine(), true);
else
newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
......@@ -1817,14 +1817,14 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, co
//
TIntermTyped* TParseContext::addConstStruct(const TString &identifier, TIntermTyped *node, const TSourceLoc& line)
{
const TTypeList* fields = node->getType().getStruct();
const TFieldList& fields = node->getType().getStruct()->fields();
size_t instanceSize = 0;
for (size_t index = 0; index < fields->size(); ++index) {
if ((*fields)[index].type->getFieldName() == identifier) {
for (size_t index = 0; index < fields.size(); ++index) {
if (fields[index]->name() == identifier) {
break;
} else {
instanceSize += (*fields)[index].type->getObjectSize();
instanceSize += fields[index]->type()->getObjectSize();
}
}
......@@ -1847,8 +1847,8 @@ TIntermTyped* TParseContext::addConstStruct(const TString &identifier, TIntermTy
//
// Interface/uniform blocks
//
TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TTypeList* typeList,
const TString& instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
{
if (reservedErrorCheck(nameLine, blockName))
recover();
......@@ -1881,94 +1881,95 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif
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");
// check for sampler types and apply layout qualifiers
for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) {
TField* field = (*fieldList)[memberIndex];
TType* fieldType = field->type();
if (IsSampler(fieldType->getBasicType())) {
error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
recover();
}
const TQualifier qualifier = memberTypeLine.type->getQualifier();
const TQualifier qualifier = fieldType->getQualifier();
switch (qualifier)
{
case EvqGlobal:
case EvqUniform:
break;
default:
error(memberTypeLine.line, "invalid qualifier on interface block member", getQualifierString(qualifier));
error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier));
recover();
break;
}
// check layout qualifiers
TLayoutQualifier memberLayoutQualifier = memberType->getLayoutQualifier();
if (layoutLocationErrorCheck(memberTypeLine.line, memberLayoutQualifier))
TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
{
recover();
}
if (memberLayoutQualifier.blockStorage != EbsUnspecified)
if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
{
error(memberTypeLine.line, "invalid layout qualifier:", getBlockStorageString(memberLayoutQualifier.blockStorage), "cannot be used here");
error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
recover();
}
if (memberLayoutQualifier.matrixPacking == EmpUnspecified)
if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
{
memberLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
}
else if (!memberType->isMatrix())
else if (!fieldType->isMatrix())
{
error(memberTypeLine.line, "invalid layout qualifier:", getMatrixPackingString(memberLayoutQualifier.matrixPacking), "can only be used on matrix types");
error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types");
recover();
}
memberType->setLayoutQualifier(memberLayoutQualifier);
fieldType->setLayoutQualifier(fieldLayoutQualifier);
}
TType* interfaceBlock = new TType(typeList, blockName);
interfaceBlock->setBasicType(EbtInterfaceBlock);
interfaceBlock->setQualifier(typeQualifier.qualifier);
interfaceBlock->setLayoutQualifier(blockLayoutQualifier);
// add array index
int arraySize = 0;
if (arrayIndex != NULL)
{
if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
recover();
}
TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize);
TString symbolName = "";
int symbolId = 0;
if (instanceName == "")
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");
for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
{
TField* field = (*fieldList)[memberIndex];
TType* fieldType = field->type();
// set parent pointer of the field variable
fieldType->setInterfaceBlock(interfaceBlock);
TVariable* fieldVariable = new TVariable(&field->name(), *fieldType);
fieldVariable->setQualifier(typeQualifier.qualifier);
if (!symbolTable.declare(*fieldVariable)) {
error(field->line(), "redefinition", field->name().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);
TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
instanceTypeDef->setQualifier(typeQualifier.qualifier);
if (!symbolTable.declare(*instanceTypeDef)) {
error(instanceLine, "redefinition", instanceName.c_str(), "interface block instance name");
error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name");
recover();
}
......@@ -1976,9 +1977,10 @@ TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualif
symbolName = instanceTypeDef->getName();
}
exitStructDeclaration();
TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, *interfaceBlock, typeQualifier.line), nameLine);
TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine);
aggregate->setOp(EOpDeclaration);
exitStructDeclaration();
return aggregate;
}
......@@ -2008,21 +2010,21 @@ const int kWebGLMaxStructNesting = 4;
} // namespace
bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TType& fieldType)
bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
{
if (!isWebGLBasedSpec(shaderSpec)) {
return false;
}
if (fieldType.getBasicType() != EbtStruct) {
if (field.type()->getBasicType() != EbtStruct) {
return false;
}
// We're already inside a structure definition at this point, so add
// one to the field's struct nesting.
if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
std::stringstream extraInfoStream;
extraInfoStream << "Reference of struct type " << fieldType.getTypeName()
extraInfoStream << "Reference of struct type " << field.type()->getStruct()->name()
<< " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
std::string extraInfo = extraInfoStream.str();
error(line, "", "", extraInfo.c_str());
......@@ -2115,7 +2117,7 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co
}
else
{
if (baseExpression->getBasicType() == EbtInterfaceBlock)
if (baseExpression->isInterfaceBlock())
{
error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions");
recover();
......@@ -2137,10 +2139,15 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co
}
else if (baseExpression->isArray())
{
if (baseExpression->getType().getStruct())
const TType &baseType = baseExpression->getType();
if (baseType.getStruct())
{
TType copyOfType(baseType.getStruct());
indexedExpression->setType(copyOfType);
}
else if (baseType.isInterfaceBlock())
{
TType copyOfType(baseExpression->getType().getStruct(), baseExpression->getType().getTypeName());
copyOfType.setBasicType(baseExpression->getType().getBasicType()); // necessary to preserve interface block basic type
TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(), baseType.getLayoutQualifier(), 0);
indexedExpression->setType(copyOfType);
}
else
......@@ -2247,8 +2254,8 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
else if (baseExpression->getBasicType() == EbtStruct)
{
bool fieldFound = false;
const TTypeList* fields = baseExpression->getType().getStruct();
if (fields == 0)
const TFieldList& fields = baseExpression->getType().getStruct()->fields();
if (fields.empty())
{
error(dotLocation, "structure has no fields", "Internal Error");
recover();
......@@ -2257,9 +2264,9 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
else
{
unsigned int i;
for (i = 0; i < fields->size(); ++i)
for (i = 0; i < fields.size(); ++i)
{
if ((*fields)[i].type->getFieldName() == fieldString)
if (fields[i]->name() == fieldString)
{
fieldFound = true;
break;
......@@ -2277,7 +2284,7 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
}
else
{
indexedExpression->setType(*(*fields)[i].type);
indexedExpression->setType(*fields[i]->type());
// change the qualifier of the return type, not of the structure field
// as the structure definition is shared between various structures.
indexedExpression->getTypePointer()->setQualifier(EvqConst);
......@@ -2287,9 +2294,9 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
{
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(i);
TIntermTyped* index = intermediate.addConstantUnion(unionArray, *(*fields)[i].type, fieldLocation);
TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation);
indexedExpression->setType(*(*fields)[i].type);
indexedExpression->setType(*fields[i]->type());
}
}
else
......@@ -2300,11 +2307,11 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
}
}
}
else if (baseExpression->getBasicType() == EbtInterfaceBlock)
else if (baseExpression->isInterfaceBlock())
{
bool fieldFound = false;
const TTypeList* fields = baseExpression->getType().getStruct();
if (fields == 0)
const TFieldList& fields = baseExpression->getType().getInterfaceBlock()->fields();
if (fields.empty())
{
error(dotLocation, "interface block has no fields", "Internal Error");
recover();
......@@ -2313,9 +2320,9 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
else
{
unsigned int i;
for (i = 0; i < fields->size(); ++i)
for (i = 0; i < fields.size(); ++i)
{
if ((*fields)[i].type->getFieldName() == fieldString)
if (fields[i]->name() == fieldString)
{
fieldFound = true;
break;
......@@ -2325,9 +2332,9 @@ TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
{
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(i);
TIntermTyped* index = intermediate.addConstantUnion(unionArray, *(*fields)[i].type, fieldLocation);
TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, dotLocation);
indexedExpression->setType(*(*fields)[i].type);
indexedExpression->setType(*fields[i]->type());
}
else
{
......@@ -2446,17 +2453,17 @@ TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualif
return joinedQualifier;
}
TTypeList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TTypeList *typeList)
TFieldList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList)
{
if (voidErrorCheck(typeSpecifier.line, (*typeList)[0].type->getFieldName(), typeSpecifier)) {
if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier)) {
recover();
}
for (unsigned int i = 0; i < typeList->size(); ++i) {
for (unsigned int i = 0; i < fieldList->size(); ++i) {
//
// Careful not to replace already known aspects of type, like array-ness
//
TType* type = (*typeList)[i].type;
TType* type = (*fieldList)[i]->type();
type->setBasicType(typeSpecifier.type);
type->setPrimarySize(typeSpecifier.primarySize);
type->setSecondarySize(typeSpecifier.secondarySize);
......@@ -2473,46 +2480,46 @@ TTypeList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifi
type->setArraySize(typeSpecifier.arraySize);
if (typeSpecifier.userDef) {
type->setStruct(typeSpecifier.userDef->getStruct());
type->setTypeName(typeSpecifier.userDef->getTypeName());
}
if (structNestingErrorCheck(typeSpecifier.line, *type)) {
if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i])) {
recover();
}
}
return typeList;
return fieldList;
}
TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString &structName, TTypeList* typeList)
TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList)
{
TType* structure = new TType(typeList, structName);
TStructure* structure = new TStructure(structName, fieldList);
TType* structureType = new TType(structure);
if (!structName.empty())
if (!structName->empty())
{
if (reservedErrorCheck(nameLine, structName))
if (reservedErrorCheck(nameLine, *structName))
{
recover();
}
TVariable* userTypeDef = new TVariable(&structName, *structure, true);
TVariable* userTypeDef = new TVariable(structName, *structureType, true);
if (!symbolTable.declare(*userTypeDef)) {
error(nameLine, "redefinition", structName.c_str(), "struct");
error(nameLine, "redefinition", structName->c_str(), "struct");
recover();
}
}
// ensure we do not specify any storage qualifiers on the struct members
for (unsigned int typeListIndex = 0; typeListIndex < typeList->size(); typeListIndex++)
for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
{
const TTypeLine &typeLine = (*typeList)[typeListIndex];
const TQualifier qualifier = typeLine.type->getQualifier();
const TField &field = *(*fieldList)[typeListIndex];
const TQualifier qualifier = field.type()->getQualifier();
switch (qualifier)
{
case EvqGlobal:
case EvqTemporary:
break;
default:
error(typeLine.line, "invalid qualifier on struct member", getQualifierString(qualifier));
error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier));
recover();
break;
}
......@@ -2520,7 +2527,7 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou
TPublicType publicType;
publicType.setBasic(EbtStruct, EvqTemporary, structLine);
publicType.userDef = structure;
publicType.userDef = structureType;
exitStructDeclaration();
return publicType;
......
......@@ -142,11 +142,11 @@ struct TParseContext {
TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc& dotLocation, const TString &fieldString, const TSourceLoc& fieldLocation);
TTypeList *addStructDeclaratorList(const TPublicType& typeSpecifier, TTypeList *typeList);
TPublicType addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString &structName, TTypeList* typeList);
TFieldList *addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList);
TPublicType addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList);
TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TTypeList* typeList,
const TString& instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine);
TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine);
TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine);
TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine);
......@@ -158,7 +158,7 @@ struct TParseContext {
bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier);
void exitStructDeclaration();
bool structNestingErrorCheck(const TSourceLoc& line, const TType& fieldType);
bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
};
int PaParseStrings(size_t count, const char* const string[], const int length[],
......
......@@ -23,20 +23,19 @@ int TSymbolTableLevel::uniqueId = 0;
TType::TType(const TPublicType &p) :
type(p.type), precision(p.precision), qualifier(p.qualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), layoutQualifier(p.layoutQualifier), arraySize(p.arraySize),
interfaceBlockType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
interfaceBlock(0), structure(0)
{
if (p.userDef) {
structure = p.userDef->getStruct();
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
computeDeepestStructNesting();
}
}
//
// Recursively generate mangled names.
//
void TType::buildMangledName(TString& mangledName)
TString TType::buildMangledName() const
{
TString mangledName;
if (isMatrix())
mangledName += 'm';
else if (isVector())
......@@ -45,7 +44,6 @@ void TType::buildMangledName(TString& mangledName)
switch (type) {
case EbtFloat: mangledName += 'f'; break;
case EbtInt: mangledName += 'i'; break;
case EbtUInt: mangledName += 'u'; break;
case EbtBool: mangledName += 'b'; break;
case EbtSampler2D: mangledName += "s2"; break;
case EbtSampler3D: mangledName += "s3"; break;
......@@ -59,33 +57,9 @@ void TType::buildMangledName(TString& mangledName)
case EbtUSampler3D: mangledName += "us3"; break;
case EbtUSamplerCube: mangledName += "usC"; break;
case EbtUSampler2DArray: mangledName += "us2a"; break;
case EbtStruct:
mangledName += "struct-";
if (typeName)
mangledName += *typeName;
{// support MSVC++6.0
for (unsigned int i = 0; i < structure->size(); ++i) {
mangledName += '-';
(*structure)[i].type->buildMangledName(mangledName);
}
}
break;
case EbtInterfaceBlock:
{
mangledName += "interface-block-";
if (typeName)
{
mangledName += *typeName;
}
for (unsigned int i = 0; i < structure->size(); ++i)
{
mangledName += '-';
(*structure)[i].type->buildMangledName(mangledName);
}
}
break;
default:
break;
case EbtStruct: mangledName += structure->mangledName(); break;
case EbtInterfaceBlock: mangledName += interfaceBlock->mangledName(); break;
default: break;
}
if (isMatrix())
......@@ -98,6 +72,7 @@ void TType::buildMangledName(TString& mangledName)
{
mangledName += static_cast<char>('0' + getNominalSize());
}
if (isArray()) {
char buf[20];
snprintf(buf, sizeof(buf), "%d", arraySize);
......@@ -105,6 +80,7 @@ void TType::buildMangledName(TString& mangledName)
mangledName += buf;
mangledName += ']';
}
return mangledName;
}
size_t TType::getObjectSize() const
......@@ -112,7 +88,7 @@ size_t TType::getObjectSize() const
size_t totalSize;
if (getBasicType() == EbtStruct)
totalSize = getStructSize();
totalSize = structure->objectSize();
else
totalSize = primarySize * secondarySize;
......@@ -127,57 +103,47 @@ size_t TType::getObjectSize() const
return totalSize;
}
size_t TType::getStructSize() const
bool TStructure::containsArrays() const
{
if (!getStruct()) {
assert(false && "Not a struct");
return 0;
}
if (structureSize == 0) {
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) {
size_t fieldSize = ((*tl).type)->getObjectSize();
if (fieldSize > INT_MAX - structureSize)
structureSize = INT_MAX;
else
structureSize += fieldSize;
}
for (size_t i = 0; i < mFields->size(); ++i) {
const TType* fieldType = (*mFields)[i]->type();
if (fieldType->isArray() || fieldType->isStructureContainingArrays())
return true;
}
return structureSize;
return false;
}
void TType::computeDeepestStructNesting()
TString TFieldListCollection::buildMangledName() const
{
if (!getStruct()) {
return;
}
int maxNesting = 0;
for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); ++tl) {
maxNesting = std::max(maxNesting, ((*tl).type)->getDeepestStructNesting());
TString mangledName(mangledNamePrefix());
mangledName += *mName;
for (size_t i = 0; i < mFields->size(); ++i) {
mangledName += '-';
mangledName += (*mFields)[i]->type()->getMangledName();
}
deepestStructNesting = 1 + maxNesting;
return mangledName;
}
bool TType::isStructureContainingArrays() const
size_t TFieldListCollection::calculateObjectSize() const
{
if (!structure)
{
return false;
size_t size = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
if (fieldSize > INT_MAX - size)
size = INT_MAX;
else
size += fieldSize;
}
return size;
}
for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
{
if (member->type->isArray() ||
member->type->isStructureContainingArrays())
{
return true;
}
int TStructure::calculateDeepestNesting() const
{
int maxNesting = 0;
for (size_t i = 0; i < mFields->size(); ++i) {
maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
}
return false;
return 1 + maxNesting;
}
//
......
......@@ -7,28 +7,131 @@
#ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED
#include "common/angleutils.h"
#include "compiler/BaseTypes.h"
#include "compiler/Common.h"
#include "compiler/debug.h"
class TType;
struct TPublicType;
class TType;
//
// Need to have association of line numbers to types in a list for building structs.
//
struct TTypeLine {
TType* type;
TSourceLoc line;
class TField
{
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
TField(TType* type, TString* name, const TSourceLoc& line) : mType(type), mName(name), mLine(line) {}
// TODO(alokp): We should only return const type.
// Fix it by tweaking grammar.
TType* type() { return mType; }
const TType* type() const { return mType; }
const TString& name() const { return *mName; }
const TSourceLoc& line() const { return mLine; }
private:
DISALLOW_COPY_AND_ASSIGN(TField);
TType* mType;
TString* mName;
TSourceLoc mLine;
};
typedef TVector<TTypeLine> TTypeList;
inline TTypeList* NewPoolTTypeList()
typedef TVector<TField*> TFieldList;
inline TFieldList* NewPoolTFieldList()
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList));
return new(memory) TTypeList;
void* memory = GlobalPoolAllocator.allocate(sizeof(TFieldList));
return new(memory) TFieldList;
}
class TFieldListCollection
{
public:
const TString& name() const { return *mName; }
const TFieldList& fields() const { return *mFields; }
const TString& mangledName() const {
if (mMangledName.empty())
mMangledName = buildMangledName();
return mMangledName;
}
size_t objectSize() const {
if (mObjectSize == 0)
mObjectSize = calculateObjectSize();
return mObjectSize;
};
protected:
TFieldListCollection(const TString* name, TFieldList* fields)
: mName(name),
mFields(fields),
mObjectSize(0) {
}
TString buildMangledName() const;
size_t calculateObjectSize() const;
virtual TString mangledNamePrefix() const = 0;
const TString* mName;
TFieldList* mFields;
mutable TString mMangledName;
mutable size_t mObjectSize;
};
// May also represent interface blocks
class TStructure : public TFieldListCollection
{
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
TStructure(const TString* name, TFieldList* fields)
: TFieldListCollection(name, fields),
mDeepestNesting(0) {
}
int deepestNesting() const {
if (mDeepestNesting == 0)
mDeepestNesting = calculateDeepestNesting();
return mDeepestNesting;
}
bool containsArrays() const;
private:
DISALLOW_COPY_AND_ASSIGN(TStructure);
virtual TString mangledNamePrefix() const { return "struct-"; }
int calculateDeepestNesting() const;
mutable int mDeepestNesting;
};
class TInterfaceBlock : public TFieldListCollection
{
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
TInterfaceBlock(const TString* name, TFieldList* fields, const TString* instanceName, int arraySize, const TLayoutQualifier& layoutQualifier)
: TFieldListCollection(name, fields),
mInstanceName(instanceName),
mArraySize(arraySize),
mBlockStorage(layoutQualifier.blockStorage),
mMatrixPacking(layoutQualifier.matrixPacking) {
}
const TString& instanceName() const { return *mInstanceName; }
bool hasInstanceName() const { return mInstanceName != NULL; }
bool isArray() const { return mArraySize > 0; }
int arraySize() const { return mArraySize; }
TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
private:
DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
virtual TString mangledNamePrefix() const { return "iblock-"; }
const TString* mInstanceName; // for interface block instance names
int mArraySize; // 0 if not an array
TLayoutBlockStorage mBlockStorage;
TLayoutMatrixPacking mMatrixPacking;
};
//
// Base class for things that have a type.
//
......@@ -39,15 +142,19 @@ public:
TType() {}
TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int ps = 1, int ss = 1, bool a = false) :
type(t), precision(p), qualifier(q), primarySize(ps), secondarySize(ss), array(a), layoutQualifier(TLayoutQualifier::create()), arraySize(0),
interfaceBlockType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0), instanceName(0)
interfaceBlock(0), structure(0)
{
}
explicit TType(const TPublicType &p);
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
TType(TStructure* userDef, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), primarySize(1), secondarySize(1), array(false), layoutQualifier(TLayoutQualifier::create()), arraySize(0),
interfaceBlockType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), instanceName(0)
interfaceBlock(0), structure(userDef)
{
}
TType(TInterfaceBlock* interfaceBlockIn, TQualifier qualifierIn, TLayoutQualifier layoutQualifierIn, int arraySizeIn) :
type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn), primarySize(1), secondarySize(1), array(arraySizeIn > 0), layoutQualifier(layoutQualifierIn), arraySize(arraySizeIn),
interfaceBlock(interfaceBlockIn), structure(0)
{
typeName = NewPoolTString(n.c_str());
}
TBasicType getBasicType() const { return type; }
......@@ -74,15 +181,14 @@ public:
int elementRegisterCount() const
{
TTypeList *structure = getStruct();
if (structure)
{
const TFieldList& fields = structure->fields();
int registerCount = 0;
for (size_t i = 0; i < structure->size(); i++)
for (size_t i = 0; i < fields.size(); i++)
{
registerCount += (*structure)[i].type->totalRegisterCount();
registerCount += fields[i]->type()->totalRegisterCount();
}
return registerCount;
......@@ -114,65 +220,25 @@ public:
int getArraySize() const { return arraySize; }
void setArraySize(int s) { array = true; arraySize = s; }
void clearArrayness() { array = false; arraySize = 0; }
void setInterfaceBlockType(TType* t) { interfaceBlockType = t; }
TType* getInterfaceBlockType() const { return interfaceBlockType; }
bool isInterfaceBlockMember() const { return interfaceBlockType != NULL; }
TInterfaceBlock* getInterfaceBlock() const { return interfaceBlock; }
void setInterfaceBlock(TInterfaceBlock* interfaceBlockIn) { interfaceBlock = interfaceBlockIn; }
bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
bool isVector() const { return primarySize > 1 && secondarySize == 1; }
bool isScalar() const { return primarySize == 1 && secondarySize == 1 && !structure; }
bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
TTypeList* getStruct() const { return structure; }
void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
const TString& getTypeName() const
{
assert(typeName);
return *typeName;
}
void setTypeName(const TString& n)
{
typeName = NewPoolTString(n.c_str());
}
TStructure* getStruct() const { return structure; }
void setStruct(TStructure* s) { structure = s; }
bool isField() const { return fieldName != 0; }
const TString& getFieldName() const
{
assert(fieldName);
return *fieldName;
}
void setFieldName(const TString& n)
{
fieldName = NewPoolTString(n.c_str());
}
TString& getMangledName() {
if (!mangled) {
mangled = NewPoolTString("");
buildMangledName(*mangled);
*mangled += ';' ;
const TString& getMangledName() {
if (mangled.empty()) {
mangled = buildMangledName();
mangled += ';';
}
return *mangled;
}
void setInstanceName(const TString& n)
{
assert(type == EbtInterfaceBlock);
instanceName = NewPoolTString(n.c_str());
}
bool hasInstanceName() const
{
assert(type == EbtInterfaceBlock);
return instanceName != NULL;
}
const TString& getInstanceName() const
{
assert(type == EbtInterfaceBlock);
assert(instanceName);
return *instanceName;
return mangled;
}
bool sameElementType(const TType& right) const {
......@@ -220,12 +286,16 @@ public:
// For type "nesting2", this method would return 2 -- the number
// of structures through which indirection must occur to reach the
// deepest field (nesting2.field1.position).
int getDeepestStructNesting() const { return deepestStructNesting; }
int getDeepestStructNesting() const {
return structure ? structure->deepestNesting() : 0;
}
bool isStructureContainingArrays() const;
bool isStructureContainingArrays() const {
return structure ? structure->containsArrays() : false;
}
private:
void buildMangledName(TString&);
protected:
TString buildMangledName() const;
size_t getStructSize() const;
void computeDeepestStructNesting();
......@@ -237,16 +307,14 @@ private:
int primarySize; // size of vector or cols matrix
int secondarySize; // rows of a matrix
int arraySize;
TType* interfaceBlockType;
TTypeList* structure; // 0 unless this is a struct
mutable size_t structureSize;
int deepestStructNesting;
// 0 unless this is an interface block, or interface block member variable
TInterfaceBlock* interfaceBlock;
// 0 unless this is a struct
TStructure* structure;
TString *fieldName; // for structure field names
TString *mangled;
TString *typeName; // for structure field type name
TString *instanceName; // for interface block instance names
mutable TString mangled;
};
//
......
......@@ -173,14 +173,15 @@ void getUserDefinedVariableInfo(const TType& type,
TVariableInfoList& infoList,
ShHashFunction64 hashFunction)
{
ASSERT(type.getBasicType() == EbtStruct);
ASSERT(type.getBasicType() == EbtStruct || type.isInterfaceBlock());
const TTypeList* structure = type.getStruct();
for (size_t i = 0; i < structure->size(); ++i) {
const TType* fieldType = (*structure)[i].type;
getVariableInfo(*fieldType,
name + "." + fieldType->getFieldName(),
mappedName + "." + TIntermTraverser::hash(fieldType->getFieldName(), hashFunction),
const TFieldList& fields = type.getStruct()->fields();
for (size_t i = 0; i < fields.size(); ++i) {
const TType& fieldType = *(fields[i]->type());
const TString& fieldName = fields[i]->name();
getVariableInfo(fieldType,
name + "." + fieldName,
mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
infoList,
hashFunction);
}
......
......@@ -79,8 +79,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
TQualifier qualifier;
TFunction* function;
TParameter param;
TTypeLine typeLine;
TTypeList* typeList;
TField* field;
TFieldList* fieldList;
};
} interm;
}
......@@ -189,8 +189,8 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason)
%type <interm.type> type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier
%type <interm.type> type_specifier_no_prec type_specifier_nonarray
%type <interm.type> struct_specifier
%type <interm.typeLine> struct_declarator
%type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list
%type <interm.field> struct_declarator
%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
%type <interm.function> function_header function_declarator function_identifier
%type <interm.function> function_header_with_parameters function_call_header
%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
......@@ -818,15 +818,15 @@ declaration
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
$$ = context->addInterfaceBlock($1, @2, *$2.string, $3, "", @$, NULL, @$);
$$ = context->addInterfaceBlock($1, @2, *$2.string, $3, NULL, @$, NULL, @$);
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
$$ = context->addInterfaceBlock($1, @2, *$2.string, $3, *$5.string, @5, NULL, @$);
$$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, NULL, @$);
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON {
ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks");
$$ = context->addInterfaceBlock($1, @2, *$2.string, $3, *$5.string, @5, $7, @6);
$$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, $7, @6);
}
| type_qualifier SEMICOLON {
context->parseGlobalLayoutQualifier($1);
......@@ -1519,10 +1519,10 @@ type_specifier_nonarray
struct_specifier
: STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
$$ = context->addStructure(@1, @2, *$2.string, $5);
$$ = context->addStructure(@1, @2, $2.string, $5);
}
| STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
$$ = context->addStructure(@1, @$, "", $4);
$$ = context->addStructure(@1, @$, NewPoolTString(""), $4);
}
;
......@@ -1532,14 +1532,15 @@ struct_declaration_list
}
| struct_declaration_list struct_declaration {
$$ = $1;
for (unsigned int i = 0; i < $2->size(); ++i) {
for (unsigned int j = 0; j < $$->size(); ++j) {
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
context->error((*$2)[i].line, "duplicate field name in structure:", "struct", (*$2)[i].type->getFieldName().c_str());
for (size_t i = 0; i < $2->size(); ++i) {
TField* field = (*$2)[i];
for (size_t j = 0; j < $$->size(); ++j) {
if ((*$$)[j]->name() == field->name()) {
context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
context->recover();
}
}
$$->push_back((*$2)[i]);
$$->push_back(field);
}
}
;
......@@ -1558,7 +1559,7 @@ struct_declaration
struct_declarator_list
: struct_declarator {
$$ = NewPoolTTypeList();
$$ = NewPoolTFieldList();
$$->push_back($1);
}
| struct_declarator_list COMMA struct_declarator {
......@@ -1571,20 +1572,20 @@ struct_declarator
if (context->reservedErrorCheck(@1, *$1.string))
context->recover();
$$.type = new TType(EbtVoid, EbpUndefined);
$$.type->setFieldName(*$1.string);
TType* type = new TType(EbtVoid, EbpUndefined);
$$ = new TField(type, $1.string, @1);
}
| identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
if (context->reservedErrorCheck(@1, *$1.string))
context->recover();
$$.type = new TType(EbtVoid, EbpUndefined);
$$.type->setFieldName(*$1.string);
TType* type = new TType(EbtVoid, EbpUndefined);
int size;
if (context->arraySizeErrorCheck(@2, $3, size))
if (context->arraySizeErrorCheck(@3, $3, size))
context->recover();
$$.type->setArraySize(size);
type->setArraySize(size);
$$ = new TField(type, $1.string, @1);
}
;
......
......@@ -294,8 +294,8 @@ typedef union YYSTYPE
TQualifier qualifier;
TFunction* function;
TParameter param;
TTypeLine typeLine;
TTypeList* typeList;
TField* field;
TFieldList* fieldList;
};
} interm;
......@@ -808,13 +808,13 @@ static const yytype_uint16 yyrline[] =
1355, 1360, 1365, 1370, 1375, 1380, 1385, 1390, 1395, 1400,
1405, 1410, 1415, 1420, 1425, 1430, 1435, 1440, 1444, 1448,
1452, 1456, 1460, 1464, 1468, 1472, 1476, 1480, 1484, 1488,
1496, 1504, 1508, 1521, 1521, 1524, 1524, 1530, 1533, 1548,
1551, 1560, 1564, 1570, 1577, 1592, 1596, 1600, 1601, 1607,
1608, 1609, 1610, 1611, 1615, 1616, 1616, 1616, 1626, 1627,
1631, 1631, 1632, 1632, 1637, 1640, 1650, 1653, 1659, 1660,
1664, 1672, 1676, 1686, 1691, 1708, 1708, 1713, 1713, 1720,
1720, 1728, 1731, 1737, 1740, 1746, 1750, 1757, 1764, 1771,
1778, 1789, 1798, 1802, 1809, 1812, 1818, 1818
1496, 1504, 1508, 1521, 1521, 1524, 1524, 1530, 1533, 1549,
1552, 1561, 1565, 1571, 1578, 1593, 1597, 1601, 1602, 1608,
1609, 1610, 1611, 1612, 1616, 1617, 1617, 1617, 1627, 1628,
1632, 1632, 1633, 1633, 1638, 1641, 1651, 1654, 1660, 1661,
1665, 1673, 1677, 1687, 1692, 1709, 1709, 1714, 1714, 1721,
1721, 1729, 1732, 1738, 1741, 1747, 1751, 1758, 1765, 1772,
1779, 1790, 1799, 1803, 1810, 1813, 1819, 1819
};
#endif
......@@ -3333,7 +3333,7 @@ yyreduce:
{
ES3_ONLY(getQualifierString((yyvsp[(1) - (5)].interm.type).qualifier), (yylsp[(1) - (5)]), "interface blocks");
(yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[(1) - (5)].interm.type), (yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(3) - (5)].interm.typeList), "", (yyloc), NULL, (yyloc));
(yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[(1) - (5)].interm.type), (yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(3) - (5)].interm.fieldList), NULL, (yyloc), NULL, (yyloc));
}
break;
......@@ -3341,7 +3341,7 @@ yyreduce:
{
ES3_ONLY(getQualifierString((yyvsp[(1) - (6)].interm.type).qualifier), (yylsp[(1) - (6)]), "interface blocks");
(yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[(1) - (6)].interm.type), (yylsp[(2) - (6)]), *(yyvsp[(2) - (6)].lex).string, (yyvsp[(3) - (6)].interm.typeList), *(yyvsp[(5) - (6)].lex).string, (yylsp[(5) - (6)]), NULL, (yyloc));
(yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[(1) - (6)].interm.type), (yylsp[(2) - (6)]), *(yyvsp[(2) - (6)].lex).string, (yyvsp[(3) - (6)].interm.fieldList), (yyvsp[(5) - (6)].lex).string, (yylsp[(5) - (6)]), NULL, (yyloc));
}
break;
......@@ -3349,7 +3349,7 @@ yyreduce:
{
ES3_ONLY(getQualifierString((yyvsp[(1) - (9)].interm.type).qualifier), (yylsp[(1) - (9)]), "interface blocks");
(yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[(1) - (9)].interm.type), (yylsp[(2) - (9)]), *(yyvsp[(2) - (9)].lex).string, (yyvsp[(3) - (9)].interm.typeList), *(yyvsp[(5) - (9)].lex).string, (yylsp[(5) - (9)]), (yyvsp[(7) - (9)].interm.intermTypedNode), (yylsp[(6) - (9)]));
(yyval.interm.intermNode) = context->addInterfaceBlock((yyvsp[(1) - (9)].interm.type), (yylsp[(2) - (9)]), *(yyvsp[(2) - (9)].lex).string, (yyvsp[(3) - (9)].interm.fieldList), (yyvsp[(5) - (9)].lex).string, (yylsp[(5) - (9)]), (yyvsp[(7) - (9)].interm.intermTypedNode), (yylsp[(6) - (9)]));
}
break;
......@@ -4381,7 +4381,7 @@ yyreduce:
case 184:
{
(yyval.interm.type) = context->addStructure((yylsp[(1) - (6)]), (yylsp[(2) - (6)]), *(yyvsp[(2) - (6)].lex).string, (yyvsp[(5) - (6)].interm.typeList));
(yyval.interm.type) = context->addStructure((yylsp[(1) - (6)]), (yylsp[(2) - (6)]), (yyvsp[(2) - (6)].lex).string, (yyvsp[(5) - (6)].interm.fieldList));
}
break;
......@@ -4393,29 +4393,30 @@ yyreduce:
case 186:
{
(yyval.interm.type) = context->addStructure((yylsp[(1) - (5)]), (yyloc), "", (yyvsp[(4) - (5)].interm.typeList));
(yyval.interm.type) = context->addStructure((yylsp[(1) - (5)]), (yyloc), NewPoolTString(""), (yyvsp[(4) - (5)].interm.fieldList));
}
break;
case 187:
{
(yyval.interm.typeList) = (yyvsp[(1) - (1)].interm.typeList);
(yyval.interm.fieldList) = (yyvsp[(1) - (1)].interm.fieldList);
}
break;
case 188:
{
(yyval.interm.typeList) = (yyvsp[(1) - (2)].interm.typeList);
for (unsigned int i = 0; i < (yyvsp[(2) - (2)].interm.typeList)->size(); ++i) {
for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) {
if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName()) {
context->error((*(yyvsp[(2) - (2)].interm.typeList))[i].line, "duplicate field name in structure:", "struct", (*(yyvsp[(2) - (2)].interm.typeList))[i].type->getFieldName().c_str());
(yyval.interm.fieldList) = (yyvsp[(1) - (2)].interm.fieldList);
for (size_t i = 0; i < (yyvsp[(2) - (2)].interm.fieldList)->size(); ++i) {
TField* field = (*(yyvsp[(2) - (2)].interm.fieldList))[i];
for (size_t j = 0; j < (yyval.interm.fieldList)->size(); ++j) {
if ((*(yyval.interm.fieldList))[j]->name() == field->name()) {
context->error((yylsp[(2) - (2)]), "duplicate field name in structure:", "struct", field->name().c_str());
context->recover();
}
}
(yyval.interm.typeList)->push_back((*(yyvsp[(2) - (2)].interm.typeList))[i]);
(yyval.interm.fieldList)->push_back(field);
}
}
break;
......@@ -4423,7 +4424,7 @@ yyreduce:
case 189:
{
(yyval.interm.typeList) = context->addStructDeclaratorList((yyvsp[(1) - (3)].interm.type), (yyvsp[(2) - (3)].interm.typeList));
(yyval.interm.fieldList) = context->addStructDeclaratorList((yyvsp[(1) - (3)].interm.type), (yyvsp[(2) - (3)].interm.fieldList));
}
break;
......@@ -4433,22 +4434,22 @@ yyreduce:
// ES3 Only, but errors should be handled elsewhere
(yyvsp[(2) - (4)].interm.type).qualifier = (yyvsp[(1) - (4)].interm.type).qualifier;
(yyvsp[(2) - (4)].interm.type).layoutQualifier = (yyvsp[(1) - (4)].interm.type).layoutQualifier;
(yyval.interm.typeList) = context->addStructDeclaratorList((yyvsp[(2) - (4)].interm.type), (yyvsp[(3) - (4)].interm.typeList));
(yyval.interm.fieldList) = context->addStructDeclaratorList((yyvsp[(2) - (4)].interm.type), (yyvsp[(3) - (4)].interm.fieldList));
}
break;
case 191:
{
(yyval.interm.typeList) = NewPoolTTypeList();
(yyval.interm.typeList)->push_back((yyvsp[(1) - (1)].interm.typeLine));
(yyval.interm.fieldList) = NewPoolTFieldList();
(yyval.interm.fieldList)->push_back((yyvsp[(1) - (1)].interm.field));
}
break;
case 192:
{
(yyval.interm.typeList)->push_back((yyvsp[(3) - (3)].interm.typeLine));
(yyval.interm.fieldList)->push_back((yyvsp[(3) - (3)].interm.field));
}
break;
......@@ -4458,8 +4459,8 @@ yyreduce:
if (context->reservedErrorCheck((yylsp[(1) - (1)]), *(yyvsp[(1) - (1)].lex).string))
context->recover();
(yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
(yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (1)].lex).string);
TType* type = new TType(EbtVoid, EbpUndefined);
(yyval.interm.field) = new TField(type, (yyvsp[(1) - (1)].lex).string, (yylsp[(1) - (1)]));
}
break;
......@@ -4469,13 +4470,13 @@ yyreduce:
if (context->reservedErrorCheck((yylsp[(1) - (4)]), *(yyvsp[(1) - (4)].lex).string))
context->recover();
(yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
(yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (4)].lex).string);
TType* type = new TType(EbtVoid, EbpUndefined);
int size;
if (context->arraySizeErrorCheck((yylsp[(2) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size))
if (context->arraySizeErrorCheck((yylsp[(3) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size))
context->recover();
(yyval.interm.typeLine).type->setArraySize(size);
type->setArraySize(size);
(yyval.interm.field) = new TField(type, (yyvsp[(1) - (4)].lex).string, (yylsp[(1) - (4)]));
}
break;
......
......@@ -211,8 +211,8 @@ typedef union YYSTYPE
TQualifier qualifier;
TFunction* function;
TParameter param;
TTypeLine typeLine;
TTypeList* typeList;
TField* field;
TFieldList* fieldList;
};
} interm;
......
......@@ -271,6 +271,7 @@ public:
int getNominalSize() const { return type.getNominalSize(); }
int getSecondarySize() const { return type.getSecondarySize(); }
bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
bool isMatrix() const { return type.isMatrix(); }
bool isArray() const { return type.isArray(); }
bool isVector() const { return type.isVector(); }
......
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