Fix glslang can't link multiple AST in a single stage

Root cause:
GlslangToSpv use symbol structure's ptr as a map key, but multiple shader object can build a new AST.
In the AST the the same symbol has different ptr point to their structure, so indext map faild.

solution:
Add a new map glslangTypeToIdMap to map ptr to symbol id, and use symbol id to index memberRemapper.
This commit is contained in:
Roy 2020-01-03 16:21:34 +08:00
parent 6334d594f6
commit 05a5b53208

View File

@ -245,7 +245,9 @@ protected:
std::unordered_map<std::string, spv::Function*> functionMap; std::unordered_map<std::string, spv::Function*> functionMap;
std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount]; std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
// for mapping glslang block indices to spv indices (e.g., due to hidden members): // for mapping glslang block indices to spv indices (e.g., due to hidden members):
std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper; std::unordered_map<int, std::vector<int>> memberRemapper;
// for mapping glslang symbol struct to symbol Id
std::unordered_map<const glslang::TTypeList*, int> glslangTypeToIdMap;
std::stack<bool> breakForLoop; // false means break for switch std::stack<bool> breakForLoop; // false means break for switch
std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator; std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
// Map pointee types for EbtReference to their forward pointers // Map pointee types for EbtReference to their forward pointers
@ -1661,6 +1663,9 @@ void TGlslangToSpvTraverser::dumpSpv(std::vector<unsigned int>& out)
void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
{ {
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (symbol->getType().isStruct())
glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId();
if (symbol->getType().getQualifier().isSpecConstant()) if (symbol->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
@ -1753,6 +1758,12 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node)
{ {
builder.setLine(node->getLoc().line, node->getLoc().getFilename()); builder.setLine(node->getLoc().line, node->getLoc().getFilename());
if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) {
glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId();
}
if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) {
glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId();
}
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant()) if (node->getType().getQualifier().isSpecConstant())
@ -1857,9 +1868,12 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
{ {
// This may be, e.g., an anonymous block-member selection, which generally need // This may be, e.g., an anonymous block-member selection, which generally need
// index remapping due to hidden members in anonymous blocks. // index remapping due to hidden members in anonymous blocks.
std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()]; int glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()];
assert(remapper.size() > 0); if (memberRemapper.find(glslangId) != memberRemapper.end()) {
spvIndex = remapper[glslangIndex]; std::vector<int>& remapper = memberRemapper[glslangId];
assert(remapper.size() > 0);
spvIndex = remapper[glslangIndex];
}
} }
// normal case for indexing array or structure or block // normal case for indexing array or structure or block
@ -3483,7 +3497,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
// else, we haven't seen it... // else, we haven't seen it...
if (type.getBasicType() == glslang::EbtBlock) if (type.getBasicType() == glslang::EbtBlock)
memberRemapper[glslangMembers].resize(glslangMembers->size()); memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size());
spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier);
} }
break; break;
@ -3619,15 +3633,15 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy
if (glslangMember.hiddenMember()) { if (glslangMember.hiddenMember()) {
++memberDelta; ++memberDelta;
if (type.getBasicType() == glslang::EbtBlock) if (type.getBasicType() == glslang::EbtBlock)
memberRemapper[glslangMembers][i] = -1; memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
} else { } else {
if (type.getBasicType() == glslang::EbtBlock) { if (type.getBasicType() == glslang::EbtBlock) {
if (filterMember(glslangMember)) { if (filterMember(glslangMember)) {
memberDelta++; memberDelta++;
memberRemapper[glslangMembers][i] = -1; memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1;
continue; continue;
} }
memberRemapper[glslangMembers][i] = i - memberDelta; memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta;
} }
// modify just this child's view of the qualifier // modify just this child's view of the qualifier
glslang::TQualifier memberQualifier = glslangMember.getQualifier(); glslang::TQualifier memberQualifier = glslangMember.getQualifier();
@ -3685,7 +3699,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
glslang::TType& glslangMember = *(*glslangMembers)[i].type; glslang::TType& glslangMember = *(*glslangMembers)[i].type;
int member = i; int member = i;
if (type.getBasicType() == glslang::EbtBlock) { if (type.getBasicType() == glslang::EbtBlock) {
member = memberRemapper[glslangMembers][i]; member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i];
if (filterMember(glslangMember)) if (filterMember(glslangMember))
continue; continue;
} }