//
// Copyright (C) 2016-2017 LunarG, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//    Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
//    Redistributions in binary form must reproduce the above
//    copyright notice, this list of conditions and the following
//    disclaimer in the documentation and/or other materials provided
//    with the distribution.
//
//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)

#include "../Include/Common.h"
#include "../Include/InfoSink.h"
#include "../Include/Types.h"

#include "gl_types.h"
#include "iomapper.h"
#include "SymbolTable.h"

//
// Map IO bindings.
//
// High-level algorithm for one stage:
//
// 1. Traverse all code (live+dead) to find the explicitly provided bindings.
//
// 2. Traverse (just) the live code to determine which non-provided bindings
//    require auto-numbering.  We do not auto-number dead ones.
//
// 3. Traverse all the code to apply the bindings:
//    a. explicitly given bindings are offset according to their type
//    b. implicit live bindings are auto-numbered into the holes, using
//       any open binding slot.
//    c. implicit dead bindings are left un-bound.
//

namespace glslang {

class TVarGatherTraverser : public TLiveTraverser {
public:
    TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList)
      : TLiveTraverser(i, traverseDeadCode, true, true, false)
      , inputList(inList)
      , outputList(outList)
      , uniformList(uniformList)
    {
    }

    virtual void visitSymbol(TIntermSymbol* base)
    {
        TVarLiveMap* target = nullptr;
        if (base->getQualifier().storage == EvqVaryingIn)
            target = &inputList;
        else if (base->getQualifier().storage == EvqVaryingOut)
            target = &outputList;
        else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant() && !base->getQualifier().isShaderRecord())
            target = &uniformList;
        // If a global is being visited, then we should also traverse it incase it's evaluation
        // ends up visiting inputs we want to tag as live
        else if (base->getQualifier().storage == EvqGlobal)
            addGlobalReference(base->getAccessName());

        if (target) {
            TVarEntryInfo ent = {base->getId(), base, ! traverseAll};
            ent.stage = intermediate.getStage();
            TVarLiveMap::iterator at = target->find(
                ent.symbol->getAccessName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
            if (at != target->end() && at->second.id == ent.id)
                at->second.live = at->second.live || ! traverseAll; // update live state
            else
                (*target)[ent.symbol->getAccessName()] = ent;
        }
    }

private:
    TVarLiveMap&    inputList;
    TVarLiveMap&    outputList;
    TVarLiveMap&    uniformList;
};

class TVarSetTraverser : public TLiveTraverser
{
public:
    TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& inList, const TVarLiveMap& outList, const TVarLiveMap& uniformList)
      : TLiveTraverser(i, true, true, true, false)
      , inputList(inList)
      , outputList(outList)
      , uniformList(uniformList)
    {
    }

    virtual void visitSymbol(TIntermSymbol* base) {
        const TVarLiveMap* source;
        if (base->getQualifier().storage == EvqVaryingIn)
            source = &inputList;
        else if (base->getQualifier().storage == EvqVaryingOut)
            source = &outputList;
        else if (base->getQualifier().isUniformOrBuffer())
            source = &uniformList;
        else
            return;

        TVarEntryInfo ent = { base->getId() };
        // Fix a defect, when block has no instance name, we need to find its block name
        TVarLiveMap::const_iterator at = source->find(base->getAccessName());
        if (at == source->end())
            return;

        if (at->second.id != ent.id)
            return;

        if (at->second.newBinding != -1)
            base->getWritableType().getQualifier().layoutBinding = at->second.newBinding;
        if (at->second.newSet != -1)
            base->getWritableType().getQualifier().layoutSet = at->second.newSet;
        if (at->second.newLocation != -1)
            base->getWritableType().getQualifier().layoutLocation = at->second.newLocation;
        if (at->second.newComponent != -1)
            base->getWritableType().getQualifier().layoutComponent = at->second.newComponent;
        if (at->second.newIndex != -1)
            base->getWritableType().getQualifier().layoutIndex = at->second.newIndex;
    }

  private:
    const TVarLiveMap&    inputList;
    const TVarLiveMap&    outputList;
    const TVarLiveMap&    uniformList;
};

struct TNotifyUniformAdaptor
{
    EShLanguage stage;
    TIoMapResolver& resolver;
    inline TNotifyUniformAdaptor(EShLanguage s, TIoMapResolver& r)
      : stage(s)
      , resolver(r)
    {
    }

    inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
    {
        resolver.notifyBinding(stage, entKey.second);
    }

private:
    TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&) = delete;
};

struct TNotifyInOutAdaptor
{
    EShLanguage stage;
    TIoMapResolver& resolver;
    inline TNotifyInOutAdaptor(EShLanguage s, TIoMapResolver& r) 
      : stage(s)
      , resolver(r)
    {
    }

    inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
    {
        resolver.notifyInOut(entKey.second.stage, entKey.second);
    }

private:
    TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&) = delete;
};

struct TResolverUniformAdaptor {
    TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TVarLiveMap* uniform[EShLangCount], TInfoSink& i, bool& e)
      : stage(s)
      , resolver(r)
      , infoSink(i)
      , error(e)
    {
        memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));
    }

    inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
        TVarEntryInfo& ent = entKey.second;
        ent.newLocation = -1;
        ent.newComponent = -1;
        ent.newBinding = -1;
        ent.newSet = -1;
        ent.newIndex = -1;
        const bool isValid = resolver.validateBinding(stage, ent);
        if (isValid) {
            resolver.resolveSet(ent.stage, ent);
            resolver.resolveBinding(ent.stage, ent);
            resolver.resolveUniformLocation(ent.stage, ent);

            if (ent.newBinding != -1) {
                if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) {
                    TString err = "mapped binding out of range: " + entKey.first;

                    infoSink.info.message(EPrefixInternalError, err.c_str());
                    error = true;
                }

                if (ent.symbol->getQualifier().hasBinding()) {
                    for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
                        if (idx == ent.stage || uniformVarMap[idx] == nullptr)
                            continue;
                        auto entKey2 = uniformVarMap[idx]->find(entKey.first);
                        if (entKey2 != uniformVarMap[idx]->end()) {
                            entKey2->second.newBinding = ent.newBinding;
                        }
                    }
                }
            }
            if (ent.newSet != -1) {
                if (ent.newSet >= int(TQualifier::layoutSetEnd)) {
                    TString err = "mapped set out of range: " + entKey.first;

                    infoSink.info.message(EPrefixInternalError, err.c_str());
                    error = true;
                }
                if (ent.symbol->getQualifier().hasSet()) {
                    for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) {
                        if ((idx == stage) || (uniformVarMap[idx] == nullptr))
                            continue;
                        auto entKey2 = uniformVarMap[idx]->find(entKey.first);
                        if (entKey2 != uniformVarMap[idx]->end()) {
                            entKey2->second.newSet = ent.newSet;
                        }
                    }
                }
            }
        } else {
            TString errorMsg = "Invalid binding: " + entKey.first;
            infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
            error = true;
        }
    }

    inline void setStage(EShLanguage s) { stage = s; }

    EShLanguage     stage;
    TIoMapResolver& resolver;
    TInfoSink&      infoSink;
    bool&           error;
    TVarLiveMap*    uniformVarMap[EShLangCount];
