Commit be13ffca by Jamie Madill

Use google test to wrap our perf tests.

This provides easy implementation with the Chromium perf bots. BUG=angleproject:744 Change-Id: I71c04e3d67cae9344ddca9fd95fd3c9849494922 Reviewed-on: https://chromium-review.googlesource.com/260644Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org>
parent 6ae6efca
# Copyright 2015 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.
#
# angle_perftests.gypi:
#
# This .gypi describes all of the sources and dependencies to build a
# unified "angle_perftests" target, which contains all of ANGLE's
# performance tests (buffer updates, texture updates, draw calls, etc)
# It requires a parent target to include this gypi in an executable
# target containing a gtest harness in a main.cpp.
{
'dependencies':
[
'<(angle_path)/src/angle.gyp:angle_common',
'<(angle_path)/src/angle.gyp:libGLESv2',
'<(angle_path)/src/angle.gyp:libEGL',
'<(angle_path)/src/tests/tests.gyp:angle_test_support',
'<(angle_path)/util/util.gyp:angle_util',
],
'include_dirs':
[
'<(angle_path)/include',
],
'sources':
[
'perf_tests/ANGLEPerfTest.cpp',
'perf_tests/ANGLEPerfTest.h',
'perf_tests/BufferSubData.cpp',
'perf_tests/PointSprites.cpp',
'perf_tests/TexSubImage.cpp',
'perf_tests/third_party/perf/perf_test.cc',
'perf_tests/third_party/perf/perf_test.h',
],
}
//
// 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.
//
// angle_perftests_main.cpp
// Entry point for the gtest-based performance tests.
//
#include <gtest/gtest.h>
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
testing::AddGlobalTestEnvironment(new testing::Environment());
int rt = RUN_ALL_TESTS();
return rt;
}
......@@ -4,14 +4,14 @@
// found in the LICENSE file.
//
#include "SimpleBenchmark.h"
#include "ANGLEPerfTest.h"
#include "third_party/perf/perf_test.h"
#include <iostream>
#include <cassert>
std::string BenchmarkParams::suffix() const
std::string PerfTestParams::suffix() const
{
switch (requestedRenderer)
{
......@@ -21,36 +21,58 @@ std::string BenchmarkParams::suffix() const
}
}
SimpleBenchmark::SimpleBenchmark(const std::string &name, size_t width, size_t height,
EGLint glesMajorVersion, const BenchmarkParams &params)
: mNumFrames(0),
ANGLEPerfTest::ANGLEPerfTest(const std::string &name, const PerfTestParams &testParams)
: mTestParams(testParams),
mNumFrames(0),
mName(name),
mRunning(false),
mSuffix(testParams.suffix()),
mDrawIterations(10),
mRunTimeSeconds(5.0),
mSuffix(params.suffix())
mRunTimeSeconds(5.0)
{
mOSWindow.reset(CreateOSWindow());
mEGLWindow.reset(new EGLWindow(width, height, glesMajorVersion, EGLPlatformParameters(params.requestedRenderer)));
mTimer.reset(CreateTimer());
}
bool SimpleBenchmark::initialize()
void ANGLEPerfTest::SetUp()
{
return initializeBenchmark();
mOSWindow.reset(CreateOSWindow());
mEGLWindow.reset(new EGLWindow(mTestParams.widowWidth,
mTestParams.windowHeight,
mTestParams.glesMajorVersion,
EGLPlatformParameters(mTestParams.requestedRenderer)));
mTimer.reset(CreateTimer());
if (!mOSWindow->initialize(mName, mEGLWindow->getWidth(), mEGLWindow->getHeight()))
{
FAIL() << "Failed initializing OSWindow";
return;
}
if (!mEGLWindow->initializeGL(mOSWindow.get()))
{
FAIL() << "Failed initializing EGLWindow";
return;
}
if (!initializeBenchmark())
{
FAIL() << "Failed initializing base perf test";
return;
}
mRunning = true;
}
void SimpleBenchmark::printResult(const std::string &trace, double value, const std::string &units, bool important) const
void ANGLEPerfTest::printResult(const std::string &trace, double value, const std::string &units, bool important) const
{
perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
}
void SimpleBenchmark::printResult(const std::string &trace, size_t value, const std::string &units, bool important) const
void ANGLEPerfTest::printResult(const std::string &trace, size_t value, const std::string &units, bool important) const
{
perf_test::PrintResult(mName, mSuffix, trace, value, units, important);
}
void SimpleBenchmark::destroy()
void ANGLEPerfTest::TearDown()
{
double totalTime = mTimer->getElapsedTime();
double averageTime = 1000.0 * totalTime / static_cast<double>(mNumFrames);
......@@ -60,14 +82,17 @@ void SimpleBenchmark::destroy()
printResult("average_time", averageTime, "ms", true);
destroyBenchmark();
mEGLWindow->destroyGL();
mOSWindow->destroy();
}
void SimpleBenchmark::step(float dt, double totalTime)
void ANGLEPerfTest::step(float dt, double totalTime)
{
stepBenchmark(dt, totalTime);
}
void SimpleBenchmark::draw()
void ANGLEPerfTest::draw()
{
if (mTimer->getElapsedTime() > mRunTimeSeconds) {
mRunning = false;
......@@ -86,27 +111,8 @@ void SimpleBenchmark::draw()
endDrawBenchmark();
}
int SimpleBenchmark::run()
void ANGLEPerfTest::run()
{
if (!mOSWindow->initialize(mName, mEGLWindow->getWidth(), mEGLWindow->getHeight()))
{
return -1;
}
if (!mEGLWindow->initializeGL(mOSWindow.get()))
{
return -1;
}
mRunning = true;
int result = 0;
if (!initialize())
{
mRunning = false;
result = -1;
}
mTimer->start();
double prevTime = 0.0;
......@@ -140,20 +146,14 @@ int SimpleBenchmark::run()
prevTime = elapsedTime;
}
destroy();
mEGLWindow->destroyGL();
mOSWindow->destroy();
return result;
}
bool SimpleBenchmark::popEvent(Event *event)
bool ANGLEPerfTest::popEvent(Event *event)
{
return mOSWindow->popEvent(event);
}
OSWindow *SimpleBenchmark::getWindow()
OSWindow *ANGLEPerfTest::getWindow()
{
return mOSWindow.get();
}
\ No newline at end of file
}
......@@ -3,39 +3,43 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ANGLEPerfTests:
// Base class for google test performance tests
//
#ifndef SAMPLE_UTIL_SIMPLE_BENCHMARK_H
#define SAMPLE_UTIL_SIMPLE_BENCHMARK_H
#ifndef PERF_TESTS_ANGLE_PERF_TEST_H_
#define PERF_TESTS_ANGLE_PERF_TEST_H_
#include <gtest/gtest.h>
#include <memory>
#include <vector>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <string>
#include "shared_utils.h"
#include "OSWindow.h"
#include "EGLWindow.h"
#include "OSWindow.h"
#include "Timer.h"
#include "shared_utils.h"
class Event;
// Base class
struct BenchmarkParams
struct PerfTestParams
{
EGLint requestedRenderer;
EGLint glesMajorVersion;
EGLint widowWidth;
EGLint windowHeight;
virtual std::string suffix() const;
};
class SimpleBenchmark
class ANGLEPerfTest : public testing::Test
{
public:
SimpleBenchmark(const std::string &name, size_t width, size_t height,
EGLint glesMajorVersion, const BenchmarkParams &params);
ANGLEPerfTest(const std::string &name, const PerfTestParams &testParams);
virtual ~SimpleBenchmark() { };
virtual ~ANGLEPerfTest() { };
virtual bool initializeBenchmark() { return true; }
virtual void destroyBenchmark() { }
......@@ -46,7 +50,6 @@ class SimpleBenchmark
virtual void drawBenchmark() = 0;
virtual void endDrawBenchmark() { }
int run();
bool popEvent(Event *event);
OSWindow *getWindow();
......@@ -54,16 +57,18 @@ class SimpleBenchmark
protected:
void printResult(const std::string &trace, double value, const std::string &units, bool important) const;
void printResult(const std::string &trace, size_t value, const std::string &units, bool important) const;
void run();
const PerfTestParams &mTestParams;
unsigned int mDrawIterations;
double mRunTimeSeconds;
int mNumFrames;
private:
DISALLOW_COPY_AND_ASSIGN(SimpleBenchmark);
DISALLOW_COPY_AND_ASSIGN(ANGLEPerfTest);
bool initialize();
void destroy();
void SetUp() override;
void TearDown() override;
void step(float dt, double totalTime);
void draw();
......@@ -77,19 +82,4 @@ class SimpleBenchmark
std::unique_ptr<Timer> mTimer;
};
template <typename BenchmarkT, typename ParamsT>
inline int RunBenchmarks(const std::vector<ParamsT> &benchmarks)
{
int result;
for (size_t benchIndex = 0; benchIndex < benchmarks.size(); benchIndex++)
{
BenchmarkT benchmark(benchmarks[benchIndex]);
result = benchmark.run();
if (result != 0) { return result; }
}
return 0;
}
#endif // SAMPLE_UTIL_SIMPLE_BENCHMARK_H
#endif // PERF_TESTS_ANGLE_PERF_TEST_H_
......@@ -3,17 +3,54 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "BufferSubData.h"
// BufferSubDataBenchmark:
// Performance test for ANGLE buffer updates.
//
#include <cassert>
#include <sstream>
#include "ANGLEPerfTest.h"
#include "shader_utils.h"
namespace
{
struct BufferSubDataParams : public PerfTestParams
{
std::string suffix() const override;
GLboolean vertexNormalized;
GLenum vertexType;
GLint vertexComponentCount;
unsigned int updateRate;
// static parameters
GLsizeiptr updateSize;
GLsizeiptr bufferSize;
unsigned int iterations;
};
class BufferSubDataBenchmark : public ANGLEPerfTest,
public ::testing::WithParamInterface<BufferSubDataParams>
{
public:
BufferSubDataBenchmark();
bool initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
DISALLOW_COPY_AND_ASSIGN(BufferSubDataBenchmark);
GLuint mProgram;
GLuint mBuffer;
uint8_t *mUpdateData;
int mNumTris;
};
GLfloat *GetFloatData(GLint componentCount)
{
static GLfloat vertices2[] =
......@@ -124,13 +161,11 @@ GLsizeiptr GetVertexData(GLenum type, GLint componentCount, GLboolean normalized
return triDataSize;
}
}
std::string BufferSubDataParams::suffix() const
{
std::stringstream strstr;
strstr << BenchmarkParams::suffix();
strstr << PerfTestParams::suffix();
if (vertexNormalized)
{
......@@ -155,22 +190,23 @@ std::string BufferSubDataParams::suffix() const
return strstr.str();
}
BufferSubDataBenchmark::BufferSubDataBenchmark(const BufferSubDataParams &params)
: SimpleBenchmark("BufferSubData", 1280, 720, 2, params),
BufferSubDataBenchmark::BufferSubDataBenchmark()
: ANGLEPerfTest("BufferSubData", GetParam()),
mProgram(0),
mBuffer(0),
mUpdateData(NULL),
mNumTris(0),
mParams(params)
mNumTris(0)
{
mDrawIterations = mParams.iterations;
assert(mParams.vertexComponentCount > 1);
assert(mParams.iterations > 0);
}
bool BufferSubDataBenchmark::initializeBenchmark()
{
const auto &params = GetParam();
assert(params.vertexComponentCount > 1);
assert(params.iterations > 0);
mDrawIterations = params.iterations;
const std::string vs = SHADER_SOURCE
(
attribute vec2 vPosition;
......@@ -203,35 +239,35 @@ bool BufferSubDataBenchmark::initializeBenchmark()
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
std::vector<uint8_t> zeroData(mParams.bufferSize);
std::vector<uint8_t> zeroData(params.bufferSize);
memset(&zeroData[0], 0, zeroData.size());
glGenBuffers(1, &mBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferData(GL_ARRAY_BUFFER, mParams.bufferSize, &zeroData[0], GL_DYNAMIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, params.bufferSize, &zeroData[0], GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, mParams.vertexComponentCount, mParams.vertexType,
mParams.vertexNormalized, 0, 0);
glVertexAttribPointer(0, params.vertexComponentCount, params.vertexType,
params.vertexNormalized, 0, 0);
glEnableVertexAttribArray(0);
if (mParams.updateSize > 0)
if (params.updateSize > 0)
{
mUpdateData = new uint8_t[mParams.updateSize];
mUpdateData = new uint8_t[params.updateSize];
}
std::vector<uint8_t> data;
GLsizei triDataSize = GetVertexData(mParams.vertexType,
mParams.vertexComponentCount,
mParams.vertexNormalized, &data);
GLsizei triDataSize = GetVertexData(params.vertexType,
params.vertexComponentCount,
params.vertexNormalized, &data);
mNumTris = mParams.updateSize / triDataSize;
mNumTris = params.updateSize / triDataSize;
for (int i = 0, offset = 0; i < mNumTris; ++i)
{
memcpy(mUpdateData + offset, &data[0], triDataSize);
offset += triDataSize;
}
if (mParams.updateSize == 0)
if (params.updateSize == 0)
{
mNumTris = 1;
glBufferSubData(GL_ARRAY_BUFFER, 0, data.size(), &data[0]);
......@@ -243,7 +279,7 @@ bool BufferSubDataBenchmark::initializeBenchmark()
GLfloat scale = 0.5f;
GLfloat offset = 0.5f;
if (mParams.vertexNormalized == GL_TRUE)
if (params.vertexNormalized == GL_TRUE)
{
scale = 2.0f;
offset = 0.5f;
......@@ -263,10 +299,12 @@ bool BufferSubDataBenchmark::initializeBenchmark()
void BufferSubDataBenchmark::destroyBenchmark()
{
const auto &params = GetParam();
// print static parameters
printResult("update_size", static_cast<size_t>(mParams.updateSize), "b", false);
printResult("buffer_size", static_cast<size_t>(mParams.bufferSize), "b", false);
printResult("iterations", static_cast<size_t>(mParams.iterations), "updates", false);
printResult("update_size", static_cast<size_t>(params.updateSize), "b", false);
printResult("buffer_size", static_cast<size_t>(params.bufferSize), "b", false);
printResult("iterations", static_cast<size_t>(params.iterations), "updates", false);
glDeleteProgram(mProgram);
glDeleteBuffers(1, &mBuffer);
......@@ -281,13 +319,60 @@ void BufferSubDataBenchmark::beginDrawBenchmark()
void BufferSubDataBenchmark::drawBenchmark()
{
for (unsigned int it = 0; it < mParams.iterations; it++)
const auto &params = GetParam();
for (unsigned int it = 0; it < params.iterations; it++)
{
if (mParams.updateSize > 0 && ((mNumFrames % mParams.updateRate) == 0))
if (params.updateSize > 0 && ((mNumFrames % params.updateRate) == 0))
{
glBufferSubData(GL_ARRAY_BUFFER, 0, mParams.updateSize, mUpdateData);
glBufferSubData(GL_ARRAY_BUFFER, 0, params.updateSize, mUpdateData);
}
glDrawArrays(GL_TRIANGLES, 0, 3 * mNumTris);
}
}
BufferSubDataParams D3D11Params()
{
BufferSubDataParams params;
params.glesMajorVersion = 2;
params.widowWidth = 1280;
params.windowHeight = 720;
params.requestedRenderer = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
params.vertexType = GL_FLOAT;
params.vertexComponentCount = 4;
params.vertexNormalized = GL_FALSE;
params.updateSize = 3000;
params.bufferSize = 67000000;
params.iterations = 10;
params.updateRate = 1;
return params;
}
BufferSubDataParams D3D9Params()
{
BufferSubDataParams params;
params.glesMajorVersion = 2;
params.widowWidth = 1280;
params.windowHeight = 720;
params.requestedRenderer = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
params.vertexType = GL_FLOAT;
params.vertexComponentCount = 4;
params.vertexNormalized = GL_FALSE;
params.updateSize = 3000;
params.bufferSize = 67000000;
params.iterations = 10;
params.updateRate = 1;
return params;
}
} // namespace
TEST_P(BufferSubDataBenchmark, BufferUpdates)
{
run();
}
INSTANTIATE_TEST_CASE_P(BufferUpdates,
BufferSubDataBenchmark,
::testing::Values(D3D11Params(), D3D9Params()));
//
// 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 BufferSubDataParams : public BenchmarkParams
{
virtual std::string suffix() const;
GLboolean vertexNormalized;
GLenum vertexType;
GLint vertexComponentCount;
unsigned int updateRate;
// static parameters
GLsizeiptr updateSize;
GLsizeiptr bufferSize;
unsigned int iterations;
};
class BufferSubDataBenchmark : public SimpleBenchmark
{
public:
BufferSubDataBenchmark(const BufferSubDataParams &params);
virtual bool initializeBenchmark();
virtual void destroyBenchmark();
virtual void beginDrawBenchmark();
virtual void drawBenchmark();
typedef BufferSubDataParams Params;
private:
DISALLOW_COPY_AND_ASSIGN(BufferSubDataBenchmark);
GLuint mProgram;
GLuint mBuffer;
uint8_t *mUpdateData;
int mNumTris;
const BufferSubDataParams mParams;
};
......@@ -3,46 +3,83 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "PointSprites.h"
// PointSpritesBenchmark:
// Performance test for ANGLE point sprites.
//
#include <cassert>
#include <sstream>
#include <iostream>
#include "ANGLEPerfTest.h"
#include "shader_utils.h"
#include "random_utils.h"
namespace
{
struct PointSpritesParams : public PerfTestParams
{
std::string suffix() const override;
unsigned int count;
float size;
unsigned int numVaryings;
// static parameters
unsigned int iterations;
};
class PointSpritesBenchmark : public ANGLEPerfTest,
public ::testing::WithParamInterface<PointSpritesParams>
{
public:
PointSpritesBenchmark();
bool initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
DISALLOW_COPY_AND_ASSIGN(PointSpritesBenchmark);
GLuint mProgram;
GLuint mBuffer;
};
std::string PointSpritesParams::suffix() const
{
std::stringstream strstr;
strstr << BenchmarkParams::suffix()
strstr << PerfTestParams::suffix()
<< "_" << count << "_" << size << "px"
<< "_" << numVaryings << "vars";
return strstr.str();
}
PointSpritesBenchmark::PointSpritesBenchmark(const PointSpritesParams &params)
: SimpleBenchmark("PointSprites", 1280, 720, 2, params),
mParams(params)
PointSpritesBenchmark::PointSpritesBenchmark()
: ANGLEPerfTest("PointSprites", GetParam())
{
mDrawIterations = mParams.iterations;
assert(mParams.iterations > 0);
}
bool PointSpritesBenchmark::initializeBenchmark()
{
const auto &params = GetParam();
mDrawIterations = params.iterations;
assert(params.iterations > 0);
std::stringstream vstrstr;
// Verify "numVaryings" is within MAX_VARYINGS limit
GLint maxVaryings;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVaryings);
if (mParams.numVaryings > static_cast<unsigned int>(maxVaryings))
if (params.numVaryings > static_cast<unsigned int>(maxVaryings))
{
std::cerr << "Varying count (" << mParams.numVaryings << ")"
std::cerr << "Varying count (" << params.numVaryings << ")"
<< " exceeds maximum varyings: " << maxVaryings << std::endl;
return false;
}
......@@ -50,7 +87,7 @@ bool PointSpritesBenchmark::initializeBenchmark()
vstrstr << "attribute vec2 vPosition;\n"
"uniform float uPointSize;\n";
for (unsigned int varCount = 0; varCount < mParams.numVaryings; varCount++)
for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
{
vstrstr << "varying vec4 v" << varCount << ";\n";
}
......@@ -58,7 +95,7 @@ bool PointSpritesBenchmark::initializeBenchmark()
vstrstr << "void main()\n"
"{\n";
for (unsigned int varCount = 0; varCount < mParams.numVaryings; varCount++)
for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
{
vstrstr << " v" << varCount << " = vec4(1.0);\n";
}
......@@ -71,7 +108,7 @@ bool PointSpritesBenchmark::initializeBenchmark()
fstrstr << "precision mediump float;\n";
for (unsigned int varCount = 0; varCount < mParams.numVaryings; varCount++)
for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
{
fstrstr << "varying vec4 v" << varCount << ";\n";
}
......@@ -80,7 +117,7 @@ bool PointSpritesBenchmark::initializeBenchmark()
"{\n"
" vec4 colorOut = vec4(1.0, 0.0, 0.0, 1.0);\n";
for (unsigned int varCount = 0; varCount < mParams.numVaryings; varCount++)
for (unsigned int varCount = 0; varCount < params.numVaryings; varCount++)
{
fstrstr << " colorOut.r += v" << varCount << ".r;\n";
}
......@@ -99,7 +136,7 @@ bool PointSpritesBenchmark::initializeBenchmark()
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
std::vector<float> vertexPositions(mParams.count * 2);
std::vector<float> vertexPositions(params.count * 2);
for (size_t pointIndex = 0; pointIndex < vertexPositions.size(); ++pointIndex)
{
vertexPositions[pointIndex] = RandomBetween(-1.0f, 1.0f);
......@@ -127,7 +164,7 @@ bool PointSpritesBenchmark::initializeBenchmark()
return false;
}
glUniform1f(pointSizeLocation, mParams.size);
glUniform1f(pointSizeLocation, params.size);
GLenum glErr = glGetError();
if (glErr != GL_NO_ERROR)
......@@ -152,9 +189,56 @@ void PointSpritesBenchmark::beginDrawBenchmark()
void PointSpritesBenchmark::drawBenchmark()
{
for (unsigned int it = 0; it < mParams.iterations; it++)
const auto &params = GetParam();
for (unsigned int it = 0; it < params.iterations; it++)
{
//TODO(jmadill): Indexed point rendering. ANGLE is bad at this.
glDrawArrays(GL_POINTS, 0, mParams.count);
glDrawArrays(GL_POINTS, 0, params.count);
}
}
PointSpritesParams D3D11Params()
{
PointSpritesParams params;
params.glesMajorVersion = 2;
params.widowWidth = 1280;
params.windowHeight = 720;
params.requestedRenderer = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
params.iterations = 10;
params.count = 10;
params.size = 3.0f;
params.numVaryings = 3;
return params;
}
PointSpritesParams D3D9Params()
{
PointSpritesParams params;
params.glesMajorVersion = 2;
params.widowWidth = 1280;
params.windowHeight = 720;
params.requestedRenderer = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
params.iterations = 10;
params.count = 10;
params.size = 3.0f;
params.numVaryings = 3;
return params;
}
} // namespace
TEST_P(PointSpritesBenchmark, Render)
{
run();
}
INSTANTIATE_TEST_CASE_P(Render,
PointSpritesBenchmark,
::testing::Values(D3D11Params(), D3D9Params()));
//
// 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
{
virtual std::string suffix() const;
unsigned int count;
float size;
unsigned int numVaryings;
// static parameters
unsigned int iterations;
};
class PointSpritesBenchmark : public SimpleBenchmark
{
public:
PointSpritesBenchmark(const PointSpritesParams &params);
virtual bool initializeBenchmark();
virtual void destroyBenchmark();
virtual void beginDrawBenchmark();
virtual void drawBenchmark();
typedef PointSpritesParams Params;
private:
DISALLOW_COPY_AND_ASSIGN(PointSpritesBenchmark);
GLuint mProgram;
GLuint mBuffer;
const PointSpritesParams mParams;
};
......@@ -3,23 +3,74 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "TexSubImage.h"
// TexSubImageBenchmark:
// Performace test for ANGLE texture updates.
//
#include <sstream>
#include <cassert>
#include "ANGLEPerfTest.h"
#include "shader_utils.h"
namespace
{
struct TexSubImageParams : public PerfTestParams
{
std::string suffix() const override;
// Static parameters
int imageWidth;
int imageHeight;
int subImageWidth;
int subImageHeight;
unsigned int iterations;
};
class TexSubImageBenchmark : public ANGLEPerfTest,
public ::testing::WithParamInterface<TexSubImageParams>
{
public:
TexSubImageBenchmark();
bool initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
DISALLOW_COPY_AND_ASSIGN(TexSubImageBenchmark);
GLuint createTexture();
// Handle to a program object
GLuint mProgram;
// Attribute locations
GLint mPositionLoc;
GLint mTexCoordLoc;
// Sampler location
GLint mSamplerLoc;
// Texture handle
GLuint mTexture;
// Buffer handle
GLuint mVertexBuffer;
GLuint mIndexBuffer;
GLubyte *mPixels;
};
std::string TexSubImageParams::suffix() const
{
// TODO(jmadill)
return BenchmarkParams::suffix();
return PerfTestParams::suffix();
}
TexSubImageBenchmark::TexSubImageBenchmark(const TexSubImageParams &params)
: SimpleBenchmark("TexSubImage", 512, 512, 2, params),
mParams(params),
TexSubImageBenchmark::TexSubImageBenchmark()
: ANGLEPerfTest("TexSubImage", GetParam()),
mProgram(0),
mPositionLoc(-1),
mTexCoordLoc(-1),
......@@ -29,12 +80,15 @@ TexSubImageBenchmark::TexSubImageBenchmark(const TexSubImageParams &params)
mIndexBuffer(0),
mPixels(NULL)
{
assert(mParams.iterations > 0);
mDrawIterations = mParams.iterations;
}
GLuint TexSubImageBenchmark::createTexture()
{
const auto &params = GetParam();
assert(params.iterations > 0);
mDrawIterations = params.iterations;
// Use tightly packed data
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
......@@ -45,7 +99,7 @@ GLuint TexSubImageBenchmark::createTexture()
// Bind the texture object
glBindTexture(GL_TEXTURE_2D, texture);
glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, mParams.imageWidth, mParams.imageHeight);
glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, params.imageWidth, params.imageHeight);
// Set the filtering mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
......@@ -56,6 +110,8 @@ GLuint TexSubImageBenchmark::createTexture()
bool TexSubImageBenchmark::initializeBenchmark()
{
const auto &params = GetParam();
const std::string vs = SHADER_SOURCE
(
attribute vec4 a_position;
......@@ -119,14 +175,14 @@ bool TexSubImageBenchmark::initializeBenchmark()
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mPixels = new GLubyte[mParams.subImageWidth * mParams.subImageHeight * 4];
mPixels = new GLubyte[params.subImageWidth * params.subImageHeight * 4];
// Fill the pixels structure with random data:
for (int y = 0; y < mParams.subImageHeight; ++y)
for (int y = 0; y < params.subImageHeight; ++y)
{
for (int x = 0; x < mParams.subImageWidth; ++x)
for (int x = 0; x < params.subImageWidth; ++x)
{
int offset = (x + (y * mParams.subImageWidth)) * 4;
int offset = (x + (y * params.subImageWidth)) * 4;
mPixels[offset + 0] = rand() % 255; // Red
mPixels[offset + 1] = rand() % 255; // Green
mPixels[offset + 2] = rand() % 255; // Blue
......@@ -139,12 +195,14 @@ bool TexSubImageBenchmark::initializeBenchmark()
void TexSubImageBenchmark::destroyBenchmark()
{
const auto &params = GetParam();
// print static parameters
printResult("image_width", static_cast<size_t>(mParams.imageWidth), "pix", false);
printResult("image_height", static_cast<size_t>(mParams.imageHeight), "pix", false);
printResult("subimage_width", static_cast<size_t>(mParams.subImageWidth), "pix", false);
printResult("subimage_height", static_cast<size_t>(mParams.subImageHeight), "pix", false);
printResult("iterations", static_cast<size_t>(mParams.iterations), "updates", false);
printResult("image_width", static_cast<size_t>(params.imageWidth), "pix", false);
printResult("image_height", static_cast<size_t>(params.imageHeight), "pix", false);
printResult("subimage_width", static_cast<size_t>(params.subImageWidth), "pix", false);
printResult("subimage_height", static_cast<size_t>(params.subImageHeight), "pix", false);
printResult("iterations", static_cast<size_t>(params.iterations), "updates", false);
glDeleteProgram(mProgram);
glDeleteBuffers(1, &mVertexBuffer);
......@@ -186,11 +244,60 @@ void TexSubImageBenchmark::beginDrawBenchmark()
void TexSubImageBenchmark::drawBenchmark()
{
const auto &params = GetParam();
glTexSubImage2D(GL_TEXTURE_2D, 0,
rand() % (mParams.imageWidth - mParams.subImageWidth),
rand() % (mParams.imageHeight - mParams.subImageHeight),
mParams.subImageWidth, mParams.subImageHeight,
rand() % (params.imageWidth - params.subImageWidth),
rand() % (params.imageHeight - params.subImageHeight),
params.subImageWidth, params.subImageHeight,
GL_RGBA, GL_UNSIGNED_BYTE, mPixels);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
}
TexSubImageParams D3D11Params()
{
TexSubImageParams params;
params.glesMajorVersion = 2;
params.widowWidth = 512;
params.windowHeight = 512;
params.requestedRenderer = EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
params.imageWidth = 1024;
params.imageHeight = 1024;
params.subImageWidth = 64;
params.subImageHeight = 64;
params.iterations = 10;
return params;
}
TexSubImageParams D3D9Params()
{
TexSubImageParams params;
params.glesMajorVersion = 2;
params.widowWidth = 512;
params.windowHeight = 512;
params.requestedRenderer = EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
params.imageWidth = 1024;
params.imageHeight = 1024;
params.subImageWidth = 64;
params.subImageHeight = 64;
params.iterations = 10;
return params;
}
} // namespace
TEST_P(TexSubImageBenchmark, TextureUpdates)
{
run();
}
INSTANTIATE_TEST_CASE_P(TextureUpdates,
TexSubImageBenchmark,
::testing::Values(D3D11Params(), D3D9Params()));
//
// 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 TexSubImageParams : public BenchmarkParams
{
virtual std::string suffix() const;
// Static parameters
int imageWidth;
int imageHeight;
int subImageWidth;
int subImageHeight;
unsigned int iterations;
};
class TexSubImageBenchmark : public SimpleBenchmark
{
public:
TexSubImageBenchmark(const TexSubImageParams &params);
virtual bool initializeBenchmark();
virtual void destroyBenchmark();
virtual void beginDrawBenchmark();
virtual void drawBenchmark();
typedef TexSubImageParams Params;
private:
GLuint createTexture();
TexSubImageParams mParams;
// Handle to a program object
GLuint mProgram;
// Attribute locations
GLint mPositionLoc;
GLint mTexCoordLoc;
// Sampler location
GLint mSamplerLoc;
// Texture handle
GLuint mTexture;
// Buffer handle
GLuint mVertexBuffer;
GLuint mIndexBuffer;
GLubyte *mPixels;
};
//
// 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 <iostream>
#include <rapidjson/document.h>
#include <rapidjson/filestream.h>
#include "BufferSubData.h"
#include "PointSprites.h"
#include "SimpleBenchmark.h"
#include "TexSubImage.h"
#include "common/Optional.h"
namespace
{
Optional<std::string> GetStringMember(const rapidjson::Document &document, const char *name)
{
auto typeIt = document.FindMember(name);
if (typeIt == document.MemberEnd() || !typeIt->value.IsString())
{
std::cerr << "JSON has missing or bad string member '" << name << "'" << std::endl;
return Optional<std::string>::None();
}
return Optional<std::string>(typeIt->value.GetString());
}
Optional<bool> GetBoolMember(const rapidjson::Document &document, const char *name)
{
auto typeIt = document.FindMember(name);
if (typeIt == document.MemberEnd() || !typeIt->value.IsBool())
{
std::cerr << "JSON has missing or bad bool member '" << name << "'" << std::endl;
return Optional<bool>::None();
}
return Optional<bool>(typeIt->value.GetBool());
}
Optional<int> GetIntMember(const rapidjson::Document &document, const char *name)
{
auto typeIt = document.FindMember(name);
if (typeIt == document.MemberEnd() || !typeIt->value.IsInt())
{
std::cerr << "JSON has missing or bad int member '" << name << "'" << std::endl;
return Optional<int>::None();
}
return Optional<int>(typeIt->value.GetInt());
}
Optional<unsigned int> GetUintMember(const rapidjson::Document &document, const char *name)
{
auto typeIt = document.FindMember(name);
if (typeIt == document.MemberEnd() || !typeIt->value.IsUint())
{
std::cerr << "JSON has missing or bad uint member '" << name << "'" << std::endl;
return Optional<unsigned int>::None();
}
return Optional<unsigned int>(typeIt->value.GetUint());
}
EGLint ParseRendererType(const std::string &value)
{
if (value == "d3d11")
{
return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
}
else if (value == "d3d9")
{
return EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
}
else if (value == "warp")
{
// TODO(jmadill): other attributes for warp
return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
}
else if (value == "default")
{
return EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
}
else
{
return EGL_NONE;
}
}
GLenum ParseAttribType(const std::string &value)
{
if (value == "float")
{
return GL_FLOAT;
}
else if (value == "int")
{
return GL_INT;
}
else if (value == "uint")
{
return GL_UNSIGNED_INT;
}
else if (value == "short")
{
return GL_SHORT;
}
else if (value == "ushort")
{
return GL_UNSIGNED_SHORT;
}
else if (value == "byte")
{
return GL_BYTE;
}
else if (value == "ubyte")
{
return GL_UNSIGNED_BYTE;
}
else
{
return GL_NONE;
}
}
bool ParseBenchmarkParams(const rapidjson::Document &document, BufferSubDataParams *params)
{
// Validate params
auto type = GetStringMember(document, "type");
auto components = GetUintMember(document, "components");
auto normalized = GetBoolMember(document, "normalized");
auto updateSize = GetUintMember(document, "update_size");
auto bufferSize = GetUintMember(document, "buffer_size");
auto iterations = GetUintMember(document, "iterations");
auto updateRate = GetUintMember(document, "update_rate");
if (!type.valid() || !components.valid() || !normalized.valid() || !updateSize.valid() ||
!bufferSize.valid() || !iterations.valid() || !updateRate.valid())
{
return false;
}
GLenum vertexType = ParseAttribType(type.value());
if (vertexType == GL_NONE)
{
std::cerr << "Invalid attribute type: " << type.value() << std::endl;
return false;
}
if (components.value() < 1 || components.value() > 4)
{
std::cerr << "Invalid component count: " << components.value() << std::endl;
return false;
}
if (normalized.value() && vertexType == GL_FLOAT)
{
std::cerr << "Normalized float is not a valid vertex type." << std::endl;
return false;
}
if (bufferSize.value() == 0)
{
std::cerr << "Zero buffer size is not valid." << std::endl;
return false;
}
if (iterations.value() == 0)
{
std::cerr << "Zero iterations not valid." << std::endl;
return false;
}
params->vertexType = vertexType;
params->vertexComponentCount = components.value();
params->vertexNormalized = normalized.value();
params->updateSize = updateSize.value();
params->bufferSize = bufferSize.value();
params->iterations = iterations.value();
params->updateRate = updateRate.value();
return true;
}
bool ParseBenchmarkParams(const rapidjson::Document &document, TexSubImageParams *params)
{
// TODO(jmadill): Parse and validate parameters
params->imageWidth = 1024;
params->imageHeight = 1024;
params->subImageHeight = 64;
params->subImageWidth = 64;
params->iterations = 10;
return true;
}
bool ParseBenchmarkParams(const rapidjson::Document &document, PointSpritesParams *params)
{
// TODO(jmadill): Parse and validate parameters
params->iterations = 10;
params->count = 10;
params->size = 3.0f;
params->numVaryings = 3;
return true;
}
template <class BenchT>
int ParseAndRunBenchmark(EGLint rendererType, const rapidjson::Document &document)
{
BenchT::Params params;
if (!ParseBenchmarkParams(document, &params))
{
// Parse or validation error
return 1;
}
params.requestedRenderer = rendererType;
BenchT benchmark(params);
// Run the benchmark
return benchmark.run();
}
}
int main(int argc, char **argv)
{
if (argc < 3)
{
std::cerr << "Must specify a renderer and source json file." << std::endl;
return 1;
}
EGLint rendererType = ParseRendererType(std::string(argv[1]));
if (rendererType == EGL_NONE)
{
std::cerr << "Invalid renderer type: " << argv[1] << std::endl;
return 1;
}
FILE *fp = fopen(argv[2], "rt");
if (fp == NULL)
{
std::cerr << "Cannot open " << argv[2] << std::endl;
return 1;
}
rapidjson::FileStream fileStream(fp);
rapidjson::Document document;
if (document.ParseStream(fileStream).HasParseError())
{
std::cerr << "JSON Parse error code " << document.GetParseError() << "." << std::endl;
return 1;
}
fclose(fp);
auto testName = GetStringMember(document, "test");
if (!testName.valid())
{
return 1;
}
if (testName.value() == "BufferSubData")
{
return ParseAndRunBenchmark<BufferSubDataBenchmark>(rendererType, document);
}
else if (testName.value() == "TexSubImage")
{
return ParseAndRunBenchmark<TexSubImageBenchmark>(rendererType, document);
}
else if (testName.value() == "PointSprites")
{
return ParseAndRunBenchmark<PointSpritesBenchmark>(rendererType, document);
}
else
{
std::cerr << "Unknown test: " << testName.value() << std::endl;
return 1;
}
}
{
"test": "BufferSubData",
"type": "float",
"components": 4,
"normalized": false,
"update_size": 3000,
"buffer_size": 67000000,
"iterations": 10,
"update_rate": 1
}
......@@ -195,49 +195,26 @@
'angle_end2end_tests_main.cpp',
],
},
{
'target_name': 'angle_perftests',
'type': 'executable',
'includes':
[
'../../build/common_defines.gypi',
'angle_perftests.gypi',
],
'sources':
[
'angle_perftests_main.cpp',
],
},
],
}],
],
}],
['OS=="win"',
{
'targets':
[
{
'target_name': 'angle_perf_tests',
'type': 'executable',
'includes': [ '../../build/common_defines.gypi', ],
'dependencies':
[
'<(angle_path)/src/angle.gyp:angle_common',
'<(angle_path)/src/angle.gyp:libGLESv2',
'<(angle_path)/src/angle.gyp:libEGL',
'<(angle_path)/util/util.gyp:angle_util',
'angle_test_support',
],
'include_dirs':
[
'<(angle_path)/include',
'<(rapidjson_include_dir)',
],
'sources':
[
'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/TexSubImage.cpp',
'perf_tests/TexSubImage.h',
'perf_tests/angle_perf_test_main.cpp',
'perf_tests/third_party/perf/perf_test.cc',
'perf_tests/third_party/perf/perf_test.h',
'<@(rapidjson_headers)',
],
},
],
'conditions':
[
['angle_build_conformance_tests',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment