//
// Copyright 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// blocklayout.cpp:
//   Implementation for block layout classes and methods.
//

#include "compiler/translator/blocklayout.h"

#include "common/mathutil.h"
#include "common/utilities.h"
#include "compiler/translator/Common.h"

namespace sh
{

bool operator==(const BlockMemberInfo &lhs, const BlockMemberInfo &rhs)
{
    return lhs.type == rhs.type && lhs.offset == rhs.offset && lhs.arrayStride == rhs.arrayStride &&
           lhs.matrixStride == rhs.matrixStride && lhs.arraySize == rhs.arraySize &&
           lhs.isRowMajorMatrix == rhs.isRowMajorMatrix &&
           lhs.topLevelArrayStride == rhs.topLevelArrayStride;
}

namespace
{
class BlockLayoutMapVisitor : public BlockEncoderVisitor
{
  public:
    BlockLayoutMapVisitor(BlockLayoutMap *blockInfoOut,
                          const std::string &instanceName,
                          BlockLayoutEncoder *encoder)
        : BlockEncoderVisitor(instanceName, instanceName, encoder), mInfoOut(blockInfoOut)
    {}

    void encodeVariable(const ShaderVariable &variable,
                        const BlockMemberInfo &variableInfo,
                        const std::string &name,
                        const std::string &mappedName) override
    {
        ASSERT(!gl::IsSamplerType(variable.type));
        if (!gl::IsOpaqueType(variable.type))
        {
            (*mInfoOut)[name] = variableInfo;
        }
    }

  private:
    BlockLayoutMap *mInfoOut;
};

template <typename VarT>
void GetInterfaceBlockInfo(const std::vector<VarT> &fields,
                           const std::string &prefix,
                           BlockLayoutEncoder *encoder,
                           bool inRowMajorLayout,
                           bool onlyActiveVariables,
                           BlockLayoutMap *blockInfoOut)
{
    BlockLayoutMapVisitor visitor(blockInfoOut, prefix, encoder);
    if (onlyActiveVariables)
    {
        TraverseActiveShaderVariables(fields, inRowMajorLayout, &visitor);
    }
    else
    {
        TraverseShaderVariables(fields, inRowMajorLayout, &visitor);
    }
}

void TraverseStructVariable(const ShaderVariable &variable,
                            bool isRowMajorLayout,
                            ShaderVariableVisitor *visitor)
{
    const std::vector<ShaderVariable> &fields = variable.fields;

    visitor->enterStructAccess(variable, isRowMajorLayout);
    TraverseShaderVariables(fields, isRowMajorLayout, visitor);
    visitor->exitStructAccess(variable, isRowMajorLayout);
}

void TraverseStructArrayVariable(const ShaderVariable &variable,
                                 bool inRowMajorLayout,
                                 ShaderVariableVisitor *visitor)
{
    visitor->enterArray(variable);

    // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
    // innermost. We make a special case for unsized arrays.
    const unsigned int currentArraySize = variable.getNestedArraySize(0);
    for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
    {
        visitor->enterArrayElement(variable, arrayElement);
        ShaderVariable elementVar = variable;
        elementVar.indexIntoArray(arrayElement);

        if (variable.arraySizes.size() > 1u)
        {
            TraverseStructArrayVariable(elementVar, inRowMajorLayout, visitor);
        }
        else
        {
            TraverseStructVariable(elementVar, inRowMajorLayout, visitor);
        }

        visitor->exitArrayElement(variable, arrayElement);
    }

    visitor->exitArray(variable);
}

void TraverseArrayOfArraysVariable(const ShaderVariable &variable,
                                   unsigned int arrayNestingIndex,
                                   bool isRowMajorMatrix,
                                   ShaderVariableVisitor *visitor)
{
    visitor->enterArray(variable);

    const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex);
    unsigned int count                  = std::max(currentArraySize, 1u);
    for (unsigned int arrayElement = 0u; arrayElement < count; ++arrayElement)
    {
        visitor->enterArrayElement(variable, arrayElement);

        ShaderVariable elementVar = variable;
        elementVar.indexIntoArray(arrayElement);

        if (arrayNestingIndex + 2u < variable.arraySizes.size())
        {
            TraverseArrayOfArraysVariable(elementVar, arrayNestingIndex, isRowMajorMatrix, visitor);
        }
        else
        {
            if (gl::IsSamplerType(variable.type) || gl::IsImageType(variable.type) ||
                variable.isFragmentInOut)
            {
                visitor->visitOpaqueObject(elementVar);
            }
            else
            {
                visitor->visitVariable(elementVar, isRowMajorMatrix);
            }
        }

        visitor->exitArrayElement(variable, arrayElement);
    }

