Commit 2c41931c by Manh Nguyen Committed by Commit Bot

Batch-compile and batch-run-replay multiple tests

Multiple tests are batch-compiled into 1 replay application instead of multiple replay applications. Replay application now runs generated code of multiple tests instead of 1 test. This reduces overhead cost and brings down runtime. Main process now receives messages sent by workers via a message queue and prints them to the main stdout so that user can know if workers are hanging. Add handle for user interrupt (Ctrl-C) so that processes are properly destroyed and cleaned up. Trace files now have the option not to be deleted. Bug: angleproject:4817 Change-Id: Ic90ae0f430e1d3c261ffea5f963be5a4e94b0ad2 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2310909Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Manh Nguyen <nguyenmh@google.com>
parent d7d79de3
angle_capture_context*
\ No newline at end of file
trace*/
angle_trace_gl.h
results.txt
\ No newline at end of file
......@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("../../../gni/angle.gni")
declare_args() {
# Determines if we build the capture_replay_tests. Off by default.
angle_build_capture_replay_tests = false
......@@ -10,27 +11,28 @@ declare_args() {
# Decide which context to replay, starting with desktop default
angle_capture_replay_test_context_id = 1
#Set the trace directory. Default is traces
# Set the trace directory. Default is traces
angle_capture_replay_test_trace_dir = "traces"
angle_capture_replay_composite_file_id = 1
}
if (angle_build_capture_replay_tests) {
# TODO (nguyenmh): http://anglebug.com/4758:
# turn angle_executable into angle_test when adding android support
import(
"${angle_capture_replay_test_trace_dir}/traces${angle_capture_replay_composite_file_id}.gni")
angle_executable("capture_replay_tests") {
testonly = true
_contextid = angle_capture_replay_test_context_id
_trace_folder_relative_path = "./" + angle_capture_replay_test_trace_dir
_trace_sources =
read_file(_trace_folder_relative_path +
"/angle_capture_context${_contextid}_files.txt",
"list lines") +
[
"angle_capture_context${_contextid}.cpp",
"angle_capture_context${_contextid}.h",
generated_sources + [
"CompositeTests${angle_capture_replay_composite_file_id}.h",
"CompositeTests${angle_capture_replay_composite_file_id}.cpp",
]
sources = rebase_path(_trace_sources, ".", _trace_folder_relative_path) +
[ "CaptureReplayTest.cpp" ]
[ "CaptureReplayTests.cpp" ]
deps = [
"$angle_root:angle_common",
"$angle_root:angle_compression",
......@@ -53,8 +55,11 @@ if (angle_build_capture_replay_tests) {
defines = [
"ANGLE_CAPTURE_REPLAY_TEST_DATA_DIR=\"${_data_path}\"",
"ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID=${_contextid}",
"ANGLE_CAPTURE_REPLAY_TEST_HEADER=" + "${angle_capture_replay_test_trace_dir}/angle_capture_context${_contextid}.h",
"ANGLE_CAPTURE_REPLAY_COMPOSITE_TESTS_HEADER=" +
angle_capture_replay_test_trace_dir +
"/CompositeTests${angle_capture_replay_composite_file_id}.h",
]
include_dirs = [ "." ]
}
} else {
group("capture_replay_tests") {
......
......@@ -17,6 +17,7 @@
#include <stdint.h>
#include <string.h>
#include <functional>
#include <iostream>
#include <list>
#include <memory>
#include <string>
......@@ -26,29 +27,31 @@
// Build the right context header based on replay ID
// This will expand to "angle_capture_context<#>.h"
#include ANGLE_MACRO_STRINGIZE(ANGLE_CAPTURE_REPLAY_TEST_HEADER)
#include ANGLE_MACRO_STRINGIZE(ANGLE_CAPTURE_REPLAY_COMPOSITE_TESTS_HEADER)
// Assign the context numbered functions based on GN arg selecting replay ID
std::function<void()> SetupContextReplay = reinterpret_cast<void (*)()>(
std::function<void(uint32_t)> SetupContextReplay = reinterpret_cast<void (*)(uint32_t)>(
ANGLE_MACRO_CONCAT(SetupContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Replay)));
std::function<void(int)> ReplayContextFrame = reinterpret_cast<void (*)(int)>(
ANGLE_MACRO_CONCAT(ReplayContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Frame)));
std::function<void()> ResetContextReplay = reinterpret_cast<void (*)()>(
std::function<void(uint32_t, uint32_t)> ReplayContextFrame =
reinterpret_cast<void (*)(uint32_t, uint32_t)>(
ANGLE_MACRO_CONCAT(ReplayContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Frame)));
std::function<void(uint32_t)> ResetContextReplay = reinterpret_cast<void (*)(uint32_t)>(
ANGLE_MACRO_CONCAT(ResetContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, Replay)));
std::function<std::vector<uint8_t>(uint32_t)> GetSerializedContextStateData =
reinterpret_cast<std::vector<uint8_t> (*)(uint32_t)>(
std::function<std::vector<uint8_t>(uint32_t, uint32_t)> GetSerializedContextStateData =
reinterpret_cast<std::vector<uint8_t> (*)(uint32_t, uint32_t)>(
ANGLE_MACRO_CONCAT(GetSerializedContext,
ANGLE_MACRO_CONCAT(ANGLE_CAPTURE_REPLAY_TEST_CONTEXT_ID, StateData)));
class CaptureReplayTest
const std::string resultTag = "*RESULT";
class CaptureReplayTests
{
public:
CaptureReplayTest(EGLint glesMajorVersion, EGLint glesMinorVersion)
CaptureReplayTests(EGLint glesMajorVersion, EGLint glesMinorVersion)
: mOSWindow(nullptr), mEGLWindow(nullptr)
{
mPlatformParams.renderer = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
mPlatformParams.deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
......@@ -56,110 +59,124 @@ class CaptureReplayTest
// Load EGL library so we can initialize the display.
mEntryPointsLib.reset(
angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ApplicationDir));
mEGLWindow = EGLWindow::New(glesMajorVersion, glesMinorVersion);
mOSWindow = OSWindow::New();
mOSWindow->disableErrorMessageDialog();
}
~CaptureReplayTest()
~CaptureReplayTests()
{
EGLWindow::Delete(&mEGLWindow);
OSWindow::Delete(&mOSWindow);
}
bool initialize()
{
// Set CWD to executable directory.
std::string exeDir = angle::GetExecutableDirectory();
if (!angle::SetCWD(exeDir.c_str()))
return false;
if (kIsBinaryDataCompressed)
{
SetBinaryDataDecompressCallback(angle::DecompressBinaryData);
}
SetBinaryDataDir(ANGLE_CAPTURE_REPLAY_TEST_DATA_DIR);
SetupContextReplay();
return true;
}
void swap() { mEGLWindow->swap(); }
int run()
bool initializeTest(uint32_t testIndex, TestTraceInfo &testTraceInfo)
{
if (!mOSWindow->initialize("Capture Replay Test", kReplayDrawSurfaceWidth,
kReplayDrawSurfaceHeight))
if (!mOSWindow->initialize(testTraceInfo.testName, testTraceInfo.replayDrawSurfaceWidth,
testTraceInfo.replayDrawSurfaceHeight))
{
return -1;
return false;
}
mOSWindow->disableErrorMessageDialog();
mOSWindow->setVisible(true);
ConfigParameters configParams;
configParams.redBits = kDefaultFramebufferRedBits;
configParams.greenBits = kDefaultFramebufferGreenBits;
configParams.blueBits = kDefaultFramebufferBlueBits;
configParams.alphaBits = kDefaultFramebufferAlphaBits;
configParams.depthBits = kDefaultFramebufferDepthBits;
configParams.stencilBits = kDefaultFramebufferStencilBits;
configParams.redBits = testTraceInfo.defaultFramebufferRedBits;
configParams.greenBits = testTraceInfo.defaultFramebufferGreenBits;
configParams.blueBits = testTraceInfo.defaultFramebufferBlueBits;
configParams.alphaBits = testTraceInfo.defaultFramebufferAlphaBits;
configParams.depthBits = testTraceInfo.defaultFramebufferDepthBits;
configParams.stencilBits = testTraceInfo.defaultFramebufferStencilBits;
if (!mEGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(),
angle::GLESDriverType::AngleEGL, mPlatformParams,
configParams))
{
return -1;
mOSWindow->destroy();
return false;
}
// Disable vsync
if (!mEGLWindow->setSwapInterval(0))
{
return -1;
cleanupTest();
return false;
}
// Set CWD to executable directory.
std::string exeDir = angle::GetExecutableDirectory();
if (!angle::SetCWD(exeDir.c_str()))
{
cleanupTest();
return false;
}
if (testTraceInfo.isBinaryDataCompressed)
{
SetBinaryDataDecompressCallback(testIndex, angle::DecompressBinaryData);
}
SetBinaryDataDir(testIndex, ANGLE_CAPTURE_REPLAY_TEST_DATA_DIR);
SetupContextReplay(testIndex);
return true;
}
void cleanupTest()
{
mEGLWindow->destroyGL();
mOSWindow->destroy();
}
int result = 0;
void swap() { mEGLWindow->swap(); }
if (!initialize())
int runTest(uint32_t testIndex, TestTraceInfo &testTraceInfo)
{
if (!initializeTest(testIndex, testTraceInfo))
{
result = -1;
return -1;
}
for (uint32_t frame = kReplayFrameStart; frame <= kReplayFrameEnd; frame++)
for (uint32_t frame = testTraceInfo.replayFrameStart; frame <= testTraceInfo.replayFrameEnd;
frame++)
{
ReplayContextFrame(frame);
ReplayContextFrame(testIndex, 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)
{
cleanupTest();
return -1;
}
bool isEqual = compareSerializedStates(frame, bos);
bool isEqual = compareSerializedStates(testIndex, frame, bos);
if (!isEqual)
{
cleanupTest();
return -1;
}
swap();
}
cleanupTest();
return 0;
}
mEGLWindow->destroyGL();
mOSWindow->destroy();
return result;
int run()
{
for (size_t i = 0; i < testTraceInfos.size(); i++)
{
int result = runTest(static_cast<uint32_t>(i), testTraceInfos[i]);
std::cout << resultTag << " " << testTraceInfos[i].testName << " " << result << "\n";
}
return 0;
}
private:
bool compareSerializedStates(uint32_t frame,
bool compareSerializedStates(uint32_t testIndex,
uint32_t frame,
const gl::BinaryOutputStream &replaySerializedContextData)
{
return GetSerializedContextStateData(frame) == replaySerializedContextData.getData();
return GetSerializedContextStateData(testIndex, frame) ==
replaySerializedContextData.getData();
}
OSWindow *mOSWindow;
EGLWindow *mEGLWindow;
EGLPlatformParameters mPlatformParams;
// Handle to the entry point binding library.
std::unique_ptr<angle::Library> mEntryPointsLib;
};
......@@ -169,6 +186,6 @@ int main(int argc, char **argv)
// TODO (nguyenmh): http://anglebug.com/4759: initialize app with arguments taken from cmdline
const EGLint glesMajorVersion = 2;
const GLint glesMinorVersion = 0;
CaptureReplayTest app(glesMajorVersion, glesMinorVersion);
CaptureReplayTests app(glesMajorVersion, glesMinorVersion);
return app.run();
}
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