//
// Copyright 2014 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.
//
// BufferSubData.cpp:
//   Performance test for ANGLE buffer updates.
//

#include <sstream>
#include "common/unsafe_buffers.h"

#include "ANGLEPerfTest.h"
#include "test_utils/draw_call_perf_utils.h"

using namespace angle;

namespace
{
constexpr unsigned int kIterationsPerStep = 4;

struct BufferSubDataParams final : public RenderTestParams
{
    BufferSubDataParams()
    {
        // Common default values
        majorVersion      = 2;
        minorVersion      = 0;
        windowWidth       = 512;
        windowHeight      = 512;
        updateSize        = 32000;
        bufferSize        = 40000;
        iterationsPerStep = kIterationsPerStep;
        updateRate        = 1;
    }

    std::string story() const override;

    GLboolean vertexNormalized;
    GLenum vertexType;
    GLint vertexComponentCount;
    unsigned int updateRate;

    // static parameters
    GLsizeiptr updateSize;
    GLsizeiptr bufferSize;
};

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

class BufferSubDataBenchmark : public ANGLERenderTest,
                               public ::testing::WithParamInterface<BufferSubDataParams>
{
  public:
    BufferSubDataBenchmark();

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

  private:
    GLuint mProgram;
    GLuint mBuffer;
    uint8_t *mUpdateData;
    int mNumTris;
};

GLfloat *GetFloatData(GLint componentCount)
{
    static GLfloat vertices2[] = {
        1, 2, 0, 0, 2, 0,
    };

    static GLfloat vertices3[] = {
        1, 2, 1, 0, 0, 1, 2, 0, 1,
    };

    static GLfloat vertices4[] = {
        1, 2, 1, 3, 0, 0, 1, 3, 2, 0, 1, 3,
    };

    switch (componentCount)
    {
        case 2:
            return vertices2;
        case 3:
            return vertices3;
        case 4:
            return vertices4;
        default:
            return nullptr;
    }
}

template <class T>
GLsizeiptr GetNormalizedData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data)
{
    GLsizeiptr triDataSize = sizeof(T) * numElements;
    data->resize(triDataSize);

    T *destPtr = ANGLE_UNSAFE_TODO(reinterpret_cast<T *>(data->data()));

    for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++)
    {
        GLfloat scaled = ANGLE_UNSAFE_TODO(floatData[dataIndex]) * 0.25f;
        ANGLE_UNSAFE_TODO(destPtr[dataIndex]) =
            static_cast<T>(scaled * static_cast<GLfloat>(std::numeric_limits<T>::max()));
    }

    return triDataSize;
}

template <class T>
GLsizeiptr GetIntData(GLsizeiptr numElements, GLfloat *floatData, std::vector<uint8_t> *data)
{
    GLsizeiptr triDataSize = sizeof(T) * numElements;
    data->resize(triDataSize);

    T *destPtr = ANGLE_UNSAFE_TODO(reinterpret_cast<T *>(data->data()));

    for (GLsizeiptr dataIndex = 0; dataIndex < numElements; dataIndex++)
    {
        ANGLE_UNSAFE_TODO(destPtr[dataIndex]) =
            static_cast<T>(ANGLE_UNSAFE_TODO(floatData[dataIndex]));
    }

    return triDataSize;
}

GLsizeiptr GetVertexData(GLenum type,
                         GLint componentCount,
                         GLboolean normalized,
                         std::vector<uint8_t> *data)
{
    GLsizeiptr triDataSize = 0;
    GLfloat *floatData     = GetFloatData(componentCount);

    if (type == GL_FLOAT)
    {
        triDataSize = sizeof(GLfloat) * componentCount * 3;
        data->resize(triDataSize);
        ANGLE_UNSAFE_TODO(memcpy(data->data(), floatData, triDataSize));
    }
    else if (normalized == GL_TRUE)
    {
        GLsizeiptr numElements = componentCount * 3;

        switch (type)
        {
            case GL_BYTE:
                triDataSize = GetNormalizedData<GLbyte>(numElements, floatData, data);
                break;
            case GL_SHORT:
                triDataSize = GetNormalizedData<GLshort>(numElements, floatData, data);
                break;
            case GL_INT:
                triDataSize = GetNormalizedData<GLint>(numElements, floatData, data);
                break;
            case GL_UNSIGNED_BYTE:
                triDataSize = GetNormalizedData<GLubyte>(numElements, floatData, data);
                break;
            case GL_UNSIGNED_SHORT:
                triDataSize = GetNormalizedData<GLushort>(numElements, floatData, data);
                break;
            case GL_UNSIGNED_INT:
                triDataSize = GetNormalizedData<GLuint>(numElements, floatData, data);
                break;
            default:
                assert(0);
        }
    }
    else
    {
        GLsizeiptr numElements = componentCount * 3;

        switch (type)
        {
            case GL_BYTE:
                triDataSize = GetIntData<GLbyte>(numElements, floatData, data);
                break;
            case GL_SHORT:
                triDataSize = GetIntData<GLshort>(numElements, floatData, data);
                break;
            case GL_INT:
                triDataSize = GetIntData<GLint>(numElements, floatData, data);
                break;
            case GL_UNSIGNED_BYTE:
                triDataSize = GetIntData<GLubyte>(numElements, floatData, data);
                break;
            case GL_UNSIGNED_SHORT:
                triDataSize = GetIntData<GLushort>(numElements, floatData, data);
                break;
            case GL_UNSIGNED_INT:
                triDataSize = GetIntData<GLuint>(numElements, floatData, data);
                break;
            default:
                assert(0);
        }
    }

    return triDataSize;
}

std::string BufferSubDataParams::story() const
{
    std::stringstream strstr;

    strstr << RenderTestParams::story();

    if (vertexNormalized)
    {
        strstr << "_norm";
    }

    switch (vertexType)
    {
        case GL_FLOAT:
            strstr << "_float";
            break;
        case GL_INT:
            strstr << "_int";
            break;
        case GL_BYTE:
            strstr << "_byte";
            break;
        case GL_SHORT:
            strstr << "_short";
            break;
        case GL_UNSIGNED_INT:
            strstr << "_uint";
            break;
        case GL_UNSIGNED_BYTE:
            strstr << "_ubyte";
            break;
        case GL_UNSIGNED_SHORT:
            strstr << "_ushort";
            break;
        default:
            strstr << "_vunk_" << vertexType << "_";
            break;
    }

    strstr << vertexComponentCount;
    strstr << "_every" << updateRate;

    return strstr.str();
}

BufferSubDataBenchmark::BufferSubDataBenchmark()
    : ANGLERenderTest("BufferSubData", GetParam()),
      mProgram(0),
      mBuffer(0),
      mUpdateData(nullptr),
      mNumTris(0)
{}

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

    ASSERT_LT(1, params.vertexComponentCount);

    mProgram = SetupSimpleScaleAndOffsetProgram();
    ASSERT_NE(0u, mProgram);

    if (params.vertexNormalized == GL_TRUE)
    {
        GLfloat scale  = 2.0f;
        GLfloat offset = -0.5f;
        glUniform1f(glGetUniformLocation(mProgram, "uScale"), scale);
        glUniform1f(glGetUniformLocation(mProgram, "uOffset"), offset);
    }

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

    std::vector<uint8_t> zeroData(params.bufferSize);
    ANGLE_UNSAFE_TODO(memset(&zeroData[0], 0, zeroData.size()));

    glGenBuffers(1, &mBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
    glBufferData(GL_ARRAY_BUFFER, params.bufferSize, &zeroData[0], GL_DYNAMIC_DRAW);

    glVertexAttribPointer(0, params.vertexComponentCount, params.vertexType,
                          params.vertexNormalized, 0, 0);
    glEnableVertexAttribArray(0);

    if (params.updateSize > 0)
    {
        mUpdateData = new uint8_t[params.updateSize];
    }

    std::vector<uint8_t> data;
    GLsizei triDataSize = static_cast<GLsizei>(GetVertexData(
        params.vertexType, params.vertexComponentCount, params.vertexNormalized, &data));

    mNumTris = static_cast<int>(params.updateSize / triDataSize);
    for (int i = 0, offset = 0; i < mNumTris; ++i)
    {
        ANGLE_UNSAFE_TODO(memcpy(mUpdateData + offset, &data[0], triDataSize));
        offset += triDataSize;
    }

    if (params.updateSize == 0)
    {
        mNumTris = 1;
        glBufferSubData(GL_ARRAY_BUFFER, 0, data.size(), &data[0]);
    }

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

    ASSERT_GL_NO_ERROR();
}

void BufferSubDataBenchmark::destroyBenchmark()
{
    glDeleteProgram(mProgram);
    glDeleteBuffers(1, &mBuffer);
    SafeDeleteArray(mUpdateData);
}

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

    const auto &params = GetParam();

    for (unsigned int it = 0; it < params.iterationsPerStep; it++)
    {
        if (params.updateSize > 0 && ((getNumStepsPerformed() % params.updateRate) == 0))
        {
            glBufferSubData(GL_ARRAY_BUFFER, 0, params.updateSize, mUpdateData);
        }

        glDrawArrays(GL_TRIANGLES, 0, 3 * mNumTris);
    }

    ASSERT_GL_NO_ERROR();
}

BufferSubDataParams BufferUpdateD3D11Params()
{
    BufferSubDataParams params;
    params.eglParameters        = egl_platform::D3D11();
    params.vertexType           = GL_FLOAT;
    params.vertexComponentCount = 4;
    params.vertexNormalized     = GL_FALSE;
    return params;
}

BufferSubDataParams BufferUpdateMetalParams()
{
    BufferSubDataParams params;
    params.eglParameters        = egl_platform::METAL();
    params.vertexType           = GL_FLOAT;
    params.vertexComponentCount = 4;
    params.vertexNormalized     = GL_FALSE;
    return params;
}

BufferSubDataParams BufferUpdateOpenGLOrGLESParams()
{
    BufferSubDataParams params;
    params.eglParameters        = egl_platform::OPENGL_OR_GLES();
    params.vertexType           = GL_FLOAT;
    params.vertexComponentCount = 4;
    params.vertexNormalized     = GL_FALSE;
    return params;
}

BufferSubDataParams BufferUpdateVulkanParams()
{
    BufferSubDataParams params;
    params.eglParameters        = egl_platform::VULKAN();
    params.vertexType           = GL_FLOAT;
    params.vertexComponentCount = 4;
    params.vertexNormalized     = GL_FALSE;
    return params;
}

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

ANGLE_INSTANTIATE_TEST(BufferSubDataBenchmark,
                       BufferUpdateD3D11Params(),
                       BufferUpdateMetalParams(),
                       BufferUpdateOpenGLOrGLESParams(),
                       BufferUpdateVulkanParams());

}  // namespace