    visitor->exitArray(variable);
}

std::string CollapseNameStack(const std::vector<std::string> &nameStack)
{
    std::stringstream strstr = sh::InitializeStream<std::stringstream>();
    for (const std::string &part : nameStack)
    {
        strstr << part;
    }
    return strstr.str();
}

size_t GetStd430BaseAlignment(GLenum variableType, bool isRowMajor)
{
    GLenum flippedType   = isRowMajor ? variableType : gl::TransposeMatrixType(variableType);
    size_t numComponents = static_cast<size_t>(gl::VariableColumnCount(flippedType));
    return ComponentAlignment(numComponents);
}

class BaseAlignmentVisitor : public ShaderVariableVisitor
{
  public:
    BaseAlignmentVisitor() = default;
    void visitVariable(const ShaderVariable &variable, bool isRowMajor) override
    {
        size_t baseAlignment = GetStd430BaseAlignment(variable.type, isRowMajor);
        mCurrentAlignment    = std::max(mCurrentAlignment, baseAlignment);
    }

    // This is in components rather than bytes.
    size_t getBaseAlignment() const { return mCurrentAlignment; }

  private:
    size_t mCurrentAlignment = 0;
};

}  // anonymous namespace

// BlockLayoutEncoder implementation.
BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) {}

BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
                                               const size_t bytesPerComponent,
                                               const std::vector<unsigned int> &arraySizes,
                                               bool isRowMajorMatrix)
{
    int arrayStride;
    int matrixStride;

    getBlockLayoutInfo(type, bytesPerComponent, arraySizes, isRowMajorMatrix, &arrayStride,
                       &matrixStride);

    const BlockMemberInfo memberInfo(type, static_cast<int>(mCurrentOffset * kBytesPerComponent),
                                     static_cast<int>(arrayStride * kBytesPerComponent),
                                     static_cast<int>(matrixStride * kBytesPerComponent),
                                     gl::ArraySizeProduct(arraySizes), isRowMajorMatrix);

    advanceOffset(type, bytesPerComponent, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);

    return memberInfo;
}

BlockMemberInfo BlockLayoutEncoder::encodeArrayOfPreEncodedStructs(
    size_t size,
    const std::vector<unsigned int> &arraySizes)
{
    const unsigned int innerArraySizeProduct = gl::InnerArraySizeProduct(arraySizes);
    const unsigned int outermostArraySize    = gl::OutermostArraySize(arraySizes);

    // The size of struct is expected to be already aligned appropriately.
    const size_t arrayStride = size * innerArraySizeProduct;
    GLenum type              = GL_INVALID_ENUM;
    const BlockMemberInfo memberInfo(type, static_cast<int>(mCurrentOffset * kBytesPerComponent),
                                     static_cast<int>(arrayStride), -1,
                                     gl::ArraySizeProduct(arraySizes), false);

    angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
    checkedOffset *= outermostArraySize;
    checkedOffset /= kBytesPerComponent;
    checkedOffset += mCurrentOffset;
    mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());

    return memberInfo;
}

size_t BlockLayoutEncoder::getCurrentOffset() const
{
    angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
    checkedOffset *= kBytesPerComponent;
    return checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
}

size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor)
{
    size_t currentOffset = mCurrentOffset;
    mCurrentOffset       = 0;
    BlockEncoderVisitor visitor("", "", this);
    enterAggregateType(structVar);
    TraverseShaderVariables(structVar.fields, isRowMajor, &visitor);
    exitAggregateType(structVar);
    size_t structVarSize = getCurrentOffset();
    mCurrentOffset       = currentOffset;
    return structVarSize;
}

// static
size_t BlockLayoutEncoder::GetBlockRegister(const BlockMemberInfo &info)
{
    return (info.offset / kBytesPerComponent) / kComponentsPerRegister;
}

