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/Platform.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() {}
72
73 protected:
74 void run();
75 void SetUp() override;
76 void TearDown() override;
77
78 // Normalize a time value according to the number of test loop iterations (mFrameCount)
79 double normalizedTime(size_t value) const;
80
81 // Call if the test step was aborted and the test should stop running.
abortTest()82 void abortTest() { mRunning = false; }
83
getNumStepsPerformed()84 unsigned int getNumStepsPerformed() const { return mNumStepsPerformed; }
85 void doRunLoop(double maxRunTime);
86
87 std::string mName;
88 std::string mBackend;
89 std::string mStory;
90 Timer mTimer;
91 uint64_t mGPUTimeNs;
92 bool mSkipTest;
93 std::unique_ptr<perf_test::PerfResultReporter> mReporter;
94
95 private:
96 double printResults();
97
98 unsigned int mStepsToRun;
99 unsigned int mNumStepsPerformed;
100 unsigned int mIterationsPerStep;
101 bool mRunning;
102 };
103
104 struct RenderTestParams : public angle::PlatformParameters
105 {
~RenderTestParamsRenderTestParams106 virtual ~RenderTestParams() {}
107
108 virtual std::string backend() const;
109 virtual std::string story() const;
110 std::string backendAndStory() const;
111
112 EGLint windowWidth = 64;
113 EGLint windowHeight = 64;
114 unsigned int iterationsPerStep = 0;
115 bool trackGpuTime = false;
116 };
117
118 class ANGLERenderTest : public ANGLEPerfTest
119 {
120 public:
121 ANGLERenderTest(const std::string &name, const RenderTestParams &testParams);
122 ~ANGLERenderTest() override;
123
124 void addExtensionPrerequisite(const char *extensionName);
125
initializeBenchmark()126 virtual void initializeBenchmark() {}
destroyBenchmark()127 virtual void destroyBenchmark() {}
128
129 virtual void drawBenchmark() = 0;
130
131 bool popEvent(Event *event);
132
133 OSWindow *getWindow();
134 GLWindowBase *getGLWindow();
135
136 std::vector<TraceEvent> &getTraceEventBuffer();
137
overrideWorkaroundsD3D(angle::FeaturesD3D * featuresD3D)138 virtual void overrideWorkaroundsD3D(angle::FeaturesD3D *featuresD3D) {}
139
140 protected:
141 const RenderTestParams &mTestParams;
142
143 void setWebGLCompatibilityEnabled(bool webglCompatibility);
144 void setRobustResourceInit(bool enabled);
145
146 void startGpuTimer();
147 void stopGpuTimer();
148
149 void beginInternalTraceEvent(const char *name);
150 void endInternalTraceEvent(const char *name);
151 void beginGLTraceEvent(const char *name, double hostTimeSec);
152 void endGLTraceEvent(const char *name, double hostTimeSec);
153
154 bool mIsTimestampQueryAvailable;
155
156 private:
157 void SetUp() override;
158 void TearDown() override;
159
160 void step() override;
161 void startTest() override;
162 void finishTest() override;
163
164 bool areExtensionPrerequisitesFulfilled() const;
165
166 GLWindowBase *mGLWindow;
167 OSWindow *mOSWindow;
168 std::vector<const char *> mExtensionPrerequisites;
169 angle::PlatformMethods mPlatformMethods;
170 ConfigParameters mConfigParams;
171
172 GLuint mTimestampQuery;
173
174 // Trace event record that can be output.
175 std::vector<TraceEvent> mTraceEventBuffer;
176
177 // Handle to the entry point binding library.
178 std::unique_ptr<angle::Library> mEntryPointsLib;
179 };
180
181 // Mixins.
182 namespace params
183 {
184 template <typename ParamsT>
Offscreen(const ParamsT & input)185 ParamsT Offscreen(const ParamsT &input)
186 {
187 ParamsT output = input;
188 output.offscreen = true;
189 return output;
190 }
191
192 template <typename ParamsT>
NullDevice(const ParamsT & input)193 ParamsT NullDevice(const ParamsT &input)
194 {
195 ParamsT output = input;
196 output.eglParameters.deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
197 output.trackGpuTime = false;
198 return output;
199 }
200
201 template <typename ParamsT>
Passthrough(const ParamsT & input)202 ParamsT Passthrough(const ParamsT &input)
203 {
204 return input;
205 }
206 } // namespace params
207
208 namespace angle
209 {
210 // Returns the time of the host since the application started in seconds.
211 double GetHostTimeSeconds();
212 } // namespace angle
213 #endif // PERF_TESTS_ANGLE_PERF_TEST_H_
214