Add a shader compile performance test.

BUG=angleproject:422

Change-Id: I10a2192c5c91360a1b7fe5e4d014bcf1fa84c96e
Reviewed-on: https://chromium-review.googlesource.com/413713
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/tests/perf_tests/LinkProgramPerfTest.cpp b/src/tests/perf_tests/LinkProgramPerfTest.cpp
new file mode 100644
index 0000000..7128066
--- /dev/null
+++ b/src/tests/perf_tests/LinkProgramPerfTest.cpp
@@ -0,0 +1,148 @@
+//
+// 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 "Vector.h"
+#include "shader_utils.h"
+
+using namespace angle;
+
+namespace
+{
+
+struct LinkProgramParams final : public RenderTestParams
+{
+    LinkProgramParams()
+    {
+        majorVersion = 2;
+        minorVersion = 0;
+        windowWidth  = 256;
+        windowHeight = 256;
+    }
+
+    std::string suffix() const override
+    {
+        std::stringstream strstr;
+        strstr << RenderTestParams::suffix();
+
+        if (eglParameters.deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
+        {
+            strstr << "_null";
+        }
+
+        return strstr.str();
+    }
+};
+
+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()
+{
+    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 program = CompileProgram(vertexShader, fragmentShader);
+    ASSERT_NE(0u, 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()
+{
+    LinkProgramParams params;
+    params.eglParameters = D3D11();
+    return params;
+}
+
+LinkProgramParams LinkProgramD3D9Params()
+{
+    LinkProgramParams params;
+    params.eglParameters = D3D9();
+    return params;
+}
+
+LinkProgramParams LinkProgramOpenGLParams()
+{
+    LinkProgramParams params;
+    params.eglParameters = OPENGL();
+    return params;
+}
+
+TEST_P(LinkProgramBenchmark, Run)
+{
+    run();
+}
+
+ANGLE_INSTANTIATE_TEST(LinkProgramBenchmark,
+                       LinkProgramD3D11Params(),
+                       LinkProgramD3D9Params(),
+                       LinkProgramOpenGLParams());
+
+}  // anonymous namespace