// static
size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info)
{
    return (info.offset / kBytesPerComponent) % kComponentsPerRegister;
}

void BlockLayoutEncoder::align(size_t baseAlignment)
{
    if (baseAlignment == 0)
    {
        return;
    }
    angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
    checkedOffset += baseAlignment;
    checkedOffset -= 1;
    angle::base::CheckedNumeric<size_t> checkedAlignmentOffset = checkedOffset;
    checkedAlignmentOffset %= baseAlignment;
    checkedOffset -= checkedAlignmentOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    assert(mCurrentOffset >= 0);
}

// StubBlockEncoder implementation.
void StubBlockEncoder::getBlockLayoutInfo(GLenum type,
                                          const size_t bytesPerComponent,
                                          const std::vector<unsigned int> &arraySizes,
                                          bool isRowMajorMatrix,
                                          int *arrayStrideOut,
                                          int *matrixStrideOut)
{
    *arrayStrideOut  = 0;
    *matrixStrideOut = 0;
}

// PackedSPIRVBlockEncoder implementation.
PackedSPIRVBlockEncoder::PackedSPIRVBlockEncoder() {}

BlockMemberInfo PackedSPIRVBlockEncoder::encodeType(GLenum type,
                                                    const size_t bytesPerComponent,
                                                    const std::vector<unsigned int> &arraySizes,
                                                    bool isRowMajorMatrix)
{
    // Similar to BlockLayoutEncoder::encodeType(), except mCurrentOffset tracks offset in number
    // of byte, instead of number of 4-byte.
    int arrayStride;
    int matrixStride;

    getBlockLayoutInfo(type, bytesPerComponent, arraySizes, isRowMajorMatrix, &arrayStride,
                       &matrixStride);

    const BlockMemberInfo memberInfo(type, static_cast<int>(mCurrentOffset), arrayStride,
                                     matrixStride, gl::ArraySizeProduct(arraySizes),
                                     isRowMajorMatrix);

    advanceOffset(type, bytesPerComponent, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);

    return memberInfo;
}

BlockMemberInfo PackedSPIRVBlockEncoder::encodeArrayOfPreEncodedStructs(
    size_t size,
    const std::vector<unsigned int> &arraySizes)
{
    // Similar to BlockLayoutEncoder::encodeArrayOfPreEncodedStructs, except mCurrentOffset tracks
    // offset in number of byte, instead of number of 4-byte.
    const unsigned int innerArraySizeProduct = gl::InnerArraySizeProduct(arraySizes);
    const unsigned int outermostArraySize    = gl::OutermostArraySize(arraySizes);

    // The size of struct is expected to be already aligned appropriately.
    const size_t arrayStride = size * innerArraySizeProduct;
    GLenum type              = GL_INVALID_ENUM;
    const BlockMemberInfo memberInfo(type, static_cast<int>(mCurrentOffset),
                                     static_cast<int>(arrayStride), -1,
                                     gl::ArraySizeProduct(arraySizes), false);

    angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
    checkedOffset *= outermostArraySize;
    checkedOffset += mCurrentOffset;
    mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());

    return memberInfo;
}

size_t PackedSPIRVBlockEncoder::getCurrentOffset() const
{
    // Similar to BlockLayoutEncoder::getCurrentOffset(), except mCurrentOffset tracks offset in
    // number of byte, instead of number of 4-byte.
    angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
    return checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
}

void PackedSPIRVBlockEncoder::enterAggregateType(const ShaderVariable &structVar)
{
    // Similar to Std140BlockEncoder::enterAggregateType(), except mCurrentOffset tracks offset in
    // number of byte, instead of number of 4-byte.
    align(getBaseAlignment(structVar));
}

void PackedSPIRVBlockEncoder::exitAggregateType(const ShaderVariable &structVar)
{
    // Similar to Std140BlockEncoder::exitAggregateType(), except mCurrentOffset tracks offset in
    // number of byte, instead of number of 4-byte.
    align(getBaseAlignment(structVar));
}

