1 //
2 // Copyright 2025 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 // TracePerfTestCL:
7 // Performance test for ANGLE CL replaying traces.
8 //
9
10 #include "tests/perf_tests/ANGLEComputeTestCL.h"
11 #include "tests/perf_tests/TracePerfTest.h"
12
13 #if defined(ANGLE_PLATFORM_ANDROID)
14 # include "util/android/AndroidWindow.h"
15 #endif
16
17 namespace angle
18 {
19 class TracePerfTestCL : public ANGLEComputeTestCL
20 {
21 public:
TracePerfTestCL(std::unique_ptr<const TracePerfParams> & params)22 TracePerfTestCL(std::unique_ptr<const TracePerfParams> ¶ms)
23 : ANGLEComputeTestCL("TracePerf", *params.get(), "ms"),
24 mParams(std::move(params)),
25 mStartFrame(0),
26 mEndFrame(0)
27 {}
28
29 void initializeBenchmark() override;
30 void drawBenchmark() override;
31 void destroyBenchmark() override;
32
frameCount() const33 uint32_t frameCount() const
34 {
35 const TraceInfo &traceInfo = mParams->traceInfo;
36 return traceInfo.frameEnd - traceInfo.frameStart + 1;
37 }
38
getStepAlignment() const39 int getStepAlignment() const override
40 {
41 // Align step counts to the number of frames in a trace.
42 return static_cast<int>(frameCount());
43 }
44
TestBody()45 void TestBody() override { run(); }
46
traceNameIs(const char * name) const47 bool traceNameIs(const char *name) const
48 {
49 return strncmp(name, mParams->traceInfo.name, kTraceInfoMaxNameLen) == 0;
50 }
51
52 private:
53 std::unique_ptr<const TracePerfParams> mParams;
54
55 uint32_t mStartFrame;
56 uint32_t mEndFrame;
57 uint32_t mCurrentFrame = 0;
58 uint32_t mCurrentIteration = 0;
59 uint32_t mTotalFrameCount = 0;
60 std::unique_ptr<TraceLibrary> mTraceReplay;
61 };
62
CreateTracePerfTestCL(std::unique_ptr<const TracePerfParams> params)63 ANGLEPerfTest *CreateTracePerfTestCL(std::unique_ptr<const TracePerfParams> params)
64 {
65 return new TracePerfTestCL(params);
66 }
67
FindTraceTestDataPath(const char * traceName,char * testDataDirOut,size_t maxDataDirLen)68 bool FindTraceTestDataPath(const char *traceName, char *testDataDirOut, size_t maxDataDirLen)
69 {
70 char relativeTestDataDir[kMaxPath] = {};
71 snprintf(relativeTestDataDir, kMaxPath, "%s%c%s", kTraceTestFolder, GetPathSeparator(),
72 traceName);
73 return angle::FindTestDataPath(relativeTestDataDir, testDataDirOut, maxDataDirLen);
74 }
75
FindTraceGzPath(const std::string & traceName)76 std::string FindTraceGzPath(const std::string &traceName)
77 {
78 std::stringstream pathStream;
79
80 char genDir[kMaxPath] = {};
81 if (!angle::FindTestDataPath("gen", genDir, kMaxPath))
82 {
83 return "";
84 }
85 pathStream << genDir << angle::GetPathSeparator() << "tracegz_" << traceName << ".gz";
86
87 return pathStream.str();
88 }
89
initializeBenchmark()90 void TracePerfTestCL::initializeBenchmark()
91 {
92 const TraceInfo &traceInfo = mParams->traceInfo;
93
94 char testDataDir[kMaxPath] = {};
95 if (!FindTraceTestDataPath(traceInfo.name, testDataDir, kMaxPath))
96 {
97 failTest("Could not find test data folder.");
98 return;
99 }
100
101 std::string baseDir = "";
102 #if defined(ANGLE_TRACE_EXTERNAL_BINARIES)
103 baseDir += AndroidWindow::GetApplicationDirectory() + "/angle_traces/";
104 #endif
105
106 if (gTraceInterpreter)
107 {
108 mTraceReplay.reset(new TraceLibrary("angle_trace_interpreter", traceInfo, baseDir));
109 if (strcmp(gTraceInterpreter, "gz") == 0)
110 {
111 std::string traceGzPath = FindTraceGzPath(traceInfo.name);
112 if (traceGzPath.empty())
113 {
114 failTest("Could not find trace gz.");
115 return;
116 }
117 mTraceReplay->setTraceGzPath(traceGzPath);
118 }
119 }
120 else
121 {
122 std::stringstream traceNameStr;
123 traceNameStr << "angle_restricted_traces_" << traceInfo.name;
124 std::string traceName = traceNameStr.str();
125 mTraceReplay.reset(new TraceLibrary(traceNameStr.str(), traceInfo, baseDir));
126 }
127
128 if (!mTraceReplay->valid())
129 {
130 failTest("Could not load trace.");
131 return;
132 }
133
134 mStartFrame = traceInfo.frameStart;
135 mEndFrame = traceInfo.frameEnd;
136 mTraceReplay->setBinaryDataDir(testDataDir);
137 mTraceReplay->setReplayResourceMode(gIncludeInactiveResources);
138 if (gScreenshotDir)
139 {
140 mTraceReplay->setDebugOutputDir(gScreenshotDir);
141 }
142
143 mCurrentFrame = mStartFrame;
144 mCurrentIteration = mStartFrame;
145
146 // Potentially slow. Can load a lot of resources.
147 mTraceReplay->setupReplay();
148 ASSERT_GE(mEndFrame, mStartFrame);
149 }
150
destroyBenchmark()151 void TracePerfTestCL::destroyBenchmark()
152 {
153 mTraceReplay->finishReplay();
154 mTraceReplay.reset(nullptr);
155 }
156
drawBenchmark()157 void TracePerfTestCL::drawBenchmark()
158 {
159 if (mCurrentFrame == mStartFrame)
160 {
161 mTraceReplay->setupFirstFrame();
162 }
163
164 char frameName[32];
165 snprintf(frameName, sizeof(frameName), "Frame %u", mCurrentFrame);
166
167 atraceCounter("TraceFrameIndex", mCurrentFrame);
168 mTraceReplay->replayFrame(mCurrentFrame);
169
170 updatePerfCounters();
171
172 mTotalFrameCount++;
173
174 if (mCurrentFrame == mEndFrame)
175 {
176 mTraceReplay->resetReplay();
177 mCurrentFrame = mStartFrame;
178 }
179 else
180 {
181 mCurrentFrame++;
182 }
183
184 // Always iterated for saving screenshots after reset
185 mCurrentIteration++;
186 }
187
188 } // namespace angle
189