Commit 8047f065 by Olli Etuaho

Improve perf testing framework

The ANGLERenderTest subclasses have a parameter "iterations". Previously most of these tests would perform iterations^2 iterations, since the looping was done both in ANGLERenderTest and in the individual test classes. Do the looping only in the individual test classes instead. This enables getting rid of separate beginDrawBenchmark() and endDrawBenchmark() functions. Some other unused code is also removed: 1. stepBenchmark function 2. unused parameters to step() This makes the core loop of running tests simpler. The perf testing framework also now has shared logic for deciding when to end a given test. The score calculation for tests is also changed. Instead of reporting just the number of operations done, it is reported relative to the actual run time of the test. This should make the test results more accurate, since run time of the tests may have some variation. It also enables changing the run time of the tests without rebaselining them. In the tests that use GPU, GPU operations are also waited to finish before stopping the timer. BUG=angleproject:1261 TEST=angle_perftests Change-Id: I69e9aad8afd2d9dedd60e144f0a5d4203618feef Reviewed-on: https://chromium-review.googlesource.com/319381 Tryjob-Request: Olli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org>
parent add0ef14
......@@ -14,9 +14,10 @@
ANGLEPerfTest::ANGLEPerfTest(const std::string &name, const std::string &suffix)
: mName(name),
mSuffix(suffix),
mRunning(false),
mTimer(nullptr),
mNumFrames(0)
mNumStepsPerformed(0),
mRunTimeSeconds(5.0),
mRunning(true)
{
mTimer = CreateTimer();
}
......@@ -29,23 +30,20 @@ ANGLEPerfTest::~ANGLEPerfTest()
void ANGLEPerfTest::run()
{
mTimer->start();
double prevTime = 0.0;
while (mRunning)
{
double elapsedTime = mTimer->getElapsedTime();
double deltaTime = elapsedTime - prevTime;
++mNumFrames;
step(static_cast<float>(deltaTime), elapsedTime);
if (!mRunning)
step();
if (mRunning)
{
break;
++mNumStepsPerformed;
}
if (mTimer->getElapsedTime() > mRunTimeSeconds)
{
mRunning = false;
}
prevTime = elapsedTime;
}
finishTest();
mTimer->stop();
}
void ANGLEPerfTest::printResult(const std::string &trace, double value, const std::string &units, bool important) const
......@@ -60,17 +58,17 @@ void ANGLEPerfTest::printResult(const std::string &trace, size_t value, const st
void ANGLEPerfTest::SetUp()
{
mRunning = true;
}
void ANGLEPerfTest::TearDown()
{
printResult("score", static_cast<size_t>(mNumFrames), "score", true);
double relativeScore = static_cast<double>(mNumStepsPerformed) / mTimer->getElapsedTime();
printResult("score", static_cast<size_t>(std::round(relativeScore)), "score", true);
}
double ANGLEPerfTest::normalizedTime(size_t value) const
{
return static_cast<double>(value) / static_cast<double>(mNumFrames);
return static_cast<double>(value) / static_cast<double>(mNumStepsPerformed);
}
std::string RenderTestParams::suffix() const
......@@ -96,8 +94,6 @@ std::string RenderTestParams::suffix() const
ANGLERenderTest::ANGLERenderTest(const std::string &name, const RenderTestParams &testParams)
: ANGLEPerfTest(name, testParams.suffix()),
mTestParams(testParams),
mDrawIterations(10),
mRunTimeSeconds(5.0),
mEGLWindow(nullptr),
mOSWindow(nullptr)
{
......@@ -143,47 +139,44 @@ void ANGLERenderTest::TearDown()
mOSWindow->destroy();
}
void ANGLERenderTest::step(float dt, double totalTime)
void ANGLERenderTest::step()
{
stepBenchmark(dt, totalTime);
// Clear events that the application did not process from this frame
Event event;
bool closed = false;
while (popEvent(&event))
{
// If the application did not catch a close event, close now
if (event.Type == Event::EVENT_CLOSED)
{
mRunning = false;
closed = true;
}
}
if (mRunning)
if (closed)
{
abortTest();
}
else
{
draw();
mEGLWindow->swap();
drawBenchmark();
// Swap is needed so that the GPU driver will occasionally flush its internal command queue
// to the GPU. The null device benchmarks are only testing CPU overhead, so they don't need
// to swap.
if (mTestParams.eglParameters.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
{
mEGLWindow->swap();
}
mOSWindow->messageLoop();
}
}
void ANGLERenderTest::draw()
void ANGLERenderTest::finishTest()
{
if (mTimer->getElapsedTime() > mRunTimeSeconds)
{
mRunning = false;
return;
}
++mNumFrames;
beginDrawBenchmark();
for (unsigned int iteration = 0; iteration < mDrawIterations; ++iteration)
if (mTestParams.eglParameters.deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
{
drawBenchmark();
glFinish();
}
endDrawBenchmark();
}
bool ANGLERenderTest::popEvent(Event *event)
......
......@@ -36,7 +36,10 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable
ANGLEPerfTest(const std::string &name, const std::string &suffix);
virtual ~ANGLEPerfTest();
virtual void step(float dt, double totalTime) = 0;
virtual void step() = 0;
// Called right before timer is stopped to let the test wait for asynchronous operations.
virtual void finishTest() {}
protected:
void run();
......@@ -48,12 +51,19 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable
// Normalize a time value according to the number of test loop iterations (mFrameCount)
double normalizedTime(size_t value) const;
// Call if the test step was aborted and the test should stop running.
void abortTest() { mRunning = false; }
int getNumStepsPerformed() const { return mNumStepsPerformed; }
std::string mName;
std::string mSuffix;
Timer *mTimer;
double mRunTimeSeconds;
private:
int mNumStepsPerformed;
bool mRunning;
Timer *mTimer;
int mNumFrames;
};
struct RenderTestParams : public angle::PlatformParameters
......@@ -73,11 +83,7 @@ class ANGLERenderTest : public ANGLEPerfTest
virtual void initializeBenchmark() { }
virtual void destroyBenchmark() { }
virtual void stepBenchmark(float dt, double totalTime) { }
virtual void beginDrawBenchmark() { }
virtual void drawBenchmark() = 0;
virtual void endDrawBenchmark() { }
bool popEvent(Event *event);
......@@ -85,15 +91,13 @@ class ANGLERenderTest : public ANGLEPerfTest
protected:
const RenderTestParams &mTestParams;
unsigned int mDrawIterations;
double mRunTimeSeconds;
private:
void SetUp() override;
void TearDown() override;
void step(float dt, double totalTime) override;
void draw();
void step() override;
void finishTest() override;
EGLWindow *mEGLWindow;
OSWindow *mOSWindow;
......
......@@ -28,7 +28,7 @@ struct BufferSubDataParams final : public RenderTestParams
windowHeight = 512;
updateSize = 3000;
bufferSize = 40000000;
iterations = 2;
iterations = 4;
updateRate = 1;
}
......@@ -59,7 +59,6 @@ class BufferSubDataBenchmark : public ANGLERenderTest,
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
......@@ -269,7 +268,6 @@ void BufferSubDataBenchmark::initializeBenchmark()
ASSERT_LT(1, params.vertexComponentCount);
ASSERT_LT(0u, params.iterations);
mDrawIterations = params.iterations;
const std::string vs = SHADER_SOURCE
(
......@@ -359,19 +357,15 @@ void BufferSubDataBenchmark::destroyBenchmark()
SafeDeleteArray(mUpdateData);
}
void BufferSubDataBenchmark::beginDrawBenchmark()
void BufferSubDataBenchmark::drawBenchmark()
{
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
}
void BufferSubDataBenchmark::drawBenchmark()
{
const auto &params = GetParam();
for (unsigned int it = 0; it < params.iterations; it++)
{
if (params.updateSize > 0 && ((mNumFrames % params.updateRate) == 0))
if (params.updateSize > 0 && ((getNumStepsPerformed() % params.updateRate) == 0))
{
glBufferSubData(GL_ARRAY_BUFFER, 0, params.updateSize, mUpdateData);
}
......
......@@ -69,7 +69,6 @@ class DrawCallPerfBenchmark : public ANGLERenderTest,
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
......@@ -92,7 +91,6 @@ void DrawCallPerfBenchmark::initializeBenchmark()
const auto &params = GetParam();
ASSERT_LT(0u, params.iterations);
mDrawIterations = params.iterations;
const std::string vs = SHADER_SOURCE
(
......@@ -166,14 +164,10 @@ void DrawCallPerfBenchmark::destroyBenchmark()
glDeleteBuffers(1, &mBuffer);
}
void DrawCallPerfBenchmark::beginDrawBenchmark()
void DrawCallPerfBenchmark::drawBenchmark()
{
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
}
void DrawCallPerfBenchmark::drawBenchmark()
{
const auto &params = GetParam();
for (unsigned int it = 0; it < params.iterations; it++)
......@@ -211,7 +205,7 @@ DrawCallPerfParams DrawCallPerfValidationOnly()
{
DrawCallPerfParams params;
params.eglParameters = DEFAULT();
params.iterations = 100;
params.iterations = 10000;
params.numTris = 0;
params.runTimeSeconds = 5.0;
return params;
......
......@@ -77,7 +77,7 @@ class EGLInitializePerfTest : public ANGLEPerfTest,
EGLInitializePerfTest();
~EGLInitializePerfTest();
void step(float dt, double totalTime) override;
void step() override;
void TearDown() override;
private:
......@@ -132,18 +132,13 @@ EGLInitializePerfTest::~EGLInitializePerfTest()
SafeDelete(mOSWindow);
}
void EGLInitializePerfTest::step(float dt, double totalTime)
void EGLInitializePerfTest::step()
{
ASSERT_NE(EGL_NO_DISPLAY, mDisplay);
EGLint majorVersion, minorVersion;
ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), eglInitialize(mDisplay, &majorVersion, &minorVersion));
ASSERT_EQ(static_cast<EGLBoolean>(EGL_TRUE), eglTerminate(mDisplay));
if (mTimer->getElapsedTime() >= 5.0)
{
mRunning = false;
}
}
void EGLInitializePerfTest::TearDown()
......
......@@ -50,7 +50,6 @@ class IndexConversionPerfTest : public ANGLERenderTest,
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
void updateBufferData();
......@@ -78,8 +77,6 @@ void IndexConversionPerfTest::initializeBenchmark()
ASSERT_LT(0u, params.iterations);
ASSERT_LT(0u, params.numIndexTris);
mDrawIterations = params.iterations;
const std::string vs = SHADER_SOURCE
(
attribute vec2 vPosition;
......@@ -165,14 +162,10 @@ void IndexConversionPerfTest::destroyBenchmark()
glDeleteBuffers(1, &mIndexBuffer);
}
void IndexConversionPerfTest::beginDrawBenchmark()
void IndexConversionPerfTest::drawBenchmark()
{
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
}
void IndexConversionPerfTest::drawBenchmark()
{
const auto &params = GetParam();
// Trigger an update to ensure we convert once a frame
......@@ -197,7 +190,7 @@ IndexConversionPerfParams IndexConversionPerfD3D11Params()
params.minorVersion = 0;
params.windowWidth = 256;
params.windowHeight = 256;
params.iterations = 15;
params.iterations = 225;
params.numIndexTris = 3000;
return params;
}
......
......@@ -116,7 +116,7 @@ class IndexDataManagerPerfTest : public ANGLEPerfTest
public:
IndexDataManagerPerfTest();
void step(float dt, double totalTime) override;
void step() override;
rx::IndexDataManager mIndexDataManager;
GLsizei mIndexCount;
......@@ -151,7 +151,7 @@ IndexDataManagerPerfTest::IndexDataManagerPerfTest()
mIndexBuffer.bufferData(&indexData[0], indexData.size() * sizeof(GLushort), GL_STATIC_DRAW);
}
void IndexDataManagerPerfTest::step(float dt, double totalTime)
void IndexDataManagerPerfTest::step()
{
rx::TranslatedIndexData translatedIndexData;
rx::SourceIndexData sourceIndexData;
......@@ -162,11 +162,6 @@ void IndexDataManagerPerfTest::step(float dt, double totalTime)
mIndexDataManager.prepareIndexData(GL_UNSIGNED_SHORT, mIndexCount, &mIndexBuffer, nullptr,
&translatedIndexData, &sourceIndexData, false);
}
if (mTimer->getElapsedTime() >= 5.0)
{
mRunning = false;
}
}
TEST_F(IndexDataManagerPerfTest, Run)
......
......@@ -83,7 +83,6 @@ class InstancingPerfBenchmark : public ANGLERenderTest,
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
......@@ -106,7 +105,6 @@ void InstancingPerfBenchmark::initializeBenchmark()
const auto &params = GetParam();
ASSERT_LT(0u, params.iterations);
mDrawIterations = params.iterations;
const std::string vs =
"attribute vec2 aPosition;\n"
......@@ -268,13 +266,10 @@ void InstancingPerfBenchmark::destroyBenchmark()
}
}
void InstancingPerfBenchmark::beginDrawBenchmark()
void InstancingPerfBenchmark::drawBenchmark()
{
glClear(GL_COLOR_BUFFER_BIT);
}
void InstancingPerfBenchmark::drawBenchmark()
{
const auto &params = GetParam();
// Animatino makes the test more interesting visually, but also eats up many CPU cycles.
......
......@@ -54,7 +54,6 @@ class InterleavedAttributeDataBenchmark
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
......@@ -149,15 +148,11 @@ void InterleavedAttributeDataBenchmark::destroyBenchmark()
}
}
void InterleavedAttributeDataBenchmark::beginDrawBenchmark()
void InterleavedAttributeDataBenchmark::drawBenchmark()
{
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
}
void InterleavedAttributeDataBenchmark::drawBenchmark()
{
for (size_t k = 0; k < 4; k++)
for (size_t k = 0; k < 20; k++)
{
for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
{
......
......@@ -29,7 +29,7 @@ struct PointSpritesParams final : public RenderTestParams
minorVersion = 0;
windowWidth = 1280;
windowHeight = 720;
iterations = 10;
iterations = 100;
count = 10;
size = 3.0f;
numVaryings = 3;
......@@ -59,7 +59,6 @@ class PointSpritesBenchmark : public ANGLERenderTest,
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
......@@ -87,7 +86,6 @@ void PointSpritesBenchmark::initializeBenchmark()
{
const auto &params = GetParam();
mDrawIterations = params.iterations;
ASSERT_LT(0u, params.iterations);
std::stringstream vstrstr;
......@@ -184,14 +182,10 @@ void PointSpritesBenchmark::destroyBenchmark()
glDeleteBuffers(1, &mBuffer);
}
void PointSpritesBenchmark::beginDrawBenchmark()
void PointSpritesBenchmark::drawBenchmark()
{
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
}
void PointSpritesBenchmark::drawBenchmark()
{
const auto &params = GetParam();
for (unsigned int it = 0; it < params.iterations; it++)
......
......@@ -31,7 +31,7 @@ struct TexSubImageParams final : public RenderTestParams
imageHeight = 1024;
subImageWidth = 64;
subImageHeight = 64;
iterations = 3;
iterations = 9;
}
std::string suffix() const override;
......@@ -58,7 +58,6 @@ class TexSubImageBenchmark : public ANGLERenderTest,
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
......@@ -108,7 +107,6 @@ GLuint TexSubImageBenchmark::createTexture()
const auto &params = GetParam();
assert(params.iterations > 0);
mDrawIterations = params.iterations;
// Use tightly packed data
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
......@@ -220,7 +218,7 @@ void TexSubImageBenchmark::destroyBenchmark()
delete[] mPixels;
}
void TexSubImageBenchmark::beginDrawBenchmark()
void TexSubImageBenchmark::drawBenchmark()
{
// Set the viewport
glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());
......@@ -251,10 +249,7 @@ void TexSubImageBenchmark::beginDrawBenchmark()
glUniform1i(mSamplerLoc, 0);
ASSERT_GL_NO_ERROR();
}
void TexSubImageBenchmark::drawBenchmark()
{
const auto &params = GetParam();
for (unsigned int iteration = 0; iteration < params.iterations; ++iteration)
......
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