Commit f0dd087e by Shahbaz Youssefi Committed by Commit Bot

Move timer functionality from util/ to common/

The main timer functionality (get absolute time) is moved to common/ for use in ANGLE itself (in upcoming overlay change). util/Timer.h is no longer an abstract class and uses this functionality to implement the timer. Bug: angleproject:3757 Change-Id: I3fe418778d80d1089c9bfe43a9e8098e43236f18 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1769061Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent eb68081e
...@@ -68,7 +68,6 @@ SampleApplication::SampleApplication(std::string name, ...@@ -68,7 +68,6 @@ SampleApplication::SampleApplication(std::string name,
angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ApplicationDir)); angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ApplicationDir));
mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion); mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion);
mTimer.reset(CreateTimer());
mOSWindow = OSWindow::New(); mOSWindow = OSWindow::New();
} }
...@@ -158,12 +157,12 @@ int SampleApplication::run() ...@@ -158,12 +157,12 @@ int SampleApplication::run()
result = -1; result = -1;
} }
mTimer->start(); mTimer.start();
double prevTime = 0.0; double prevTime = 0.0;
while (mRunning) while (mRunning)
{ {
double elapsedTime = mTimer->getElapsedTime(); double elapsedTime = mTimer.getElapsedTime();
double deltaTime = elapsedTime - prevTime; double deltaTime = elapsedTime - prevTime;
step(static_cast<float>(deltaTime), elapsedTime); step(static_cast<float>(deltaTime), elapsedTime);
......
...@@ -61,7 +61,7 @@ class SampleApplication ...@@ -61,7 +61,7 @@ class SampleApplication
uint32_t mHeight; uint32_t mHeight;
bool mRunning; bool mRunning;
std::unique_ptr<Timer> mTimer; Timer mTimer;
EGLWindow *mEGLWindow; EGLWindow *mEGLWindow;
OSWindow *mOSWindow; OSWindow *mOSWindow;
......
...@@ -130,12 +130,6 @@ void main() ...@@ -130,12 +130,6 @@ void main()
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mOrigTimer = CreateTimer();
mResizeDrawTimer = CreateTimer();
mResizeDefineTimer = CreateTimer();
mNewTexDrawTimer = CreateTimer();
mNewTexDefineTimer = CreateTimer();
return true; return true;
} }
...@@ -191,54 +185,54 @@ void main() ...@@ -191,54 +185,54 @@ void main()
// unreleated to texture creation. mTimeFrame is set to true on the fifth frame. // unreleated to texture creation. mTimeFrame is set to true on the fifth frame.
if (mTimeFrame) if (mTimeFrame)
{ {
mOrigTimer->start(); mOrigTimer.start();
} }
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
if (mTimeFrame) if (mTimeFrame)
{ {
mOrigTimer->stop(); mOrigTimer.stop();
// This timer indicates draw time for an already-created texture resident on the GPU, // This timer indicates draw time for an already-created texture resident on the GPU,
// which needs no updates. It will be faster than the other draws. // which needs no updates. It will be faster than the other draws.
std::cout << "Original texture draw: " << mOrigTimer->getElapsedTime() * 1000 << "msec" std::cout << "Original texture draw: " << mOrigTimer.getElapsedTime() * 1000 << "msec"
<< std::endl; << std::endl;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Now, change the texture dimensions of the original texture // Now, change the texture dimensions of the original texture
mResizeDefineTimer->start(); mResizeDefineTimer.start();
defineSquareTexture2D(mTextureIds[0], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsResize); defineSquareTexture2D(mTextureIds[0], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsResize);
mResizeDefineTimer->stop(); mResizeDefineTimer.stop();
mResizeDrawTimer->start(); mResizeDrawTimer.start();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
mResizeDrawTimer->stop(); mResizeDrawTimer.stop();
// This timer indicates draw time for a texture which has already been used in a draw, // This timer indicates draw time for a texture which has already been used in a draw,
// causing the underlying resource to be allocated, and then resized, requiring resource // causing the underlying resource to be allocated, and then resized, requiring resource
// reallocation and related overhead. // reallocation and related overhead.
std::cout << "Resized texture definition: " std::cout << "Resized texture definition: "
<< mResizeDefineTimer->getElapsedTime() * 1000 << "msec" << std::endl; << mResizeDefineTimer.getElapsedTime() * 1000 << "msec" << std::endl;
std::cout << "Resized texture draw: " << mResizeDrawTimer->getElapsedTime() * 1000 std::cout << "Resized texture draw: " << mResizeDrawTimer.getElapsedTime() * 1000
<< "msec" << std::endl; << "msec" << std::endl;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Create texure at same dimensions we resized previous texture to // Create texure at same dimensions we resized previous texture to
mNewTexDefineTimer->start(); mNewTexDefineTimer.start();
defineSquareTexture2D(mTextureIds[1], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsNewTex); defineSquareTexture2D(mTextureIds[1], 512, GL_RGBA, GL_UNSIGNED_BYTE, mPixelsNewTex);
mNewTexDefineTimer->stop(); mNewTexDefineTimer.stop();
mNewTexDrawTimer->start(); mNewTexDrawTimer.start();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
mNewTexDrawTimer->stop(); mNewTexDrawTimer.stop();
// This timer indicates draw time for a texture newly created this frame. The underlying // This timer indicates draw time for a texture newly created this frame. The underlying
// resource will need to be created, but because it has not previously been used, there // resource will need to be created, but because it has not previously been used, there
// is no already-resident texture object to manage. This draw is expected to be faster // is no already-resident texture object to manage. This draw is expected to be faster
// than the resized texture draw. // than the resized texture draw.
std::cout << "Newly created texture definition: " std::cout << "Newly created texture definition: "
<< mNewTexDefineTimer->getElapsedTime() * 1000 << "msec" << std::endl; << mNewTexDefineTimer.getElapsedTime() * 1000 << "msec" << std::endl;
std::cout << "Newly created texture draw: " << mNewTexDrawTimer->getElapsedTime() * 1000 std::cout << "Newly created texture draw: " << mNewTexDrawTimer.getElapsedTime() * 1000
<< "msec" << std::endl; << "msec" << std::endl;
} }
...@@ -269,11 +263,11 @@ void main() ...@@ -269,11 +263,11 @@ void main()
GLubyte *mPixelsResize; GLubyte *mPixelsResize;
GLubyte *mPixelsNewTex; GLubyte *mPixelsNewTex;
Timer *mOrigTimer; Timer mOrigTimer;
Timer *mResizeDrawTimer; Timer mResizeDrawTimer;
Timer *mResizeDefineTimer; Timer mResizeDefineTimer;
Timer *mNewTexDrawTimer; Timer mNewTexDrawTimer;
Timer *mNewTexDefineTimer; Timer mNewTexDefineTimer;
bool mTimeFrame; bool mTimeFrame;
unsigned int mFrameCount; unsigned int mFrameCount;
}; };
......
...@@ -157,8 +157,6 @@ void main() ...@@ -157,8 +157,6 @@ void main()
createVertexBuffers(); createVertexBuffers();
mFanTimer = CreateTimer();
mTriTimer = CreateTimer();
mFanTotalTime = 0; mFanTotalTime = 0;
mTriTotalTime = 0; mTriTotalTime = 0;
...@@ -191,33 +189,33 @@ void main() ...@@ -191,33 +189,33 @@ void main()
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
// Draw using triangle fans, stored in VBO // Draw using triangle fans, stored in VBO
mFanTimer->start(); mFanTimer.start();
for (unsigned i = 0; i < mNumSquares; ++i) for (unsigned i = 0; i < mNumSquares; ++i)
{ {
glBindBuffer(GL_ARRAY_BUFFER, mFanBufId[i]); glBindBuffer(GL_ARRAY_BUFFER, mFanBufId[i]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLE_FAN, 0, mNumFanVerts); glDrawArrays(GL_TRIANGLE_FAN, 0, mNumFanVerts);
} }
mFanTimer->stop(); mFanTimer.stop();
mFanTotalTime += static_cast<unsigned int>( mFanTotalTime += static_cast<unsigned int>(
mFanTimer->getElapsedTime() * 1000); // convert from usec to msec when accumulating mFanTimer.getElapsedTime() * 1000); // convert from usec to msec when accumulating
// Clear to eliminate driver-side gains from occlusion // Clear to eliminate driver-side gains from occlusion
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
// Draw using triangles, stored in VBO // Draw using triangles, stored in VBO
mTriTimer->start(); mTriTimer.start();
for (unsigned i = 1; i < mNumSquares; ++i) for (unsigned i = 1; i < mNumSquares; ++i)
{ {
glBindBuffer(GL_ARRAY_BUFFER, mTriBufId[i]); glBindBuffer(GL_ARRAY_BUFFER, mTriBufId[i]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, mNumTriVerts); glDrawArrays(GL_TRIANGLES, 0, mNumTriVerts);
} }
mTriTimer->stop(); mTriTimer.stop();
mTriTotalTime += static_cast<unsigned int>( mTriTotalTime += static_cast<unsigned int>(
mTriTimer->getElapsedTime() * 1000); // convert from usec to msec when accumulating mTriTimer.getElapsedTime() * 1000); // convert from usec to msec when accumulating
mFrameCount++; mFrameCount++;
} }
...@@ -230,8 +228,8 @@ void main() ...@@ -230,8 +228,8 @@ void main()
GLuint mFanBufId[mNumSquares]; GLuint mFanBufId[mNumSquares];
GLuint mTriBufId[mNumSquares]; GLuint mTriBufId[mNumSquares];
Timer *mFanTimer; Timer mFanTimer;
Timer *mTriTimer; Timer mTriTimer;
unsigned int mFrameCount; unsigned int mFrameCount;
unsigned int mTriTotalTime; unsigned int mTriTotalTime;
unsigned int mFanTotalTime; unsigned int mFanTotalTime;
......
...@@ -26,6 +26,9 @@ const char *GetPathSeparator(); ...@@ -26,6 +26,9 @@ const char *GetPathSeparator();
bool PrependPathToEnvironmentVar(const char *variableName, const char *path); bool PrependPathToEnvironmentVar(const char *variableName, const char *path);
bool IsDirectory(const char *filename); bool IsDirectory(const char *filename);
// Get absolute time in seconds. Use this function to get an absolute time with an unknown origin.
double GetCurrentTime();
// Run an application and get the output. Gets a nullptr-terminated set of args to execute the // Run an application and get the output. Gets a nullptr-terminated set of args to execute the
// application with, and returns the stdout and stderr outputs as well as the exit code. // application with, and returns the stdout and stderr outputs as well as the exit code.
// //
......
...@@ -44,4 +44,12 @@ const char *GetSharedLibraryExtension() ...@@ -44,4 +44,12 @@ const char *GetSharedLibraryExtension()
{ {
return "so"; return "so";
} }
double GetCurrentTime()
{
struct timespec currentTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
return currentTime.tv_sec + currentTime.tv_nsec * 1e-9;
}
} // namespace angle } // namespace angle
...@@ -10,7 +10,10 @@ ...@@ -10,7 +10,10 @@
#include <unistd.h> #include <unistd.h>
#include <CoreServices/CoreServices.h>
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <cstdlib> #include <cstdlib>
#include <vector> #include <vector>
...@@ -49,4 +52,13 @@ const char *GetSharedLibraryExtension() ...@@ -49,4 +52,13 @@ const char *GetSharedLibraryExtension()
{ {
return "dylib"; return "dylib";
} }
double GetCurrentTime()
{
mach_timebase_info_data_t timebaseInfo;
mach_timebase_info(&timebaseInfo);
double secondCoeff = timebaseInfo.numer * 1e-9 / timebaseInfo.denom;
return secondCoeff * mach_absolute_time();
}
} // namespace angle } // namespace angle
...@@ -131,6 +131,17 @@ const char *GetPathSeparator() ...@@ -131,6 +131,17 @@ const char *GetPathSeparator()
return ";"; return ";";
} }
double GetCurrentTime()
{
LARGE_INTEGER frequency = {};
QueryPerformanceFrequency(&frequency);
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
return static_cast<double>(curTime.QuadPart) / frequency.QuadPart;
}
bool RunApp(const std::vector<const char *> &args, bool RunApp(const std::vector<const char *> &args,
std::string *stdoutOut, std::string *stdoutOut,
std::string *stderrOut, std::string *stderrOut,
......
...@@ -376,28 +376,28 @@ TEST_P(EGLSurfaceTest, SwapInterval) ...@@ -376,28 +376,28 @@ TEST_P(EGLSurfaceTest, SwapInterval)
{ {
if (maxInterval >= 1) if (maxInterval >= 1)
{ {
std::unique_ptr<Timer> timer(CreateTimer()); Timer timer;
eglSwapInterval(mDisplay, 1); eglSwapInterval(mDisplay, 1);
timer->start(); timer.start();
for (int i = 0; i < 180; ++i) for (int i = 0; i < 180; ++i)
{ {
eglSwapBuffers(mDisplay, mWindowSurface); eglSwapBuffers(mDisplay, mWindowSurface);
} }
timer->stop(); timer.stop();
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
// 120 frames at 60fps should take 3s. At lower fps, it should take even longer. At // 120 frames at 60fps should take 3s. At lower fps, it should take even longer. At
// 144fps, it would take 1.25s. Let's use 1s as a lower bound. // 144fps, it would take 1.25s. Let's use 1s as a lower bound.
ASSERT_GT(timer->getElapsedTime(), 1); ASSERT_GT(timer.getElapsedTime(), 1);
} }
if (minInterval <= 0) if (minInterval <= 0)
{ {
std::unique_ptr<Timer> timer(CreateTimer()); Timer timer;
eglSwapInterval(mDisplay, 0); eglSwapInterval(mDisplay, 0);
timer->start(); timer.start();
for (int i = 0; i < 100; ++i) for (int i = 0; i < 100; ++i)
{ {
eglSwapBuffers(mDisplay, mWindowSurface); eglSwapBuffers(mDisplay, mWindowSurface);
...@@ -406,7 +406,7 @@ TEST_P(EGLSurfaceTest, SwapInterval) ...@@ -406,7 +406,7 @@ TEST_P(EGLSurfaceTest, SwapInterval)
// http://anglebug.com/3144. // http://anglebug.com/3144.
ANGLE_SKIP_TEST_IF(IsNVIDIAShield()); ANGLE_SKIP_TEST_IF(IsNVIDIAShield());
} }
timer->stop(); timer.stop();
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
// 100 no-op swaps should be fairly fast, though there is no guarantee how fast it can // 100 no-op swaps should be fairly fast, though there is no guarantee how fast it can
...@@ -415,7 +415,7 @@ TEST_P(EGLSurfaceTest, SwapInterval) ...@@ -415,7 +415,7 @@ TEST_P(EGLSurfaceTest, SwapInterval)
// TODO(syoussefi): if a surface doesn't truly allow no-vsync, this can fail. Until // TODO(syoussefi): if a surface doesn't truly allow no-vsync, this can fail. Until
// there's a way to query the exact minInterval from the surface, this test cannot be // there's a way to query the exact minInterval from the surface, this test cannot be
// enabled. // enabled.
// ASSERT_LT(timer->getElapsedTime(), 1); // ASSERT_LT(timer.getElapsedTime(), 1);
} }
} }
} }
......
...@@ -113,11 +113,10 @@ void UpdateTraceEventDuration(angle::PlatformMethods *platform, ...@@ -113,11 +113,10 @@ void UpdateTraceEventDuration(angle::PlatformMethods *platform,
double MonotonicallyIncreasingTime(angle::PlatformMethods *platform) double MonotonicallyIncreasingTime(angle::PlatformMethods *platform)
{ {
ANGLERenderTest *renderTest = static_cast<ANGLERenderTest *>(platform->context);
// Move the time origin to the first call to this function, to avoid generating unnecessarily // Move the time origin to the first call to this function, to avoid generating unnecessarily
// large timestamps. // large timestamps.
static double origin = renderTest->getTimer()->getAbsoluteTime(); static double origin = angle::GetCurrentTime();
return renderTest->getTimer()->getAbsoluteTime() - origin; return angle::GetCurrentTime() - origin;
} }
void DumpTraceEventsToJSONFile(const std::vector<TraceEvent> &traceEvents, void DumpTraceEventsToJSONFile(const std::vector<TraceEvent> &traceEvents,
...@@ -165,7 +164,6 @@ ANGLEPerfTest::ANGLEPerfTest(const std::string &name, ...@@ -165,7 +164,6 @@ ANGLEPerfTest::ANGLEPerfTest(const std::string &name,
: mName(name), : mName(name),
mBackend(backend), mBackend(backend),
mStory(story), mStory(story),
mTimer(CreateTimer()),
mGPUTimeNs(0), mGPUTimeNs(0),
mSkipTest(false), mSkipTest(false),
mStepsToRun(std::numeric_limits<unsigned int>::max()), mStepsToRun(std::numeric_limits<unsigned int>::max()),
...@@ -189,7 +187,6 @@ ANGLEPerfTest::ANGLEPerfTest(const std::string &name, ...@@ -189,7 +187,6 @@ ANGLEPerfTest::ANGLEPerfTest(const std::string &name,
ANGLEPerfTest::~ANGLEPerfTest() ANGLEPerfTest::~ANGLEPerfTest()
{ {
SafeDelete(mTimer);
} }
void ANGLEPerfTest::run() void ANGLEPerfTest::run()
...@@ -205,7 +202,7 @@ void ANGLEPerfTest::run() ...@@ -205,7 +202,7 @@ void ANGLEPerfTest::run()
doRunLoop(kCalibrationRunTimeSeconds); doRunLoop(kCalibrationRunTimeSeconds);
// Scale steps down according to the time that exeeded one second. // Scale steps down according to the time that exeeded one second.
double scale = kCalibrationRunTimeSeconds / mTimer->getElapsedTime(); double scale = kCalibrationRunTimeSeconds / mTimer.getElapsedTime();
mStepsToRun = static_cast<size_t>(static_cast<double>(mNumStepsPerformed) * scale); mStepsToRun = static_cast<size_t>(static_cast<double>(mNumStepsPerformed) * scale);
// Calibration allows the perf test runner script to save some time. // Calibration allows the perf test runner script to save some time.
...@@ -235,7 +232,7 @@ void ANGLEPerfTest::doRunLoop(double maxRunTime) ...@@ -235,7 +232,7 @@ void ANGLEPerfTest::doRunLoop(double maxRunTime)
{ {
mNumStepsPerformed = 0; mNumStepsPerformed = 0;
mRunning = true; mRunning = true;
mTimer->start(); mTimer.start();
startTest(); startTest();
while (mRunning) while (mRunning)
...@@ -244,7 +241,7 @@ void ANGLEPerfTest::doRunLoop(double maxRunTime) ...@@ -244,7 +241,7 @@ void ANGLEPerfTest::doRunLoop(double maxRunTime)
if (mRunning) if (mRunning)
{ {
++mNumStepsPerformed; ++mNumStepsPerformed;
if (mTimer->getElapsedTime() > maxRunTime) if (mTimer.getElapsedTime() > maxRunTime)
{ {
mRunning = false; mRunning = false;
} }
...@@ -255,7 +252,7 @@ void ANGLEPerfTest::doRunLoop(double maxRunTime) ...@@ -255,7 +252,7 @@ void ANGLEPerfTest::doRunLoop(double maxRunTime)
} }
} }
finishTest(); finishTest();
mTimer->stop(); mTimer.stop();
} }
void ANGLEPerfTest::SetUp() {} void ANGLEPerfTest::SetUp() {}
...@@ -265,7 +262,7 @@ void ANGLEPerfTest::TearDown() {} ...@@ -265,7 +262,7 @@ void ANGLEPerfTest::TearDown() {}
double ANGLEPerfTest::printResults() double ANGLEPerfTest::printResults()
{ {
double elapsedTimeSeconds[2] = { double elapsedTimeSeconds[2] = {
mTimer->getElapsedTime(), mTimer.getElapsedTime(),
mGPUTimeNs * 1e-9, mGPUTimeNs * 1e-9,
}; };
......
...@@ -69,8 +69,6 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable ...@@ -69,8 +69,6 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable
// Called right before timer is stopped to let the test wait for asynchronous operations. // Called right before timer is stopped to let the test wait for asynchronous operations.
virtual void finishTest() {} virtual void finishTest() {}
Timer *getTimer() const { return mTimer; }
protected: protected:
void run(); void run();
void SetUp() override; void SetUp() override;
...@@ -88,7 +86,7 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable ...@@ -88,7 +86,7 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable
std::string mName; std::string mName;
std::string mBackend; std::string mBackend;
std::string mStory; std::string mStory;
Timer *mTimer; Timer mTimer;
uint64_t mGPUTimeNs; uint64_t mGPUTimeNs;
bool mSkipTest; bool mSkipTest;
std::unique_ptr<perf_test::PerfResultReporter> mReporter; std::unique_ptr<perf_test::PerfResultReporter> mReporter;
......
...@@ -20,7 +20,7 @@ namespace ...@@ -20,7 +20,7 @@ namespace
// Only applies to D3D11 // Only applies to D3D11
struct Captures final : private angle::NonCopyable struct Captures final : private angle::NonCopyable
{ {
Timer *timer = CreateTimer(); Timer timer;
size_t loadDLLsMS = 0; size_t loadDLLsMS = 0;
size_t createDeviceMS = 0; size_t createDeviceMS = 0;
size_t initResourcesMS = 0; size_t initResourcesMS = 0;
...@@ -29,7 +29,7 @@ struct Captures final : private angle::NonCopyable ...@@ -29,7 +29,7 @@ struct Captures final : private angle::NonCopyable
double CapturePlatform_currentTime(angle::PlatformMethods *platformMethods) double CapturePlatform_currentTime(angle::PlatformMethods *platformMethods)
{ {
Captures *captures = static_cast<Captures *>(platformMethods->context); Captures *captures = static_cast<Captures *>(platformMethods->context);
return captures->timer->getElapsedTime(); return captures->timer.getElapsedTime();
} }
void CapturePlatform_histogramCustomCounts(angle::PlatformMethods *platformMethods, void CapturePlatform_histogramCustomCounts(angle::PlatformMethods *platformMethods,
......
...@@ -276,7 +276,7 @@ void InstancingPerfBenchmark::drawBenchmark() ...@@ -276,7 +276,7 @@ void InstancingPerfBenchmark::drawBenchmark()
// Animatino makes the test more interesting visually, but also eats up many CPU cycles. // Animatino makes the test more interesting visually, but also eats up many CPU cycles.
if (params.animationEnabled) if (params.animationEnabled)
{ {
float time = static_cast<float>(mTimer->getElapsedTime()); float time = static_cast<float>(mTimer.getElapsedTime());
for (size_t pointIndex = 0; pointIndex < mTranslateData.size(); ++pointIndex) for (size_t pointIndex = 0; pointIndex < mTranslateData.size(); ++pointIndex)
{ {
......
//
// Copyright 2019 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.
//
// Timer.cpp: Implementation of a high precision timer class.
//
#include "util/Timer.h"
#include "common/system_utils.h"
Timer::Timer() : mRunning(false), mStartTime(0), mStopTime(0) {}
void Timer::start()
{
mStartTime = angle::GetCurrentTime();
mRunning = true;
}
void Timer::stop()
{
mStopTime = angle::GetCurrentTime();
mRunning = false;
}
double Timer::getElapsedTime() const
{
double endTime;
if (mRunning)
{
endTime = angle::GetCurrentTime();
}
else
{
endTime = mStopTime;
}
return endTime - mStartTime;
}
// //
// Copyright 2014 The ANGLE Project Authors. All rights reserved. // Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -9,23 +9,23 @@ ...@@ -9,23 +9,23 @@
#include "util/util_export.h" #include "util/util_export.h"
class ANGLE_UTIL_EXPORT Timer class ANGLE_UTIL_EXPORT Timer final
{ {
public: public:
virtual ~Timer() {} Timer();
~Timer() {}
// Timer functionality: Use start() and stop() to record the duration and use getElapsedTime() // Use start() and stop() to record the duration and use getElapsedTime() to query that
// to query that duration. If getElapsedTime() is called in between, it will report the elapsed // duration. If getElapsedTime() is called in between, it will report the elapsed time since
// time since start(). // start().
virtual void start() = 0; void start();
virtual void stop() = 0; void stop();
virtual double getElapsedTime() const = 0; double getElapsedTime() const;
// Timestamp functionality: Use getAbsoluteTime() to get an absolute time with an unknown private:
// origin. This time moves forward regardless of start()/stop(). bool mRunning;
virtual double getAbsoluteTime() = 0; double mStartTime;
double mStopTime;
}; };
ANGLE_UTIL_EXPORT Timer *CreateTimer();
#endif // SAMPLE_UTIL_TIMER_H #endif // SAMPLE_UTIL_TIMER_H
//
// 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.
//
// OSXTimer.cpp: Implementation of a high precision timer class on OSX
#include "util/osx/OSXTimer.h"
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
OSXTimer::OSXTimer() : mRunning(false), mSecondCoeff(0) {}
double OSXTimer::getSecondCoeff()
{
// If this is the first time we've run, get the timebase.
if (mSecondCoeff == 0.0)
{
mach_timebase_info_data_t timebaseInfo;
mach_timebase_info(&timebaseInfo);
mSecondCoeff = timebaseInfo.numer * (1.0 / 1000000000) / timebaseInfo.denom;
}
return mSecondCoeff;
}
void OSXTimer::start()
{
mStartTime = mach_absolute_time();
// Cache secondCoeff
getSecondCoeff();
mRunning = true;
}
void OSXTimer::stop()
{
mStopTime = mach_absolute_time();
mRunning = false;
}
double OSXTimer::getElapsedTime() const
{
if (mRunning)
{
return mSecondCoeff * (mach_absolute_time() - mStartTime);
}
else
{
return mSecondCoeff * (mStopTime - mStartTime);
}
}
double OSXTimer::getAbsoluteTime()
{
return getSecondCoeff() * mach_absolute_time();
}
Timer *CreateTimer()
{
return new OSXTimer();
}
//
// 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.
//
// OSXTimer.h: Definition of a high precision timer class on OSX
#ifndef UTIL_OSX_TIMER_H_
#define UTIL_OSX_TIMER_H_
#include <stdint.h>
#include <time.h>
#include "util/Timer.h"
class ANGLE_UTIL_EXPORT OSXTimer : public Timer
{
public:
OSXTimer();
void start() override;
void stop() override;
double getElapsedTime() const override;
double getAbsoluteTime() override;
private:
double getSecondCoeff();
bool mRunning;
uint64_t mStartTime;
uint64_t mStopTime;
double mSecondCoeff;
};
#endif // UTIL_OSX_TIMER_H_
//
// 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.
//
// PosixTimer.cpp: Implementation of a high precision timer class on POSIX
#include "util/posix/PosixTimer.h"
#include <iostream>
PosixTimer::PosixTimer() : mRunning(false) {}
namespace
{
uint64_t getCurrentTimeNs()
{
struct timespec currentTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
return currentTime.tv_sec * 1'000'000'000llu + currentTime.tv_nsec;
}
} // anonymous namespace
void PosixTimer::start()
{
mStartTimeNs = getCurrentTimeNs();
mRunning = true;
}
void PosixTimer::stop()
{
mStopTimeNs = getCurrentTimeNs();
mRunning = false;
}
double PosixTimer::getElapsedTime() const
{
uint64_t endTimeNs;
if (mRunning)
{
endTimeNs = getCurrentTimeNs();
}
else
{
endTimeNs = mStopTimeNs;
}
return (endTimeNs - mStartTimeNs) * 1e-9;
}
double PosixTimer::getAbsoluteTime()
{
return getCurrentTimeNs() * 1e-9;
}
Timer *CreateTimer()
{
return new PosixTimer();
}
//
// 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.
//
// PosixTimer.h: Definition of a high precision timer class on Linux
#ifndef UTIL_POSIX_TIMER_H
#define UTIL_POSIX_TIMER_H
#include <stdint.h>
#include <time.h>
#include "util/Timer.h"
class ANGLE_UTIL_EXPORT PosixTimer : public Timer
{
public:
PosixTimer();
void start() override;
void stop() override;
double getElapsedTime() const override;
double getAbsoluteTime() override;
private:
bool mRunning;
uint64_t mStartTimeNs;
uint64_t mStopTimeNs;
};
#endif // UTIL_POSIX_TIMER_H
...@@ -24,6 +24,7 @@ util_sources = [ ...@@ -24,6 +24,7 @@ util_sources = [
"util/OSWindow.cpp", "util/OSWindow.cpp",
"util/OSWindow.h", "util/OSWindow.h",
"util/Timer.h", "util/Timer.h",
"util/Timer.cpp",
] ]
util_win_sources = [ util_win_sources = [
...@@ -33,16 +34,12 @@ util_win_sources = [ ...@@ -33,16 +34,12 @@ util_win_sources = [
"util/windows/win32/Win32Window.cpp", "util/windows/win32/Win32Window.cpp",
"util/windows/win32/Win32Window.h", "util/windows/win32/Win32Window.h",
"util/windows/Windows_system_utils.cpp", "util/windows/Windows_system_utils.cpp",
"util/windows/WindowsTimer.cpp",
"util/windows/WindowsTimer.h",
"util/windows/WGLWindow.h", "util/windows/WGLWindow.h",
] ]
util_win_shared_sources = [ "util/windows/WGLWindow.cpp" ] util_win_shared_sources = [ "util/windows/WGLWindow.cpp" ]
util_posix_sources = [ util_posix_sources = [
"util/posix/PosixTimer.cpp",
"util/posix/PosixTimer.h",
"util/posix/Posix_crash_handler.cpp", "util/posix/Posix_crash_handler.cpp",
"util/posix/Posix_system_utils.cpp", "util/posix/Posix_system_utils.cpp",
] ]
...@@ -68,8 +65,6 @@ util_ozone_sources = [ ...@@ -68,8 +65,6 @@ util_ozone_sources = [
] ]
util_osx_sources = [ util_osx_sources = [
"util/osx/OSXTimer.cpp",
"util/osx/OSXTimer.h",
"util/osx/OSXPixmap.mm", "util/osx/OSXPixmap.mm",
"util/osx/OSXPixmap.h", "util/osx/OSXPixmap.h",
"util/osx/OSXWindow.mm", "util/osx/OSXWindow.mm",
......
//
// Copyright 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.
//
// WindowsTimer.cpp: Implementation of a high precision timer class on Windows
#include "util/windows/WindowsTimer.h"
WindowsTimer::WindowsTimer() : mRunning(false), mStartTime(0), mStopTime(0), mFrequency(0) {}
LONGLONG WindowsTimer::getFrequency()
{
if (mFrequency == 0)
{
LARGE_INTEGER frequency = {};
QueryPerformanceFrequency(&frequency);
mFrequency = frequency.QuadPart;
}
return mFrequency;
}
void WindowsTimer::start()
{
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
mStartTime = curTime.QuadPart;
// Cache the frequency
getFrequency();
mRunning = true;
}
void WindowsTimer::stop()
{
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
mStopTime = curTime.QuadPart;
mRunning = false;
}
double WindowsTimer::getElapsedTime() const
{
LONGLONG endTime;
if (mRunning)
{
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
endTime = curTime.QuadPart;
}
else
{
endTime = mStopTime;
}
return static_cast<double>(endTime - mStartTime) / mFrequency;
}
double WindowsTimer::getAbsoluteTime()
{
LARGE_INTEGER curTime;
QueryPerformanceCounter(&curTime);
return static_cast<double>(curTime.QuadPart) / getFrequency();
}
Timer *CreateTimer()
{
return new WindowsTimer();
}
//
// Copyright 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.
//
// WindowsTimer.h: Definition of a high precision timer class on Windows
#ifndef UTIL_WINDOWS_TIMER_H
#define UTIL_WINDOWS_TIMER_H
#include <windows.h>
#include "util/Timer.h"
class ANGLE_UTIL_EXPORT WindowsTimer : public Timer
{
public:
WindowsTimer();
void start() override;
void stop() override;
double getElapsedTime() const override;
double getAbsoluteTime() override;
private:
LONGLONG getFrequency();
bool mRunning;
LONGLONG mStartTime;
LONGLONG mStopTime;
LONGLONG mFrequency;
};
#endif // UTIL_WINDOWS_TIMER_H
...@@ -486,7 +486,6 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP ...@@ -486,7 +486,6 @@ LRESULT CALLBACK Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LP
Win32Window::Win32Window() Win32Window::Win32Window()
: mIsVisible(false), : mIsVisible(false),
mSetVisibleTimer(CreateTimer()),
mIsMouseInWindow(false), mIsMouseInWindow(false),
mNativeWindow(0), mNativeWindow(0),
mParentWindow(0), mParentWindow(0),
...@@ -496,7 +495,6 @@ Win32Window::Win32Window() ...@@ -496,7 +495,6 @@ Win32Window::Win32Window()
Win32Window::~Win32Window() Win32Window::~Win32Window()
{ {
destroy(); destroy();
delete mSetVisibleTimer;
} }
bool Win32Window::initialize(const std::string &name, int width, int height) bool Win32Window::initialize(const std::string &name, int width, int height)
...@@ -611,7 +609,7 @@ bool Win32Window::takeScreenshot(uint8_t *pixelData) ...@@ -611,7 +609,7 @@ bool Win32Window::takeScreenshot(uint8_t *pixelData)
// for a while before issuing screenshot if window was just made visible. // for a while before issuing screenshot if window was just made visible.
{ {
static const double WAIT_WINDOW_VISIBLE_MS = 0.5; // Half a second for the animation static const double WAIT_WINDOW_VISIBLE_MS = 0.5; // Half a second for the animation
double timeSinceVisible = mSetVisibleTimer->getElapsedTime(); double timeSinceVisible = mSetVisibleTimer.getElapsedTime();
if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS) if (timeSinceVisible < WAIT_WINDOW_VISIBLE_MS)
{ {
...@@ -804,8 +802,8 @@ void Win32Window::setVisible(bool isVisible) ...@@ -804,8 +802,8 @@ void Win32Window::setVisible(bool isVisible)
if (isVisible) if (isVisible)
{ {
mSetVisibleTimer->stop(); mSetVisibleTimer.stop();
mSetVisibleTimer->start(); mSetVisibleTimer.start();
} }
} }
......
...@@ -48,7 +48,7 @@ class Win32Window : public OSWindow ...@@ -48,7 +48,7 @@ class Win32Window : public OSWindow
std::string mChildClassName; std::string mChildClassName;
bool mIsVisible; bool mIsVisible;
Timer *mSetVisibleTimer; Timer mSetVisibleTimer;
bool mIsMouseInWindow; bool mIsMouseInWindow;
......
...@@ -427,20 +427,18 @@ bool X11Window::resize(int width, int height) ...@@ -427,20 +427,18 @@ bool X11Window::resize(int width, int height)
XResizeWindow(mDisplay, mWindow, width, height); XResizeWindow(mDisplay, mWindow, width, height);
XFlush(mDisplay); XFlush(mDisplay);
Timer *timer = CreateTimer(); Timer timer;
timer->start(); timer.start();
// Wait until the window as actually been resized so that the code calling resize // Wait until the window as actually been resized so that the code calling resize
// can assume the window has been resized. // can assume the window has been resized.
const double kResizeWaitDelay = 0.2; const double kResizeWaitDelay = 0.2;
while ((mHeight != height || mWidth != width) && timer->getElapsedTime() < kResizeWaitDelay) while ((mHeight != height || mWidth != width) && timer.getElapsedTime() < kResizeWaitDelay)
{ {
messageLoop(); messageLoop();
angle::Sleep(10); angle::Sleep(10);
} }
delete timer;
return true; return true;
} }
......
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