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)
{ {
......
...@@ -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