private:
    TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete;
};

struct TResolverInOutAdaptor {
    TResolverInOutAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
      : stage(s)
      , resolver(r)
      , infoSink(i)
      , error(e)
    {
    }

    inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey)
    {
        TVarEntryInfo& ent = entKey.second;
        ent.newLocation = -1;
        ent.newComponent = -1;
        ent.newBinding = -1;
        ent.newSet = -1;
        ent.newIndex = -1;
        const bool isValid = resolver.validateInOut(ent.stage, ent);
        if (isValid) {
            resolver.resolveInOutLocation(stage, ent);
            resolver.resolveInOutComponent(stage, ent);
            resolver.resolveInOutIndex(stage, ent);
        } else {
            TString errorMsg;
            if (ent.symbol->getType().getQualifier().semanticName != nullptr) {
                errorMsg = "Invalid shader In/Out variable semantic: ";
                errorMsg += ent.symbol->getType().getQualifier().semanticName;
            } else {
                errorMsg = "Invalid shader In/Out variable: ";
                errorMsg += ent.symbol->getName();
            }
            infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
            error = true;
        }
    }

    inline void setStage(EShLanguage s) { stage = s; }

    EShLanguage     stage;
    TIoMapResolver& resolver;
    TInfoSink&      infoSink;
    bool&           error;

private:
    TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&) = delete;
};

// The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings
// xxTODO: maybe this logic should be moved into the resolver's "validateInOut" and "validateUniform"

