//
// Copyright 2015 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.
//
// InstancingPerf:
//   Performance tests for ANGLE instanced draw calls.
//

#include <cmath>
#include <sstream>

#include "ANGLEPerfTest.h"
#include "Matrix.h"
#include "random_utils.h"
#include "shader_utils.h"

using namespace angle;
using namespace egl_platform;

namespace
{

float AnimationSignal(float t)
{
    float l = t / 2.0f;
    float f = l - std::floor(l);
    return (f > 0.5f ? 1.0f - f : f) * 4.0f - 1.0f;
}

template <typename T>
size_t VectorSizeBytes(const std::vector<T> &vec)
{
    return sizeof(T) * vec.size();
}

Vector3 RandomVector3(RNG *rng)
{
    return Vector3(rng->randomNegativeOneToOne(), rng->randomNegativeOneToOne(),
                   rng->randomNegativeOneToOne());
}

struct InstancingPerfParams final : public RenderTestParams
{
    // Common default options
    InstancingPerfParams()
    {
        majorVersion      = 2;
        minorVersion      = 0;
        windowWidth       = 256;
        windowHeight      = 256;
        iterations        = 1;
        runTimeSeconds    = 10.0;
        animationEnabled  = false;
        instancingEnabled = true;
    }

    std::string suffix() const override
    {
        std::stringstream strstr;

        strstr << RenderTestParams::suffix();

        if (!instancingEnabled)
        {
            strstr << "_billboards";
        }

        return strstr.str();
    }

    unsigned int iterations;
    double runTimeSeconds;
    bool animationEnabled;
    bool instancingEnabled;
};

std::ostream &operator<<(std::ostream &os, const InstancingPerfParams &params)
{
    os << params.suffix().substr(1);
    return os;
}

class InstancingPerfBenchmark : public ANGLERenderTest,
                                public ::testing::WithParamInterface<InstancingPerfParams>
{
  public:
    InstancingPerfBenchmark();

    void initializeBenchmark() override;
    void destroyBenchmark() override;
    void drawBenchmark() override;

  private:
    GLuint mProgram;
    std::vector<GLuint> mBuffers;
    GLuint mNumPoints;
    std::vector<Vector3> mTranslateData;
    std::vector<float> mSizeData;
    std::vector<Vector3> mColorData;
    angle::RNG mRNG;
};

InstancingPerfBenchmark::InstancingPerfBenchmark()
    : ANGLERenderTest("InstancingPerf", GetParam()), mProgram(0), mNumPoints(75000)
{
    mRunTimeSeconds = GetParam().runTimeSeconds;
}

void InstancingPerfBenchmark::initializeBenchmark()
{
    const auto &params = GetParam();

    ASSERT_LT(0u, params.iterations);

    const std::string vs =
        "attribute vec2 aPosition;\n"
        "attribute vec3 aTranslate;\n"
        "attribute float aScale;\n"
        "attribute vec3 aColor;\n"
        "uniform mat4 uWorldMatrix;\n"
        "uniform mat4 uProjectionMatrix;\n"
        "varying vec3 vColor;\n"
        "void main()\n"
        "{\n"
        "    vec4 position = uWorldMatrix * vec4(aTranslate, 1.0);\n"
        "    position.xy += aPosition * aScale;\n"
        "    gl_Position = uProjectionMatrix * position;\n"
        "    vColor = aColor;\n"
        "}\n";

    const std::string fs =
        "precision mediump float;\n"
        "varying vec3 vColor;\n"
        "void main()\n"
        "{\n"
        "    gl_FragColor = vec4(vColor, 1.0);\n"
        "}\n";

    mProgram = CompileProgram(vs, fs);
    ASSERT_NE(0u, mProgram);

    glUseProgram(mProgram);

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

    GLuint baseIndexData[6]     = {0, 1, 2, 1, 3, 2};
    Vector2 basePositionData[4] = {Vector2(-1.0f, 1.0f), Vector2(1.0f, 1.0f), Vector2(-1.0f, -1.0f),
                                   Vector2(1.0f, -1.0f)};

    std::vector<GLuint> indexData;
    std::vector<Vector2> positionData;

    if (!params.instancingEnabled)
    {
        GLuint pointVertexStride = 4;
        for (GLuint pointIndex = 0; pointIndex < mNumPoints; ++pointIndex)
        {
            for (GLuint indexIndex = 0; indexIndex < 6; ++indexIndex)
            {
                indexData.push_back(baseIndexData[indexIndex] + pointIndex * pointVertexStride);
            }

            Vector3 randVec = RandomVector3(&mRNG);
            for (GLuint vertexIndex = 0; vertexIndex < 4; ++vertexIndex)
            {
                positionData.push_back(basePositionData[vertexIndex]);
                mTranslateData.push_back(randVec);
            }
        }

        mSizeData.resize(mNumPoints * 4, 0.012f);
        mColorData.resize(mNumPoints * 4, Vector3(1.0f, 0.0f, 0.0f));
    }
    else
    {
        for (GLuint index : baseIndexData)
        {
            indexData.push_back(index);
        }

        for (const Vector2 &position : basePositionData)
        {
            positionData.push_back(position);
        }

        for (GLuint pointIndex = 0; pointIndex < mNumPoints; ++pointIndex)
        {
            Vector3 randVec = RandomVector3(&mRNG);
            mTranslateData.push_back(randVec);
        }

        mSizeData.resize(mNumPoints, 0.012f);
        mColorData.resize(mNumPoints, Vector3(1.0f, 0.0f, 0.0f));
    }

    mBuffers.resize(5, 0);
    glGenBuffers(static_cast<GLsizei>(mBuffers.size()), &mBuffers[0]);

    // Index Data
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffers[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, VectorSizeBytes(indexData), &indexData[0],
                 GL_STATIC_DRAW);

    // Position Data
    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[1]);
    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(positionData), &positionData[0], GL_STATIC_DRAW);
    GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
    ASSERT_NE(-1, positionLocation);
    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
    glEnableVertexAttribArray(positionLocation);

    // Translate Data
    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[2]);
    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mTranslateData), &mTranslateData[0],
                 GL_STATIC_DRAW);
    GLint translateLocation = glGetAttribLocation(mProgram, "aTranslate");
    ASSERT_NE(-1, translateLocation);
    glVertexAttribPointer(translateLocation, 3, GL_FLOAT, GL_FALSE, 12, nullptr);
    glEnableVertexAttribArray(translateLocation);
    glVertexAttribDivisorANGLE(translateLocation, 1);

    // Scale Data
    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[3]);
    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mSizeData), nullptr, GL_DYNAMIC_DRAW);
    GLint scaleLocation = glGetAttribLocation(mProgram, "aScale");
    ASSERT_NE(-1, scaleLocation);
    glVertexAttribPointer(scaleLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
    glEnableVertexAttribArray(scaleLocation);
    glVertexAttribDivisorANGLE(scaleLocation, 1);

    // Color Data
    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[4]);
    glBufferData(GL_ARRAY_BUFFER, VectorSizeBytes(mColorData), nullptr, GL_DYNAMIC_DRAW);
    GLint colorLocation = glGetAttribLocation(mProgram, "aColor");
    ASSERT_NE(-1, colorLocation);
    glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 12, nullptr);
    glEnableVertexAttribArray(colorLocation);
    glVertexAttribDivisorANGLE(colorLocation, 1);

    // Set the viewport
    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

    // Init matrices
    GLint worldMatrixLocation = glGetUniformLocation(mProgram, "uWorldMatrix");
    ASSERT_NE(-1, worldMatrixLocation);
    Matrix4 worldMatrix = Matrix4::translate(Vector3(0, 0, -3.0f));
    worldMatrix *= Matrix4::rotate(25.0f, Vector3(0.6f, 1.0f, 0.0f));
    glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, &worldMatrix.data[0]);

    GLint projectionMatrixLocation = glGetUniformLocation(mProgram, "uProjectionMatrix");
    ASSERT_NE(-1, projectionMatrixLocation);
    float fov =
        static_cast<float>(getWindow()->getWidth()) / static_cast<float>(getWindow()->getHeight());
    Matrix4 projectionMatrix = Matrix4::perspective(60.0f, fov, 1.0f, 300.0f);
    glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix.data[0]);

    getWindow()->setVisible(true);

    ASSERT_GL_NO_ERROR();
}

