зеркало из https://github.com/AvaloniaUI/angle.git
Add flag to label captures
Add an optional parameter (ANGLE_CAPTURE_LABEL) to ANGLE frame capture that tags files and functions uniquely, allowing multiple frame captures to be replayed by a test harness. Example: ANGLE_CAPTURE_LABEL=foo Results in filenames like this: foo_capture_context1.cpp foo_capture_context1.h foo_capture_context1_files.txt foo_capture_context1_frame000.angledata foo_capture_context1_frame000.cpp foo_capture_context1_frame001.angledata foo_capture_context1_frame001.cpp ... Functions wrapped in namespaces like this: namespace foo { void ReplayContext1Frame0(); void ReplayContext1Frame1(); } For use like this: foo::SetupContext1Replay(); for (...) { foo::ReplayContext1Frame(i); } Bug: angleproject:3630 Change-Id: Ibe27dc4d40a36606ee40678a9e4d43b5a4baf976 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1949603 Commit-Queue: Cody Northrop <cnorthrop@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
554b453c95
Коммит
1d77542f56
|
@ -41,6 +41,36 @@ Some simple environment variables control frame capture:
|
|||
* `ANGLE_CAPTURE_FRAME_END=<n>`:
|
||||
* By default ANGLE will capture the first ten frames. This variable can override the default.
|
||||
* Example: `ANGLE_CAPTURE_FRAME_END=4`. Default is `10`.
|
||||
* `ANGLE_CAPTURE_LABEL=<label>`:
|
||||
* When specified, files and functions will be labeled uniquely.
|
||||
* Example: `ANGLE_CAPTURE_LABEL=foo`
|
||||
* Results in filenames like this:
|
||||
```
|
||||
foo_capture_context1.cpp
|
||||
foo_capture_context1.h
|
||||
foo_capture_context1_files.txt
|
||||
foo_capture_context1_frame000.angledata
|
||||
foo_capture_context1_frame000.cpp
|
||||
foo_capture_context1_frame001.angledata
|
||||
foo_capture_context1_frame001.cpp
|
||||
...
|
||||
```
|
||||
* Functions wrapped in namespaces like this:
|
||||
```
|
||||
namespace foo
|
||||
{
|
||||
void ReplayContext1Frame0();
|
||||
void ReplayContext1Frame1();
|
||||
}
|
||||
```
|
||||
* For use like this:
|
||||
```
|
||||
foo::SetupContext1Replay();
|
||||
for (...)
|
||||
{
|
||||
foo::ReplayContext1Frame(i);
|
||||
}
|
||||
```
|
||||
|
||||
A good way to test out the capture is to use environment variables in conjunction with the sample
|
||||
template. For example:
|
||||
|
@ -105,6 +135,7 @@ as the GLES driver for your application.
|
|||
$ adb shell setprop debug.angle.capture.enabled 0
|
||||
$ adb shell setprop debug.angle.capture.out_dir foo
|
||||
$ adb shell setprop debug.angle.capture.frame_start 0
|
||||
$ adb shell setprop debug.angle.capture.label bar
|
||||
```
|
||||
|
||||
3. Run the application, then pull the files to the capture_replay directory
|
||||
|
|
|
@ -40,6 +40,7 @@ constexpr char kEnabledVarName[] = "ANGLE_CAPTURE_ENABLED";
|
|||
constexpr char kOutDirectoryVarName[] = "ANGLE_CAPTURE_OUT_DIR";
|
||||
constexpr char kFrameStartVarName[] = "ANGLE_CAPTURE_FRAME_START";
|
||||
constexpr char kFrameEndVarName[] = "ANGLE_CAPTURE_FRAME_END";
|
||||
constexpr char kCaptureLabel[] = "ANGLE_CAPTURE_LABEL";
|
||||
|
||||
#if defined(ANGLE_PLATFORM_ANDROID)
|
||||
|
||||
|
@ -47,6 +48,7 @@ constexpr char kAndroidCaptureEnabled[] = "debug.angle.capture.enabled";
|
|||
constexpr char kAndroidOutDir[] = "debug.angle.capture.out_dir";
|
||||
constexpr char kAndroidFrameStart[] = "debug.angle.capture.frame_start";
|
||||
constexpr char kAndroidFrameEnd[] = "debug.angle.capture.frame_end";
|
||||
constexpr char kAndroidCaptureLabel[] = "debug.angle.capture.label";
|
||||
|
||||
constexpr int kStreamSize = 64;
|
||||
|
||||
|
@ -102,6 +104,13 @@ void PrimeAndroidEnvironmentVariables()
|
|||
INFO() << "Frame capture read " << frameEnd << " from " << kAndroidFrameEnd;
|
||||
setenv(kFrameEndVarName, frameEnd.c_str(), 1);
|
||||
}
|
||||
|
||||
std::string captureLabel = AndroidGetEnvFromProp(kAndroidCaptureLabel);
|
||||
if (!captureLabel.empty())
|
||||
{
|
||||
INFO() << "Capture label read " << captureLabel << " from " << kAndroidCaptureLabel;
|
||||
setenv(kCaptureLabel, captureLabel.c_str(), 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -148,13 +157,24 @@ std::string GetDefaultOutDirectory()
|
|||
|
||||
struct FmtCapturePrefix
|
||||
{
|
||||
FmtCapturePrefix(int contextIdIn) : contextId(contextIdIn) {}
|
||||
FmtCapturePrefix(int contextIdIn, const std::string &captureLabelIn)
|
||||
: contextId(contextIdIn), captureLabel(captureLabelIn)
|
||||
{}
|
||||
int contextId;
|
||||
const std::string &captureLabel;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const FmtCapturePrefix &fmt)
|
||||
{
|
||||
os << "angle_capture_context" << fmt.contextId;
|
||||
if (fmt.captureLabel.empty())
|
||||
{
|
||||
os << "angle";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << fmt.captureLabel;
|
||||
}
|
||||
os << "_capture_context" << fmt.contextId;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
@ -173,20 +193,24 @@ std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt)
|
|||
return os;
|
||||
}
|
||||
|
||||
std::string GetCaptureFileName(int contextId, uint32_t frameIndex, const char *suffix)
|
||||
std::string GetCaptureFileName(int contextId,
|
||||
const std::string &captureLabel,
|
||||
uint32_t frameIndex,
|
||||
const char *suffix)
|
||||
{
|
||||
std::stringstream fnameStream;
|
||||
fnameStream << FmtCapturePrefix(contextId) << "_frame" << std::setfill('0') << std::setw(3)
|
||||
<< frameIndex << suffix;
|
||||
fnameStream << FmtCapturePrefix(contextId, captureLabel) << "_frame" << std::setfill('0')
|
||||
<< std::setw(3) << frameIndex << suffix;
|
||||
return fnameStream.str();
|
||||
}
|
||||
|
||||
std::string GetCaptureFilePath(const std::string &outDir,
|
||||
int contextId,
|
||||
const std::string &captureLabel,
|
||||
uint32_t frameIndex,
|
||||
const char *suffix)
|
||||
{
|
||||
return outDir + GetCaptureFileName(contextId, frameIndex, suffix);
|
||||
return outDir + GetCaptureFileName(contextId, captureLabel, frameIndex, suffix);
|
||||
}
|
||||
|
||||
void WriteParamStaticVarName(const CallCapture &call,
|
||||
|
@ -515,16 +539,19 @@ struct SaveFileHelper
|
|||
void SaveBinaryData(const std::string &outDir,
|
||||
std::ostream &out,
|
||||
int contextId,
|
||||
const std::string &captureLabel,
|
||||
uint32_t frameIndex,
|
||||
const char *suffix,
|
||||
const std::vector<uint8_t> &binaryData)
|
||||
{
|
||||
std::string binaryDataFileName = GetCaptureFileName(contextId, frameIndex, suffix);
|
||||
std::string binaryDataFileName =
|
||||
GetCaptureFileName(contextId, captureLabel, frameIndex, suffix);
|
||||
|
||||
out << " LoadBinaryData(\"" << binaryDataFileName << "\", "
|
||||
<< static_cast<int>(binaryData.size()) << ");\n";
|
||||
|
||||
std::string dataFilepath = GetCaptureFilePath(outDir, contextId, frameIndex, suffix);
|
||||
std::string dataFilepath =
|
||||
GetCaptureFilePath(outDir, contextId, captureLabel, frameIndex, suffix);
|
||||
|
||||
SaveFileHelper saveData(dataFilepath, std::ios::binary);
|
||||
saveData.ofs.write(reinterpret_cast<const char *>(binaryData.data()), binaryData.size());
|
||||
|
@ -532,6 +559,7 @@ void SaveBinaryData(const std::string &outDir,
|
|||
|
||||
void WriteCppReplay(const std::string &outDir,
|
||||
int contextId,
|
||||
const std::string &captureLabel,
|
||||
uint32_t frameIndex,
|
||||
const std::vector<CallCapture> &frameCalls,
|
||||
const std::vector<CallCapture> &setupCalls)
|
||||
|
@ -541,12 +569,18 @@ void WriteCppReplay(const std::string &outDir,
|
|||
std::stringstream out;
|
||||
std::stringstream header;
|
||||
|
||||
header << "#include \"" << FmtCapturePrefix(contextId) << ".h\"\n";
|
||||
header << "#include \"" << FmtCapturePrefix(contextId, captureLabel) << ".h\"\n";
|
||||
header << "";
|
||||
header << "\n";
|
||||
header << "namespace\n";
|
||||
header << "{\n";
|
||||
|
||||
if (!captureLabel.empty())
|
||||
{
|
||||
out << "namespace " << captureLabel << "\n";
|
||||
out << "{\n";
|
||||
}
|
||||
|
||||
if (frameIndex == 0 || !setupCalls.empty())
|
||||
{
|
||||
out << "void SetupContext" << Str(contextId) << "Replay()\n";
|
||||
|
@ -564,7 +598,8 @@ void WriteCppReplay(const std::string &outDir,
|
|||
|
||||
if (!setupBinaryData.empty())
|
||||
{
|
||||
SaveBinaryData(outDir, out, contextId, frameIndex, ".setup.angledata", setupBinaryData);
|
||||
SaveBinaryData(outDir, out, contextId, captureLabel, frameIndex, ".setup.angledata",
|
||||
setupBinaryData);
|
||||
}
|
||||
|
||||
out << setupCallStream.str();
|
||||
|
@ -588,19 +623,25 @@ void WriteCppReplay(const std::string &outDir,
|
|||
|
||||
if (!binaryData.empty())
|
||||
{
|
||||
SaveBinaryData(outDir, out, contextId, frameIndex, ".angledata", binaryData);
|
||||
SaveBinaryData(outDir, out, contextId, captureLabel, frameIndex, ".angledata", binaryData);
|
||||
}
|
||||
|
||||
out << callStream.str();
|
||||
out << "}\n";
|
||||
|
||||
if (!captureLabel.empty())
|
||||
{
|
||||
out << "} // namespace " << captureLabel << "\n";
|
||||
}
|
||||
|
||||
header << "} // namespace\n";
|
||||
|
||||
{
|
||||
std::string outString = out.str();
|
||||
std::string headerString = header.str();
|
||||
|
||||
std::string cppFilePath = GetCaptureFilePath(outDir, contextId, frameIndex, ".cpp");
|
||||
std::string cppFilePath =
|
||||
GetCaptureFilePath(outDir, contextId, captureLabel, frameIndex, ".cpp");
|
||||
|
||||
SaveFileHelper saveCpp(cppFilePath);
|
||||
saveCpp << headerString << "\n" << outString;
|
||||
|
@ -609,6 +650,7 @@ void WriteCppReplay(const std::string &outDir,
|
|||
|
||||
void WriteCppReplayIndexFiles(const std::string &outDir,
|
||||
int contextId,
|
||||
const std::string &captureLabel,
|
||||
uint32_t frameStart,
|
||||
uint32_t frameEnd,
|
||||
size_t readBufferSize,
|
||||
|
@ -631,6 +673,13 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
|
|||
header << "\n";
|
||||
header << "// Replay functions\n";
|
||||
header << "\n";
|
||||
header << "using ResourceMap = std::unordered_map<GLuint, GLuint>;\n";
|
||||
header << "\n";
|
||||
if (!captureLabel.empty())
|
||||
{
|
||||
header << "namespace " << captureLabel << "\n";
|
||||
header << "{\n";
|
||||
}
|
||||
header << "constexpr uint32_t kReplayFrameStart = " << frameStart << ";\n";
|
||||
header << "constexpr uint32_t kReplayFrameEnd = " << frameEnd << ";\n";
|
||||
header << "\n";
|
||||
|
@ -647,11 +696,9 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
|
|||
header << "\n";
|
||||
header << "// Global state\n";
|
||||
header << "\n";
|
||||
header << "using ResourceMap = std::unordered_map<GLuint, GLuint>;\n";
|
||||
header << "\n";
|
||||
header << "extern uint8_t *gBinaryData;\n";
|
||||
|
||||
source << "#include \"" << FmtCapturePrefix(contextId) << ".h\"\n";
|
||||
source << "#include \"" << FmtCapturePrefix(contextId, captureLabel) << ".h\"\n";
|
||||
source << "\n";
|
||||
source << "namespace\n";
|
||||
source << "{\n";
|
||||
|
@ -659,13 +706,22 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
|
|||
"readBufferOffset)\n";
|
||||
source << "{\n";
|
||||
source << " GLuint returnedID;\n";
|
||||
source << " memcpy(&returnedID, &gReadBuffer[readBufferOffset], sizeof(GLuint));\n";
|
||||
std::string captureNamespace = !captureLabel.empty() ? captureLabel + "::" : "";
|
||||
source << " memcpy(&returnedID, &" << captureNamespace
|
||||
<< "gReadBuffer[readBufferOffset], sizeof(GLuint));\n ";
|
||||
source << " (*resourceMap)[id] = returnedID;\n";
|
||||
source << "}\n";
|
||||
source << "\n";
|
||||
source << "const char *gBinaryDataDir = \".\";\n";
|
||||
source << "} // namespace\n";
|
||||
source << "\n";
|
||||
|
||||
if (!captureLabel.empty())
|
||||
{
|
||||
source << "namespace " << captureLabel << "\n";
|
||||
source << "{\n";
|
||||
}
|
||||
|
||||
source << "uint8_t *gBinaryData = nullptr;\n";
|
||||
|
||||
if (readBufferSize > 0)
|
||||
|
@ -754,11 +810,17 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
|
|||
source << "}\n";
|
||||
}
|
||||
|
||||
if (!captureLabel.empty())
|
||||
{
|
||||
header << "} // namespace " << captureLabel << "\n";
|
||||
source << "} // namespace " << captureLabel << "\n";
|
||||
}
|
||||
|
||||
{
|
||||
std::string headerContents = header.str();
|
||||
|
||||
std::stringstream headerPathStream;
|
||||
headerPathStream << outDir << FmtCapturePrefix(contextId) << ".h";
|
||||
headerPathStream << outDir << FmtCapturePrefix(contextId, captureLabel) << ".h";
|
||||
std::string headerPath = headerPathStream.str();
|
||||
|
||||
SaveFileHelper saveHeader(headerPath);
|
||||
|
@ -769,7 +831,7 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
|
|||
std::string sourceContents = source.str();
|
||||
|
||||
std::stringstream sourcePathStream;
|
||||
sourcePathStream << outDir << FmtCapturePrefix(contextId) << ".cpp";
|
||||
sourcePathStream << outDir << FmtCapturePrefix(contextId, captureLabel) << ".cpp";
|
||||
std::string sourcePath = sourcePathStream.str();
|
||||
|
||||
SaveFileHelper saveSource(sourcePath);
|
||||
|
@ -778,13 +840,13 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
|
|||
|
||||
{
|
||||
std::stringstream indexPathStream;
|
||||
indexPathStream << outDir << FmtCapturePrefix(contextId) << "_files.txt";
|
||||
indexPathStream << outDir << FmtCapturePrefix(contextId, captureLabel) << "_files.txt";
|
||||
std::string indexPath = indexPathStream.str();
|
||||
|
||||
SaveFileHelper saveIndex(indexPath);
|
||||
for (uint32_t frameIndex = frameStart; frameIndex <= frameEnd; ++frameIndex)
|
||||
{
|
||||
saveIndex << GetCaptureFileName(contextId, frameIndex, ".cpp") << "\n";
|
||||
saveIndex << GetCaptureFileName(contextId, captureLabel, frameIndex, ".cpp") << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1865,6 +1927,13 @@ FrameCapture::FrameCapture()
|
|||
{
|
||||
mFrameEnd = atoi(endFromEnv.c_str());
|
||||
}
|
||||
|
||||
std::string labelFromEnv = angle::GetEnvironmentVar(kCaptureLabel);
|
||||
if (!labelFromEnv.empty())
|
||||
{
|
||||
// Optional label to provide unique file names and namespaces
|
||||
mCaptureLabel = labelFromEnv;
|
||||
}
|
||||
}
|
||||
|
||||
FrameCapture::~FrameCapture() = default;
|
||||
|
@ -2032,13 +2101,15 @@ void FrameCapture::onEndFrame(const gl::Context *context)
|
|||
// Note that we currently capture before the start frame to collect shader and program sources.
|
||||
if (!mFrameCalls.empty() && mFrameIndex >= mFrameStart)
|
||||
{
|
||||
WriteCppReplay(mOutDirectory, context->id(), mFrameIndex, mFrameCalls, mSetupCalls);
|
||||
WriteCppReplay(mOutDirectory, context->id(), mCaptureLabel, mFrameIndex, mFrameCalls,
|
||||
mSetupCalls);
|
||||
|
||||
// Save the index files after the last frame.
|
||||
if (mFrameIndex == mFrameEnd)
|
||||
{
|
||||
WriteCppReplayIndexFiles(mOutDirectory, context->id(), mFrameStart, mFrameEnd,
|
||||
mReadBufferSize, mClientArraySizes, mHasResourceType);
|
||||
WriteCppReplayIndexFiles(mOutDirectory, context->id(), mCaptureLabel, mFrameStart,
|
||||
mFrameEnd, mReadBufferSize, mClientArraySizes,
|
||||
mHasResourceType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -201,6 +201,7 @@ class FrameCapture final : angle::NonCopyable
|
|||
|
||||
bool mEnabled;
|
||||
std::string mOutDirectory;
|
||||
std::string mCaptureLabel;
|
||||
gl::AttribArray<int> mClientVertexArrayMap;
|
||||
uint32_t mFrameIndex;
|
||||
uint32_t mFrameStart;
|
||||
|
|
Загрузка…
Ссылка в новой задаче