struct TSymbolValidater
{
    TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount],
                     TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version)
        : resolver(r)
        , infoSink(i)
        , hadError(hadError)
        , profile(profile)
        , version(version)
    {
        memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*)));
        memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*)));
        memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*)));

        std::map<TString, TString> anonymousMemberMap;
        std::vector<TRange> usedUniformLocation;
        std::vector<TString> usedUniformName;
        usedUniformLocation.clear();
        usedUniformName.clear();
        for (int i = 0; i < EShLangCount; i++) {
            if (uniformVarMap[i]) {
                for (auto uniformVar : *uniformVarMap[i])
                {
                    TIntermSymbol* pSymbol = uniformVar.second.symbol;
                    TQualifier qualifier = uniformVar.second.symbol->getQualifier();
                    TString symbolName = pSymbol->getAccessName();

                    // All the uniform needs multi-stage location check (block/default)
                    int uniformLocation = qualifier.layoutLocation;

                    if (uniformLocation != TQualifier::layoutLocationEnd) {
                        // Total size of current uniform, could be block, struct or other types.
                        int size = TIntermediate::computeTypeUniformLocationSize(pSymbol->getType());

                        TRange locationRange(uniformLocation, uniformLocation + size - 1);

                        // Combine location and component ranges
                        int overlapLocation = -1;
                        bool diffLocation = false;

                        // Check for collisions, except for vertex inputs on desktop targeting OpenGL
                        overlapLocation = checkLocationOverlap(locationRange, usedUniformLocation, symbolName, usedUniformName, diffLocation);

                        // Overlap locations of uniforms, regardless of components (multi stages)
                        if (overlapLocation == -1) {
                            usedUniformLocation.push_back(locationRange);
                            usedUniformName.push_back(symbolName);
                        }
                        else if (overlapLocation >= 0) {
                            if (diffLocation == true) {
                                TString err = ("Uniform location should be equal for same uniforms: " +std::to_string(overlapLocation)).c_str();
                                infoSink.info.message(EPrefixInternalError, err.c_str());
                                hadError = true;
                                break;
                            }
                            else {
                                TString err = ("Uniform location overlaps across stages: " + std::to_string(overlapLocation)).c_str();
                                infoSink.info.message(EPrefixInternalError, err.c_str());
                                hadError = true;
                                break;
                            }
                        }
                    }

                    if ((uniformVar.second.symbol->getBasicType() == EbtBlock) &&
                        IsAnonymous(uniformVar.second.symbol->getName()))
                    {
                        auto blockType = uniformVar.second.symbol->getType().getStruct();
                        for (size_t memberIdx = 0; memberIdx < blockType->size(); ++memberIdx) {
                            auto memberName = (*blockType)[memberIdx].type->getFieldName();
                            if (anonymousMemberMap.find(memberName) != anonymousMemberMap.end())
                            {
                                if (anonymousMemberMap[memberName] != uniformVar.second.symbol->getType().getTypeName())
                                {
                                    TString err = "Invalid block member name: " + memberName;
                                    infoSink.info.message(EPrefixInternalError, err.c_str());
                                    hadError = true;
                                    break;
                                }
                            }
                            else
                            {
                                anonymousMemberMap[memberName] = uniformVar.second.symbol->getType().getTypeName();
                            }
                        }
                    }
                    if (hadError)
                        break;
                }
            }
        }
    }

    // In case we need to new an intermediate, which costs too much
    int checkLocationOverlap(const TRange& locationRange, std::vector<TRange>& usedUniformLocation, const TString symbolName, std::vector<TString>& usedUniformName, bool& diffLocation)
    {
        for (size_t r = 0; r < usedUniformLocation.size(); ++r) {
            if (usedUniformName[r] == symbolName) {
                diffLocation = true;
                return (usedUniformLocation[r].start == locationRange.start &&
                        usedUniformLocation[r].last == locationRange.last)
                       ? -2 : std::max(locationRange.start, usedUniformLocation[r].start);
            }
            if (locationRange.overlap(usedUniformLocation[r])) {
                // there is a collision; pick one
                return std::max(locationRange.start, usedUniformLocation[r].start);
            }
        }

        return -1; // no collision
    }

    inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
        TVarEntryInfo& ent1 = entKey.second;
        TIntermSymbol* base = ent1.symbol;
        const TType& type = ent1.symbol->getType();
        const TString& name = entKey.first;
        TString mangleName1, mangleName2;
        EShLanguage stage = ent1.stage;
        EShLanguage preStage, currentStage, nextStage;

        preStage = EShLangCount;
        for (int i = stage - 1; i >= 0; i--) {
            if (inVarMaps[i] != nullptr) {
                preStage = static_cast<EShLanguage>(i);
                break;
            }
        }
        currentStage = stage;
        nextStage = EShLangCount;
        for (int i = stage + 1; i < EShLangCount; i++) {
            if (inVarMaps[i] != nullptr) {
                nextStage = static_cast<EShLanguage>(i);
                break;
            }
        }

        if (type.getQualifier().isArrayedIo(stage)) {
            TType subType(type, 0);
            subType.appendMangledName(mangleName1);
        } else {
            type.appendMangledName(mangleName1);
        }


        // basic checking that symbols match
        // more extensive checking in the link stage
        if (base->getQualifier().storage == EvqVaryingIn) {
            // validate stage in;
            if (preStage == EShLangCount)
                return;
            if (TSymbolTable::isBuiltInSymbol(base->getId()))
                return;
            if (outVarMaps[preStage] != nullptr) {
                auto ent2 = outVarMaps[preStage]->find(name);
                uint32_t location = base->getType().getQualifier().layoutLocation;
                if (ent2 == outVarMaps[preStage]->end() &&
                    location != glslang::TQualifier::layoutLocationEnd) {
                    for (auto var = outVarMaps[preStage]->begin(); var != ent2; var++) {
                        if (var->second.symbol->getType().getQualifier().layoutLocation == location) {
                            ent2 = var;
                            break;
                        }
                    }
                }
                if (ent2 != outVarMaps[preStage]->end()) {
                    auto& type1 = base->getType();
                    auto& type2 = ent2->second.symbol->getType();
                    hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
                    if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) {
                        TType subType(ent2->second.symbol->getType(), 0);
                        subType.appendMangledName(mangleName2);
                    } else {
                        ent2->second.symbol->getType().appendMangledName(mangleName2);
                    }

                    if (mangleName1 == mangleName2) {
                        // For ES 3.0 only, other versions have no such restrictions
                        // According to ES 3.0 spec: The type and presence of the interpolation qualifiers and
                        // storage qualifiers  of variables with the same name declared in all linked shaders must
                        // match, otherwise the link command will fail.
                        if (profile == EEsProfile && version == 300) {
                            // Don't need to check smooth qualifier, as it uses the default interpolation mode
                            if (ent1.stage == EShLangFragment && type1.isBuiltIn() == false) {
                                if (type1.getQualifier().flat != type2.getQualifier().flat ||
                                    type1.getQualifier().nopersp != type2.getQualifier().nopersp) {
                                    TString err = "Interpolation qualifier mismatch : " + entKey.first;
                                    infoSink.info.message(EPrefixInternalError, err.c_str());
                                    hadError = true;
                                }
                            }
                        }
                        return;
                    }
                    else {
                        TString err = "Invalid In/Out variable type : " + entKey.first;
                        infoSink.info.message(EPrefixInternalError, err.c_str());
                        hadError = true;
                    }
                }
                else if (!base->getType().isBuiltIn()) {
                    // According to spec: A link error is generated if any statically referenced input variable
                    // or block does not have a matching output
                    if (profile == EEsProfile && ent1.live) {
                        hadError = true;
                        TString errorStr = name + ": not been declare as a output variable in pre shader stage.";
                        infoSink.info.message(EPrefixError, errorStr.c_str());
                    }
                }
                return;
            }
        } else if (base->getQualifier().storage == EvqVaryingOut) {
            // validate stage out;
            if (nextStage == EShLangCount)
                return;
            if (TSymbolTable::isBuiltInSymbol(base->getId()))
                return;
            if (inVarMaps[nextStage] != nullptr) {
                auto ent2 = inVarMaps[nextStage]->find(name);
                if (ent2 != inVarMaps[nextStage]->end()) {
                    if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) {
                        TType subType(ent2->second.symbol->getType(), 0);
                        subType.appendMangledName(mangleName2);
                    } else {
                        ent2->second.symbol->getType().appendMangledName(mangleName2);
                    }
                    if (mangleName1 == mangleName2)
                        return;
                    else {
                        TString err = "Invalid In/Out variable type : " + entKey.first;
                        infoSink.info.message(EPrefixInternalError, err.c_str());
                        hadError = true;
                    }
                }
                return;
            }
        } else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) {
            // validate uniform type;
            for (int i = 0; i < EShLangCount; i++) {
                if (i != currentStage && outVarMaps[i] != nullptr) {
                    auto ent2 = uniformVarMap[i]->find(name);
                    if (ent2 != uniformVarMap[i]->end()) {
                        ent2->second.symbol->getType().appendMangledName(mangleName2);
                        if (mangleName1 != mangleName2) {
                            ent2->second.symbol->getType().sameElementType(type);
                            TString err = "Invalid Uniform variable type : " + entKey.first;
                            infoSink.info.message(EPrefixInternalError, err.c_str());
                            hadError = true;
                        }
                        mangleName2.clear();

                        // validate instance name of blocks
                        if (hadError == false &&
                            base->getType().getBasicType() == EbtBlock &&
                            IsAnonymous(base->getName()) != IsAnonymous(ent2->second.symbol->getName())) {
                            TString err = "Matched uniform block names must also either all be lacking "
                                          "an instance name or all having an instance name: " + entKey.first;
                            infoSink.info.message(EPrefixInternalError, err.c_str());
                            hadError = true;
                        }

                        // validate uniform block member qualifier and member names
                        auto& type1 = base->getType();
                        auto& type2 = ent2->second.symbol->getType();
                        if (hadError == false && base->getType().getBasicType() == EbtBlock) {
                            hadError = hadError || typeCheck(&type1, &type2, name.c_str(), true);
                        }
                        else {
                            hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false);
                        }
                    }
                    else if (base->getBasicType() == EbtBlock)
                    {
                        if (IsAnonymous(base->getName()))
                        {
                            // The name of anonymous block member can't same with default uniform variable.
                            auto blockType1 = base->getType().getStruct();
                            for (size_t memberIdx = 0; memberIdx < blockType1->size(); ++memberIdx) {
                                auto memberName = (*blockType1)[memberIdx].type->getFieldName();
                                if (uniformVarMap[i]->find(memberName) != uniformVarMap[i]->end())
                                {
                                    TString err = "Invalid Uniform variable name : " + memberName;
                                    infoSink.info.message(EPrefixInternalError, err.c_str());
                                    hadError = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount];

    // Use for mark current shader stage for resolver
    TIoMapResolver& resolver;
    TInfoSink& infoSink;
    bool& hadError;
    EProfile profile;
    int version;

private:
    TSymbolValidater& operator=(TSymbolValidater&) = delete;

    bool qualifierCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
    {
        bool hasError = false;
        const TQualifier& qualifier1 = type1->getQualifier();
        const TQualifier& qualifier2 = type2->getQualifier();

        if (((isBlock == false) &&
            (type1->getQualifier().storage == EvqUniform && type2->getQualifier().storage == EvqUniform)) ||
            (type1->getQualifier().storage == EvqGlobal && type2->getQualifier().storage == EvqGlobal)) {
            if (qualifier1.precision != qualifier2.precision) {
                hasError = true;
                std::string errorStr = name + ": have precision conflict cross stage.";
                infoSink.info.message(EPrefixError, errorStr.c_str());
            }
            if (qualifier1.hasFormat() && qualifier2.hasFormat()) {
                if (qualifier1.layoutFormat != qualifier2.layoutFormat) {
                    hasError = true;
                    std::string errorStr = name + ": have layout format conflict cross stage.";
                    infoSink.info.message(EPrefixError, errorStr.c_str());
                }

            }
        }

        if (isBlock == true) {
            if (qualifier1.layoutPacking != qualifier2.layoutPacking) {
                hasError = true;
                std::string errorStr = name + ": have layoutPacking conflict cross stage.";
                infoSink.info.message(EPrefixError, errorStr.c_str());
            }
            if (qualifier1.layoutMatrix != qualifier2.layoutMatrix) {
                hasError = true;
                std::string errorStr = name + ": have layoutMatrix conflict cross stage.";
                infoSink.info.message(EPrefixError, errorStr.c_str());
            }
            if (qualifier1.layoutOffset != qualifier2.layoutOffset) {
                hasError = true;
                std::string errorStr = name + ": have layoutOffset conflict cross stage.";
                infoSink.info.message(EPrefixError, errorStr.c_str());
            }
            if (qualifier1.layoutAlign != qualifier2.layoutAlign) {
                hasError = true;
                std::string errorStr = name + ": have layoutAlign conflict cross stage.";
                infoSink.info.message(EPrefixError, errorStr.c_str());
            }
        }

        return hasError;
    }

    bool typeCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock)
    {
        bool hasError = false;
        if (!(type1->isStruct() && type2->isStruct())) {
            hasError = hasError || qualifierCheck(type1, type2, name, isBlock);
        }
        else {
            if (type1->getBasicType() == EbtBlock && type2->getBasicType() == EbtBlock)
                isBlock = true;
            const TTypeList* typeList1 = type1->getStruct();
            const TTypeList* typeList2 = type2->getStruct();

            std::string newName = name;
            size_t memberCount = typeList1->size();
            size_t index2 = 0;
            for (size_t index = 0; index < memberCount; index++, index2++) {
                // Skip inactive member
                if (typeList1->at(index).type->getBasicType() == EbtVoid)
                    continue;
                while (index2 < typeList2->size() && typeList2->at(index2).type->getBasicType() == EbtVoid) {
                    ++index2;
                }

                // TypeList1 has more members in list
                if (index2 == typeList2->size()) {
                    std::string errorStr = name + ": struct mismatch.";
                    infoSink.info.message(EPrefixError, errorStr.c_str());
                    hasError = true;
                    break;
                }

                if (typeList1->at(index).type->getFieldName() != typeList2->at(index2).type->getFieldName()) {
                    std::string errorStr = name + ": member name mismatch.";
                    infoSink.info.message(EPrefixError, errorStr.c_str());
                    hasError = true;
                }
                else {
                    newName = typeList1->at(index).type->getFieldName().c_str();
                }
                hasError = hasError || typeCheck(typeList1->at(index).type, typeList2->at(index2).type, newName, isBlock);
            }

            while (index2 < typeList2->size())
            {
                // TypeList2 has more members
                if (typeList2->at(index2).type->getBasicType() != EbtVoid) {
                    std::string errorStr = name + ": struct mismatch.";
                    infoSink.info.message(EPrefixError, errorStr.c_str());
                    hasError = true;
                    break;
                }
                ++index2;
            }
        }
        return hasError;
    }
};

struct TSlotCollector {
    TSlotCollector(TIoMapResolver& r, TInfoSink& i) : resolver(r), infoSink(i) { }

    inline void operator()(std::pair<const TString, TVarEntryInfo>& entKey) {
        resolver.reserverStorageSlot(entKey.second, infoSink);
        resolver.reserverResourceSlot(entKey.second, infoSink);
    }
    TIoMapResolver& resolver;
    TInfoSink& infoSink;

private:
    TSlotCollector& operator=(TSlotCollector&) = delete;
};

TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate)
    : referenceIntermediate(intermediate)
    , nextUniformLocation(intermediate.getUniformLocationBase())
    , nextInputLocation(0)
    , nextOutputLocation(0)
{
    memset(stageMask, false, sizeof(bool) * (EShLangCount + 1));
    memset(stageIntermediates, 0, sizeof(TIntermediate*) * (EShLangCount));
    stageIntermediates[intermediate.getStage()] = &intermediate;
}

int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const {
    return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set))
                                     : selectBaseBinding(referenceIntermediate.getShiftBinding(res), referenceIntermediate.getShiftBindingForSet(res, set));
}

