Add a point sprite benchmark.

This benchmark will attempt to reproduce the slowdown we see
in D3D11 on the turbulenz GPU particles demo.

BUG=angle:705

Change-Id: I9c4c2f09d4282feae30f448fd374cdbb6bceae9b
Reviewed-on: https://chromium-review.googlesource.com/216467
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/projects/samples/sample_util.vcxproj b/projects/samples/sample_util.vcxproj
index 5944555..4efdfee 100644
--- a/projects/samples/sample_util.vcxproj
+++ b/projects/samples/sample_util.vcxproj
@@ -205,7 +205,6 @@
     <ClInclude Include="..\..\samples\angle\sample_util\Vector.h"/>
     <ClInclude Include="..\..\samples\angle\sample_util\geometry_utils.h"/>
     <ClInclude Include="..\..\samples\angle\sample_util\Matrix.h"/>
-    <ClInclude Include="..\..\samples\angle\sample_util\random_utils.h"/>
     <ClInclude Include="..\..\samples\angle\sample_util\tga_utils.h"/>
     <ClInclude Include="..\..\samples\angle\sample_util\SampleApplication.h"/>
     <ClInclude Include="..\..\samples\angle\sample_util\texture_utils.h"/>
@@ -213,10 +212,9 @@
   <ItemGroup>
     <ClCompile Include="..\..\samples\angle\sample_util\texture_utils.cpp"/>
     <ClCompile Include="..\..\samples\angle\sample_util\SampleApplication.cpp"/>
-    <ClCompile Include="..\..\samples\angle\sample_util\geometry_utils.cpp"/>
     <ClCompile Include="..\..\samples\angle\sample_util\Vector.cpp"/>
+    <ClCompile Include="..\..\samples\angle\sample_util\geometry_utils.cpp"/>
     <ClCompile Include="..\..\samples\angle\sample_util\tga_utils.cpp"/>
-    <ClCompile Include="..\..\samples\angle\sample_util\random_utils.cpp"/>
     <ClCompile Include="..\..\samples\angle\sample_util\Matrix.cpp"/>
   </ItemGroup>
   <ItemGroup>
diff --git a/projects/samples/sample_util.vcxproj.filters b/projects/samples/sample_util.vcxproj.filters
index 7ac54a3..be04fb2 100644
--- a/projects/samples/sample_util.vcxproj.filters
+++ b/projects/samples/sample_util.vcxproj.filters
@@ -25,13 +25,10 @@
     <ClInclude Include="..\..\samples\angle\sample_util\Matrix.h">
       <Filter>angle\sample_util</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\samples\angle\sample_util\random_utils.h">
-      <Filter>angle\sample_util</Filter>
-    </ClInclude>
-    <ClCompile Include="..\..\samples\angle\sample_util\geometry_utils.cpp">
+    <ClCompile Include="..\..\samples\angle\sample_util\Vector.cpp">
       <Filter>angle\sample_util</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\samples\angle\sample_util\Vector.cpp">
+    <ClCompile Include="..\..\samples\angle\sample_util\geometry_utils.cpp">
       <Filter>angle\sample_util</Filter>
     </ClCompile>
     <ClCompile Include="..\..\samples\angle\sample_util\tga_utils.cpp">
@@ -40,9 +37,6 @@
     <ClInclude Include="..\..\samples\angle\sample_util\tga_utils.h">
       <Filter>angle\sample_util</Filter>
     </ClInclude>
-    <ClCompile Include="..\..\samples\angle\sample_util\random_utils.cpp">
-      <Filter>angle\sample_util</Filter>
-    </ClCompile>
     <ClInclude Include="..\..\samples\angle\sample_util\SampleApplication.h">
       <Filter>angle\sample_util</Filter>
     </ClInclude>
