Added BufferSubData benchmark.
BUG=angle:705
Change-Id: I65d557f35e4c9f1d94853a775330a92b7d428847
Reviewed-on: https://chromium-review.googlesource.com/213810
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/common/angleutils.h b/src/common/angleutils.h
index 95f1b60..e85237e 100644
--- a/src/common/angleutils.h
+++ b/src/common/angleutils.h
@@ -24,8 +24,8 @@
TypeName(const TypeName&); \
void operator=(const TypeName&)
-template <typename T, unsigned int N>
-inline unsigned int ArraySize(T(&)[N])
+template <typename T, size_t N>
+inline size_t ArraySize(T(&)[N])
{
return N;
}
diff --git a/tests/perf_tests/BufferSubData.cpp b/tests/perf_tests/BufferSubData.cpp
new file mode 100644
index 0000000..db614cf
--- /dev/null
+++ b/tests/perf_tests/BufferSubData.cpp
@@ -0,0 +1,174 @@
+//
+// 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 "BufferSubData.h"
+
+#include <cassert>
+#include <sstream>
+
+std::string BufferSubDataParams::name() const
+{
+ std::stringstream strstr;
+
+ strstr << "BufferSubData - ";
+
+ switch (requestedRenderer)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: strstr << "D3D11"; break;
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: strstr << "D3D9"; break;
+ default: strstr << "UNKNOWN RENDERER (" << requestedRenderer << ")"; break;
+ }
+
+ strstr << " - ";
+
+ 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 << "UNKNOWN FORMAT (" << vertexType << ")"; break;
+ }
+
+ strstr << vertexComponentCount;
+
+ strstr << " - " << updateSize << "b updates - ";
+ strstr << (bufferSize >> 10) << "k buffer - ";
+ strstr << iterations << " updates";
+
+ return strstr.str();
+}
+
+BufferSubDataBenchmark::BufferSubDataBenchmark(const BufferSubDataParams ¶ms)
+ : SimpleBenchmark(params.name(), 1280, 720, 2, params.requestedRenderer),
+ mParams(params)
+{
+ mDrawIterations = mParams.iterations;
+
+ assert(mParams.vertexComponentCount > 1);
+ assert(mParams.iterations > 0);
+}
+
+bool BufferSubDataBenchmark::initializeBenchmark()
+{
+ const std::string vs = SHADER_SOURCE
+ (
+ attribute vec4 vPosition;
+ void main()
+ {
+ gl_Position = vPosition;
+ }
+ );
+
+ 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);
+
+ glGenBuffers(1, &mBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+ glBufferData(GL_ARRAY_BUFFER, mParams.bufferSize, 0, GL_DYNAMIC_DRAW);
+
+ glVertexAttribPointer(0, mParams.vertexComponentCount, mParams.vertexType,
+ mParams.vertexNormalized, 0, 0);
+ glEnableVertexAttribArray(0);
+
+ mUpdateData = new uint8_t[mParams.updateSize];
+
+ GLfloat vertices2[] =
+ {
+ 0.0f, 0.5f,
+ -0.5f, -0.5f,
+ 0.5f, -0.5f,
+ };
+
+ GLfloat vertices3[] =
+ {
+ 0.0f, 0.5f, 0.0f,
+ -0.5f, -0.5f, 0.0f,
+ 0.5f, -0.5f, 0.0f,
+ };
+
+ GLfloat vertices4[] =
+ {
+ 0.0f, 0.5f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f,
+ 0.5f, -0.5f, 0.0f, 1.0f,
+ };
+
+ float *vertexData = NULL;
+
+ switch (mParams.vertexComponentCount)
+ {
+ case 2: vertexData = vertices2; break;
+ case 3: vertexData = vertices3; break;
+ case 4: vertexData = vertices4; break;
+ default: break;
+ }
+
+ assert(vertexData != NULL);
+
+ GLsizeiptr vertexDataSize = sizeof(GLfloat) * mParams.vertexComponentCount;
+ GLsizeiptr triDataSize = vertexDataSize * 3;
+ mNumTris = mParams.updateSize / triDataSize;
+ int offset = 0;
+ for (int i = 0; i < mNumTris; ++i)
+ {
+ memcpy(mUpdateData + offset, vertexData, triDataSize);
+ offset += triDataSize;
+ }
+
+ // Set the viewport
+ glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
+
+ GLenum glErr = glGetError();
+ if (glErr != GL_NO_ERROR)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void BufferSubDataBenchmark::destroyBenchmark()
+{
+ glDeleteProgram(mProgram);
+ glDeleteBuffers(1, &mBuffer);
+ delete[] mUpdateData;
+}
+
+void BufferSubDataBenchmark::beginDrawBenchmark()
+{
+ // Clear the color buffer
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void BufferSubDataBenchmark::drawBenchmark()
+{
+ for (unsigned int it = 0; it < mParams.iterations; it++)
+ {
+ glBufferSubData(GL_ARRAY_BUFFER, 0, mParams.updateSize, mUpdateData);
+ glDrawArrays(GL_TRIANGLES, 0, 3 * mNumTris);
+ }
+}
diff --git a/tests/perf_tests/BufferSubData.h b/tests/perf_tests/BufferSubData.h
new file mode 100644
index 0000000..f138bcc
--- /dev/null
+++ b/tests/perf_tests/BufferSubData.h
@@ -0,0 +1,47 @@
+//
+// 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"
+
+const int BUFFER_SIZE = 1024 * 1024;
+const int UPDATE_SIZE = 300;
+
+#include "shader_utils.h"
+
+struct BufferSubDataParams : public BenchmarkParams
+{
+ EGLint requestedRenderer;
+ GLenum vertexType;
+ GLint vertexComponentCount;
+ GLboolean vertexNormalized;
+ GLsizeiptr updateSize;
+ GLsizeiptr bufferSize;
+ unsigned int iterations;
+
+ virtual std::string name() const;
+};
+
+class BufferSubDataBenchmark : public SimpleBenchmark
+{
+ public:
+ BufferSubDataBenchmark(const BufferSubDataParams ¶ms);
+
+ virtual bool initializeBenchmark();
+ virtual void destroyBenchmark();
+ virtual void beginDrawBenchmark();
+ virtual void drawBenchmark();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BufferSubDataBenchmark);
+
+ GLuint mProgram;
+ GLuint mBuffer;
+ uint8_t *mUpdateData;
+ int mNumTris;
+
+ const BufferSubDataParams mParams;
+};
+
diff --git a/tests/perf_tests/SimpleBenchmark.cpp b/tests/perf_tests/SimpleBenchmark.cpp
index b47daf0..b1e83a3 100644
--- a/tests/perf_tests/SimpleBenchmark.cpp
+++ b/tests/perf_tests/SimpleBenchmark.cpp
@@ -10,7 +10,9 @@
SimpleBenchmark::SimpleBenchmark(const std::string &name, size_t width, size_t height, EGLint glesMajorVersion, EGLint requestedRenderer)
: mNumFrames(0),
mName(name),
- mRunning(false)
+ mRunning(false),
+ mDrawIterations(10),
+ mRunTimeSeconds(5.0)
{
mOSWindow.reset(CreateOSWindow());
mEGLWindow.reset(new EGLWindow(width, height, glesMajorVersion, requestedRenderer));
@@ -41,7 +43,7 @@
void SimpleBenchmark::draw()
{
- if (mTimer->getElapsedTime() > runTimeSeconds()) {
+ if (mTimer->getElapsedTime() > mRunTimeSeconds) {
mRunning = false;
return;
}
@@ -50,7 +52,7 @@
beginDrawBenchmark();
- for (int i = 0; i < drawIterations(); ++i)
+ for (unsigned int iteration = 0; iteration < mDrawIterations; ++iteration)
{
drawBenchmark();
}
diff --git a/tests/perf_tests/SimpleBenchmark.h b/tests/perf_tests/SimpleBenchmark.h
index 76ffd88..e128366 100644
--- a/tests/perf_tests/SimpleBenchmark.h
+++ b/tests/perf_tests/SimpleBenchmark.h
@@ -30,9 +30,6 @@
virtual ~SimpleBenchmark() { };
- virtual int drawIterations() const { return 10; }
- virtual double runTimeSeconds() const { return 10.0; }
-
virtual bool initializeBenchmark() { return true; }
virtual void destroyBenchmark() { }
@@ -47,6 +44,10 @@
OSWindow *getWindow();
+ protected:
+ unsigned int mDrawIterations;
+ double mRunTimeSeconds;
+
private:
DISALLOW_COPY_AND_ASSIGN(SimpleBenchmark);
diff --git a/tests/perf_tests/SimpleBenchmarks.cpp b/tests/perf_tests/SimpleBenchmarks.cpp
index d538fd7..dc4734b 100644
--- a/tests/perf_tests/SimpleBenchmarks.cpp
+++ b/tests/perf_tests/SimpleBenchmarks.cpp
@@ -5,8 +5,63 @@
//
#include "SimpleBenchmark.h"
+#include "BufferSubData.h"
+
+EGLint platforms[] =
+{
+ EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
+ EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
+};
+
+GLenum vertexTypes[] = { GL_FLOAT };
+GLint componentCounts[] = { 2, 3, 4 };
+GLboolean vertexNorms[] = { GL_FALSE };
+GLsizeiptr updateSizes[] = { 300 };
+GLsizeiptr bufferSizes[] = { 1024 * 1024 };
+unsigned int iterationCounts[] = { 10 };
int main(int argc, char **argv)
{
- // TODO
+ std::vector<BufferSubDataParams> benchmarks;
+
+ for (size_t platIt = 0; platIt < ArraySize(platforms); platIt++)
+ {
+ for (size_t typeIt = 0; typeIt < ArraySize(vertexTypes); typeIt++)
+ {
+ for (size_t compIt = 0; compIt < ArraySize(componentCounts); compIt++)
+ {
+ for (size_t normIt = 0; normIt < ArraySize(vertexNorms); normIt++)
+ {
+ // No normalized float data
+ if (vertexTypes[typeIt] == GL_FLOAT && vertexNorms[normIt] == GL_TRUE)
+ {
+ continue;
+ }
+
+ for (size_t updateIt = 0; updateIt < ArraySize(updateSizes); updateIt++)
+ {
+ for (size_t bufszIt = 0; bufszIt < ArraySize(bufferSizes); bufszIt++)
+ {
+ for (size_t itIt = 0; itIt < ArraySize(iterationCounts); itIt++)
+ {
+ BufferSubDataParams params;
+ params.requestedRenderer = platforms[platIt];
+ params.vertexType = vertexTypes[typeIt];
+ params.vertexComponentCount = componentCounts[compIt];
+ params.vertexNormalized = vertexNorms[normIt];
+ params.updateSize = updateSizes[updateIt];
+ params.bufferSize = bufferSizes[bufszIt];
+ params.iterations = iterationCounts[itIt];
+
+ benchmarks.push_back(params);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Enumerates permutations
+ RunBenchmarks<BufferSubDataBenchmark>(benchmarks);
}
diff --git a/tests/tests.gyp b/tests/tests.gyp
index ef0f7a6..1af7f21 100644
--- a/tests/tests.gyp
+++ b/tests/tests.gyp
@@ -209,6 +209,8 @@
],
'sources':
[
+ 'perf_tests/BufferSubData.cpp',
+ 'perf_tests/BufferSubData.h',
'perf_tests/SimpleBenchmark.cpp',
'perf_tests/SimpleBenchmark.h',
'perf_tests/SimpleBenchmarks.cpp',
diff --git a/util/shared_utils.h b/util/shared_utils.h
index 9a23048..375aff8 100644
--- a/util/shared_utils.h
+++ b/util/shared_utils.h
@@ -15,4 +15,10 @@
TypeName(const TypeName&); \
void operator=(const TypeName&)
+template <typename T, size_t N>
+inline size_t ArraySize(T(&)[N])
+{
+ return N;
+}
+
#endif // UTIL_SHARED_UTILS_H