const std::vector<std::string>& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const {
    return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding()
                                     : referenceIntermediate.getResourceSetBinding();
}

bool TDefaultIoResolverBase::doAutoBindingMapping() const { return referenceIntermediate.getAutoMapBindings(); }

bool TDefaultIoResolverBase::doAutoLocationMapping() const { return referenceIntermediate.getAutoMapLocations(); }

TDefaultIoResolverBase::TSlotSet::iterator TDefaultIoResolverBase::findSlot(int set, int slot) {
    return std::lower_bound(slots[set].begin(), slots[set].end(), slot);
}

bool TDefaultIoResolverBase::checkEmpty(int set, int slot) {
    TSlotSet::iterator at = findSlot(set, slot);
    return ! (at != slots[set].end() && *at == slot);
}

int TDefaultIoResolverBase::reserveSlot(int set, int slot, int size) {
    TSlotSet::iterator at = findSlot(set, slot);
    // tolerate aliasing, by not double-recording aliases
    // (policy about appropriateness of the alias is higher up)
    for (int i = 0; i < size; i++) {
        if (at == slots[set].end() || *at != slot + i)
            at = slots[set].insert(at, slot + i);
        ++at;
    }
    return slot;
}

int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) {
    TSlotSet::iterator at = findSlot(set, base);
    if (at == slots[set].end())
        return reserveSlot(set, base, size);
    // look for a big enough gap
    for (; at != slots[set].end(); ++at) {
        if (*at - base >= size)
            break;
        base = *at + 1;
    }
    return reserveSlot(set, base, size);
}

int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) {
    const TType& type = ent.symbol->getType();
    if (type.getQualifier().hasSet()) {
        return ent.newSet = type.getQualifier().layoutSet;
    }
    // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
    if (getResourceSetBinding(stage).size() == 1) {
        return ent.newSet = atoi(getResourceSetBinding(stage)[0].c_str());
    }
    return ent.newSet = 0;
}

int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
    const TType& type = ent.symbol->getType();
    const char* name =  ent.symbol->getAccessName().c_str();
    // kick out of not doing this
    if (! doAutoLocationMapping()) {
        return ent.newLocation = -1;
    }
    // no locations added if already present, a built-in variable, a block, or an opaque
    if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
        type.isAtomic() || (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
        return ent.newLocation = -1;
    }
    // no locations on blocks of built-in variables
    if (type.isStruct()) {
        if (type.getStruct()->size() < 1) {
            return ent.newLocation = -1;
        }
        if ((*type.getStruct())[0].type->isBuiltIn()) {
            return ent.newLocation = -1;
        }
    }
    int location = referenceIntermediate.getUniformLocationOverride(name);
    if (location != -1) {
        return ent.newLocation = location;
    }
    location = nextUniformLocation;
    nextUniformLocation += TIntermediate::computeTypeUniformLocationSize(type);
    return ent.newLocation = location;
}