void PackedSPIRVBlockEncoder::getBlockLayoutInfo(GLenum type,
                                                 const size_t bytesPerComponent,
                                                 const std::vector<unsigned int> &arraySizes,
                                                 bool isRowMajorMatrix,
                                                 int *arrayStrideOut,
                                                 int *matrixStrideOut)
{
    // Right now we only pass kBytesPer16BitComponent for 16-bit float and vectors: half, half2,
    // half3, half4. For all other data types, we pass kBytesPerComponent.
    ASSERT(bytesPerComponent == kBytesPer16BitComponent || bytesPerComponent == kBytesPerComponent);
    size_t baseAlignment = 0;
    int matrixStride     = 0;
    int arrayStride      = 0;

    if (gl::IsMatrixType(type))
    {
        baseAlignment = getTypeBaseAlignment(type, isRowMajorMatrix);
        matrixStride  = static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix));

        if (!arraySizes.empty())
        {
            const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
            arrayStride =
                static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix) * numRegisters);
        }
    }
    else if (!arraySizes.empty())
    {
        baseAlignment = static_cast<int>(getTypeBaseAlignment(type, false));
        arrayStride   = static_cast<int>(getTypeBaseAlignment(type, false));
    }
    else
    {
        if (bytesPerComponent == kBytesPer16BitComponent)
        {
            ASSERT(gl::IsFloatScalarAndVectorType(type));
            baseAlignment = bytesPerComponent;
        }
        else
        {
            ASSERT(bytesPerComponent == kBytesPerComponent);
            const size_t numComponents = static_cast<size_t>(gl::VariableComponentCount(type));
            baseAlignment              = ComponentAlignment(numComponents) * bytesPerComponent;
        }
    }

    align(baseAlignment);

    if (bytesPerComponent == kBytesPer16BitComponent && gl::IsFloatVectorType(type))
    {
        if (isVectorStraddle(type))
        {
            adjustAlignmentForStraddleVector();
        }
    }

    *matrixStrideOut = matrixStride;
    *arrayStrideOut  = arrayStride;
}

void PackedSPIRVBlockEncoder::advanceOffset(GLenum type,
                                            const size_t bytesPerComponent,
                                            const std::vector<unsigned int> &arraySizes,
                                            bool isRowMajorMatrix,
                                            int arrayStride,
                                            int matrixStride)
{
    // Similar to Std140BlockEncoder::advanceOffset(), except mCurrentOffset tracks offset in
    // number of byte, instead of number of 4-byte.
    if (!arraySizes.empty())
    {
        angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
        checkedOffset *= gl::ArraySizeProduct(arraySizes);
        checkedOffset += mCurrentOffset;
        mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    }
    else if (gl::IsMatrixType(type))
    {
        angle::base::CheckedNumeric<size_t> checkedOffset(matrixStride);
        checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix);
        checkedOffset += mCurrentOffset;
        mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    }
    else
    {
        angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
        checkedOffset += (gl::VariableComponentCount(type) * bytesPerComponent);
        mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    }
}

size_t PackedSPIRVBlockEncoder::getBaseAlignment(const ShaderVariable &variable) const
{
    // Similar to Std140BlockEncoder::getBaseAlignment(), except it returns the number of byte
    // count, instead of number of 4-byte count.
    return kComponentsPerRegister * kBytesPerComponent;
}

size_t PackedSPIRVBlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
{
    // Similar to Std140BlockEncoder::getTypeBaseAlignment(), except it returns the number of byte
    // count, instead of number of 4-byte count.
    return kComponentsPerRegister * kBytesPerComponent;
}

// Check if the memory occupied by data crosses 16-byte boundary:
// startMemory / 16 != (startMemory + dataSize) / 16 ? crosses boundary : does not cross boundary
bool PackedSPIRVBlockEncoder::isVectorStraddle(GLenum type)
{
    angle::base::CheckedNumeric<size_t> checked16ByteOffset(mCurrentOffset);
    checked16ByteOffset /= 16;
    const size_t vectorSize =
        kBytesPer16BitComponent * static_cast<size_t>(gl::VariableComponentCount(type));
    angle::base::CheckedNumeric<size_t> checkedOffsetWithVector(mCurrentOffset);
    checkedOffsetWithVector += vectorSize;
    checkedOffsetWithVector /= 16;
    if (checked16ByteOffset.ValueOrDefault(std::numeric_limits<size_t>::max()) !=
        checkedOffsetWithVector.ValueOrDefault(std::numeric_limits<size_t>::max()))
    {
        return true;
    }
    return false;
}

