//
// 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/blocklayoutHLSL.h"

#include "common/mathutil.h"
#include "common/utilities.h"

namespace sh
{

HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy, bool transposeMatrices)
    : mEncoderStrategy(strategy), mTransposeMatrices(transposeMatrices)
{}

void HLSLBlockEncoder::enterAggregateType(const ShaderVariable &structVar)
{
    align(kComponentsPerRegister);
}

void HLSLBlockEncoder::exitAggregateType(const ShaderVariable &structVar) {}

void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
                                          const std::vector<unsigned int> &arraySizes,
                                          bool isRowMajorMatrix,
                                          int *arrayStrideOut,
                                          int *matrixStrideOut)
{
    GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);

    // We assume we are only dealing with 4 byte components (no doubles or half-words currently)
    ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == kBytesPerComponent);

    int matrixStride = 0;
    int arrayStride  = 0;

    // if variables are not to be packed, or we're about to
    // pack a matrix or array, skip to the start of the next
    // register
    if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty())
    {
        align(kComponentsPerRegister);
    }

    if (gl::IsMatrixType(type))
    {
        matrixStride = kComponentsPerRegister;

        if (!arraySizes.empty())
        {
            const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
            arrayStride            = kComponentsPerRegister * numRegisters;
        }
    }
    else if (!arraySizes.empty())
    {
        arrayStride = kComponentsPerRegister;
    }
    else if (isPacked())
    {
        int numComponents = gl::VariableComponentCount(type);
        if ((numComponents + (mCurrentOffset % kComponentsPerRegister)) > kComponentsPerRegister)
        {
            align(kComponentsPerRegister);
        }
    }

    *matrixStrideOut = matrixStride;
    *arrayStrideOut  = arrayStride;
}

void HLSLBlockEncoder::advanceOffset(GLenum typeIn,
                                     const std::vector<unsigned int> &arraySizes,
                                     bool isRowMajorMatrix,
                                     int arrayStride,
                                     int matrixStride)
{
    GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);

    if (!arraySizes.empty())
    {
        unsigned int arraySize = gl::ArraySizeProduct(arraySizes);
        if (arraySize > 0)
        {
            mCurrentOffset += arrayStride * (arraySize - 1);
        }
    }

    if (gl::IsMatrixType(type))
    {
        ASSERT(matrixStride == kComponentsPerRegister);
        const int numRegisters  = gl::MatrixRegisterCount(type, isRowMajorMatrix);
        const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix);
        mCurrentOffset += kComponentsPerRegister * (numRegisters - 1);
        mCurrentOffset += numComponents;
    }
    else if (isPacked())
    {
        mCurrentOffset += gl::VariableComponentCount(type);
    }
    else
    {
        mCurrentOffset += kComponentsPerRegister;
    }
}

void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters)
{
    mCurrentOffset += (numRegisters * kComponentsPerRegister);
}

HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(
    ShShaderOutput outputType)
{
    switch (outputType)
    {
        case SH_HLSL_3_0_OUTPUT:
            return ENCODE_LOOSE;
        case SH_HLSL_4_1_OUTPUT:
        case SH_HLSL_4_0_FL9_3_OUTPUT:
            return ENCODE_PACKED;
        default:
            UNREACHABLE();
            return ENCODE_PACKED;
    }
}

template <class ShaderVarType>
void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder)
{
    if (variable.isStruct())
    {
        for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++)
        {
            encoder->enterAggregateType(variable);

            for (const ShaderVariable &field : variable.fields)
            {
                HLSLVariableRegisterCount(field, encoder);
            }

            encoder->exitAggregateType(variable);
        }
    }
    else
    {
        // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
        encoder->encodeType(variable.type, variable.arraySizes, false);
    }
}

unsigned int HLSLVariableRegisterCount(const ShaderVariable &variable, ShShaderOutput outputType)
{
    HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType), true);
    HLSLVariableRegisterCount(variable, &encoder);

    const size_t registerBytes = (encoder.kBytesPerComponent * encoder.kComponentsPerRegister);
    return static_cast<unsigned int>(
        rx::roundUp<size_t>(encoder.getCurrentOffset(), registerBytes) / registerBytes);
}
}  // namespace sh