int TDefaultIoResolverBase::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
    const TType& type = ent.symbol->getType();
    // kick out of not doing this
    if (! doAutoLocationMapping()) {
        return ent.newLocation = -1;
    }

    // no locations added if already present, or a built-in variable
    if (type.getQualifier().hasLocation() || type.isBuiltIn()) {
        return ent.newLocation = -1;
    }

    // no locations on blocks of built-in variables
    if (type.isStruct()) {
        if (type.getStruct()->size() < 1) {
            return ent.newLocation = -1;
        }
        if ((*type.getStruct())[0].type->isBuiltIn()) {
            return ent.newLocation = -1;
        }
    }
    // point to the right input or output location counter
    int& nextLocation = type.getQualifier().isPipeInput() ? nextInputLocation : nextOutputLocation;
    // Placeholder. This does not do proper cross-stage lining up, nor
    // work with mixed location/no-location declarations.
    int location = nextLocation;
    int typeLocationSize;
    // Don’t take into account the outer-most array if the stage’s
    // interface is automatically an array.
    typeLocationSize = computeTypeLocationSize(type, stage);
    nextLocation += typeLocationSize;
    return ent.newLocation = location;
}

int TDefaultIoResolverBase::resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) {
    return ent.newComponent = -1;
}

int TDefaultIoResolverBase::resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) { return ent.newIndex = -1; }

uint32_t TDefaultIoResolverBase::computeTypeLocationSize(const TType& type, EShLanguage stage) {
    int typeLocationSize;
    // Don’t take into account the outer-most array if the stage’s
    // interface is automatically an array.
    if (type.getQualifier().isArrayedIo(stage)) {
        TType elementType(type, 0);
        typeLocationSize = TIntermediate::computeTypeLocationSize(elementType, stage);
    } else {
        typeLocationSize = TIntermediate::computeTypeLocationSize(type, stage);
    }
    return typeLocationSize;
}

//TDefaultGlslIoResolver
TResourceType TDefaultGlslIoResolver::getResourceType(const glslang::TType& type) {
    if (isImageType(type)) {
        return EResImage;
    }
    if (isTextureType(type)) {
        return EResTexture;
    }
    if (isSsboType(type)) {
        return EResSsbo;
    }
    if (isSamplerType(type)) {
        return EResSampler;
    }
    if (isUboType(type)) {
        return EResUbo;
    }
    return EResCount;
}

TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate)
    : TDefaultIoResolverBase(intermediate)
    , preStage(EShLangCount)
    , currentStage(EShLangCount)
{ }

int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) {
    const TType& type = ent.symbol->getType();
    const TString& name = ent.symbol->getAccessName();
    if (currentStage != stage) {
        preStage = currentStage;
        currentStage = stage;
    }
    // kick out if not doing this
    if (! doAutoLocationMapping()) {
        return ent.newLocation = -1;
    }
    // expand the location to each element if the symbol is a struct or array
    if (type.getQualifier().hasLocation()) {
        return ent.newLocation = type.getQualifier().layoutLocation;
    }
    // no locations added if already present, or a built-in variable
    if (type.isBuiltIn()) {
        return ent.newLocation = -1;
    }
    // no locations on blocks of built-in variables
    if (type.isStruct()) {
        if (type.getStruct()->size() < 1) {
            return ent.newLocation = -1;
        }
        if ((*type.getStruct())[0].type->isBuiltIn()) {
            return ent.newLocation = -1;
        }
    }
    int typeLocationSize = computeTypeLocationSize(type, stage);
    int location = type.getQualifier().layoutLocation;
    bool hasLocation = false;
    EShLanguage keyStage(EShLangCount);
    TStorageQualifier storage;
    storage = EvqInOut;
    if (type.getQualifier().isPipeInput()) {
        // If this symbol is a input, search pre stage's out
        keyStage = preStage;
    }
    if (type.getQualifier().isPipeOutput()) {
        // If this symbol is a output, search next stage's in
        keyStage = currentStage;
    }
    // The in/out in current stage is not declared with location, but it is possible declared
    // with explicit location in other stages, find the storageSlotMap firstly to check whether
    // the in/out has location
    int resourceKey = buildStorageKey(keyStage, storage);
    if (! storageSlotMap[resourceKey].empty()) {
        TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name);
        if (iter != storageSlotMap[resourceKey].end()) {
            // If interface resource be found, set it has location and this symbol's new location
            // equal the symbol's explicit location declaration in pre or next stage.
            //
            // vs:    out vec4 a;
            // fs:    layout(..., location = 3,...) in vec4 a;
            hasLocation = true;
            location = iter->second;
            // if we want deal like that:
            // vs:    layout(location=4) out vec4 a;
            //        out vec4 b;
            //
            // fs:    in vec4 a;
            //        layout(location = 4) in vec4 b;
            // we need retraverse the map.
        }
        if (! hasLocation) {
            // If interface resource note found, It's mean the location in two stage are both implicit declarat.
            // So we should find a new slot for this interface.
            //
            // vs: out vec4 a;
            // fs: in vec4 a;
            location = getFreeSlot(resourceKey, 0, typeLocationSize);
            storageSlotMap[resourceKey][name] = location;
        }
    } else {
        // the first interface declarated in a program.
        TVarSlotMap varSlotMap;
        location = getFreeSlot(resourceKey, 0, typeLocationSize);
        varSlotMap[name] = location;
        storageSlotMap[resourceKey] = varSlotMap;
    }
    //Update location
    return ent.newLocation = location;
}

int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) {
    const TType& type = ent.symbol->getType();
    const TString& name = ent.symbol->getAccessName();
    // kick out of not doing this
    if (! doAutoLocationMapping()) {
        return ent.newLocation = -1;
    }
    // expand the location to each element if the symbol is a struct or array
    if (type.getQualifier().hasLocation() && (type.isStruct() || type.isArray())) {
        return ent.newLocation = type.getQualifier().layoutLocation;
    } else {
        // no locations added if already present, a built-in variable, a block, or an opaque
        if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock ||
            type.isAtomic() || (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) {
            return ent.newLocation = -1;
        }
        // no locations on blocks of built-in variables
        if (type.isStruct()) {
            if (type.getStruct()->size() < 1) {
                return ent.newLocation = -1;
            }
            if ((*type.getStruct())[0].type->isBuiltIn()) {
                return ent.newLocation = -1;
            }
        }
    }
    int location = referenceIntermediate.getUniformLocationOverride(name.c_str());
    if (location != -1) {
        return ent.newLocation = location;
    }

    int size = TIntermediate::computeTypeUniformLocationSize(type);

    // The uniform in current stage is not declared with location, but it is possible declared
    // with explicit location in other stages, find the storageSlotMap firstly to check whether
    // the uniform has location
    bool hasLocation = false;
    int resourceKey = buildStorageKey(EShLangCount, EvqUniform);
    TVarSlotMap& slotMap = storageSlotMap[resourceKey];
    // Check dose shader program has uniform resource
    if (! slotMap.empty()) {
        // If uniform resource not empty, try find a same name uniform
        TVarSlotMap::iterator iter = slotMap.find(name);
        if (iter != slotMap.end()) {
            // If uniform resource be found, set it has location and this symbol's new location
            // equal the uniform's explicit location declaration in other stage.
            //
            // vs:    uniform vec4 a;
            // fs:    layout(..., location = 3,...) uniform vec4 a;
            hasLocation = true;
            location = iter->second;
        }
        if (! hasLocation) {
            // No explicit location declaration in other stage.
            // So we should find a new slot for this uniform.
            //
            // vs:    uniform vec4 a;
            // fs:    uniform vec4 a;
            location = getFreeSlot(resourceKey, 0, computeTypeLocationSize(type, currentStage));
            storageSlotMap[resourceKey][name] = location;
        }
    } else {
        // the first uniform declaration in a program.
        TVarSlotMap varSlotMap;
        location = getFreeSlot(resourceKey, 0, size);
        varSlotMap[name] = location;
        storageSlotMap[resourceKey] = varSlotMap;
    }
    return ent.newLocation = location;
}