diff --git a/projects/util/angle_util.vcxproj b/projects/util/angle_util.vcxproj
index 38e9ade..91bfd45 100644
--- a/projects/util/angle_util.vcxproj
+++ b/projects/util/angle_util.vcxproj
@@ -204,23 +204,25 @@
   <ItemGroup>
     <ClInclude Include="..\..\util\mouse.h"/>
     <ClInclude Include="..\..\util\shared_utils.h"/>
-    <ClInclude Include="..\..\util\Timer.h"/>
     <ClInclude Include="..\..\util\EGLWindow.h"/>
+    <ClInclude Include="..\..\util\Timer.h"/>
     <ClInclude Include="..\..\util\path_utils.h"/>
     <ClInclude Include="..\..\util\shader_utils.h"/>
     <ClInclude Include="..\..\util\OSWindow.h"/>
+    <ClInclude Include="..\..\util\random_utils.h"/>
     <ClInclude Include="..\..\util\keyboard.h"/>
     <ClInclude Include="..\..\util\Event.h"/>
-    <ClInclude Include="..\..\util\win32\Win32Window.h"/>
     <ClInclude Include="..\..\util\win32\Win32Timer.h"/>
+    <ClInclude Include="..\..\util\win32\Win32Window.h"/>
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\util\random_utils.cpp"/>
     <ClCompile Include="..\..\util\shader_utils.cpp"/>
     <ClCompile Include="..\..\util\OSWindow.cpp"/>
     <ClCompile Include="..\..\util\EGLWindow.cpp"/>
-    <ClCompile Include="..\..\util\win32\Win32_path_utils.cpp"/>
     <ClCompile Include="..\..\util\win32\Win32Window.cpp"/>
     <ClCompile Include="..\..\util\win32\Win32Timer.cpp"/>
+    <ClCompile Include="..\..\util\win32\Win32_path_utils.cpp"/>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\src\libEGL.vcxproj">
diff --git a/projects/util/angle_util.vcxproj.filters b/projects/util/angle_util.vcxproj.filters
index f32e6de..6df62c9 100644
--- a/projects/util/angle_util.vcxproj.filters
+++ b/projects/util/angle_util.vcxproj.filters
@@ -8,20 +8,22 @@
   <ItemGroup>
     <ClInclude Include="..\..\util\mouse.h"/>
     <ClInclude Include="..\..\util\shared_utils.h"/>
-    <ClInclude Include="..\..\util\Timer.h"/>
+    <ClCompile Include="..\..\util\random_utils.cpp"/>
     <ClInclude Include="..\..\util\EGLWindow.h"/>
+    <ClInclude Include="..\..\util\Timer.h"/>
     <ClInclude Include="..\..\util\path_utils.h"/>
     <None Include="..\..\util\util.gyp"/>
     <ClInclude Include="..\..\util\shader_utils.h"/>
     <ClCompile Include="..\..\util\shader_utils.cpp"/>
     <ClInclude Include="..\..\util\OSWindow.h"/>
+    <ClInclude Include="..\..\util\random_utils.h"/>
     <ClCompile Include="..\..\util\OSWindow.cpp"/>
     <ClInclude Include="..\..\util\keyboard.h"/>
     <ClCompile Include="..\..\util\EGLWindow.cpp"/>
     <ClInclude Include="..\..\util\Event.h"/>
-    <ClCompile Include="..\..\util\win32\Win32_path_utils.cpp">
+    <ClInclude Include="..\..\util\win32\Win32Timer.h">
       <Filter>win32</Filter>
-    </ClCompile>
+    </ClInclude>
     <ClCompile Include="..\..\util\win32\Win32Window.cpp">
       <Filter>win32</Filter>
     </ClCompile>
@@ -31,8 +33,8 @@
     <ClInclude Include="..\..\util\win32\Win32Window.h">
       <Filter>win32</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\util\win32\Win32Timer.h">
+    <ClCompile Include="..\..\util\win32\Win32_path_utils.cpp">
       <Filter>win32</Filter>
