| // |
| // Copyright 2025 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. |
| // |
| // TracePerfTestCL: |
| // Performance test for ANGLE CL replaying traces. |
| // |
| |
| #include "tests/perf_tests/ANGLEComputeTestCL.h" |
| #include "tests/perf_tests/TracePerfTest.h" |
| |
| #if defined(ANGLE_PLATFORM_ANDROID) |
| # include "util/android/AndroidWindow.h" |
| #endif |
| |
| namespace angle |
| { |
| class TracePerfTestCL : public ANGLEComputeTestCL |
| { |
| public: |
| TracePerfTestCL(std::unique_ptr<const TracePerfParams> ¶ms) |
| : ANGLEComputeTestCL("TracePerf", *params.get(), "ms"), |
| mParams(std::move(params)), |
| mStartFrame(0), |
| mEndFrame(0) |
| {} |
| |
| void initializeBenchmark() override; |
| void drawBenchmark() override; |
| void destroyBenchmark() override; |
| |
| uint32_t frameCount() const |
| { |
| const TraceInfo &traceInfo = mParams->traceInfo; |
| return traceInfo.frameEnd - traceInfo.frameStart + 1; |
| } |
| |
| int getStepAlignment() const override |
| { |
| // Align step counts to the number of frames in a trace. |
| return static_cast<int>(frameCount()); |
| } |
| |
| void TestBody() override { run(); } |
| |
| bool traceNameIs(const char *name) const |
| { |
| return strncmp(name, mParams->traceInfo.name, kTraceInfoMaxNameLen) == 0; |
| } |
| |
| private: |
| std::unique_ptr<const TracePerfParams> mParams; |
| |
| uint32_t mStartFrame; |
| uint32_t mEndFrame; |
| uint32_t mCurrentFrame = 0; |
| uint32_t mCurrentIteration = 0; |
| uint32_t mTotalFrameCount = 0; |
| std::unique_ptr<TraceLibrary> mTraceReplay; |
| }; |
| |
| ANGLEPerfTest *CreateTracePerfTestCL(std::unique_ptr<const TracePerfParams> params) |
| { |
| return new TracePerfTestCL(params); |
| } |
| |
| bool FindTraceTestDataPath(const char *traceName, char *testDataDirOut, size_t maxDataDirLen) |
| { |
| char relativeTestDataDir[kMaxPath] = {}; |
| snprintf(relativeTestDataDir, kMaxPath, "%s%c%s", kTraceTestFolder, GetPathSeparator(), |
| traceName); |
| return angle::FindTestDataPath(relativeTestDataDir, testDataDirOut, maxDataDirLen); |
| } |
| |
| std::string FindTraceGzPath(const std::string &traceName) |
| { |
| std::stringstream pathStream; |
| |
| char genDir[kMaxPath] = {}; |
| if (!angle::FindTestDataPath("gen", genDir, kMaxPath)) |
| { |
| return ""; |
| } |
| pathStream << genDir << angle::GetPathSeparator() << "tracegz_" << traceName << ".gz"; |
| |
| return pathStream.str(); |
| } |
| |
| void TracePerfTestCL::initializeBenchmark() |
| { |
| const TraceInfo &traceInfo = mParams->traceInfo; |
| |
| char testDataDir[kMaxPath] = {}; |
| if (!FindTraceTestDataPath(traceInfo.name, testDataDir, kMaxPath)) |
| { |
| failTest("Could not find test data folder."); |
| return; |
| } |
| |
| std::string baseDir = ""; |
| #if defined(ANGLE_TRACE_EXTERNAL_BINARIES) |
| baseDir += AndroidWindow::GetApplicationDirectory() + "/angle_traces/"; |
| #endif |
| |
| if (gTraceInterpreter) |
| { |
| mTraceReplay.reset(new TraceLibrary("angle_trace_interpreter", traceInfo, baseDir)); |
| if (strcmp(gTraceInterpreter, "gz") == 0) |
| { |
| std::string traceGzPath = FindTraceGzPath(traceInfo.name); |
| if (traceGzPath.empty()) |
| { |
| failTest("Could not find trace gz."); |
| return; |
| } |
| mTraceReplay->setTraceGzPath(traceGzPath); |
| } |
| } |
| else |
| { |
| std::stringstream traceNameStr; |
| traceNameStr << "angle_restricted_traces_" << traceInfo.name; |
| std::string traceName = traceNameStr.str(); |
| mTraceReplay.reset(new TraceLibrary(traceNameStr.str(), traceInfo, baseDir)); |
| } |
| |
| if (!mTraceReplay->valid()) |
| { |
| failTest("Could not load trace."); |
| return; |
| } |
| |
| mStartFrame = traceInfo.frameStart; |
| mEndFrame = traceInfo.frameEnd; |
| mTraceReplay->setBinaryDataDir(testDataDir); |
| mTraceReplay->setReplayResourceMode(gIncludeInactiveResources); |
| if (gScreenshotDir) |
| { |
| mTraceReplay->setDebugOutputDir(gScreenshotDir); |
| } |
| |
| mCurrentFrame = mStartFrame; |
| mCurrentIteration = mStartFrame; |
| |
| // Potentially slow. Can load a lot of resources. |
| mTraceReplay->setupReplay(); |
| ASSERT_GE(mEndFrame, mStartFrame); |
| } |
| |
| void TracePerfTestCL::destroyBenchmark() |
| { |
| mTraceReplay->finishReplay(); |
| mTraceReplay.reset(nullptr); |
| } |
| |
| void TracePerfTestCL::drawBenchmark() |
| { |
| if (mCurrentFrame == mStartFrame) |
| { |
| mTraceReplay->setupFirstFrame(); |
| } |
| |
| char frameName[32]; |
| snprintf(frameName, sizeof(frameName), "Frame %u", mCurrentFrame); |
| |
| atraceCounter("TraceFrameIndex", mCurrentFrame); |
| mTraceReplay->replayFrame(mCurrentFrame); |
| |
| updatePerfCounters(); |
| |
| mTotalFrameCount++; |
| |
| if (mCurrentFrame == mEndFrame) |
| { |
| mTraceReplay->resetReplay(); |
| mCurrentFrame = mStartFrame; |
| } |
| else |
| { |
| mCurrentFrame++; |
| } |
| |
| // Always iterated for saving screenshots after reset |
| mCurrentIteration++; |
| } |
| |
| } // namespace angle |