int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent) {
    const TType& type = ent.symbol->getType();
    const TString& name = ent.symbol->getAccessName();
    // On OpenGL arrays of opaque types take a separate binding for each element
    int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
    TResourceType resource = getResourceType(type);
    // don't need to handle uniform symbol, it will be handled in resolveUniformLocation
    if (resource == EResUbo && type.getBasicType() != EbtBlock) {
        return ent.newBinding = -1;
    }
    // There is no 'set' qualifier in OpenGL shading language, each resource has its own
    // binding name space, so remap the 'set' to resource type which make each resource
    // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS
    int set = referenceIntermediate.getSpv().openGl != 0 ? resource : ent.newSet;
    int resourceKey = set;
    if (resource < EResCount) {
        if (type.getQualifier().hasBinding()) {
            int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
            return ent.newBinding = newBinding;

        } else {
            // The resource in current stage is not declared with binding, but it is possible declared
            // with explicit binding in other stages, find the resourceSlotMap firstly to check whether
            // the resource has binding, don't need to allocate if it already has a binding
            bool hasBinding = false;
            ent.newBinding = -1; // leave as -1 if it isn't set below

            if (! resourceSlotMap[resourceKey].empty()) {
                TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name);
                if (iter != resourceSlotMap[resourceKey].end()) {
                    hasBinding = true;
                    ent.newBinding = iter->second;
                }
            }
            if (!hasBinding && (ent.live && doAutoBindingMapping())) {
                // find free slot, the caller did make sure it passes all vars with binding
                // first and now all are passed that do not have a binding and needs one
                int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings);
                resourceSlotMap[resourceKey][name] = binding;
                ent.newBinding = binding;
            }
            return ent.newBinding;
        }
    }
    return ent.newBinding = -1;
}

void TDefaultGlslIoResolver::beginResolve(EShLanguage stage) {
    // reset stage state
    if (stage == EShLangCount)
        preStage = currentStage = stage;
    // update stage state
    else if (currentStage != stage) {
        preStage = currentStage;
        currentStage = stage;
    }
}

void TDefaultGlslIoResolver::endResolve(EShLanguage /*stage*/) {
    // TODO nothing
}

void TDefaultGlslIoResolver::beginCollect(EShLanguage stage) {
    // reset stage state
    if (stage == EShLangCount)
        preStage = currentStage = stage;
    // update stage state
    else if (currentStage != stage) {
        preStage = currentStage;
        currentStage = stage;
    }
}

void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) {
    // TODO nothing
}

void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
    const TType& type = ent.symbol->getType();
    const TString& name = ent.symbol->getAccessName();
    TStorageQualifier storage = type.getQualifier().storage;
    EShLanguage stage(EShLangCount);
    switch (storage) {
    case EvqUniform:
        if (type.getBasicType() != EbtBlock && type.getQualifier().hasLocation()) {
            //
            // Reserve the slots for the uniforms who has explicit location
            int storageKey = buildStorageKey(EShLangCount, EvqUniform);
            int location = type.getQualifier().layoutLocation;
            TVarSlotMap& varSlotMap = storageSlotMap[storageKey];
            TVarSlotMap::iterator iter = varSlotMap.find(name);
            if (iter == varSlotMap.end()) {
                int numLocations = TIntermediate::computeTypeUniformLocationSize(type);
                reserveSlot(storageKey, location, numLocations);
                varSlotMap[name] = location;
            } else {
                // Allocate location by name for OpenGL driver, so the uniform in different
                // stages should be declared with the same location
                if (iter->second != location) {
                    TString errorMsg = "Invalid location: " + name;
                    infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
                    hasError = true;
                }
            }
        }
        break;
    case EvqVaryingIn:
    case EvqVaryingOut:
        //
        // Reserve the slots for the inout who has explicit location
        if (type.getQualifier().hasLocation()) {
            stage = storage == EvqVaryingIn ? preStage : stage;
            stage = storage == EvqVaryingOut ? currentStage : stage;
            int storageKey = buildStorageKey(stage, EvqInOut);
            int location = type.getQualifier().layoutLocation;
            TVarSlotMap& varSlotMap = storageSlotMap[storageKey];
            TVarSlotMap::iterator iter = varSlotMap.find(name);
            if (iter == varSlotMap.end()) {
                int numLocations = TIntermediate::computeTypeUniformLocationSize(type);
                reserveSlot(storageKey, location, numLocations);
                varSlotMap[name] = location;
            } else {
                // Allocate location by name for OpenGL driver, so the uniform in different
                // stages should be declared with the same location
                if (iter->second != location) {
                    TString errorMsg = "Invalid location: " + name;
                    infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
                    hasError = true;
                }
            }
        }
        break;
    default:
        break;
    }
}

void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) {
    const TType& type = ent.symbol->getType();
    const TString& name = ent.symbol->getAccessName();
    TResourceType resource = getResourceType(type);
    int set = referenceIntermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent);
    int resourceKey = set;

    if (type.getQualifier().hasBinding()) {
        TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey];
        TVarSlotMap::iterator iter = varSlotMap.find(name);
        int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set);

        if (iter == varSlotMap.end()) {
            // Reserve the slots for the ubo, ssbo and opaques who has explicit binding
            int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
            varSlotMap[name] = binding;
            reserveSlot(resourceKey, binding, numBindings);
        } else {
            // Allocate binding by name for OpenGL driver, so the resource in different
            // stages should be declared with the same binding
            if (iter->second != binding) {
                TString errorMsg = "Invalid binding: " + name;
                infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
                hasError = true;
            }
        }
    }
}

//TDefaultGlslIoResolver end

/*
 * Basic implementation of glslang::TIoMapResolver that replaces the
 * previous offset behavior.
 * It does the same, uses the offsets for the corresponding uniform
 * types. Also respects the EOptionAutoMapBindings flag and binds
 * them if needed.
 */
/*
 * Default resolver
 */
struct TDefaultIoResolver : public TDefaultIoResolverBase {
    TDefaultIoResolver(const TIntermediate& intermediate) : TDefaultIoResolverBase(intermediate) { }

    bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }

    TResourceType getResourceType(const glslang::TType& type) override {
        if (isImageType(type)) {
            return EResImage;
        }
        if (isTextureType(type)) {
            return EResTexture;
        }
        if (isSsboType(type)) {
            return EResSsbo;
        }
        if (isSamplerType(type)) {
            return EResSampler;
        }
        if (isUboType(type)) {
            return EResUbo;
        }
        return EResCount;
    }

    int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
        const TType& type = ent.symbol->getType();
        const int set = getLayoutSet(type);
        // On OpenGL arrays of opaque types take a seperate binding for each element
        int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1;
        TResourceType resource = getResourceType(type);
        if (resource < EResCount) {
            if (type.getQualifier().hasBinding()) {
                return ent.newBinding = reserveSlot(
                           set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings);
            } else if (ent.live && doAutoBindingMapping()) {
                // find free slot, the caller did make sure it passes all vars with binding
                // first and now all are passed that do not have a binding and needs one
                return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings);
            }
        }
        return ent.newBinding = -1;
    }
};

