//
// Copyright 2020 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.
//
// MultisampledRenderToTextureBenchmark:
//   Performance test for rendering to multisampled-render-to-texture attachments.
//

#include "ANGLEPerfTest.h"

#include <iostream>
#include <random>
#include <sstream>

#include "test_utils/gl_raii.h"
#include "util/shader_utils.h"

using namespace angle;

namespace
{
constexpr uint32_t kMultipassPassCount = 5;

struct MultisampledRenderToTextureParams final : public RenderTestParams
{
    MultisampledRenderToTextureParams()
    {
        iterationsPerStep = 1;
        trackGpuTime      = true;

        textureWidth  = 1920;
        textureHeight = 1080;

        multiplePasses   = false;
        withDepthStencil = false;
    }

    std::string story() const override;

    GLsizei textureWidth;
    GLsizei textureHeight;

    bool multiplePasses;
    bool withDepthStencil;
};

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

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

    strstr << RenderTestParams::story();

    if (multiplePasses)
    {
        strstr << "_multipass";
    }

    if (withDepthStencil)
    {
        strstr << "_ds";
    }

    return strstr.str();
}

class MultisampledRenderToTextureBenchmark
    : public ANGLERenderTest,
      public ::testing::WithParamInterface<MultisampledRenderToTextureParams>
{
  public:
    MultisampledRenderToTextureBenchmark();

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

  protected:
    void initShaders();

    GLuint mFramebuffer              = 0;
    GLuint mProgram                  = 0;
    GLuint mColorTexture             = 0;
    GLuint mDepthStencilRenderbuffer = 0;

    std::vector<uint8_t> mTextureData;
};

MultisampledRenderToTextureBenchmark::MultisampledRenderToTextureBenchmark()
    : ANGLERenderTest("MultisampledRenderToTexture", GetParam())
{
    // Crashes on nvidia+d3d11. http://crbug.com/945415
    if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    {
        mSkipTest = true;
    }

    // Fails on Windows7 NVIDIA Vulkan, presumably due to old drivers. http://crbug.com/1096510
    if (IsWindows7() && IsNVIDIA() &&
        GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
    {
        mSkipTest = true;
    }

    // Fails on Pixel 2 GLES: http://anglebug.com/5120
    if (IsPixel2() && GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
    {
        mSkipTest = true;
    }

    // http://anglebug.com/5380
    if (IsLinux() && IsAMD() &&
        GetParam().eglParameters.renderer == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE &&
        GetParam().multiplePasses && GetParam().withDepthStencil)
    {
        mSkipTest = true;
    }
}

void MultisampledRenderToTextureBenchmark::initializeBenchmark()
{
    if (!IsGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"))
    {
        mSkipTest = true;
        return;
    }

    const auto &params = GetParam();

    initShaders();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

    glGenFramebuffers(1, &mFramebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);

    glGenTextures(1, &mColorTexture);
    glBindTexture(GL_TEXTURE_2D, mColorTexture);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, params.textureWidth, params.textureHeight, 0, GL_RGBA,
                 GL_UNSIGNED_BYTE, nullptr);
    glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                         mColorTexture, 0, 4);

    if (params.withDepthStencil)
    {
        glGenRenderbuffers(1, &mDepthStencilRenderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, mDepthStencilRenderbuffer);
        glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8,
                                            params.textureWidth, params.textureHeight);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
                                  mDepthStencilRenderbuffer);
    }

    ASSERT_GL_NO_ERROR();
}

void MultisampledRenderToTextureBenchmark::initShaders()
{
    constexpr char kVS[] = R"(void main()
{
    gl_Position = vec4(0, 0, 0, 1);
})";

    constexpr char kFS[] = R"(precision mediump float;
void main()
{
    gl_FragColor = vec4(0);
})";

    mProgram = CompileProgram(kVS, kFS);
    ASSERT_NE(0u, mProgram);

    glUseProgram(mProgram);

    ASSERT_GL_NO_ERROR();
}

void MultisampledRenderToTextureBenchmark::destroyBenchmark()
{
    glDeleteFramebuffers(1, &mFramebuffer);
    glDeleteRenderbuffers(1, &mDepthStencilRenderbuffer);
    glDeleteTextures(1, &mColorTexture);
    glDeleteProgram(mProgram);
}

void MultisampledRenderToTextureBenchmark::drawBenchmark()
{
    const auto &params = GetParam();

    GLTexture mMockTexture;
    glBindTexture(GL_TEXTURE_2D, mMockTexture);

    startGpuTimer();

    // Initially clear the color attachment to avoid having to load from the resolved image.  The
    // depth/stencil attachment doesn't need this as it's contents are always undefined between
    // render passes.
    glClear(GL_COLOR_BUFFER_BIT);

    const uint32_t passCount = params.multiplePasses ? kMultipassPassCount : 1;
    for (uint32_t pass = 0; pass < passCount; ++pass)
    {
        // Perform a draw just to have something in the render pass.  With the position attributes
        // not set, a constant default value is used, resulting in a very cheap draw.
        glDrawArrays(GL_TRIANGLES, 0, 3);

        // Force the render pass to break by cheaply reading back from the color attachment.
        glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 1, 1, 0);
    }
    stopGpuTimer();

    ASSERT_GL_NO_ERROR();
}

MultisampledRenderToTextureParams D3D11Params(bool multiplePasses, bool withDepthStencil)
{
    MultisampledRenderToTextureParams params;
    params.eglParameters    = egl_platform::D3D11();
    params.majorVersion     = 3;
    params.minorVersion     = 0;
    params.multiplePasses   = multiplePasses;
    params.withDepthStencil = withDepthStencil;
    return params;
}

MultisampledRenderToTextureParams OpenGLOrGLESParams(bool multiplePasses, bool withDepthStencil)
{
    MultisampledRenderToTextureParams params;
    params.eglParameters    = egl_platform::OPENGL_OR_GLES();
    params.majorVersion     = 3;
    params.minorVersion     = 0;
    params.multiplePasses   = multiplePasses;
    params.withDepthStencil = withDepthStencil;
    return params;
}

MultisampledRenderToTextureParams VulkanParams(bool multiplePasses, bool withDepthStencil)
{
    MultisampledRenderToTextureParams params;
    params.eglParameters    = egl_platform::VULKAN();
    params.majorVersion     = 3;
    params.minorVersion     = 0;
    params.multiplePasses   = multiplePasses;
    params.withDepthStencil = withDepthStencil;
    return params;
}

}  // anonymous namespace

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

using namespace params;

ANGLE_INSTANTIATE_TEST(MultisampledRenderToTextureBenchmark,
                       D3D11Params(false, false),
                       D3D11Params(true, true),
                       OpenGLOrGLESParams(false, false),
                       OpenGLOrGLESParams(true, true),
                       VulkanParams(false, false),
                       VulkanParams(true, false),
                       VulkanParams(false, true),
                       VulkanParams(true, true));