void InstancingPerfBenchmark::destroyBenchmark()
{
    glDeleteProgram(mProgram);

    if (!mBuffers.empty())
    {
        glDeleteBuffers(static_cast<GLsizei>(mBuffers.size()), &mBuffers[0]);
        mBuffers.clear();
    }
}

void InstancingPerfBenchmark::drawBenchmark()
{
    glClear(GL_COLOR_BUFFER_BIT);

    const auto &params = GetParam();

    // Animatino makes the test more interesting visually, but also eats up many CPU cycles.
    if (params.animationEnabled)
    {
        // Not implemented for billboards.
        ASSERT(params.instancingEnabled);

        float time = static_cast<float>(mTimer->getElapsedTime());

        for (size_t pointIndex = 0; pointIndex < mTranslateData.size(); ++pointIndex)
        {
            const Vector3 &translate = mTranslateData[pointIndex];

            float tx = translate.x() + time;
            float ty = translate.y() + time;
            float tz = translate.z() + time;

            float scale           = AnimationSignal(tx) * 0.01f + 0.01f;
            mSizeData[pointIndex] = scale;

            Vector3 color =
                Vector3(AnimationSignal(tx), AnimationSignal(ty), AnimationSignal(tz)) * 0.5f +
                Vector3(0.5f);

            mColorData[pointIndex] = color;
        }
    }

    // Update scales and colors.
    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[3]);
    glBufferSubData(GL_ARRAY_BUFFER, 0, VectorSizeBytes(mSizeData), &mSizeData[0]);

    glBindBuffer(GL_ARRAY_BUFFER, mBuffers[4]);
    glBufferSubData(GL_ARRAY_BUFFER, 0, VectorSizeBytes(mColorData), &mColorData[0]);

    // Render the instances/billboards.
    if (params.instancingEnabled)
    {
        for (unsigned int it = 0; it < params.iterations; it++)
        {
            glDrawElementsInstancedANGLE(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, mNumPoints);
        }
    }
    else
    {
        for (unsigned int it = 0; it < params.iterations; it++)
        {
            glDrawElements(GL_TRIANGLES, 6 * mNumPoints, GL_UNSIGNED_INT, nullptr);
        }
    }

    ASSERT_GL_NO_ERROR();
}

InstancingPerfParams InstancingPerfD3D11Params()
{
    InstancingPerfParams params;
    params.eglParameters = D3D11();
    return params;
}

InstancingPerfParams InstancingPerfD3D9Params()
{
    InstancingPerfParams params;
    params.eglParameters = D3D9();
    return params;
}

InstancingPerfParams InstancingPerfOpenGLParams()
{
    InstancingPerfParams params;
    params.eglParameters = OPENGL();
    return params;
}

TEST_P(InstancingPerfBenchmark, Run)
{
    run();
}

ANGLE_INSTANTIATE_TEST(InstancingPerfBenchmark,
                       InstancingPerfD3D11Params(),
                       InstancingPerfD3D9Params(),
                       InstancingPerfOpenGLParams());

}  // anonymous namespace
