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(
TType *fieldType = new TType(*field->type());
// set parent pointer of the field variable
fieldType->setInterfaceBlock(interfaceBlock);
fieldType->setInterfaceBlockField(interfaceBlock, memberIndex);
fieldType->setQualifier(typeQualifier.qualifier);
......
......@@ -207,11 +207,14 @@ bool DeclareDefaultUniforms(TCompiler *compiler,
// Create a map from the uniform variables to new variables that reference the fields of the
// block.
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());
replacementType->setPrecision(EbpUndefined);
replacementType->setInterfaceBlock(uniformBlock->getType().getInterfaceBlock());
replacementType->setInterfaceBlockField(uniformBlock->getType().getInterfaceBlock(),
fieldIndex);
TVariable *replacementVariable =
new TVariable(symbolTable, variable->name(), replacementType, variable->symbolType());
......
......@@ -185,6 +185,7 @@ TType::TType(const TPublicType &p)
mInterfaceBlock(nullptr),
mStructure(nullptr),
mIsStructSpecifier(false),
mInterfaceBlockFieldIndex(0),
mMangledName(nullptr)
{
ASSERT(primarySize <= 4);
......@@ -223,20 +224,21 @@ TType::TType(const TType &t)
TType &TType::operator=(const TType &t)
{
type = t.type;
precision = t.precision;
qualifier = t.qualifier;
invariant = t.invariant;
precise = t.precise;
memoryQualifier = t.memoryQualifier;
layoutQualifier = t.layoutQualifier;
primarySize = t.primarySize;
secondarySize = t.secondarySize;
mArraySizesStorage = nullptr;
mInterfaceBlock = t.mInterfaceBlock;
mStructure = t.mStructure;
mIsStructSpecifier = t.mIsStructSpecifier;
mMangledName = t.mMangledName;
type = t.type;
precision = t.precision;
qualifier = t.qualifier;
invariant = t.invariant;
precise = t.precise;
memoryQualifier = t.memoryQualifier;
layoutQualifier = t.layoutQualifier;
primarySize = t.primarySize;
secondarySize = t.secondarySize;
mArraySizesStorage = nullptr;
mInterfaceBlock = t.mInterfaceBlock;
mStructure = t.mStructure;
mIsStructSpecifier = t.mIsStructSpecifier;
mInterfaceBlockFieldIndex = t.mInterfaceBlockFieldIndex;
mMangledName = t.mMangledName;
if (t.mArraySizesStorage)
{
......@@ -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
{
if (mMangledName == nullptr)
......
......@@ -128,6 +128,7 @@ class TType
mInterfaceBlock(nullptr),
mStructure(nullptr),
mIsStructSpecifier(false),
mInterfaceBlockFieldIndex(0),
mMangledName(mangledName)
{}
......@@ -146,6 +147,7 @@ class TType
mInterfaceBlock(t.mInterfaceBlock),
mStructure(t.mStructure),
mIsStructSpecifier(t.mIsStructSpecifier),
mInterfaceBlockFieldIndex(0),
mMangledName(t.mMangledName)
{
t.mArraySizesStorage = nullptr;
......@@ -230,6 +232,9 @@ class TType
void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn);
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 isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); }
bool isScalar() const
......@@ -389,6 +394,10 @@ class TType
const TStructure *mStructure;
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;
};
......
......@@ -67,7 +67,7 @@ class ValidateAST : public TIntermTraverser
// For validateVariableReferences:
std::vector<std::set<const TVariable *>> mDeclaredVariables;
std::set<ImmutableString> mNamelessInterfaceBlockFields;
std::set<const TInterfaceBlock *> mNamelessInterfaceBlocks;
bool mVariableReferencesFailed = false;
// For validateNullNodes:
......@@ -210,14 +210,27 @@ void ValidateAST::visitSymbol(TIntermSymbol *node)
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 (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(),
"Found reference to undeclared nameless interface block field "
"<validateVariableReferences>",
"Found reference to undeclared or inconsistenly redeclared "
"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());
mVariableReferencesFailed = true;
}
......@@ -380,23 +393,17 @@ bool ValidateAST::visitDeclaration(Visit visit, TIntermDeclaration *node)
mDeclaredVariables.back().insert(variable);
if (variable->symbolType() == SymbolType::Empty &&
variable->getType().getInterfaceBlock())
const TInterfaceBlock *interfaceBlock = variable->getType().getInterfaceBlock();
if (variable->symbolType() == SymbolType::Empty && interfaceBlock != nullptr)
{
// 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
// should have already generated a compile error.
// are matched by field index, and then verified to match by name. Conflict in
// names should have already generated a compile error.
ASSERT(mDeclaredVariables.size() == 1);
ASSERT(mNamelessInterfaceBlocks.count(interfaceBlock) == 0);
const TFieldList &fieldList = variable->getType().getInterfaceBlock()->fields();
for (size_t memberIndex = 0; memberIndex < fieldList.size(); ++memberIndex)
{
TField *field = fieldList[memberIndex];
ASSERT(mNamelessInterfaceBlockFields.count(field->name()) == 0);
mNamelessInterfaceBlockFields.insert(field->name());
}
mNamelessInterfaceBlocks.insert(interfaceBlock);
}
}
}
......
......@@ -663,35 +663,29 @@ class RewriteRowMajorMatricesTraverser : public TIntermTraverser
// Find which field it is
const TVector<TField *> fields = interfaceBlock->fields();
for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
{
const TField *field = fields[fieldIndex];
if (field->name() != symbolName)
{
continue;
}
const size_t fieldIndex = variable->getType().getInterfaceBlockFieldIndex();
ASSERT(fieldIndex < fields.size());
// If this field doesn't need a rewrite, there's nothing to do.
if (mInterfaceBlockFieldConvertedIn.count(field) == 0 ||
!mInterfaceBlockFieldConvertedIn.at(field))
{
break;
}
const TField *field = fields[fieldIndex];
ASSERT(field->name() == symbolName);
// Create a new variable that references the replaced interface block.
TType *newType = new TType(variable->getType());
newType->setInterfaceBlock(iter.second->getType().getInterfaceBlock());
// If this field doesn't need a rewrite, there's nothing to do.
if (mInterfaceBlockFieldConvertedIn.count(field) == 0 ||
!mInterfaceBlockFieldConvertedIn.at(field))
{
break;
}
TVariable *newVariable =
new TVariable(mSymbolTable, variable->name(), newType, variable->symbolType(),
variable->extension());
// Create a new variable that references the replaced interface block.
TType *newType = new TType(variable->getType());
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;
......
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