-    </ClInclude>
+    </ClCompile>
   </ItemGroup>
 </Project>
diff --git a/tests/perf_tests/PointSprites.cpp b/tests/perf_tests/PointSprites.cpp
new file mode 100644
index 0000000..89a5c1b
--- /dev/null
+++ b/tests/perf_tests/PointSprites.cpp
@@ -0,0 +1,124 @@
+//
+// Copyright (c) 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.
+//
+
+#include "PointSprites.h"
+
+#include <cassert>
+#include <sstream>
+
+#include "shader_utils.h"
+#include "random_utils.h"
+
+std::string PointSpritesParams::name() const
+{
+    std::stringstream strstr;
+
+    strstr << "PointSprites - " << BenchmarkParams::name()
+           << " - " << count << " sprites - size " << size;
+
+    return strstr.str();
+}
+
+PointSpritesBenchmark::PointSpritesBenchmark(const PointSpritesParams &params)
+    : SimpleBenchmark(params.name(), 1280, 720, 2, params.requestedRenderer),
+      mParams(params)
+{
+    mDrawIterations = mParams.iterations;
+    assert(mParams.iterations > 0);
+}
+
+bool PointSpritesBenchmark::initializeBenchmark()
+{
+    const std::string vs = SHADER_SOURCE
+    (
+        attribute vec2 vPosition;
+        uniform float uPointSize;
+        void main()
+        {
+            gl_Position = vec4(vPosition, 0.0, 1.0);
+            gl_PointSize = uPointSize;
+        }
+    );
+
+    const std::string fs = SHADER_SOURCE
+    (
+        precision mediump float;
+        void main()
+        {
+            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+        }
+    );
+
+    mProgram = CompileProgram(vs, fs);
+    if (!mProgram)
+    {
+        return false;
+    }
+
+    // Use the program object
+    glUseProgram(mProgram);
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    std::vector<float> vertexPositions(mParams.count * 2);
+    for (size_t pointIndex = 0; pointIndex < vertexPositions.size(); ++pointIndex)
+    {
+        vertexPositions[pointIndex] = RandomBetween(-1.0f, 1.0f);
+    }
+
+    glGenBuffers(1, &mBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+    glBufferData(GL_ARRAY_BUFFER, vertexPositions.size() * sizeof(float), vertexPositions.data(), GL_STATIC_DRAW);
+
+    int positionLocation = glGetAttribLocation(mProgram, "vPosition");
+    if (positionLocation == -1)
+    {
+        return false;
+    }
+
+    glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+    glEnableVertexAttribArray(positionLocation);
+
+    // Set the viewport
+    glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+    int pointSizeLocation = glGetUniformLocation(mProgram, "uPointSize");
+    if (pointSizeLocation == -1)
+    {
+        return false;
+    }
+
+    glUniform1f(pointSizeLocation, mParams.size);
+
+    GLenum glErr = glGetError();
+    if (glErr != GL_NO_ERROR)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void PointSpritesBenchmark::destroyBenchmark()
+{
+    glDeleteProgram(mProgram);
+    glDeleteBuffers(1, &mBuffer);
+}
+
+void PointSpritesBenchmark::beginDrawBenchmark()
+{
+    // Clear the color buffer
+    glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void PointSpritesBenchmark::drawBenchmark()
+{
+    for (unsigned int it = 0; it < mParams.iterations; it++)
+    {
+        //TODO(jmadill): Indexed point rendering. ANGLE is bad at this.
+        glDrawArrays(GL_POINTS, 0, mParams.count);
+    }
+}
diff --git a/tests/perf_tests/PointSprites.h b/tests/perf_tests/PointSprites.h
new file mode 100644
index 0000000..a1ce228
--- /dev/null
+++ b/tests/perf_tests/PointSprites.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 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.
+//
+
+#include "SimpleBenchmark.h"
+
+struct PointSpritesParams : public BenchmarkParams
+{
+    unsigned int iterations;
+    unsigned int count;
+    float size;
+
+    virtual std::string name() const;
+};
+
+class PointSpritesBenchmark : public SimpleBenchmark
+{
+public:
+    PointSpritesBenchmark(const PointSpritesParams &params);
+
+    virtual bool initializeBenchmark();
+    virtual void destroyBenchmark();
+    virtual void beginDrawBenchmark();
+    virtual void drawBenchmark();
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(PointSpritesBenchmark);
+
+    GLuint mProgram;
+    GLuint mBuffer;
+
+    const PointSpritesParams mParams;
+};
diff --git a/tests/perf_tests/SimpleBenchmarks.cpp b/tests/perf_tests/SimpleBenchmarks.cpp
index e598674..6ceeddd 100644
--- a/tests/perf_tests/SimpleBenchmarks.cpp
+++ b/tests/perf_tests/SimpleBenchmarks.cpp
@@ -7,6 +7,7 @@
 #include "SimpleBenchmark.h"
 #include "BufferSubData.h"
 #include "TexSubImage.h"
+#include "PointSprites.h"
 
 EGLint platforms[] =
 {
@@ -100,4 +101,20 @@
     }
 
     RunBenchmarks<TexSubImageBenchmark>(subImageParams);
+
+    std::vector<PointSpritesParams> pointSpriteParams;
+
+    for (size_t platIt = 0; platIt < ArraySize(platforms); platIt++)
+    {
+        PointSpritesParams params;
+
+        params.requestedRenderer = platforms[platIt];
+        params.iterations = 10;
+        params.count = 10;
+        params.size = 3.0f;
+
+        pointSpriteParams.push_back(params);
+    }
+
+    RunBenchmarks<PointSpritesBenchmark>(pointSpriteParams);
 }
diff --git a/tests/tests.gyp b/tests/tests.gyp
index 5985c34..7a218d1 100644
--- a/tests/tests.gyp
+++ b/tests/tests.gyp
@@ -211,6 +211,8 @@
                     [
                         'perf_tests/BufferSubData.cpp',
                         'perf_tests/BufferSubData.h',
+                        'perf_tests/PointSprites.cpp',
+                        'perf_tests/PointSprites.h',
                         'perf_tests/SimpleBenchmark.cpp',
                         'perf_tests/SimpleBenchmark.h',
                         'perf_tests/SimpleBenchmarks.cpp',
diff --git a/samples/angle/sample_util/random_utils.cpp b/util/random_utils.cpp
similarity index 100%
rename from samples/angle/sample_util/random_utils.cpp
rename to util/random_utils.cpp
diff --git a/samples/angle/sample_util/random_utils.h b/util/random_utils.h
similarity index 67%
rename from samples/angle/sample_util/random_utils.h
rename to util/random_utils.h
index 42acc37..ea0c853 100644
--- a/samples/angle/sample_util/random_utils.h
+++ b/util/random_utils.h
@@ -4,9 +4,9 @@
 // found in the LICENSE file.
 //
 
-#ifndef SAMPLE_UTIL_RANDOM_UTILS_H
-#define SAMPLE_UTIL_RANDOM_UTILS_H
+#ifndef UTIL_RANDOM_UTILS_H
+#define UTIL_RANDOM_UTILS_H
 
 float RandomBetween(float min, float max);
 
-#endif // SAMPLE_UTIL_RANDOM_UTILS_H
+#endif // UTIL_RANDOM_UTILS_H
diff --git a/util/util.gyp b/util/util.gyp
index 1bd29ff..a81393e 100644
--- a/util/util.gyp
+++ b/util/util.gyp
@@ -28,6 +28,8 @@
                         'keyboard.h',
                         'mouse.h',
                         'path_utils.h',
+                        'random_utils.cpp',
+                        'random_utils.h',
                         'shader_utils.cpp',
                         'shader_utils.h',
                         'shared_utils.h',