#ifdef ENABLE_HLSL
/********************************************************************************
The following IO resolver maps types in HLSL register space, as follows:

t - for shader resource views (SRV)
   TEXTURE1D
   TEXTURE1DARRAY
   TEXTURE2D
   TEXTURE2DARRAY
   TEXTURE3D
   TEXTURECUBE
   TEXTURECUBEARRAY
   TEXTURE2DMS
   TEXTURE2DMSARRAY
   STRUCTUREDBUFFER
   BYTEADDRESSBUFFER
   BUFFER
   TBUFFER

s - for samplers
   SAMPLER
   SAMPLER1D
   SAMPLER2D
   SAMPLER3D
   SAMPLERCUBE
   SAMPLERSTATE
   SAMPLERCOMPARISONSTATE

u - for unordered access views (UAV)
   RWBYTEADDRESSBUFFER
   RWSTRUCTUREDBUFFER
   APPENDSTRUCTUREDBUFFER
   CONSUMESTRUCTUREDBUFFER
   RWBUFFER
   RWTEXTURE1D
   RWTEXTURE1DARRAY
   RWTEXTURE2D
   RWTEXTURE2DARRAY
   RWTEXTURE3D

b - for constant buffer views (CBV)
   CBUFFER
   CONSTANTBUFFER
 ********************************************************************************/
struct TDefaultHlslIoResolver : public TDefaultIoResolverBase {
    TDefaultHlslIoResolver(const TIntermediate& intermediate) : TDefaultIoResolverBase(intermediate) { }

    bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }

    TResourceType getResourceType(const glslang::TType& type) override {
        if (isUavType(type)) {
            return EResUav;
        }
        if (isSrvType(type)) {
            return EResTexture;
        }
        if (isSamplerType(type)) {
            return EResSampler;
        }
        if (isUboType(type)) {
            return EResUbo;
        }
        return EResCount;
    }

    int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override {
        const TType& type = ent.symbol->getType();
        const int set = getLayoutSet(type);
        TResourceType resource = getResourceType(type);
        if (resource < EResCount) {
            if (type.getQualifier().hasBinding()) {
                return ent.newBinding = reserveSlot(set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding);
            } else if (ent.live && doAutoBindingMapping()) {
                // find free slot, the caller did make sure it passes all vars with binding
                // first and now all are passed that do not have a binding and needs one
                return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set));
            }
        }
        return ent.newBinding = -1;
    }
};
#endif

// Map I/O variables to provided offsets, and make bindings for
// unbound but live variables.
//
// Returns false if the input is too malformed to do this.
bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
    bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() ||
                         intermediate.getAutoMapLocations();
    // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
    // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
    for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
        somethingToDo = somethingToDo || (intermediate.getShiftBinding(TResourceType(res)) != 0) ||
                        intermediate.hasShiftBindingForSet(TResourceType(res));
    }
    if (! somethingToDo && resolver == nullptr)
        return true;
    if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
        return false;
    TIntermNode* root = intermediate.getTreeRoot();
    if (root == nullptr)
        return false;
    // if no resolver is provided, use the default resolver with the given shifts and auto map settings
    TDefaultIoResolver defaultResolver(intermediate);
#ifdef ENABLE_HLSL
    TDefaultHlslIoResolver defaultHlslResolver(intermediate);
    if (resolver == nullptr) {
        // TODO: use a passed in IO mapper for this
        if (intermediate.usingHlslIoMapping())
            resolver = &defaultHlslResolver;
        else
            resolver = &defaultResolver;
    }
#else
    resolver = &defaultResolver;
#endif
    resolver->addStage(stage, intermediate);

    TVarLiveMap inVarMap, outVarMap, uniformVarMap;
    TVarLiveVector inVector, outVector, uniformVector;
    TVarGatherTraverser iter_binding_all(intermediate, true, inVarMap, outVarMap, uniformVarMap);
    TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap);
    root->traverse(&iter_binding_all);
    iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
    while (! iter_binding_live.destinations.empty()) {
        TIntermNode* destination = iter_binding_live.destinations.back();
        iter_binding_live.destinations.pop_back();
        destination->traverse(&iter_binding_live);
    }

    // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
    for (auto& var : inVarMap) { inVector.push_back(var); }
    std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
        return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
    });
    for (auto& var : outVarMap) { outVector.push_back(var); }
    std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
        return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
    });
    for (auto& var : uniformVarMap) { uniformVector.push_back(var); }
    std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
        return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
    });
    bool hadError = false;
    TVarLiveMap* dummyUniformVarMap[EShLangCount] = {};
    TNotifyInOutAdaptor inOutNotify(stage, *resolver);
    TNotifyUniformAdaptor uniformNotify(stage, *resolver);
    TResolverUniformAdaptor uniformResolve(stage, *resolver, dummyUniformVarMap, infoSink, hadError);
    TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError);
    resolver->beginNotifications(stage);
    std::for_each(inVector.begin(), inVector.end(), inOutNotify);
    std::for_each(outVector.begin(), outVector.end(), inOutNotify);
    std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify);
    resolver->endNotifications(stage);
    resolver->beginResolve(stage);
    for (auto& var : inVector) { inOutResolve(var); }
    std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) {
        auto at = inVarMap.find(p.second.symbol->getAccessName());
        if (at != inVarMap.end() && p.second.id == at->second.id)
            at->second = p.second;
    });
    for (auto& var : outVector) { inOutResolve(var); }
    std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) {
        auto at = outVarMap.find(p.second.symbol->getAccessName());
        if (at != outVarMap.end() && p.second.id == at->second.id)
            at->second = p.second;
    });
    std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve);
    std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) {
        auto at = uniformVarMap.find(p.second.symbol->getAccessName());
        if (at != uniformVarMap.end() && p.second.id == at->second.id)
            at->second = p.second;
    });
    resolver->endResolve(stage);
    if (!hadError) {
        TVarSetTraverser iter_iomap(intermediate, inVarMap, outVarMap, uniformVarMap);
        root->traverse(&iter_iomap);
    }
    return !hadError;
}

// Map I/O variables to provided offsets, and make bindings for
// unbound but live variables.
//
// Returns false if the input is too malformed to do this.
bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) {
    bool somethingToDo = !intermediate.getResourceSetBinding().empty() ||
        intermediate.getAutoMapBindings() ||
        intermediate.getAutoMapLocations();

    // Profile and version are use for symbol validate.
    profile = intermediate.getProfile();
    version = intermediate.getVersion();

    // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce
    // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true.
    for (int res = 0; (res < EResCount && !somethingToDo); ++res) {
        somethingToDo = somethingToDo || (intermediate.getShiftBinding(TResourceType(res)) != 0) ||
                        intermediate.hasShiftBindingForSet(TResourceType(res));
    }
    if (! somethingToDo && resolver == nullptr) {
        return true;
    }
    if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive()) {
        return false;
    }
    TIntermNode* root = intermediate.getTreeRoot();
    if (root == nullptr) {
        return false;
    }
    // if no resolver is provided, use the default resolver with the given shifts and auto map settings
    TDefaultGlslIoResolver defaultResolver(intermediate);
