Fix issue with remapping global uniform blocks

Avoid adding global uniform blocks to stages that don't already have it.
Otherwise multiple stages point to the same block object, and a
remapping that occurs later on will change the mapping on multiple
stages.
This commit is contained in:
Malcolm Bechard 2021-03-17 18:47:13 -04:00
parent 48f08c60e2
commit 5340752190
7 changed files with 332 additions and 6 deletions

View file

@ -2124,7 +2124,12 @@ bool TProgram::crossStageCheck(EShMessages) {
// copy final definition of global block back into each stage
for (unsigned int i = 0; i < activeStages.size(); ++i) {
activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms);
// We only want to merge into already existing global uniform blocks.
// A stage that doesn't already know about the global doesn't care about it's content.
// Otherwise we end up pointing to the same object between different stages
// and that will break binding/set remappings
bool mergeExistingOnly = true;
activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms, mergeExistingOnly);
}
// compare cross stage symbols for each stage boundary

View file

@ -108,7 +108,8 @@ void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit
unitLinkerObjects.resize(end - unitLinkerObjects.begin());
// merge uniforms and do error checking
mergeGlobalUniformBlocks(infoSink, unit);
bool mergeExistingOnly = false;
mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly);
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
}
@ -362,7 +363,8 @@ void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
remapIds(idMaps, idShift + 1, unit);
mergeBodies(infoSink, globals, unitGlobals);
mergeGlobalUniformBlocks(infoSink, unit);
bool mergeExistingOnly = false;
mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly);
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage());
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
}
@ -525,7 +527,7 @@ static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIn
// merge the members of different stages to allow them to be linked properly
// as a single block
//
void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit)
void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly)
{
TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
@ -552,7 +554,7 @@ void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate&
auto itUnitBlock = unitDefaultBlocks.begin();
for (; itUnitBlock != unitDefaultBlocks.end(); itUnitBlock++) {
bool add = true;
bool add = !mergeExistingOnly;
auto itBlock = defaultBlocks.begin();
for (; itBlock != defaultBlocks.end(); itBlock++) {

View file

@ -915,7 +915,7 @@ public:
void merge(TInfoSink&, TIntermediate&);
void finalCheck(TInfoSink&, bool keepUncalled);
void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit);
void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly);
void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit);
void checkStageIO(TInfoSink&, TIntermediate&);