1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ANGLEPerfTests:
7 // Base class for google test performance tests
8 //
9
10 #ifndef PERF_TESTS_ANGLE_PERF_TEST_H_
11 #define PERF_TESTS_ANGLE_PERF_TEST_H_
12
13 #include <gtest/gtest.h>
14
15 #include <string>
16 #include <unordered_map>
17 #include <vector>
18
19 #include "platform/PlatformMethods.h"
20 #include "test_utils/angle_test_configs.h"
21 #include "test_utils/angle_test_instantiate.h"
22 #include "test_utils/angle_test_platform.h"
23 #include "third_party/perf/perf_result_reporter.h"
24 #include "util/EGLWindow.h"
25 #include "util/OSWindow.h"
26 #include "util/Timer.h"
27 #include "util/util_gl.h"
28
29 class Event;
30
31 #if !defined(ASSERT_GL_NO_ERROR)
32 # define ASSERT_GL_NO_ERROR() ASSERT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError())
33 #endif // !defined(ASSERT_GL_NO_ERROR)
34
35 #if !defined(ASSERT_GLENUM_EQ)
36 # define ASSERT_GLENUM_EQ(expected, actual) \
37 ASSERT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
38 #endif // !defined(ASSERT_GLENUM_EQ)
39
40 // These are trace events according to Google's "Trace Event Format".
41 // See https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU
42 // Only a subset of the properties are implemented.
43 struct TraceEvent final
44 {
TraceEventfinal45 TraceEvent() {}
46 TraceEvent(char phaseIn, const char *categoryNameIn, const char *nameIn, double timestampIn);
47
48 static constexpr uint32_t kMaxNameLen = 64;
49
50 char phase = 0;
51 const char *categoryName = nullptr;
52 char name[kMaxNameLen] = {};
53 double timestamp = 0;
54 uint32_t tid = 0;
55 };
56
57 class ANGLEPerfTest : public testing::Test, angle::NonCopyable
58 {
59 public:
60 ANGLEPerfTest(const std::string &name,
61 const std::string &backend,
62 const std::string &story,
63 unsigned int iterationsPerStep);
64 ~ANGLEPerfTest() override;
65
66 virtual void step() = 0;
67
68 // Called right after the timer starts to let the test initialize other metrics if necessary
startTest()69 virtual void startTest() {}
70 // Called right before timer is stopped to let the test wait for asynchronous operations.
finishTest()71 virtual void finishTest() {}
flush()72 virtual void flush() {}
73
74 protected:
75 void run();
76 void SetUp() override;
77 void TearDown() override;
78
79 // Normalize a time value according to the number of test loop iterations (mFrameCount)
80 double normalizedTime(size_t value) const;
81
82 // Call if the test step was aborted and the test should stop running.
abortTest()83 void abortTest() { mRunning = false; }
84
getNumStepsPerformed()85 unsigned int getNumStepsPerformed() const { return mNumStepsPerformed; }
86 void doRunLoop(double maxRunTime);
87
88 // Overriden in trace perf tests.
saveScreenshot(const std::string & screenshotName)89 virtual void saveScreenshot(const std::string &screenshotName) {}
90
91 std::string mName;
92 std::string mBackend;
93 std::string mStory;
94 Timer mTimer;
95 uint64_t mGPUTimeNs;
96 bool mSkipTest;
97 std::unique_ptr<perf_test::PerfResultReporter> mReporter;
98
99 private:
100 double printResults();
101
102 unsigned int mStepsToRun;
103 unsigned int mNumStepsPerformed;
104 unsigned int mIterationsPerStep;
105 bool mRunning;
106 };
107
108 struct RenderTestParams : public angle::PlatformParameters
109 {
~RenderTestParamsRenderTestParams110 virtual ~RenderTestParams() {}
111
112 virtual std::string backend() const;
113 virtual std::string story() const;
114 std::string backendAndStory() const;
115
116 EGLint windowWidth = 64;
117 EGLint windowHeight = 64;
118 unsigned int iterationsPerStep = 0;
119 bool trackGpuTime = false;
120 };
121
122 class ANGLERenderTest : public ANGLEPerfTest
123 {
124 public:
125 ANGLERenderTest(const std::string &name, const RenderTestParams &testParams);
126 ~ANGLERenderTest() override;
127
128 void addExtensionPrerequisite(const char *extensionName);
129
initializeBenchmark()130 virtual void initializeBenchmark() {}
destroyBenchmark()131 virtual void destroyBenchmark() {}
132
133 virtual void drawBenchmark() = 0;
134
135 bool popEvent(Event *event);
136
137 OSWindow *getWindow();
138 GLWindowBase *getGLWindow();
139
140 std::vector<TraceEvent> &getTraceEventBuffer();
141
overrideWorkaroundsD3D(angle::FeaturesD3D * featuresD3D)142 virtual void overrideWorkaroundsD3D(angle::FeaturesD3D *featuresD3D) {}
143
144 protected:
145 const RenderTestParams &mTestParams;
146
147 void setWebGLCompatibilityEnabled(bool webglCompatibility);
148 void setRobustResourceInit(bool enabled);
149
150 void startGpuTimer();
151 void stopGpuTimer();
152
153 void beginInternalTraceEvent(const char *name);
154 void endInternalTraceEvent(const char *name);
155 void beginGLTraceEvent(const char *name, double hostTimeSec);
156 void endGLTraceEvent(const char *name, double hostTimeSec);
157
disableTestHarnessSwap()158 void disableTestHarnessSwap() { mSwapEnabled = false; }
159
160 bool mIsTimestampQueryAvailable;
161
162 private:
163 void SetUp() override;
164 void TearDown() override;
165
166 void step() override;
167 void startTest() override;
168 void finishTest() override;
169
170 bool areExtensionPrerequisitesFulfilled() const;
171
172 GLWindowBase *mGLWindow;
173 OSWindow *mOSWindow;
174 std::vector<const char *> mExtensionPrerequisites;
175 angle::PlatformMethods mPlatformMethods;
176 ConfigParameters mConfigParams;
177 bool mSwapEnabled;
178
179 GLuint mTimestampQuery;
180
181 // Trace event record that can be output.
182 std::vector<TraceEvent> mTraceEventBuffer;
183
184 // Handle to the entry point binding library.
185 std::unique_ptr<angle::Library> mEntryPointsLib;
186 };
187
188 // Mixins.
189 namespace params
190 {
191 template <typename ParamsT>
Offscreen(const ParamsT & input)192 ParamsT Offscreen(const ParamsT &input)
193 {
194 ParamsT output = input;
195 output.offscreen = true;
196 return output;
197 }
198
199 template <typename ParamsT>
NullDevice(const ParamsT & input)200 ParamsT NullDevice(const ParamsT &input)
201 {
202 ParamsT output = input;
203 output.eglParameters.deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
204 output.trackGpuTime = false;
205 return output;
206 }
207
208 template <typename ParamsT>
Passthrough(const ParamsT & input)209 ParamsT Passthrough(const ParamsT &input)
210 {
211 return input;
212 }
213 } // namespace params
214
215 namespace angle
216 {
217 // Returns the time of the host since the application started in seconds.
218 double GetHostTimeSeconds();
219 } // namespace angle
220 #endif // PERF_TESTS_ANGLE_PERF_TEST_H_
221