#ifdef ENABLE_HLSL
    TDefaultHlslIoResolver defaultHlslResolver(intermediate);
    if (resolver == nullptr) {
        // TODO: use a passed in IO mapper for this
        if (intermediate.usingHlslIoMapping())
            resolver = &defaultHlslResolver;
        else
            resolver = &defaultResolver;
    }
#else
    if (resolver == nullptr) {
        resolver = &defaultResolver;
    }
#endif
    resolver->addStage(stage, intermediate);
    inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap();
    TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage],
                                         *uniformVarMap[stage]);
    TVarGatherTraverser iter_binding_live(intermediate, false, *inVarMaps[stage], *outVarMaps[stage],
                                          *uniformVarMap[stage]);
    root->traverse(&iter_binding_all);
    iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
    while (! iter_binding_live.destinations.empty()) {
        TIntermNode* destination = iter_binding_live.destinations.back();
        iter_binding_live.destinations.pop_back();
        destination->traverse(&iter_binding_live);
    }

    TNotifyInOutAdaptor inOutNotify(stage, *resolver);
    TNotifyUniformAdaptor uniformNotify(stage, *resolver);
    // Resolve current stage input symbol location with previous stage output here,
    // uniform symbol, ubo, ssbo and opaque symbols are per-program resource,
    // will resolve uniform symbol location and ubo/ssbo/opaque binding in doMap()
    resolver->beginNotifications(stage);
    std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutNotify);
    std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutNotify);
    std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(), uniformNotify);
    resolver->endNotifications(stage);
    TSlotCollector slotCollector(*resolver, infoSink);
    resolver->beginCollect(stage);
    std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), slotCollector);
    std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), slotCollector);
    std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(), slotCollector);
    resolver->endCollect(stage);
    intermediates[stage] = &intermediate;
    return !hadError;
}

bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) {
    resolver->endResolve(EShLangCount);
    if (!hadError) {
        //Resolve uniform location, ubo/ssbo/opaque bindings across stages
        TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, uniformVarMap, infoSink, hadError);
        TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError);
        TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps,
                                         outVarMaps, uniformVarMap, hadError, profile, version);

        TVarLiveVector inVectors[EShLangCount];
        TVarLiveVector outVectors[EShLangCount];
        TVarLiveVector uniformVector;

        resolver->beginResolve(EShLangCount);
        for (int stage = EShLangVertex; stage < EShLangCount; stage++) {
            if (inVarMaps[stage] != nullptr) {
                inOutResolve.setStage(EShLanguage(stage));

                // copy vars into a sorted list
                std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(),
                        [&inVectors, stage](TVarLivePair p) { inVectors[stage].push_back(p); });
                std::sort(inVectors[stage].begin(), inVectors[stage].end(),
                        [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
                            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
                });

                std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(),
                        [&outVectors, stage](TVarLivePair p) { outVectors[stage].push_back(p); });
                std::sort(outVectors[stage].begin(), outVectors[stage].end(),
                        [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
                            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
                });

                for (auto& var : inVectors[stage]) { symbolValidater(var); }
                for (auto& var : inVectors[stage]) { inOutResolve(var); }
                for (auto& var : outVectors[stage]) { symbolValidater(var); }
                for (auto& var : outVectors[stage]) { inOutResolve(var); }

                // copy results back into maps
                std::for_each(inVectors[stage].begin(), inVectors[stage].end(),
                    [this, stage](TVarLivePair p) {
                        auto at = inVarMaps[stage]->find(p.first);
                        if (at != inVarMaps[stage]->end())
                            at->second = p.second;
                });

                std::for_each(outVectors[stage].begin(), outVectors[stage].end(),
                    [this, stage](TVarLivePair p) {
                        auto at = outVarMaps[stage]->find(p.first);
                        if (at != outVarMaps[stage]->end())
                            at->second = p.second;
                });

            }
            if (uniformVarMap[stage] != nullptr) {
                uniformResolve.setStage(EShLanguage(stage));
                for (auto& var : *(uniformVarMap[stage])) { uniformVector.push_back(var); }
            }
        }
        std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
            return TVarEntryInfo::TOrderByPriorityAndLive()(p1.second, p2.second);
        });
        for (auto& var : uniformVector) { symbolValidater(var); }
        for (auto& var : uniformVector) { uniformResolve(var); }
        std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool {
            return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second);
        });
        resolver->endResolve(EShLangCount);
        if (autoPushConstantBlockName.length()) {
            bool upgraded = false;
            for (size_t stage = 0; stage < EShLangCount; stage++) {
                if (intermediates[stage] != nullptr) {
                    TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap;
                    auto at = pUniformVarMap[stage]->find(autoPushConstantBlockName);
                    if (at == pUniformVarMap[stage]->end())
                        continue;
                    TQualifier& qualifier = at->second.symbol->getQualifier();
                    if (!qualifier.isUniform())
                        continue;
                    TType& t = at->second.symbol->getWritableType();
                    int size, stride;
                    TIntermediate::getBaseAlignment(t, size, stride, autoPushConstantBlockPacking,
                                                    qualifier.layoutMatrix == ElmRowMajor);
                    if (size <= int(autoPushConstantMaxSize)) {
                        qualifier.setBlockStorage(EbsPushConstant);
                        qualifier.layoutPacking = autoPushConstantBlockPacking;
                        upgraded = true;
                    }
                }
            }
            // If it's been upgraded to push_constant, then remove it from the uniformVector
            // so it doesn't get a set/binding assigned to it.
            if (upgraded) {
                auto at = std::find_if(uniformVector.begin(), uniformVector.end(),
                                       [this](const TVarLivePair& p) { return p.first == autoPushConstantBlockName; });
                if (at != uniformVector.end())
                    uniformVector.erase(at);
            }
        }
        for (size_t stage = 0; stage < EShLangCount; stage++) {
            if (intermediates[stage] != nullptr) {
                // traverse each stage, set new location to each input/output and unifom symbol, set new binding to
                // ubo, ssbo and opaque symbols
                TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap;
                std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) {
                    auto at = pUniformVarMap[stage]->find(p.second.symbol->getAccessName());
                    if (at != pUniformVarMap[stage]->end() && at->second.id == p.second.id){
                        int resolvedBinding = at->second.newBinding;
                        at->second = p.second;
                        if (resolvedBinding > 0)
                            at->second.newBinding = resolvedBinding;
                    }
                });
                TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage],
                                            *uniformResolve.uniformVarMap[stage]);
                intermediates[stage]->getTreeRoot()->traverse(&iter_iomap);
            }
        }
        return !hadError;
    } else {
        return false;
    }
}

} // end namespace glslang

#endif // !GLSLANG_WEB && !GLSLANG_ANGLE
