From b239d22f7be2ca73230b50d660969ebe8b43dd2a Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine <arseny.kapoulkine@gmail.com> Date: Mon, 21 May 2018 15:27:07 -0700 Subject: [PATCH] Fix TextureUpgradeAndSamplerRemovalTransform when used with qualifiers The transform removes sampler arguments from functions and function calls; this causes function arguments to change their indices. When some function arguments have an output qualifier, this qualifier can get lost because of the removal which can lead to incorrect results (e.g. out qualifier not having effect). To fix this we iterate through both seq & qual arrays in lock-step and manually remove/replace entries as appropriate. --- glslang/MachineIndependent/Intermediate.cpp | 42 ++++++++++++++------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 0333e5d01..de722179c 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -3769,23 +3769,39 @@ struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser { bool visitAggregate(TVisit, TIntermAggregate* ag) override { using namespace std; TIntermSequence& seq = ag->getSequence(); - // remove pure sampler variables - TIntermSequence::iterator newEnd = remove_if(seq.begin(), seq.end(), [](TIntermNode* node) { - TIntermSymbol* symbol = node->getAsSymbolNode(); - if (!symbol) - return false; + TQualifierList& qual = ag->getQualifierList(); + + // qual and seq are indexed using the same indices, so we have to modify both in lock-step + assert(seq.size() == qual.size() || qual.empty()); + + size_t write = 0; + for (size_t i = 0; i < seq.size(); ++i) { + TIntermSymbol* symbol = seq[i]->getAsSymbolNode(); + if (symbol && symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()) { + // remove pure sampler variables + continue; + } + + TIntermNode* result = seq[i]; - return (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()); - }); - seq.erase(newEnd, seq.end()); - // replace constructors with sampler/textures - for_each(seq.begin(), seq.end(), [](TIntermNode*& node) { - TIntermAggregate *constructor = node->getAsAggregate(); + // replace constructors with sampler/textures + TIntermAggregate *constructor = seq[i]->getAsAggregate(); if (constructor && constructor->getOp() == EOpConstructTextureSampler) { if (!constructor->getSequence().empty()) - node = constructor->getSequence()[0]; + result = constructor->getSequence()[0]; } - }); + + // write new node & qualifier + seq[write] = result; + if (!qual.empty()) + qual[write] = qual[i]; + write++; + } + + seq.resize(write); + if (!qual.empty()) + qual.resize(write); + return true; } }; -- GitLab