Commit c2d1a464 by Shahbaz Youssefi Committed by Commit Bot

Translator: Track nameless interface block field indices in type

Fields of nameless interface blocks are stored as TVariables and referenced through a TIntermSymbols (unlike named blocks which use EOpIndexDirectInterfaceBlock with a constant field indices). With this change, the field index is stored in the variable's type which let's the TField of the TInterfaceBlock be directly accessible (and not need a search by name). This will be helpful in translation to SPIR-V as interface block members are accessed by field index. Bug: angleproject:4889 Change-Id: If3ab45b1e5f5f9576721dc52e2bdf1161882514f Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2818242 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent 6ec55494
...@@ -4506,7 +4506,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock( ...@@ -4506,7 +4506,7 @@ TIntermDeclaration *TParseContext::addInterfaceBlock(
TType *fieldType = new TType(*field->type()); TType *fieldType = new TType(*field->type());
// set parent pointer of the field variable // set parent pointer of the field variable
fieldType->setInterfaceBlock(interfaceBlock); fieldType->setInterfaceBlockField(interfaceBlock, memberIndex);
fieldType->setQualifier(typeQualifier.qualifier); fieldType->setQualifier(typeQualifier.qualifier);
......
...@@ -207,11 +207,14 @@ bool DeclareDefaultUniforms(TCompiler *compiler, ...@@ -207,11 +207,14 @@ bool DeclareDefaultUniforms(TCompiler *compiler,
// Create a map from the uniform variables to new variables that reference the fields of the // Create a map from the uniform variables to new variables that reference the fields of the
// block. // block.
VariableReplacementMap variableMap; VariableReplacementMap variableMap;
for (const TVariable *variable : uniformVars) for (size_t fieldIndex = 0; fieldIndex < uniformVars.size(); ++fieldIndex)
{ {
const TVariable *variable = uniformVars[fieldIndex];
TType *replacementType = new TType(variable->getType()); TType *replacementType = new TType(variable->getType());
replacementType->setPrecision(EbpUndefined); replacementType->setPrecision(EbpUndefined);
replacementType->setInterfaceBlock(uniformBlock->getType().getInterfaceBlock()); replacementType->setInterfaceBlockField(uniformBlock->getType().getInterfaceBlock(),
fieldIndex);
TVariable *replacementVariable = TVariable *replacementVariable =
new TVariable(symbolTable, variable->name(), replacementType, variable->symbolType()); new TVariable(symbolTable, variable->name(), replacementType, variable->symbolType());
......
...@@ -185,6 +185,7 @@ TType::TType(const TPublicType &p) ...@@ -185,6 +185,7 @@ TType::TType(const TPublicType &p)
mInterfaceBlock(nullptr), mInterfaceBlock(nullptr),
mStructure(nullptr), mStructure(nullptr),
mIsStructSpecifier(false), mIsStructSpecifier(false),
mInterfaceBlockFieldIndex(0),
mMangledName(nullptr) mMangledName(nullptr)
{ {
ASSERT(primarySize <= 4); ASSERT(primarySize <= 4);
...@@ -223,20 +224,21 @@ TType::TType(const TType &t) ...@@ -223,20 +224,21 @@ TType::TType(const TType &t)
TType &TType::operator=(const TType &t) TType &TType::operator=(const TType &t)
{ {
type = t.type; type = t.type;
precision = t.precision; precision = t.precision;
qualifier = t.qualifier; qualifier = t.qualifier;
invariant = t.invariant; invariant = t.invariant;
precise = t.precise; precise = t.precise;
memoryQualifier = t.memoryQualifier; memoryQualifier = t.memoryQualifier;
layoutQualifier = t.layoutQualifier; layoutQualifier = t.layoutQualifier;
primarySize = t.primarySize; primarySize = t.primarySize;
secondarySize = t.secondarySize; secondarySize = t.secondarySize;
mArraySizesStorage = nullptr; mArraySizesStorage = nullptr;
mInterfaceBlock = t.mInterfaceBlock; mInterfaceBlock = t.mInterfaceBlock;
mStructure = t.mStructure; mStructure = t.mStructure;
mIsStructSpecifier = t.mIsStructSpecifier; mIsStructSpecifier = t.mIsStructSpecifier;
mMangledName = t.mMangledName; mInterfaceBlockFieldIndex = t.mInterfaceBlockFieldIndex;
mMangledName = t.mMangledName;
if (t.mArraySizesStorage) if (t.mArraySizesStorage)
{ {
...@@ -707,6 +709,12 @@ void TType::setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn) ...@@ -707,6 +709,12 @@ void TType::setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn)
} }
} }
void TType::setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex)
{
setInterfaceBlock(interfaceBlockIn);
mInterfaceBlockFieldIndex = fieldIndex;
}
const char *TType::getMangledName() const const char *TType::getMangledName() const
{ {
if (mMangledName == nullptr) if (mMangledName == nullptr)
......
...@@ -128,6 +128,7 @@ class TType ...@@ -128,6 +128,7 @@ class TType
mInterfaceBlock(nullptr), mInterfaceBlock(nullptr),
mStructure(nullptr), mStructure(nullptr),
mIsStructSpecifier(false), mIsStructSpecifier(false),
mInterfaceBlockFieldIndex(0),
mMangledName(mangledName) mMangledName(mangledName)
{} {}
...@@ -146,6 +147,7 @@ class TType ...@@ -146,6 +147,7 @@ class TType
mInterfaceBlock(t.mInterfaceBlock), mInterfaceBlock(t.mInterfaceBlock),
mStructure(t.mStructure), mStructure(t.mStructure),
mIsStructSpecifier(t.mIsStructSpecifier), mIsStructSpecifier(t.mIsStructSpecifier),
mInterfaceBlockFieldIndex(0),
mMangledName(t.mMangledName) mMangledName(t.mMangledName)
{ {
t.mArraySizesStorage = nullptr; t.mArraySizesStorage = nullptr;
...@@ -230,6 +232,9 @@ class TType ...@@ -230,6 +232,9 @@ class TType
void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn); void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn);
bool isInterfaceBlock() const { return type == EbtInterfaceBlock; } bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
void setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex);
size_t getInterfaceBlockFieldIndex() const { return mInterfaceBlockFieldIndex; }
bool isVector() const { return primarySize > 1 && secondarySize == 1; } bool isVector() const { return primarySize > 1 && secondarySize == 1; }
bool isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); } bool isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); }
bool isScalar() const bool isScalar() const
...@@ -389,6 +394,10 @@ class TType ...@@ -389,6 +394,10 @@ class TType
const TStructure *mStructure; const TStructure *mStructure;
bool mIsStructSpecifier; bool mIsStructSpecifier;
// If this is a field of a nameless interface block, this would indicate which member it's
// refering to.
size_t mInterfaceBlockFieldIndex;
mutable const char *mMangledName; mutable const char *mMangledName;
}; };
......
...@@ -67,7 +67,7 @@ class ValidateAST : public TIntermTraverser ...@@ -67,7 +67,7 @@ class ValidateAST : public TIntermTraverser
// For validateVariableReferences: // For validateVariableReferences:
std::vector<std::set<const TVariable *>> mDeclaredVariables; std::vector<std::set<const TVariable *>> mDeclaredVariables;
std::set<ImmutableString> mNamelessInterfaceBlockFields; std::set<const TInterfaceBlock *> mNamelessInterfaceBlocks;
bool mVariableReferencesFailed = false; bool mVariableReferencesFailed = false;
// For validateNullNodes: // For validateNullNodes:
...@@ -210,14 +210,27 @@ void ValidateAST::visitSymbol(TIntermSymbol *node) ...@@ -210,14 +210,27 @@ void ValidateAST::visitSymbol(TIntermSymbol *node)
if (mOptions.validateVariableReferences && variableNeedsDeclaration(variable)) if (mOptions.validateVariableReferences && variableNeedsDeclaration(variable))
{ {
// If it's a reference to a field of a nameless interface block, match it by name. // If it's a reference to a field of a nameless interface block, match it by index and name.
if (type.getInterfaceBlock() && !type.isInterfaceBlock()) if (type.getInterfaceBlock() && !type.isInterfaceBlock())
{ {
if (mNamelessInterfaceBlockFields.count(node->getName()) == 0) const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
const TFieldList &fieldList = interfaceBlock->fields();
const size_t fieldIndex = type.getInterfaceBlockFieldIndex();
if (mNamelessInterfaceBlocks.count(interfaceBlock) == 0)
{ {
mDiagnostics->error(node->getLine(), mDiagnostics->error(node->getLine(),
"Found reference to undeclared nameless interface block field " "Found reference to undeclared or inconsistenly redeclared "
"<validateVariableReferences>", "nameless interface block <validateVariableReferences>",
node->getName().data());
mVariableReferencesFailed = true;
}
else if (fieldIndex >= fieldList.size() ||
node->getName() != fieldList[fieldIndex]->name())
{
mDiagnostics->error(node->getLine(),
"Found reference to inconsistenly redeclared nameless "
"interface block field <validateVariableReferences>",
node->getName().data()); node->getName().data());
mVariableReferencesFailed = true; mVariableReferencesFailed = true;
} }
...@@ -380,23 +393,17 @@ bool ValidateAST::visitDeclaration(Visit visit, TIntermDeclaration *node) ...@@ -380,23 +393,17 @@ bool ValidateAST::visitDeclaration(Visit visit, TIntermDeclaration *node)
mDeclaredVariables.back().insert(variable); mDeclaredVariables.back().insert(variable);
if (variable->symbolType() == SymbolType::Empty && const TInterfaceBlock *interfaceBlock = variable->getType().getInterfaceBlock();
variable->getType().getInterfaceBlock())
if (variable->symbolType() == SymbolType::Empty && interfaceBlock != nullptr)
{ {
// Nameless interface blocks can only be declared at the top level. Their fields // Nameless interface blocks can only be declared at the top level. Their fields
// are not identified by TVariables, so resort to name-matching. Conflict in names // are matched by field index, and then verified to match by name. Conflict in
// should have already generated a compile error. // names should have already generated a compile error.
ASSERT(mDeclaredVariables.size() == 1); ASSERT(mDeclaredVariables.size() == 1);
ASSERT(mNamelessInterfaceBlocks.count(interfaceBlock) == 0);
const TFieldList &fieldList = variable->getType().getInterfaceBlock()->fields(); mNamelessInterfaceBlocks.insert(interfaceBlock);
for (size_t memberIndex = 0; memberIndex < fieldList.size(); ++memberIndex)
{
TField *field = fieldList[memberIndex];
ASSERT(mNamelessInterfaceBlockFields.count(field->name()) == 0);
mNamelessInterfaceBlockFields.insert(field->name());
}
} }
} }
} }
......
...@@ -663,35 +663,29 @@ class RewriteRowMajorMatricesTraverser : public TIntermTraverser ...@@ -663,35 +663,29 @@ class RewriteRowMajorMatricesTraverser : public TIntermTraverser
// Find which field it is // Find which field it is
const TVector<TField *> fields = interfaceBlock->fields(); const TVector<TField *> fields = interfaceBlock->fields();
for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex) const size_t fieldIndex = variable->getType().getInterfaceBlockFieldIndex();
{ ASSERT(fieldIndex < fields.size());
const TField *field = fields[fieldIndex];
if (field->name() != symbolName)
{
continue;
}
// If this field doesn't need a rewrite, there's nothing to do. const TField *field = fields[fieldIndex];
if (mInterfaceBlockFieldConvertedIn.count(field) == 0 || ASSERT(field->name() == symbolName);
!mInterfaceBlockFieldConvertedIn.at(field))
{
break;
}
// Create a new variable that references the replaced interface block. // If this field doesn't need a rewrite, there's nothing to do.
TType *newType = new TType(variable->getType()); if (mInterfaceBlockFieldConvertedIn.count(field) == 0 ||
newType->setInterfaceBlock(iter.second->getType().getInterfaceBlock()); !mInterfaceBlockFieldConvertedIn.at(field))
{
break;
}
TVariable *newVariable = // Create a new variable that references the replaced interface block.
new TVariable(mSymbolTable, variable->name(), newType, variable->symbolType(), TType *newType = new TType(variable->getType());
variable->extension()); newType->setInterfaceBlockField(iter.second->getType().getInterfaceBlock(), fieldIndex);
(*mInterfaceBlockMap)[variable] = newVariable; TVariable *newVariable = new TVariable(mSymbolTable, variable->name(), newType,
variable->symbolType(), variable->extension());
return true; (*mInterfaceBlockMap)[variable] = newVariable;
}
break; return true;
} }
return false; return false;
......
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