Commit e5c18475 by Manh Nguyen Committed by Commit Bot

Multi-frames serialization + comparision for capture replay test

Changes how context states are serialized during capture run. Now, context states are serialized after each frame until the end frame is reached, or context is destroyed. Adds an api to the trace files to query serialization results of multiple frames. Makes change to CaptureReplayTest to serialize multiple frames then compares the serialization results with the ones retrieved from said api. Adds to capture replay the ability to produce working, compilable trace files even when end frame is not reached. Adds to the generated trace files config information and makes CaptureReplayTest utilize said config information to reproduce the exact environment of the captured application. Bug: angleproject:4817 Change-Id: Ie3d487af2bacf349dc3ff6f6b1b5f89e1169dc84 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2282885 Commit-Queue: Manh Nguyen <nguyenmh@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 92ffd40e
...@@ -531,7 +531,7 @@ void Context::initialize() ...@@ -531,7 +531,7 @@ void Context::initialize()
egl::Error Context::onDestroy(const egl::Display *display) egl::Error Context::onDestroy(const egl::Display *display)
{ {
// Dump frame capture if enabled. // Dump frame capture if enabled.
mFrameCapture->onEndFrame(this); mFrameCapture->onDestroyContext(this);
if (mGLES1Renderer) if (mGLES1Renderer)
{ {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "common/mathutil.h" #include "common/mathutil.h"
#include "common/system_utils.h" #include "common/system_utils.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Fence.h" #include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
...@@ -214,6 +215,22 @@ std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt) ...@@ -214,6 +215,22 @@ std::ostream &operator<<(std::ostream &os, const FmtReplayFunction &fmt)
return os; return os;
} }
struct FmtGetSerializedContextStateDataFunction
{
FmtGetSerializedContextStateDataFunction(gl::ContextID contextIdIn, uint32_t frameIndexIn)
: contextId(contextIdIn), frameIndex(frameIndexIn)
{}
gl::ContextID contextId;
uint32_t frameIndex;
};
std::ostream &operator<<(std::ostream &os, const FmtGetSerializedContextStateDataFunction &fmt)
{
os << "GetSerializedContext" << static_cast<int>(fmt.contextId) << "StateFrame"
<< fmt.frameIndex << "Data()";
return os;
}
std::string GetCaptureFileName(gl::ContextID contextId, std::string GetCaptureFileName(gl::ContextID contextId,
const std::string &captureLabel, const std::string &captureLabel,
uint32_t frameIndex, uint32_t frameIndex,
...@@ -806,21 +823,23 @@ void MaybeResetResources(std::stringstream &out, ...@@ -806,21 +823,23 @@ void MaybeResetResources(std::stringstream &out,
void WriteCppReplay(bool compression, void WriteCppReplay(bool compression,
const std::string &outDir, const std::string &outDir,
gl::ContextID contextId, const gl::Context *context,
const std::string &captureLabel, const std::string &captureLabel,
uint32_t frameIndex, uint32_t frameIndex,
uint32_t frameStart,
uint32_t frameEnd, uint32_t frameEnd,
const std::vector<CallCapture> &frameCalls, const std::vector<CallCapture> &frameCalls,
const std::vector<CallCapture> &setupCalls, const std::vector<CallCapture> &setupCalls,
ResourceTracker *resourceTracker, ResourceTracker *resourceTracker,
std::vector<uint8_t> *binaryData) std::vector<uint8_t> *binaryData,
bool serializeStateEnabled)
{ {
DataCounters counters; DataCounters counters;
std::stringstream out; std::stringstream out;
std::stringstream header; std::stringstream header;
header << "#include \"" << FmtCapturePrefix(contextId, captureLabel) << ".h\"\n"; header << "#include \"" << FmtCapturePrefix(context->id(), captureLabel) << ".h\"\n";
header << ""; header << "";
header << "\n"; header << "\n";
header << "namespace\n"; header << "namespace\n";
...@@ -832,14 +851,14 @@ void WriteCppReplay(bool compression, ...@@ -832,14 +851,14 @@ void WriteCppReplay(bool compression,
out << "{\n"; out << "{\n";
} }
if (frameIndex == 0 || !setupCalls.empty()) if (frameIndex == frameStart)
{ {
out << "void SetupContext" << Str(static_cast<int>(contextId)) << "Replay()\n"; out << "void SetupContext" << Str(static_cast<int>(context->id())) << "Replay()\n";
out << "{\n"; out << "{\n";
std::stringstream setupCallStream; std::stringstream setupCallStream;
WriteLoadBinaryDataCall(compression, setupCallStream, contextId, captureLabel); WriteLoadBinaryDataCall(compression, setupCallStream, context->id(), captureLabel);
for (const CallCapture &call : setupCalls) for (const CallCapture &call : setupCalls)
{ {
...@@ -857,7 +876,7 @@ void WriteCppReplay(bool compression, ...@@ -857,7 +876,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>(contextId)) << "Replay()\n"; out << "void ResetContext" << Str(static_cast<int>(context->id())) << "Replay()\n";
out << "{\n"; out << "{\n";
std::stringstream restoreCallStream; std::stringstream restoreCallStream;
...@@ -876,7 +895,7 @@ void WriteCppReplay(bool compression, ...@@ -876,7 +895,7 @@ void WriteCppReplay(bool compression,
out << "\n"; out << "\n";
} }
out << "void " << FmtReplayFunction(contextId, frameIndex) << "\n"; out << "void " << FmtReplayFunction(context->id(), frameIndex) << "\n";
out << "{\n"; out << "{\n";
std::stringstream callStream; std::stringstream callStream;
...@@ -891,6 +910,30 @@ void WriteCppReplay(bool compression, ...@@ -891,6 +910,30 @@ void WriteCppReplay(bool compression,
out << callStream.str(); out << callStream.str();
out << "}\n"; out << "}\n";
if (serializeStateEnabled)
{
gl::BinaryOutputStream serializedContextData{};
if (SerializeContext(&serializedContextData, const_cast<gl::Context *>(context)) ==
Result::Continue)
{
size_t serializedContextLength = serializedContextData.length();
size_t serializedContextOffset = rx::roundUp(binaryData->size(), kBinaryAlignment);
binaryData->resize(serializedContextOffset + serializedContextLength);
memcpy(binaryData->data() + serializedContextOffset, serializedContextData.data(),
serializedContextLength);
out << "std::vector<uint8_t> "
<< FmtGetSerializedContextStateDataFunction(context->id(), frameIndex) << "\n";
out << "{\n";
out << " std::vector<uint8_t> serializedContextData(" << serializedContextLength
<< ");\n";
out << " memcpy(serializedContextData.data(), &gBinaryData["
<< serializedContextOffset << "], " << serializedContextLength << ");\n";
out << " return serializedContextData;\n";
out << "}\n";
out << "\n";
}
}
if (!captureLabel.empty()) if (!captureLabel.empty())
{ {
out << "} // namespace " << captureLabel << "\n"; out << "} // namespace " << captureLabel << "\n";
...@@ -903,7 +946,7 @@ void WriteCppReplay(bool compression, ...@@ -903,7 +946,7 @@ void WriteCppReplay(bool compression,
std::string headerString = header.str(); std::string headerString = header.str();
std::string cppFilePath = std::string cppFilePath =
GetCaptureFilePath(outDir, contextId, captureLabel, frameIndex, ".cpp"); GetCaptureFilePath(outDir, context->id(), captureLabel, frameIndex, ".cpp");
SaveFileHelper saveCpp(cppFilePath); SaveFileHelper saveCpp(cppFilePath);
saveCpp << headerString << "\n" << outString; saveCpp << headerString << "\n" << outString;
...@@ -912,7 +955,7 @@ void WriteCppReplay(bool compression, ...@@ -912,7 +955,7 @@ void WriteCppReplay(bool compression,
void WriteCppReplayIndexFiles(bool compression, void WriteCppReplayIndexFiles(bool compression,
const std::string &outDir, const std::string &outDir,
const gl::Context *context, const gl::ContextID contextId,
const std::string &captureLabel, const std::string &captureLabel,
uint32_t frameStart, uint32_t frameStart,
uint32_t frameEnd, uint32_t frameEnd,
...@@ -922,25 +965,11 @@ void WriteCppReplayIndexFiles(bool compression, ...@@ -922,25 +965,11 @@ void WriteCppReplayIndexFiles(bool compression,
const gl::AttribArray<size_t> &clientArraySizes, const gl::AttribArray<size_t> &clientArraySizes,
const HasResourceTypeMap &hasResourceType, const HasResourceTypeMap &hasResourceType,
bool serializeStateEnabled, bool serializeStateEnabled,
bool writeResetContextCall,
const egl::Config *config,
std::vector<uint8_t> &binaryData) std::vector<uint8_t> &binaryData)
{ {
gl::ContextID contextId = context->id();
size_t serializedContextLength = 0;
size_t serializedContextOffset = 0;
if (serializeStateEnabled)
{
gl::BinaryOutputStream serializedContextData{};
if (SerializeContext(&serializedContextData, context) != Result::Continue)
{
return;
}
// store serialized context behind capture replay data
serializedContextLength = serializedContextData.length();
serializedContextOffset = rx::roundUp(binaryData.size(), kBinaryAlignment);
binaryData.resize(serializedContextOffset + serializedContextLength);
memcpy(binaryData.data() + serializedContextOffset, serializedContextData.data(),
serializedContextLength);
}
size_t maxClientArraySize = MaxClientArraySize(clientArraySizes); size_t maxClientArraySize = MaxClientArraySize(clientArraySizes);
std::stringstream header; std::stringstream header;
...@@ -982,6 +1011,12 @@ void WriteCppReplayIndexFiles(bool compression, ...@@ -982,6 +1011,12 @@ void WriteCppReplayIndexFiles(bool compression,
header << "constexpr uint32_t kReplayFrameEnd = " << frameEnd << ";\n"; header << "constexpr uint32_t kReplayFrameEnd = " << frameEnd << ";\n";
header << "constexpr EGLint kReplayDrawSurfaceWidth = " << drawSurfaceWidth << ";\n"; header << "constexpr EGLint kReplayDrawSurfaceWidth = " << drawSurfaceWidth << ";\n";
header << "constexpr EGLint kReplayDrawSurfaceHeight = " << drawSurfaceHeight << ";\n"; header << "constexpr EGLint kReplayDrawSurfaceHeight = " << drawSurfaceHeight << ";\n";
header << "constexpr EGLint kDefaultFramebufferRedBits = " << config->redSize << ";\n";
header << "constexpr EGLint kDefaultFramebufferGreenBits = " << config->greenSize << ";\n";
header << "constexpr EGLint kDefaultFramebufferBlueBits = " << config->blueSize << ";\n";
header << "constexpr EGLint kDefaultFramebufferAlphaBits = " << config->alphaSize << ";\n";
header << "constexpr EGLint kDefaultFramebufferDepthBits = " << config->depthSize << ";\n";
header << "constexpr EGLint kDefaultFramebufferStencilBits = " << config->stencilSize << ";\n";
header << "\n"; header << "\n";
header << "void SetupContext" << static_cast<int>(contextId) << "Replay();\n"; header << "void SetupContext" << static_cast<int>(contextId) << "Replay();\n";
header << "void ReplayContext" << static_cast<int>(contextId) header << "void ReplayContext" << static_cast<int>(contextId)
...@@ -989,8 +1024,8 @@ void WriteCppReplayIndexFiles(bool compression, ...@@ -989,8 +1024,8 @@ void WriteCppReplayIndexFiles(bool compression,
header << "void ResetContext" << static_cast<int>(contextId) << "Replay();\n"; header << "void ResetContext" << static_cast<int>(contextId) << "Replay();\n";
if (serializeStateEnabled) if (serializeStateEnabled)
{ {
header << "std::vector<uint8_t> GetSerializedContextState" << static_cast<int>(contextId) header << "std::vector<uint8_t> GetSerializedContext" << static_cast<int>(contextId)
<< "Data();\n"; << "StateData(uint32_t frameIndex);\n";
} }
header << "\n"; header << "\n";
header << "using FramebufferChangeCallback = void(*)(void *userData, GLenum target, GLuint " header << "using FramebufferChangeCallback = void(*)(void *userData, GLenum target, GLuint "
...@@ -1004,6 +1039,16 @@ void WriteCppReplayIndexFiles(bool compression, ...@@ -1004,6 +1039,16 @@ void WriteCppReplayIndexFiles(bool compression,
header << "void " << FmtReplayFunction(contextId, frameIndex) << ";\n"; header << "void " << FmtReplayFunction(contextId, frameIndex) << ";\n";
} }
header << "\n"; header << "\n";
if (serializeStateEnabled)
{
for (uint32_t frameIndex = frameStart; frameIndex <= frameEnd; ++frameIndex)
{
header << "std::vector<uint8_t> "
<< FmtGetSerializedContextStateDataFunction(contextId, frameIndex) << ";\n";
}
}
header << "\n";
header << "constexpr bool kIsBinaryDataCompressed = " << (compression ? "true" : "false") header << "constexpr bool kIsBinaryDataCompressed = " << (compression ? "true" : "false")
<< ";\n"; << ";\n";
header << "\n"; header << "\n";
...@@ -1124,16 +1169,32 @@ void WriteCppReplayIndexFiles(bool compression, ...@@ -1124,16 +1169,32 @@ void WriteCppReplayIndexFiles(bool compression,
source << "}\n"; source << "}\n";
source << "\n"; source << "\n";
if (writeResetContextCall)
{
source << "void ResetContext" << Str(static_cast<int>(contextId)) << "Replay()\n";
source << "{\n";
source << " // Reset context is empty because context is destroyed before end "
"frame is reached\n";
source << "}\n";
source << "\n";
}
if (serializeStateEnabled) if (serializeStateEnabled)
{ {
source << "std::vector<uint8_t> GetSerializedContextState" << static_cast<int>(contextId) source << "std::vector<uint8_t> GetSerializedContext" << static_cast<int>(contextId)
<< "Data()\n"; << "StateData(uint32_t frameIndex)\n";
source << "{\n"; source << "{\n";
source << " std::vector<uint8_t> serializedContextData(" << serializedContextLength source << " switch (frameIndex)\n";
<< ");\n"; source << " {\n";
source << " memcpy(serializedContextData.data(), &gBinaryData[" for (uint32_t frameIndex = frameStart; frameIndex <= frameEnd; ++frameIndex)
<< serializedContextOffset << "], " << serializedContextLength << ");\n"; {
source << " return serializedContextData;\n"; source << " case " << frameIndex << ":\n";
source << " return "
<< FmtGetSerializedContextStateDataFunction(contextId, frameIndex) << ";\n";
}
source << " default:\n";
source << " return {};\n";
source << " }\n";
source << "}\n"; source << "}\n";
source << "\n"; source << "\n";
} }
...@@ -2676,7 +2737,11 @@ void CaptureMidExecutionSetup(const gl::Context *context, ...@@ -2676,7 +2737,11 @@ void CaptureMidExecutionSetup(const gl::Context *context,
// Bind the current XFB buffer after populating XFB objects // Bind the current XFB buffer after populating XFB objects
gl::TransformFeedback *currentXFB = apiState.getCurrentTransformFeedback(); gl::TransformFeedback *currentXFB = apiState.getCurrentTransformFeedback();
cap(CaptureBindTransformFeedback(replayState, true, GL_TRANSFORM_FEEDBACK, currentXFB->id())); if (currentXFB)
{
cap(CaptureBindTransformFeedback(replayState, true, GL_TRANSFORM_FEEDBACK,
currentXFB->id()));
}
// Capture Sampler Objects // Capture Sampler Objects
const gl::SamplerManager &samplers = apiState.getSamplerManagerForCapture(); const gl::SamplerManager &samplers = apiState.getSamplerManagerForCapture();
...@@ -3902,22 +3967,28 @@ void FrameCapture::onEndFrame(const gl::Context *context) ...@@ -3902,22 +3967,28 @@ void FrameCapture::onEndFrame(const gl::Context *context)
// Note that we currently capture before the start frame to collect shader and program sources. // Note that we currently capture before the start frame to collect shader and program sources.
if (!mFrameCalls.empty() && mFrameIndex >= mFrameStart) if (!mFrameCalls.empty() && mFrameIndex >= mFrameStart)
{ {
WriteCppReplay(mCompression, mOutDirectory, context->id(), mCaptureLabel, mFrameIndex, if (mIsFirstFrame)
mFrameEnd, mFrameCalls, mSetupCalls, &mResourceTracker, &mBinaryData); {
mFrameStart = mFrameIndex;
// Save the index files after the last frame. mIsFirstFrame = false;
}
WriteCppReplay(mCompression, mOutDirectory, context, mCaptureLabel, mFrameIndex,
mFrameStart, mFrameEnd, mFrameCalls, mSetupCalls, &mResourceTracker,
&mBinaryData, mSerializeStateEnabled);
if (mFrameIndex == mFrameEnd) if (mFrameIndex == mFrameEnd)
{ {
WriteCppReplayIndexFiles(mCompression, mOutDirectory, context, mCaptureLabel, // Save the index files after the last frame.
mFrameStart, mFrameEnd, mDrawSurfaceWidth, mDrawSurfaceHeight, WriteCppReplayIndexFiles(
mReadBufferSize, mClientArraySizes, mHasResourceType, mCompression, mOutDirectory, context->id(), mCaptureLabel, mFrameStart, mFrameEnd,
mSerializeStateEnabled, mBinaryData); mDrawSurfaceWidth, mDrawSurfaceHeight, mReadBufferSize, mClientArraySizes,
mHasResourceType, mSerializeStateEnabled, false, context->getConfig(), mBinaryData);
if (!mBinaryData.empty()) if (!mBinaryData.empty())
{ {
SaveBinaryData(mCompression, mOutDirectory, context->id(), mCaptureLabel, SaveBinaryData(mCompression, mOutDirectory, context->id(), mCaptureLabel,
mBinaryData); mBinaryData);
mBinaryData.clear(); mBinaryData.clear();
} }
mWroteIndexFile = true;
} }
} }
...@@ -3946,6 +4017,32 @@ void FrameCapture::onEndFrame(const gl::Context *context) ...@@ -3946,6 +4017,32 @@ void FrameCapture::onEndFrame(const gl::Context *context)
} }
} }
void FrameCapture::onDestroyContext(const gl::Context *context)
{
if (!mEnabled)
{
return;
}
if (!mWroteIndexFile && mFrameIndex > mFrameStart)
{
// If context is destroyed before end frame is reached and at least
// 1 frame has been recorded, then write the index files.
// It doesnt make sense to write the index files when no frame has been recorded
mFrameIndex -= 1;
mFrameEnd = mFrameIndex;
WriteCppReplayIndexFiles(mCompression, mOutDirectory, context->id(), mCaptureLabel,
mFrameStart, mFrameEnd, mDrawSurfaceWidth, mDrawSurfaceHeight,
mReadBufferSize, mClientArraySizes, mHasResourceType,
mSerializeStateEnabled, true, context->getConfig(), mBinaryData);
if (!mBinaryData.empty())
{
SaveBinaryData(mCompression, mOutDirectory, context->id(), mCaptureLabel, mBinaryData);
mBinaryData.clear();
}
mWroteIndexFile = true;
}
}
void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface) void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface)
{ {
if (!drawSurface) if (!drawSurface)
......
...@@ -273,6 +273,7 @@ class FrameCapture final : angle::NonCopyable ...@@ -273,6 +273,7 @@ class FrameCapture final : angle::NonCopyable
void captureCall(const gl::Context *context, CallCapture &&call); void captureCall(const gl::Context *context, CallCapture &&call);
void onEndFrame(const gl::Context *context); void onEndFrame(const gl::Context *context);
void onDestroyContext(const gl::Context *context);
void onMakeCurrent(const egl::Surface *drawSurface); void onMakeCurrent(const egl::Surface *drawSurface);
bool enabled() const { return mEnabled; } bool enabled() const { return mEnabled; }
...@@ -319,6 +320,8 @@ class FrameCapture final : angle::NonCopyable ...@@ -319,6 +320,8 @@ class FrameCapture final : angle::NonCopyable
uint32_t mFrameIndex; uint32_t mFrameIndex;
uint32_t mFrameStart; uint32_t mFrameStart;
uint32_t mFrameEnd; uint32_t mFrameEnd;
bool mIsFirstFrame = true;
bool mWroteIndexFile = false;
EGLint mDrawSurfaceWidth = 0; EGLint mDrawSurfaceWidth = 0;
EGLint mDrawSurfaceHeight = 0; EGLint mDrawSurfaceHeight = 0;
gl::AttribArray<size_t> mClientArraySizes; gl::AttribArray<size_t> mClientArraySizes;
......
...@@ -25,5 +25,6 @@ FrameCapture::FrameCapture() {} ...@@ -25,5 +25,6 @@ FrameCapture::FrameCapture() {}
FrameCapture::~FrameCapture() {} FrameCapture::~FrameCapture() {}
void FrameCapture::onEndFrame(const gl::Context *context) {} void FrameCapture::onEndFrame(const gl::Context *context) {}
void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface) {} void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface) {}
void FrameCapture::onDestroyContext(const gl::Context *context) {}
void FrameCapture::replay(gl::Context *context) {} void FrameCapture::replay(gl::Context *context) {}
} // namespace angle } // namespace angle
...@@ -160,20 +160,22 @@ def ClearFolderContent(path): ...@@ -160,20 +160,22 @@ def ClearFolderContent(path):
def CanRunReplay(path): def CanRunReplay(path):
required_trace_files = { required_trace_files = {
"angle_capture_context1.h", "angle_capture_context1.cpp", "angle_capture_context1.h", "angle_capture_context1.cpp",
"angle_capture_context1_files.txt", "angle_capture_context1_frame000.cpp" "angle_capture_context1_files.txt"
} }
binary_data_file = "angle_capture_context1.angledata.gz"
required_trace_files_count = 0 required_trace_files_count = 0
frame_files_count = 0
for f in os.listdir(path): for f in os.listdir(path):
if not os.path.isfile(os.path.join(path, f)):
continue
if f in required_trace_files: if f in required_trace_files:
required_trace_files_count += 1 required_trace_files_count += 1
elif os.path.isfile(os.path.join(path, f)) and f != binary_data_file and \ elif f.startswith("angle_capture_context1_frame"):
f.startswith("angle_capture_context"): frame_files_count += 1
elif f.startswith("angle_capture_context") and not f.startswith("angle_capture_context1"):
# if trace_files of another context exists, then the test creates multiple contexts # if trace_files of another context exists, then the test creates multiple contexts
# or capture multiple frames
return False return False
# angle_capture_context1.angledata.gz can be missing # angle_capture_context1.angledata.gz can be missing
return required_trace_files_count == len(required_trace_files) return required_trace_files_count == len(required_trace_files) and frame_files_count >= 1
def SetCWDToAngleFolder(): def SetCWDToAngleFolder():
...@@ -190,7 +192,7 @@ def main(build_dir, verbose, use_goma, gtest_filter, test_exec): ...@@ -190,7 +192,7 @@ def main(build_dir, verbose, use_goma, gtest_filter, test_exec):
capture_out_dir = "src/tests/capture_replay_tests/traces" # relative to ANGLE folder capture_out_dir = "src/tests/capture_replay_tests/traces" # relative to ANGLE folder
if not os.path.isdir(capture_out_dir): if not os.path.isdir(capture_out_dir):
os.mkdir(capture_out_dir) os.mkdir(capture_out_dir)
environment_vars = [("ANGLE_CAPTURE_FRAME_END", "0"), environment_vars = [("ANGLE_CAPTURE_FRAME_END", "100"),
("ANGLE_CAPTURE_OUT_DIR", capture_out_dir), ("ANGLE_CAPTURE_OUT_DIR", capture_out_dir),
("ANGLE_CAPTURE_SERIALIZE_STATE", "1")] ("ANGLE_CAPTURE_SERIALIZE_STATE", "1")]
replay_exec = "capture_replay_tests" replay_exec = "capture_replay_tests"
...@@ -248,7 +250,8 @@ def main(build_dir, verbose, use_goma, gtest_filter, test_exec): ...@@ -248,7 +250,8 @@ def main(build_dir, verbose, use_goma, gtest_filter, test_exec):
if os.path.isdir(capture_out_dir): if os.path.isdir(capture_out_dir):
shutil.rmtree(capture_out_dir) shutil.rmtree(capture_out_dir)
print("\n\n\n") print("\n\n\n")
print("Passed:", passed_count, "Failed:", failed_count, "Skipped:", skipped_count) print("Passed: "+ str(passed_count) + " Failed: " + str(failed_count) + \
" Skipped: " + str(skipped_count))
print("Failed tests:") print("Failed tests:")
for failed_test in failed_tests: for failed_test in failed_tests:
print("\t" + failed_test) print("\t" + failed_test)
......
...@@ -38,16 +38,16 @@ std::function<void(int)> ReplayContextFrame = reinterpret_cast<void (*)(int)>( ...@@ -38,16 +38,16 @@ std::function<void(int)> ReplayContextFrame = reinterpret_cast<void (*)(int)>(
std::function<void()> ResetContextReplay = reinterpret_cast<void (*)()>( std::function<void()> ResetContextReplay = reinterpret_cast<void (*)()>(
ANGLE_MACRO_CONCAT(ResetContext, ANGLE_MACRO_CONCAT(ResetContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Replay))); ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Replay)));
std::function<std::vector<uint8_t>()> GetSerializedContextStateData = std::function<std::vector<uint8_t>(uint32_t)> GetSerializedContextStateData =
reinterpret_cast<std::vector<uint8_t> (*)()>( reinterpret_cast<std::vector<uint8_t> (*)(uint32_t)>(
ANGLE_MACRO_CONCAT(GetSerializedContextState, ANGLE_MACRO_CONCAT(GetSerializedContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Data))); ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, StateData)));
class CaptureReplayTest class CaptureReplayTest
{ {
public: public:
CaptureReplayTest(int width, int height, EGLint glesMajorVersion, EGLint glesMinorVersion) CaptureReplayTest(EGLint glesMajorVersion, EGLint glesMinorVersion)
: mWidth(width), mHeight(height), mOSWindow(nullptr), mEGLWindow(nullptr) : mOSWindow(nullptr), mEGLWindow(nullptr)
{ {
mPlatformParams.renderer = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; mPlatformParams.renderer = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
...@@ -59,6 +59,7 @@ class CaptureReplayTest ...@@ -59,6 +59,7 @@ class CaptureReplayTest
mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion); mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion);
mOSWindow = OSWindow::New(); mOSWindow = OSWindow::New();
mOSWindow->disableErrorMessageDialog();
} }
~CaptureReplayTest() ~CaptureReplayTest()
...@@ -83,13 +84,12 @@ class CaptureReplayTest ...@@ -83,13 +84,12 @@ class CaptureReplayTest
return true; return true;
} }
void draw() { ReplayContextFrame(0); }
void swap() { mEGLWindow->swap(); } void swap() { mEGLWindow->swap(); }
int run() int run()
{ {
if (!mOSWindow->initialize("Capture Replay Test", mWidth, mHeight)) if (!mOSWindow->initialize("Capture Replay Test", kReplayDrawSurfaceWidth,
kReplayDrawSurfaceHeight))
{ {
return -1; return -1;
} }
...@@ -97,12 +97,12 @@ class CaptureReplayTest ...@@ -97,12 +97,12 @@ class CaptureReplayTest
mOSWindow->setVisible(true); mOSWindow->setVisible(true);
ConfigParameters configParams; ConfigParameters configParams;
configParams.redBits = 8; configParams.redBits = kDefaultFramebufferRedBits;
configParams.greenBits = 8; configParams.greenBits = kDefaultFramebufferGreenBits;
configParams.blueBits = 8; configParams.blueBits = kDefaultFramebufferBlueBits;
configParams.alphaBits = 8; configParams.alphaBits = kDefaultFramebufferAlphaBits;
configParams.depthBits = 24; configParams.depthBits = kDefaultFramebufferDepthBits;
configParams.stencilBits = 8; configParams.stencilBits = kDefaultFramebufferStencilBits;
if (!mEGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(), if (!mEGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(),
angle::GLESDriverType::AngleEGL, mPlatformParams, angle::GLESDriverType::AngleEGL, mPlatformParams,
...@@ -124,20 +124,23 @@ class CaptureReplayTest ...@@ -124,20 +124,23 @@ class CaptureReplayTest
result = -1; result = -1;
} }
draw(); for (uint32_t frame = kReplayFrameStart; frame <= kReplayFrameEnd; frame++)
gl::Context *context = static_cast<gl::Context *>(mEGLWindow->getContext());
gl::BinaryOutputStream bos;
if (angle::SerializeContext(&bos, context) != angle::Result::Continue)
{
return -1;
}
bool isEqual = compareSerializedStates(bos);
if (!isEqual)
{ {
result = -1; ReplayContextFrame(frame);
gl::Context *context = static_cast<gl::Context *>(mEGLWindow->getContext());
gl::BinaryOutputStream bos;
// If swapBuffers is not called, then default framebuffer should not be serialized
if (angle::SerializeContext(&bos, context) != angle::Result::Continue)
{
return -1;
}
bool isEqual = compareSerializedStates(frame, bos);
if (!isEqual)
{
return -1;
}
swap();
} }
swap();
mEGLWindow->destroyGL(); mEGLWindow->destroyGL();
mOSWindow->destroy(); mOSWindow->destroy();
...@@ -146,13 +149,12 @@ class CaptureReplayTest ...@@ -146,13 +149,12 @@ class CaptureReplayTest
} }
private: private:
bool compareSerializedStates(const gl::BinaryOutputStream &replaySerializedContextData) bool compareSerializedStates(uint32_t frame,
const gl::BinaryOutputStream &replaySerializedContextData)
{ {
return GetSerializedContextStateData() == replaySerializedContextData.getData(); return GetSerializedContextStateData(frame) == replaySerializedContextData.getData();
} }
uint32_t mWidth;
uint32_t mHeight;
OSWindow *mOSWindow; OSWindow *mOSWindow;
EGLWindow *mEGLWindow; EGLWindow *mEGLWindow;
...@@ -165,10 +167,8 @@ class CaptureReplayTest ...@@ -165,10 +167,8 @@ class CaptureReplayTest
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// TODO (nguyenmh): http://anglebug.com/4759: initialize app with arguments taken from cmdline // TODO (nguyenmh): http://anglebug.com/4759: initialize app with arguments taken from cmdline
const int width = 128;
const int height = 128;
const EGLint glesMajorVersion = 2; const EGLint glesMajorVersion = 2;
const GLint glesMinorVersion = 0; const GLint glesMinorVersion = 0;
CaptureReplayTest app(width, height, glesMajorVersion, glesMinorVersion); CaptureReplayTest app(glesMajorVersion, glesMinorVersion);
return app.run(); return app.run();
} }
...@@ -436,6 +436,7 @@ void ANGLETestBase::initOSWindow() ...@@ -436,6 +436,7 @@ void ANGLETestBase::initOSWindow()
if (!mFixture->osWindow) if (!mFixture->osWindow)
{ {
mFixture->osWindow = OSWindow::New(); mFixture->osWindow = OSWindow::New();
mFixture->osWindow->disableErrorMessageDialog();
if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128)) if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128))
{ {
std::cerr << "Failed to initialize OS Window."; std::cerr << "Failed to initialize OS Window.";
......
...@@ -27,6 +27,7 @@ class ANGLE_UTIL_EXPORT OSWindow ...@@ -27,6 +27,7 @@ class ANGLE_UTIL_EXPORT OSWindow
virtual bool initialize(const std::string &name, int width, int height) = 0; virtual bool initialize(const std::string &name, int width, int height) = 0;
virtual void destroy() = 0; virtual void destroy() = 0;
virtual void disableErrorMessageDialog() = 0;
int getX() const; int getX() const;
int getY() const; int getY() const;
......
...@@ -31,6 +31,8 @@ bool AndroidWindow::initialize(const std::string &name, int width, int height) ...@@ -31,6 +31,8 @@ bool AndroidWindow::initialize(const std::string &name, int width, int height)
} }
void AndroidWindow::destroy() {} void AndroidWindow::destroy() {}
void AndroidWindow::disableErrorMessageDialog() {}
void AndroidWindow::resetNativeWindow() {} void AndroidWindow::resetNativeWindow() {}
EGLNativeWindowType AndroidWindow::getNativeWindow() const EGLNativeWindowType AndroidWindow::getNativeWindow() const
......
...@@ -18,6 +18,7 @@ class AndroidWindow : public OSWindow ...@@ -18,6 +18,7 @@ class AndroidWindow : public OSWindow
~AndroidWindow() override; ~AndroidWindow() override;
bool initialize(const std::string &name, int width, int height) override; bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override; void destroy() override;
void resetNativeWindow() override; void resetNativeWindow() override;
......
...@@ -114,6 +114,8 @@ bool ScenicWindow::initialize(const std::string &name, int width, int height) ...@@ -114,6 +114,8 @@ bool ScenicWindow::initialize(const std::string &name, int width, int height)
return true; return true;
} }
void ScenicWindow::disableErrorMessageDialog() {}
void ScenicWindow::destroy() void ScenicWindow::destroy()
{ {
while (mInFlightPresents != 0 && !mLostSession) while (mInFlightPresents != 0 && !mLostSession)
......
...@@ -42,6 +42,7 @@ class ANGLE_UTIL_EXPORT ScenicWindow : public OSWindow ...@@ -42,6 +42,7 @@ class ANGLE_UTIL_EXPORT ScenicWindow : public OSWindow
// OSWindow: // OSWindow:
bool initialize(const std::string &name, int width, int height) override; bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override; void destroy() override;
void resetNativeWindow() override; void resetNativeWindow() override;
EGLNativeWindowType getNativeWindow() const override; EGLNativeWindowType getNativeWindow() const override;
......
...@@ -36,6 +36,7 @@ class OSXWindow : public OSWindow ...@@ -36,6 +36,7 @@ class OSXWindow : public OSWindow
~OSXWindow() override; ~OSXWindow() override;
bool initialize(const std::string &name, int width, int height) override; bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override; void destroy() override;
void resetNativeWindow() override; void resetNativeWindow() override;
......
...@@ -676,6 +676,8 @@ bool OSXWindow::initialize(const std::string &name, int width, int height) ...@@ -676,6 +676,8 @@ bool OSXWindow::initialize(const std::string &name, int width, int height)
return true; return true;
} }
void OSXWindow::disableErrorMessageDialog() {}
void OSXWindow::destroy() void OSXWindow::destroy()
{ {
AllWindows().erase(this); AllWindows().erase(this);
......
...@@ -27,6 +27,8 @@ bool OzoneWindow::initialize(const std::string &name, int width, int height) ...@@ -27,6 +27,8 @@ bool OzoneWindow::initialize(const std::string &name, int width, int height)
return true; return true;
} }
void OzoneWindow::disableErrorMessageDialog() {}
void OzoneWindow::destroy() {} void OzoneWindow::destroy() {}
void OzoneWindow::resetNativeWindow() {} void OzoneWindow::resetNativeWindow() {}
......
...@@ -20,6 +20,7 @@ class OzoneWindow : public OSWindow ...@@ -20,6 +20,7 @@ class OzoneWindow : public OSWindow
~OzoneWindow() override; ~OzoneWindow() override;
bool initialize(const std::string &name, int width, int height) override; bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override; void destroy() override;
void resetNativeWindow() override; void resetNativeWindow() override;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "util/windows/win32/Win32Window.h" #include "util/windows/win32/Win32Window.h"
#include <crtdbg.h>
#include <sstream> #include <sstream>
#include "common/debug.h" #include "common/debug.h"
...@@ -572,6 +573,12 @@ bool Win32Window::initialize(const std::string &name, int width, int height) ...@@ -572,6 +573,12 @@ bool Win32Window::initialize(const std::string &name, int width, int height)
return true; return true;
} }
void Win32Window::disableErrorMessageDialog()
{
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
}
void Win32Window::destroy() void Win32Window::destroy()
{ {
if (mNativeDisplay) if (mNativeDisplay)
......
...@@ -23,6 +23,7 @@ class Win32Window : public OSWindow ...@@ -23,6 +23,7 @@ class Win32Window : public OSWindow
bool initialize(const std::string &name, int width, int height) override; bool initialize(const std::string &name, int width, int height) override;
void destroy() override; void destroy() override;
void disableErrorMessageDialog() override;
bool takeScreenshot(uint8_t *pixelData) override; bool takeScreenshot(uint8_t *pixelData) override;
......
...@@ -371,6 +371,8 @@ bool X11Window::initialize(const std::string &name, int width, int height) ...@@ -371,6 +371,8 @@ bool X11Window::initialize(const std::string &name, int width, int height)
return true; return true;
} }
void X11Window::disableErrorMessageDialog() {}
void X11Window::destroy() void X11Window::destroy()
{ {
if (mWindow) if (mWindow)
......
...@@ -25,6 +25,7 @@ class ANGLE_UTIL_EXPORT X11Window : public OSWindow ...@@ -25,6 +25,7 @@ class ANGLE_UTIL_EXPORT X11Window : public OSWindow
~X11Window() override; ~X11Window() override;
bool initialize(const std::string &name, int width, int height) override; bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override; void destroy() override;
void resetNativeWindow() override; void resetNativeWindow() override;
......
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