Commit d24752e6 by Jamie Madill Committed by Commit Bot

Capture/Replay: Write to single binary data file.

Previously the tool would save to a separate file for every frame and one additional file for the setup function. Frames without binary data would not get an "angledata" binary file. Using a single file has a few advantages: - makes it simpler to track the data dependencies in GN - should be easier to compress and decompress for speed up transfers - no need to wonder if we have frames with missing data files - less overhead reading from the HDD since the whole trace is buffered We might need to worry about extemely huge memory use cases. For now buffering the whole file into memory on startup is simple and fast. Also makes the binary data loader function more robust. Bug: angleproject:4484 Change-Id: Ia74fb0bc65200adf7a21c3143f98aa4da86457b1 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2104554 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 7c334c56
...@@ -604,33 +604,38 @@ struct SaveFileHelper ...@@ -604,33 +604,38 @@ struct SaveFileHelper
std::string filePath; std::string filePath;
}; };
std::string GetBinaryDataFilePath(int contextId, const std::string &captureLabel)
{
std::stringstream fnameStream;
fnameStream << FmtCapturePrefix(contextId, captureLabel) << ".angledata";
return fnameStream.str();
}
void SaveBinaryData(const std::string &outDir, void SaveBinaryData(const std::string &outDir,
std::ostream &out,
int contextId, int contextId,
const std::string &captureLabel, const std::string &captureLabel,
uint32_t frameIndex,
const char *suffix,
const std::vector<uint8_t> &binaryData) const std::vector<uint8_t> &binaryData)
{ {
std::string binaryDataFileName = std::string binaryDataFileName = GetBinaryDataFilePath(contextId, captureLabel);
GetCaptureFileName(contextId, captureLabel, frameIndex, suffix); std::string dataFilepath = outDir + binaryDataFileName;
out << " LoadBinaryData(\"" << binaryDataFileName << "\", "
<< static_cast<int>(binaryData.size()) << ");\n";
std::string dataFilepath =
GetCaptureFilePath(outDir, contextId, captureLabel, frameIndex, suffix);
SaveFileHelper saveData(dataFilepath, std::ios::binary); SaveFileHelper saveData(dataFilepath, std::ios::binary);
saveData.ofs.write(reinterpret_cast<const char *>(binaryData.data()), binaryData.size()); saveData.ofs.write(reinterpret_cast<const char *>(binaryData.data()), binaryData.size());
} }
void WriteLoadBinaryDataCall(std::ostream &out, int contextId, const std::string &captureLabel)
{
std::string binaryDataFileName = GetBinaryDataFilePath(contextId, captureLabel);
out << " LoadBinaryData(\"" << binaryDataFileName << "\");\n";
}
void WriteCppReplay(const std::string &outDir, void WriteCppReplay(const std::string &outDir,
int contextId, int contextId,
const std::string &captureLabel, const std::string &captureLabel,
uint32_t frameIndex, uint32_t frameIndex,
const std::vector<CallCapture> &frameCalls, const std::vector<CallCapture> &frameCalls,
const std::vector<CallCapture> &setupCalls) const std::vector<CallCapture> &setupCalls,
std::vector<uint8_t> *binaryData)
{ {
DataCounters counters; DataCounters counters;
...@@ -655,21 +660,16 @@ void WriteCppReplay(const std::string &outDir, ...@@ -655,21 +660,16 @@ void WriteCppReplay(const std::string &outDir,
out << "{\n"; out << "{\n";
std::stringstream setupCallStream; std::stringstream setupCallStream;
std::vector<uint8_t> setupBinaryData;
WriteLoadBinaryDataCall(setupCallStream, contextId, captureLabel);
for (const CallCapture &call : setupCalls) for (const CallCapture &call : setupCalls)
{ {
setupCallStream << " "; setupCallStream << " ";
WriteCppReplayForCall(call, &counters, setupCallStream, header, &setupBinaryData); WriteCppReplayForCall(call, &counters, setupCallStream, header, binaryData);
setupCallStream << ";\n"; setupCallStream << ";\n";
} }
if (!setupBinaryData.empty())
{
SaveBinaryData(outDir, out, contextId, captureLabel, frameIndex, ".setup.angledata",
setupBinaryData);
}
out << setupCallStream.str(); out << setupCallStream.str();
out << "}\n"; out << "}\n";
...@@ -680,20 +680,14 @@ void WriteCppReplay(const std::string &outDir, ...@@ -680,20 +680,14 @@ void WriteCppReplay(const std::string &outDir,
out << "{\n"; out << "{\n";
std::stringstream callStream; std::stringstream callStream;
std::vector<uint8_t> binaryData;
for (const CallCapture &call : frameCalls) for (const CallCapture &call : frameCalls)
{ {
callStream << " "; callStream << " ";
WriteCppReplayForCall(call, &counters, callStream, header, &binaryData); WriteCppReplayForCall(call, &counters, callStream, header, binaryData);
callStream << ";\n"; callStream << ";\n";
} }
if (!binaryData.empty())
{
SaveBinaryData(outDir, out, contextId, captureLabel, frameIndex, ".angledata", binaryData);
}
out << callStream.str(); out << callStream.str();
out << "}\n"; out << "}\n";
...@@ -779,7 +773,7 @@ void WriteCppReplayIndexFiles(const std::string &outDir, ...@@ -779,7 +773,7 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
} }
header << "\n"; header << "\n";
header << "void SetBinaryDataDir(const char *dataDir);\n"; header << "void SetBinaryDataDir(const char *dataDir);\n";
header << "void LoadBinaryData(const char *fileName, size_t size);\n"; header << "void LoadBinaryData(const char *fileName);\n";
header << "\n"; header << "\n";
header << "// Global state\n"; header << "// Global state\n";
header << "\n"; header << "\n";
...@@ -890,16 +884,24 @@ void WriteCppReplayIndexFiles(const std::string &outDir, ...@@ -890,16 +884,24 @@ void WriteCppReplayIndexFiles(const std::string &outDir,
source << " gBinaryDataDir = dataDir;\n"; source << " gBinaryDataDir = dataDir;\n";
source << "}\n"; source << "}\n";
source << "\n"; source << "\n";
source << "void LoadBinaryData(const char *fileName, size_t size)\n"; source << "void LoadBinaryData(const char *fileName)\n";
source << "{\n"; source << "{\n";
source << " if (gBinaryData != nullptr)\n"; source << " if (gBinaryData != nullptr)\n";
source << " {\n"; source << " {\n";
source << " delete [] gBinaryData;\n"; source << " delete [] gBinaryData;\n";
source << " }\n"; source << " }\n";
source << " gBinaryData = new uint8_t[size];\n";
source << " char pathBuffer[1000] = {};\n"; source << " char pathBuffer[1000] = {};\n";
source << " sprintf(pathBuffer, \"%s/%s\", gBinaryDataDir, fileName);\n"; source << " sprintf(pathBuffer, \"%s/%s\", gBinaryDataDir, fileName);\n";
source << " FILE *fp = fopen(pathBuffer, \"rb\");\n"; source << " FILE *fp = fopen(pathBuffer, \"rb\");\n";
source << " if (fp == 0)\n";
source << " {\n";
source << " fprintf(stderr, \"Error loading binary data file: %s\\n\", fileName);\n";
source << " exit(1);\n";
source << " }\n";
source << " fseek(fp, 0, SEEK_END);\n";
source << " long size = ftell(fp);\n";
source << " fseek(fp, 0, SEEK_SET);\n";
source << " gBinaryData = new uint8_t[size];\n";
source << " (void)fread(gBinaryData, 1, size, fp);\n"; source << " (void)fread(gBinaryData, 1, size, fp);\n";
source << " fclose(fp);\n"; source << " fclose(fp);\n";
source << "}\n"; source << "}\n";
...@@ -2983,7 +2985,7 @@ void FrameCapture::onEndFrame(const gl::Context *context) ...@@ -2983,7 +2985,7 @@ void FrameCapture::onEndFrame(const gl::Context *context)
if (!mFrameCalls.empty() && mFrameIndex >= mFrameStart) if (!mFrameCalls.empty() && mFrameIndex >= mFrameStart)
{ {
WriteCppReplay(mOutDirectory, context->id(), mCaptureLabel, mFrameIndex, mFrameCalls, WriteCppReplay(mOutDirectory, context->id(), mCaptureLabel, mFrameIndex, mFrameCalls,
mSetupCalls); mSetupCalls, &mBinaryData);
// Save the index files after the last frame. // Save the index files after the last frame.
if (mFrameIndex == mFrameEnd) if (mFrameIndex == mFrameEnd)
...@@ -2991,6 +2993,12 @@ void FrameCapture::onEndFrame(const gl::Context *context) ...@@ -2991,6 +2993,12 @@ void FrameCapture::onEndFrame(const gl::Context *context)
WriteCppReplayIndexFiles(mOutDirectory, context->id(), mCaptureLabel, mFrameStart, WriteCppReplayIndexFiles(mOutDirectory, context->id(), mCaptureLabel, mFrameStart,
mFrameEnd, mReadBufferSize, mClientArraySizes, mFrameEnd, mReadBufferSize, mClientArraySizes,
mHasResourceType); mHasResourceType);
if (!mBinaryData.empty())
{
SaveBinaryData(mOutDirectory, context->id(), mCaptureLabel, mBinaryData);
mBinaryData.clear();
}
} }
} }
......
...@@ -218,6 +218,10 @@ class FrameCapture final : angle::NonCopyable ...@@ -218,6 +218,10 @@ class FrameCapture final : angle::NonCopyable
std::vector<CallCapture> mFrameCalls; std::vector<CallCapture> mFrameCalls;
std::vector<CallCapture> mTearDownCalls; std::vector<CallCapture> mTearDownCalls;
// We save one large buffer of binary data for the whole CPP replay.
// This simplifies a lot of file management.
std::vector<uint8_t> mBinaryData;
bool mEnabled; bool mEnabled;
std::string mOutDirectory; std::string mOutDirectory;
std::string mCaptureLabel; std::string mCaptureLabel;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment