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

#include <cmath>
#include <sstream>

#include "util/Matrix.h"
#include "util/random_utils.h"
#include "util/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;
        iterationsPerStep = 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();
    }

    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)
{}

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

    const char kVS[] =
        "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";

    constexpr char kFS[] =
        "precision mediump float;\n"
        "varying vec3 vColor;\n"
        "void main()\n"
        "{\n"
        "    gl_FragColor = vec4(vColor, 1.0);\n"
        "}\n";

    mProgram = CompileProgram(kVS, kFS);
    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)
    {
        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.iterationsPerStep; it++)
        {
            glDrawElementsInstancedANGLE(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, mNumPoints);
        }
    }
    else
    {
        for (unsigned int it = 0; it < params.iterationsPerStep; 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 InstancingPerfOpenGLOrGLESParams()
{
    InstancingPerfParams params;
    params.eglParameters = OPENGL_OR_GLES(false);
    return params;
}

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

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

}  // anonymous namespace
