| // | |
| // 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 "common/unsafe_buffers.h" | |
| #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 ANGLE_UNSAFE_TODO(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] = {}; | |
| ANGLE_UNSAFE_TODO(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 (ANGLE_UNSAFE_TODO(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 |