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()
egl::Error Context::onDestroy(const egl::Display *display)
{
// Dump frame capture if enabled.
mFrameCapture->onEndFrame(this);
mFrameCapture->onDestroyContext(this);
if (mGLES1Renderer)
{
......
......@@ -273,6 +273,7 @@ class FrameCapture final : angle::NonCopyable
void captureCall(const gl::Context *context, CallCapture &&call);
void onEndFrame(const gl::Context *context);
void onDestroyContext(const gl::Context *context);
void onMakeCurrent(const egl::Surface *drawSurface);
bool enabled() const { return mEnabled; }
......@@ -319,6 +320,8 @@ class FrameCapture final : angle::NonCopyable
uint32_t mFrameIndex;
uint32_t mFrameStart;
uint32_t mFrameEnd;
bool mIsFirstFrame = true;
bool mWroteIndexFile = false;
EGLint mDrawSurfaceWidth = 0;
EGLint mDrawSurfaceHeight = 0;
gl::AttribArray<size_t> mClientArraySizes;
......
......@@ -25,5 +25,6 @@ FrameCapture::FrameCapture() {}
FrameCapture::~FrameCapture() {}
void FrameCapture::onEndFrame(const gl::Context *context) {}
void FrameCapture::onMakeCurrent(const egl::Surface *drawSurface) {}
void FrameCapture::onDestroyContext(const gl::Context *context) {}
void FrameCapture::replay(gl::Context *context) {}
} // namespace angle
......@@ -160,20 +160,22 @@ def ClearFolderContent(path):
def CanRunReplay(path):
required_trace_files = {
"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
frame_files_count = 0
for f in os.listdir(path):
if not os.path.isfile(os.path.join(path, f)):
continue
if f in required_trace_files:
required_trace_files_count += 1
elif os.path.isfile(os.path.join(path, f)) and f != binary_data_file and \
f.startswith("angle_capture_context"):
elif f.startswith("angle_capture_context1_frame"):
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
# or capture multiple frames
return False
# 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():
......@@ -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
if not os.path.isdir(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_SERIALIZE_STATE", "1")]
replay_exec = "capture_replay_tests"
......@@ -248,7 +250,8 @@ def main(build_dir, verbose, use_goma, gtest_filter, test_exec):
if os.path.isdir(capture_out_dir):
shutil.rmtree(capture_out_dir)
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:")
for failed_test in failed_tests:
print("\t" + failed_test)
......
......@@ -38,16 +38,16 @@ std::function<void(int)> ReplayContextFrame = reinterpret_cast<void (*)(int)>(
std::function<void()> ResetContextReplay = reinterpret_cast<void (*)()>(
ANGLE_MACRO_CONCAT(ResetContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Replay)));
std::function<std::vector<uint8_t>()> GetSerializedContextStateData =
reinterpret_cast<std::vector<uint8_t> (*)()>(
ANGLE_MACRO_CONCAT(GetSerializedContextState,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Data)));
std::function<std::vector<uint8_t>(uint32_t)> GetSerializedContextStateData =
reinterpret_cast<std::vector<uint8_t> (*)(uint32_t)>(
ANGLE_MACRO_CONCAT(GetSerializedContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, StateData)));
class CaptureReplayTest
{
public:
CaptureReplayTest(int width, int height, EGLint glesMajorVersion, EGLint glesMinorVersion)
: mWidth(width), mHeight(height), mOSWindow(nullptr), mEGLWindow(nullptr)
CaptureReplayTest(EGLint glesMajorVersion, EGLint glesMinorVersion)
: mOSWindow(nullptr), mEGLWindow(nullptr)
{
mPlatformParams.renderer = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
......@@ -59,6 +59,7 @@ class CaptureReplayTest
mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion);
mOSWindow = OSWindow::New();
mOSWindow->disableErrorMessageDialog();
}
~CaptureReplayTest()
......@@ -83,13 +84,12 @@ class CaptureReplayTest
return true;
}
void draw() { ReplayContextFrame(0); }
void swap() { mEGLWindow->swap(); }
int run()
{
if (!mOSWindow->initialize("Capture Replay Test", mWidth, mHeight))
if (!mOSWindow->initialize("Capture Replay Test", kReplayDrawSurfaceWidth,
kReplayDrawSurfaceHeight))
{
return -1;
}
......@@ -97,12 +97,12 @@ class CaptureReplayTest
mOSWindow->setVisible(true);
ConfigParameters configParams;
configParams.redBits = 8;
configParams.greenBits = 8;
configParams.blueBits = 8;
configParams.alphaBits = 8;
configParams.depthBits = 24;
configParams.stencilBits = 8;
configParams.redBits = kDefaultFramebufferRedBits;
configParams.greenBits = kDefaultFramebufferGreenBits;
configParams.blueBits = kDefaultFramebufferBlueBits;
configParams.alphaBits = kDefaultFramebufferAlphaBits;
configParams.depthBits = kDefaultFramebufferDepthBits;
configParams.stencilBits = kDefaultFramebufferStencilBits;
if (!mEGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(),
angle::GLESDriverType::AngleEGL, mPlatformParams,
......@@ -124,20 +124,23 @@ class CaptureReplayTest
result = -1;
}
draw();
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)
for (uint32_t frame = kReplayFrameStart; frame <= kReplayFrameEnd; frame++)
{
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();
mOSWindow->destroy();
......@@ -146,13 +149,12 @@ class CaptureReplayTest
}
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;
EGLWindow *mEGLWindow;
......@@ -165,10 +167,8 @@ class CaptureReplayTest
int main(int argc, char **argv)
{
// 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 GLint glesMinorVersion = 0;
CaptureReplayTest app(width, height, glesMajorVersion, glesMinorVersion);
CaptureReplayTest app(glesMajorVersion, glesMinorVersion);
return app.run();
}
......@@ -436,6 +436,7 @@ void ANGLETestBase::initOSWindow()
if (!mFixture->osWindow)
{
mFixture->osWindow = OSWindow::New();
mFixture->osWindow->disableErrorMessageDialog();
if (!mFixture->osWindow->initialize(windowName.c_str(), 128, 128))
{
std::cerr << "Failed to initialize OS Window.";
......
......@@ -27,6 +27,7 @@ class ANGLE_UTIL_EXPORT OSWindow
virtual bool initialize(const std::string &name, int width, int height) = 0;
virtual void destroy() = 0;
virtual void disableErrorMessageDialog() = 0;
int getX() const;
int getY() const;
......
......@@ -31,6 +31,8 @@ bool AndroidWindow::initialize(const std::string &name, int width, int height)
}
void AndroidWindow::destroy() {}
void AndroidWindow::disableErrorMessageDialog() {}
void AndroidWindow::resetNativeWindow() {}
EGLNativeWindowType AndroidWindow::getNativeWindow() const
......
......@@ -18,6 +18,7 @@ class AndroidWindow : public OSWindow
~AndroidWindow() override;
bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override;
void resetNativeWindow() override;
......
......@@ -114,6 +114,8 @@ bool ScenicWindow::initialize(const std::string &name, int width, int height)
return true;
}
void ScenicWindow::disableErrorMessageDialog() {}
void ScenicWindow::destroy()
{
while (mInFlightPresents != 0 && !mLostSession)
......
......@@ -42,6 +42,7 @@ class ANGLE_UTIL_EXPORT ScenicWindow : public OSWindow
// OSWindow:
bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override;
void resetNativeWindow() override;
EGLNativeWindowType getNativeWindow() const override;
......
......@@ -36,6 +36,7 @@ class OSXWindow : public OSWindow
~OSXWindow() override;
bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override;
void resetNativeWindow() override;
......
......@@ -676,6 +676,8 @@ bool OSXWindow::initialize(const std::string &name, int width, int height)
return true;
}
void OSXWindow::disableErrorMessageDialog() {}
void OSXWindow::destroy()
{
AllWindows().erase(this);
......
......@@ -27,6 +27,8 @@ bool OzoneWindow::initialize(const std::string &name, int width, int height)
return true;
}
void OzoneWindow::disableErrorMessageDialog() {}
void OzoneWindow::destroy() {}
void OzoneWindow::resetNativeWindow() {}
......
......@@ -20,6 +20,7 @@ class OzoneWindow : public OSWindow
~OzoneWindow() override;
bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() override;
void resetNativeWindow() override;
......
......@@ -8,6 +8,7 @@
#include "util/windows/win32/Win32Window.h"
#include <crtdbg.h>
#include <sstream>
#include "common/debug.h"
......@@ -572,6 +573,12 @@ bool Win32Window::initialize(const std::string &name, int width, int height)
return true;
}
void Win32Window::disableErrorMessageDialog()
{
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
}
void Win32Window::destroy()
{
if (mNativeDisplay)
......
......@@ -23,6 +23,7 @@ class Win32Window : public OSWindow
bool initialize(const std::string &name, int width, int height) override;
void destroy() override;
void disableErrorMessageDialog() override;
bool takeScreenshot(uint8_t *pixelData) override;
......
......@@ -371,6 +371,8 @@ bool X11Window::initialize(const std::string &name, int width, int height)
return true;
}
void X11Window::disableErrorMessageDialog() {}
void X11Window::destroy()
{
if (mWindow)
......
......@@ -25,6 +25,7 @@ class ANGLE_UTIL_EXPORT X11Window : public OSWindow
~X11Window() override;
bool initialize(const std::string &name, int width, int height) override;
void disableErrorMessageDialog() override;
void destroy() 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