void PackedSPIRVBlockEncoder::adjustAlignmentForStraddleVector()
{
    // align the mCurrentOffset to the next 16 byte
    align(16u);
}

// Std140BlockEncoder implementation.
Std140BlockEncoder::Std140BlockEncoder() {}

void Std140BlockEncoder::enterAggregateType(const ShaderVariable &structVar)
{
    align(getBaseAlignment(structVar));
}

void Std140BlockEncoder::exitAggregateType(const ShaderVariable &structVar)
{
    align(getBaseAlignment(structVar));
}

void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
                                            const size_t bytesPerComponent,
                                            const std::vector<unsigned int> &arraySizes,
                                            bool isRowMajorMatrix,
                                            int *arrayStrideOut,
                                            int *matrixStrideOut)
{
    // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
    ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent);

    size_t baseAlignment = 0;
    int matrixStride     = 0;
    int arrayStride      = 0;

    if (gl::IsMatrixType(type))
    {
        baseAlignment = getTypeBaseAlignment(type, isRowMajorMatrix);
        matrixStride  = static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix));

        if (!arraySizes.empty())
        {
            const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
            arrayStride =
                static_cast<int>(getTypeBaseAlignment(type, isRowMajorMatrix) * numRegisters);
        }
    }
    else if (!arraySizes.empty())
    {
        baseAlignment = static_cast<int>(getTypeBaseAlignment(type, false));
        arrayStride   = static_cast<int>(getTypeBaseAlignment(type, false));
    }
    else
    {
        const size_t numComponents = static_cast<size_t>(gl::VariableComponentCount(type));
        baseAlignment              = ComponentAlignment(numComponents);
    }

    align(baseAlignment);

    *matrixStrideOut = matrixStride;
    *arrayStrideOut  = arrayStride;
}

void Std140BlockEncoder::advanceOffset(GLenum type,
                                       const size_t bytesPerComponent,
                                       const std::vector<unsigned int> &arraySizes,
                                       bool isRowMajorMatrix,
                                       int arrayStride,
                                       int matrixStride)
{
    if (!arraySizes.empty())
    {
        angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
        checkedOffset *= gl::ArraySizeProduct(arraySizes);
        checkedOffset += mCurrentOffset;
        mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    }
    else if (gl::IsMatrixType(type))
    {
        angle::base::CheckedNumeric<size_t> checkedOffset(matrixStride);
        checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix);
        checkedOffset += mCurrentOffset;
        mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    }
    else
    {
        angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
        checkedOffset += gl::VariableComponentCount(type);
        mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
    }
}

size_t Std140BlockEncoder::getBaseAlignment(const ShaderVariable &variable) const
{
    return kComponentsPerRegister;
}

size_t Std140BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
{
    return kComponentsPerRegister;
}

// Std430BlockEncoder implementation.
Std430BlockEncoder::Std430BlockEncoder() {}

size_t Std430BlockEncoder::getBaseAlignment(const ShaderVariable &shaderVar) const
{
    if (shaderVar.isStruct())
    {
        BaseAlignmentVisitor visitor;
        TraverseShaderVariables(shaderVar.fields, false, &visitor);
        return visitor.getBaseAlignment();
    }

    return GetStd430BaseAlignment(shaderVar.type, shaderVar.isRowMajorLayout);
}

size_t Std430BlockEncoder::getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const
{
    return GetStd430BaseAlignment(type, isRowMajorMatrix);
}

void GetInterfaceBlockInfo(const std::vector<ShaderVariable> &fields,
                           const std::string &prefix,
                           BlockLayoutEncoder *encoder,
                           BlockLayoutMap *blockInfoOut)
{
    // Matrix packing is always recorded in individual fields, so they'll set the row major layout
    // flag to true if needed.
    // Iterates over all variables.
    GetInterfaceBlockInfo(fields, prefix, encoder, false, false, blockInfoOut);
}

void GetActiveUniformBlockInfo(const std::vector<ShaderVariable> &uniforms,
                               const std::string &prefix,
                               BlockLayoutEncoder *encoder,
                               BlockLayoutMap *blockInfoOut)
{
    // Matrix packing is always recorded in individual fields, so they'll set the row major layout
    // flag to true if needed.
    // Iterates only over the active variables.
    GetInterfaceBlockInfo(uniforms, prefix, encoder, false, true, blockInfoOut);
}

