Commit c15d1e2d by Jamie Madill Committed by Commit Bot

Capture/Replay: Generalize function splitting.

We can use this to split up the replay function as well as very large setup functions. This will let us replay the gfxbench offscreen benchmarks directly. Bug: angleproject:5133 Change-Id: Ic24f25f2ab6821e68356a28a698cb84301e99be2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2446896 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 34445b29
...@@ -223,6 +223,13 @@ std::ostream &operator<<(std::ostream &os, const FmtCapturePrefix &fmt) ...@@ -223,6 +223,13 @@ std::ostream &operator<<(std::ostream &os, const FmtCapturePrefix &fmt)
return os; return os;
} }
enum class ReplayFunc
{
Replay,
Setup,
Reset,
};
struct FmtReplayFunction struct FmtReplayFunction
{ {
FmtReplayFunction(gl::ContextID contextIdIn, uint32_t frameIndexIn) FmtReplayFunction(gl::ContextID contextIdIn, uint32_t frameIndexIn)
...@@ -238,6 +245,81 @@ std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt) ...@@ -238,6 +245,81 @@ std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt)
return os; return os;
} }
constexpr uint32_t kNoPartId = std::numeric_limits<uint32_t>::max();
struct FmtSetupFunction
{
FmtSetupFunction(gl::ContextID contextIdIn, uint32_t partIdIn)
: contextId(contextIdIn), partId(partIdIn)
{}
gl::ContextID contextId;
uint32_t partId;
};
std::ostream &operator<<(std::ostream &os, const FmtSetupFunction &fmt)
{
os << "SetupContext" << Str(static_cast<int>(fmt.contextId)) << "Replay";
if (fmt.partId != kNoPartId)
{
os << "Part" << fmt.partId;
}
os << "()";
return os;
}
struct FmtResetFunction
{
FmtResetFunction(gl::ContextID contextIdIn) : contextId(contextIdIn) {}
gl::ContextID contextId;
};
std::ostream &operator<<(std::ostream &os, const FmtResetFunction &fmt)
{
os << "ResetContext" << Str(static_cast<int>(fmt.contextId)) << "Replay()";
return os;
}
struct FmtFunction
{
FmtFunction(ReplayFunc funcTypeIn,
gl::ContextID contextIdIn,
uint32_t frameIndexIn,
uint32_t partIdIn)
: funcType(funcTypeIn), contextId(contextIdIn), frameIndex(frameIndexIn), partId(partIdIn)
{}
ReplayFunc funcType;
gl::ContextID contextId;
uint32_t frameIndex;
uint32_t partId;
};
std::ostream &operator<<(std::ostream &os, const FmtFunction &fmt)
{
switch (fmt.funcType)
{
case ReplayFunc::Replay:
os << FmtReplayFunction(fmt.contextId, fmt.frameIndex);
break;
case ReplayFunc::Setup:
os << FmtSetupFunction(fmt.contextId, fmt.partId);
break;
case ReplayFunc::Reset:
os << FmtResetFunction(fmt.contextId);
break;
default:
UNREACHABLE();
break;
}
return os;
}
struct FmtGetSerializedContextStateDataFunction struct FmtGetSerializedContextStateDataFunction
{ {
FmtGetSerializedContextStateDataFunction(gl::ContextID contextIdIn, uint32_t frameIndexIn) FmtGetSerializedContextStateDataFunction(gl::ContextID contextIdIn, uint32_t frameIndexIn)
...@@ -901,6 +983,68 @@ void MaybeResetResources(std::stringstream &out, ...@@ -901,6 +983,68 @@ void MaybeResetResources(std::stringstream &out,
} }
} }
void WriteCppReplayFunctionWithParts(const gl::Context *context,
ReplayFunc replayFunc,
DataTracker *dataTracker,
uint32_t frameIndex,
std::vector<uint8_t> *binaryData,
const std::vector<CallCapture> &calls,
std::stringstream &header,
std::stringstream &callStream,
std::stringstream &out)
{
std::stringstream callStreamParts;
int callCount = 0;
int partCount = 0;
// Setup can get quite large. If over a certain size, break up the function to avoid
// overflowing the stack
if (calls.size() > kFunctionSizeLimit)
{
callStreamParts << "void "
<< FmtFunction(replayFunc, context->id(), frameIndex, ++partCount) << "\n";
callStreamParts << "{\n";
}
for (const CallCapture &call : calls)
{
callStreamParts << " ";
WriteCppReplayForCall(call, dataTracker, callStreamParts, header, binaryData);
callStreamParts << ";\n";
if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0)
{
callStreamParts << "}\n";
callStreamParts << "\n";
callStreamParts << "void "
<< FmtFunction(replayFunc, context->id(), frameIndex, ++partCount)
<< "\n";
callStreamParts << "{\n";
}
}
if (partCount > 0)
{
callStreamParts << "}\n";
callStreamParts << "\n";
// Write out the parts
out << callStreamParts.str();
// Write out the calls to the parts
for (int i = 1; i <= partCount; i++)
{
callStream << " " << FmtFunction(replayFunc, context->id(), frameIndex, i) << ";\n";
}
}
else
{
// If we didn't chunk it up, write all the calls directly to SetupContext
callStream << callStreamParts.str();
}
}
void WriteCppReplay(bool compression, void WriteCppReplay(bool compression,
const std::string &outDir, const std::string &outDir,
const gl::Context *context, const gl::Context *context,
...@@ -935,62 +1079,13 @@ void WriteCppReplay(bool compression, ...@@ -935,62 +1079,13 @@ void WriteCppReplay(bool compression,
if (frameIndex == frameStart) if (frameIndex == frameStart)
{ {
std::stringstream setupCallStream; std::stringstream setupCallStream;
std::stringstream setupCallStreamParts;
setupCallStream << "void SetupContext" << Str(static_cast<int>(context->id())) setupCallStream << "void " << FmtSetupFunction(context->id(), kNoPartId) << "\n";
<< "Replay()\n";
setupCallStream << "{\n"; setupCallStream << "{\n";
WriteLoadBinaryDataCall(compression, setupCallStream, context->id(), captureLabel); WriteLoadBinaryDataCall(compression, setupCallStream, context->id(), captureLabel);
WriteCppReplayFunctionWithParts(context, ReplayFunc::Setup, &dataTracker, frameIndex,
int callCount = 0; binaryData, setupCalls, header, setupCallStream, out);
int partCount = 0;
// Setup can get quite large. If over a certain size, break up the function to avoid
// overflowing the stack
if (setupCalls.size() > kFunctionSizeLimit)
{
setupCallStreamParts << "void SetupContext" << Str(static_cast<int>(context->id()))
<< "ReplayPart" << ++partCount << "()\n";
setupCallStreamParts << "{\n";
}
for (const CallCapture &call : setupCalls)
{
setupCallStreamParts << " ";
WriteCppReplayForCall(call, &dataTracker, setupCallStreamParts, header, binaryData);
setupCallStreamParts << ";\n";
if (partCount > 0 && ++callCount % kFunctionSizeLimit == 0)
{
setupCallStreamParts << "}\n";
setupCallStreamParts << "\n";
setupCallStreamParts << "void SetupContext" << Str(static_cast<int>(context->id()))
<< "ReplayPart" << ++partCount << "()\n";
setupCallStreamParts << "{\n";
}
}
if (partCount > 0)
{
setupCallStreamParts << "}\n";
setupCallStreamParts << "\n";
// Write out the parts
out << setupCallStreamParts.str();
// Write out the calls to the parts
for (int i = 1; i <= partCount; i++)
{
setupCallStream << " SetupContext" << Str(static_cast<int>(context->id()))
<< "ReplayPart" << i << "();\n";
}
}
else
{
// If we didn't chunk it up, write all the calls directly to SetupContext
setupCallStream << setupCallStreamParts.str();
}
out << setupCallStream.str(); out << setupCallStream.str();
out << "}\n"; out << "}\n";
...@@ -1000,7 +1095,7 @@ void WriteCppReplay(bool compression, ...@@ -1000,7 +1095,7 @@ void WriteCppReplay(bool compression,
if (frameIndex == frameEnd) if (frameIndex == frameEnd)
{ {
// Emit code to reset back to starting state // Emit code to reset back to starting state
out << "void ResetContext" << Str(static_cast<int>(context->id())) << "Replay()\n"; out << "void " << FmtResetFunction(context->id()) << "\n";
out << "{\n"; out << "{\n";
std::stringstream restoreCallStream; std::stringstream restoreCallStream;
......
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