• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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