// VariableNameVisitor implementation.
VariableNameVisitor::VariableNameVisitor(const std::string &namePrefix,
                                         const std::string &mappedNamePrefix)
{
    if (!namePrefix.empty())
    {
        mNameStack.push_back(namePrefix + ".");
    }

    if (!mappedNamePrefix.empty())
    {
        mMappedNameStack.push_back(mappedNamePrefix + ".");
    }
}

VariableNameVisitor::~VariableNameVisitor() = default;

void VariableNameVisitor::enterStruct(const ShaderVariable &structVar)
{
    mNameStack.push_back(structVar.name);
    mMappedNameStack.push_back(structVar.mappedName);
}

void VariableNameVisitor::exitStruct(const ShaderVariable &structVar)
{
    mNameStack.pop_back();
    mMappedNameStack.pop_back();
}

void VariableNameVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{
    mNameStack.push_back(".");
    mMappedNameStack.push_back(".");
}

void VariableNameVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{
    mNameStack.pop_back();
    mMappedNameStack.pop_back();
}

void VariableNameVisitor::enterArray(const ShaderVariable &arrayVar)
{
    if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
    {
        mNameStack.push_back(arrayVar.name);
        mMappedNameStack.push_back(arrayVar.mappedName);
    }
    mArraySizeStack.push_back(arrayVar.getOutermostArraySize());
}

void VariableNameVisitor::exitArray(const ShaderVariable &arrayVar)
{
    if (!arrayVar.hasParentArrayIndex() && !arrayVar.isStruct())
    {
        mNameStack.pop_back();
        mMappedNameStack.pop_back();
    }
    mArraySizeStack.pop_back();
}

void VariableNameVisitor::enterArrayElement(const ShaderVariable &arrayVar,
                                            unsigned int arrayElement)
{
    std::stringstream strstr = sh::InitializeStream<std::stringstream>();
    strstr << "[" << arrayElement << "]";
    std::string elementString = strstr.str();
    mNameStack.push_back(elementString);
    mMappedNameStack.push_back(elementString);
}

void VariableNameVisitor::exitArrayElement(const ShaderVariable &arrayVar,
                                           unsigned int arrayElement)
{
    mNameStack.pop_back();
    mMappedNameStack.pop_back();
}

std::string VariableNameVisitor::collapseNameStack() const
{
    return CollapseNameStack(mNameStack);
}

std::string VariableNameVisitor::collapseMappedNameStack() const
{
    return CollapseNameStack(mMappedNameStack);
}

void VariableNameVisitor::visitOpaqueObject(const sh::ShaderVariable &variable)
{
    if (!variable.hasParentArrayIndex())
    {
        mNameStack.push_back(variable.name);
        mMappedNameStack.push_back(variable.mappedName);
    }

    std::string name       = collapseNameStack();
    std::string mappedName = collapseMappedNameStack();

    if (!variable.hasParentArrayIndex())
    {
        mNameStack.pop_back();
        mMappedNameStack.pop_back();
    }

    visitNamedOpaqueObject(variable, name, mappedName, mArraySizeStack);
}

void VariableNameVisitor::visitVariable(const ShaderVariable &variable, bool isRowMajor)
{
    if (!variable.hasParentArrayIndex())
    {
        mNameStack.push_back(variable.name);
        mMappedNameStack.push_back(variable.mappedName);
    }

    std::string name       = collapseNameStack();
    std::string mappedName = collapseMappedNameStack();

    if (!variable.hasParentArrayIndex())
    {
        mNameStack.pop_back();
        mMappedNameStack.pop_back();
    }

    visitNamedVariable(variable, isRowMajor, name, mappedName, mArraySizeStack);
}

// BlockEncoderVisitor implementation.
BlockEncoderVisitor::BlockEncoderVisitor(const std::string &namePrefix,
                                         const std::string &mappedNamePrefix,
                                         BlockLayoutEncoder *encoder)
    : VariableNameVisitor(namePrefix, mappedNamePrefix), mEncoder(encoder)
{}

