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: Courtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com>
diff --git a/src/libANGLE/FrameCapture.cpp b/src/libANGLE/FrameCapture.cpp index dd0ea28..626a1f9 100644 --- a/src/libANGLE/FrameCapture.cpp +++ b/src/libANGLE/FrameCapture.cpp
@@ -604,33 +604,38 @@ 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, - 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, captureLabel, frameIndex, suffix); - - out << " LoadBinaryData(\"" << binaryDataFileName << "\", " - << static_cast<int>(binaryData.size()) << ");\n"; - - std::string dataFilepath = - GetCaptureFilePath(outDir, contextId, captureLabel, frameIndex, suffix); + std::string binaryDataFileName = GetBinaryDataFilePath(contextId, captureLabel); + std::string dataFilepath = outDir + binaryDataFileName; SaveFileHelper saveData(dataFilepath, std::ios::binary); 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, int contextId, const std::string &captureLabel, uint32_t frameIndex, const std::vector<CallCapture> &frameCalls, - const std::vector<CallCapture> &setupCalls) + const std::vector<CallCapture> &setupCalls, + std::vector<uint8_t> *binaryData) { DataCounters counters; @@ -655,21 +660,16 @@ out << "{\n"; std::stringstream setupCallStream; - std::vector<uint8_t> setupBinaryData; + + WriteLoadBinaryDataCall(setupCallStream, contextId, captureLabel); for (const CallCapture &call : setupCalls) { setupCallStream << " "; - WriteCppReplayForCall(call, &counters, setupCallStream, header, &setupBinaryData); + WriteCppReplayForCall(call, &counters, setupCallStream, header, binaryData); setupCallStream << ";\n"; } - if (!setupBinaryData.empty()) - { - SaveBinaryData(outDir, out, contextId, captureLabel, frameIndex, ".setup.angledata", - setupBinaryData); - } - out << setupCallStream.str(); out << "}\n"; @@ -680,20 +680,14 @@ out << "{\n"; std::stringstream callStream; - std::vector<uint8_t> binaryData; for (const CallCapture &call : frameCalls) { callStream << " "; - WriteCppReplayForCall(call, &counters, callStream, header, &binaryData); + WriteCppReplayForCall(call, &counters, callStream, header, binaryData); callStream << ";\n"; } - if (!binaryData.empty()) - { - SaveBinaryData(outDir, out, contextId, captureLabel, frameIndex, ".angledata", binaryData); - } - out << callStream.str(); out << "}\n"; @@ -779,7 +773,7 @@ } header << "\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 << "// Global state\n"; header << "\n"; @@ -890,16 +884,24 @@ source << " gBinaryDataDir = dataDir;\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 << " if (gBinaryData != nullptr)\n"; source << " {\n"; source << " delete [] gBinaryData;\n"; source << " }\n"; - source << " gBinaryData = new uint8_t[size];\n"; source << " char pathBuffer[1000] = {};\n"; source << " sprintf(pathBuffer, \"%s/%s\", gBinaryDataDir, fileName);\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 << " fclose(fp);\n"; source << "}\n"; @@ -2983,7 +2985,7 @@ if (!mFrameCalls.empty() && mFrameIndex >= mFrameStart) { WriteCppReplay(mOutDirectory, context->id(), mCaptureLabel, mFrameIndex, mFrameCalls, - mSetupCalls); + mSetupCalls, &mBinaryData); // Save the index files after the last frame. if (mFrameIndex == mFrameEnd) @@ -2991,6 +2993,12 @@ WriteCppReplayIndexFiles(mOutDirectory, context->id(), mCaptureLabel, mFrameStart, mFrameEnd, mReadBufferSize, mClientArraySizes, mHasResourceType); + + if (!mBinaryData.empty()) + { + SaveBinaryData(mOutDirectory, context->id(), mCaptureLabel, mBinaryData); + mBinaryData.clear(); + } } }
diff --git a/src/libANGLE/FrameCapture.h b/src/libANGLE/FrameCapture.h index 1f42eb0..5451280 100644 --- a/src/libANGLE/FrameCapture.h +++ b/src/libANGLE/FrameCapture.h
@@ -218,6 +218,10 @@ std::vector<CallCapture> mFrameCalls; 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; std::string mOutDirectory; std::string mCaptureLabel;