//
// Copyright (c) 2016 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.
//
// LinkProgramPerfTest:
//   Performance tests compiling a lot of shaders.
//

#include "ANGLEPerfTest.h"

#include <array>

#include "common/vector_utils.h"
#include "util/shader_utils.h"

using namespace angle;

namespace
{

enum class TaskOption
{
    CompileOnly,
    CompileAndLink,

    Unspecified
};

enum class ThreadOption
{
    SingleThread,
    MultiThread,

    Unspecified
};

struct LinkProgramParams final : public RenderTestParams
{
    LinkProgramParams(TaskOption taskOptionIn, ThreadOption threadOptionIn)
    {
        iterationsPerStep = 1;

        majorVersion = 2;
        minorVersion = 0;
        windowWidth  = 256;
        windowHeight = 256;
        taskOption   = taskOptionIn;
        threadOption = threadOptionIn;
    }

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

        if (taskOption == TaskOption::CompileOnly)
        {
            strstr << "_compile_only";
        }
        else if (taskOption == TaskOption::CompileAndLink)
        {
            strstr << "_compile_and_link";
        }

        if (threadOption == ThreadOption::SingleThread)
        {
            strstr << "_single_thread";
        }
        else if (threadOption == ThreadOption::MultiThread)
        {
            strstr << "_multi_thread";
        }

        if (eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
        {
            strstr << "_null";
        }

        return strstr.str();
    }

    TaskOption taskOption;
    ThreadOption threadOption;
};

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

class LinkProgramBenchmark : public ANGLERenderTest,
                             public ::testing::WithParamInterface<LinkProgramParams>
{
  public:
    LinkProgramBenchmark();

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

  protected:
    GLuint mVertexBuffer = 0;
};

LinkProgramBenchmark::LinkProgramBenchmark() : ANGLERenderTest("LinkProgram", GetParam()) {}

void LinkProgramBenchmark::initializeBenchmark()
{
    if (GetParam().threadOption == ThreadOption::SingleThread)
    {
        glMaxShaderCompilerThreadsKHR(0);
    }

    std::array<Vector3, 6> vertices = {{Vector3(-1.0f, 1.0f, 0.5f), Vector3(-1.0f, -1.0f, 0.5f),
                                        Vector3(1.0f, -1.0f, 0.5f), Vector3(-1.0f, 1.0f, 0.5f),
                                        Vector3(1.0f, -1.0f, 0.5f), Vector3(1.0f, 1.0f, 0.5f)}};

    glGenBuffers(1, &mVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vector3), vertices.data(),
                 GL_STATIC_DRAW);
}

void LinkProgramBenchmark::destroyBenchmark()
{
    glDeleteBuffers(1, &mVertexBuffer);
}

void LinkProgramBenchmark::drawBenchmark()
{
    static const char *vertexShader =
        "attribute vec2 position;\n"
        "void main() {\n"
        "    gl_Position = vec4(position, 0, 1);\n"
        "}";
    static const char *fragmentShader =
        "precision mediump float;\n"
        "void main() {\n"
        "    gl_FragColor = vec4(1, 0, 0, 1);\n"
        "}";
    GLuint vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    ASSERT_NE(0u, vs);
    ASSERT_NE(0u, fs);
    if (GetParam().taskOption == TaskOption::CompileOnly)
    {
        glDeleteShader(vs);
        glDeleteShader(fs);
        return;
    }

    GLuint program = glCreateProgram();
    ASSERT_NE(0u, program);

    glAttachShader(program, vs);
    glDeleteShader(vs);
    glAttachShader(program, fs);
    glDeleteShader(fs);
    glLinkProgram(program);
    glUseProgram(program);

    GLint positionLoc = glGetAttribLocation(program, "position");
    glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 8, nullptr);
    glEnableVertexAttribArray(positionLoc);

    // Draw with the program to ensure the shader gets compiled and used.
    glDrawArrays(GL_TRIANGLES, 0, 6);

    glDeleteProgram(program);
}

using namespace egl_platform;

LinkProgramParams LinkProgramD3D11Params(TaskOption taskOption, ThreadOption threadOption)
{
    LinkProgramParams params(taskOption, threadOption);
    params.eglParameters = D3D11();
    return params;
}

LinkProgramParams LinkProgramD3D9Params(TaskOption taskOption, ThreadOption threadOption)
{
    LinkProgramParams params(taskOption, threadOption);
    params.eglParameters = D3D9();
    return params;
}

LinkProgramParams LinkProgramOpenGLOrGLESParams(TaskOption taskOption, ThreadOption threadOption)
{
    LinkProgramParams params(taskOption, threadOption);
    params.eglParameters = OPENGL_OR_GLES(false);
    return params;
}

LinkProgramParams LinkProgramVulkanParams(TaskOption taskOption, ThreadOption threadOption)
{
    LinkProgramParams params(taskOption, threadOption);
    params.eglParameters = VULKAN();
    return params;
}

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

ANGLE_INSTANTIATE_TEST(
    LinkProgramBenchmark,
    LinkProgramD3D11Params(TaskOption::CompileOnly, ThreadOption::MultiThread),
    LinkProgramD3D9Params(TaskOption::CompileOnly, ThreadOption::MultiThread),
    LinkProgramOpenGLOrGLESParams(TaskOption::CompileOnly, ThreadOption::MultiThread),
    LinkProgramVulkanParams(TaskOption::CompileOnly, ThreadOption::MultiThread),
    LinkProgramD3D11Params(TaskOption::CompileAndLink, ThreadOption::MultiThread),
    LinkProgramD3D9Params(TaskOption::CompileAndLink, ThreadOption::MultiThread),
    LinkProgramOpenGLOrGLESParams(TaskOption::CompileAndLink, ThreadOption::MultiThread),
    LinkProgramVulkanParams(TaskOption::CompileAndLink, ThreadOption::MultiThread),
    LinkProgramD3D11Params(TaskOption::CompileOnly, ThreadOption::SingleThread),
    LinkProgramD3D9Params(TaskOption::CompileOnly, ThreadOption::SingleThread),
    LinkProgramOpenGLOrGLESParams(TaskOption::CompileOnly, ThreadOption::SingleThread),
    LinkProgramVulkanParams(TaskOption::CompileOnly, ThreadOption::SingleThread),
    LinkProgramD3D11Params(TaskOption::CompileAndLink, ThreadOption::SingleThread),
    LinkProgramD3D9Params(TaskOption::CompileAndLink, ThreadOption::SingleThread),
    LinkProgramOpenGLOrGLESParams(TaskOption::CompileAndLink, ThreadOption::SingleThread),
    LinkProgramVulkanParams(TaskOption::CompileAndLink, ThreadOption::SingleThread));

}  // anonymous namespace