BlockEncoderVisitor::~BlockEncoderVisitor() = default;

void BlockEncoderVisitor::enterStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{
    mStructStackSize++;
    if (!mIsTopLevelArrayStrideReady)
    {
        size_t structSize = mEncoder->getShaderVariableSize(structVar, isRowMajor);
        mTopLevelArrayStride *= structSize;
        mIsTopLevelArrayStrideReady = true;
    }

    VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
    mEncoder->enterAggregateType(structVar);
}

void BlockEncoderVisitor::exitStructAccess(const ShaderVariable &structVar, bool isRowMajor)
{
    mStructStackSize--;
    mEncoder->exitAggregateType(structVar);
    VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
}

void BlockEncoderVisitor::enterArrayElement(const sh::ShaderVariable &arrayVar,
                                            unsigned int arrayElement)
{
    if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex())
    {
        // From the ES 3.1 spec "7.3.1.1 Naming Active Resources":
        // For an active shader storage block member declared as an array of an aggregate type,
        // an entry will be generated only for the first array element, regardless of its type.
        // Such block members are referred to as top-level arrays. If the block member is an
        // aggregate type, the enumeration rules are then applied recursively.
        if (arrayElement == 0)
        {
            mTopLevelArraySize          = arrayVar.getOutermostArraySize();
            mTopLevelArrayStride        = arrayVar.getInnerArraySizeProduct();
            mIsTopLevelArrayStrideReady = false;
        }
        else
        {
            mSkipEnabled = true;
        }
    }
    VariableNameVisitor::enterArrayElement(arrayVar, arrayElement);
}

void BlockEncoderVisitor::exitArrayElement(const sh::ShaderVariable &arrayVar,
                                           unsigned int arrayElement)
{
    if (mStructStackSize == 0 && !arrayVar.hasParentArrayIndex())
    {
        mTopLevelArraySize          = 1;
        mTopLevelArrayStride        = 0;
        mIsTopLevelArrayStrideReady = true;
        mSkipEnabled                = false;
    }
    VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
}

void BlockEncoderVisitor::visitNamedVariable(const ShaderVariable &variable,
                                             bool isRowMajor,
                                             const std::string &name,
                                             const std::string &mappedName,
                                             const std::vector<unsigned int> &arraySizes)
{
    std::vector<unsigned int> innermostArraySize;

    if (variable.isArray())
    {
        innermostArraySize.push_back(variable.getNestedArraySize(0));
    }
    BlockMemberInfo variableInfo =
        mEncoder->encodeType(variable.type,
                             variable.isFloat16 ? BlockLayoutEncoder::kBytesPer16BitComponent
                                                : BlockLayoutEncoder::kBytesPerComponent,
                             innermostArraySize, isRowMajor);
    if (!mIsTopLevelArrayStrideReady)
    {
        ASSERT(mTopLevelArrayStride);
        mTopLevelArrayStride *= variableInfo.arrayStride;
        mIsTopLevelArrayStrideReady = true;
    }
    variableInfo.topLevelArrayStride = mTopLevelArrayStride;
    encodeVariable(variable, variableInfo, name, mappedName);
}

void TraverseShaderVariable(const ShaderVariable &variable,
                            bool isRowMajorLayout,
                            ShaderVariableVisitor *visitor)
{
    bool rowMajorLayout = (isRowMajorLayout || variable.isRowMajorLayout);
    bool isRowMajor     = rowMajorLayout && gl::IsMatrixType(variable.type);

    if (variable.isStruct())
    {
        visitor->enterStruct(variable);
        if (variable.isArray())
        {
            TraverseStructArrayVariable(variable, rowMajorLayout, visitor);
        }
        else
        {
            TraverseStructVariable(variable, rowMajorLayout, visitor);
        }
        visitor->exitStruct(variable);
    }
    else if (variable.isArrayOfArrays())
    {
        TraverseArrayOfArraysVariable(variable, 0u, isRowMajor, visitor);
    }
    else if (gl::IsSamplerType(variable.type) || gl::IsImageType(variable.type) ||
             variable.isFragmentInOut)
    {
        visitor->visitOpaqueObject(variable);
    }
    else
    {
        visitor->visitVariable(variable, isRowMajor);
    }
}

}  // namespace sh
