1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
7.8 KiB

//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CaptureReplayTest.cpp:
// Application that runs replay for testing of capture replay
//
#include "common/debug.h"
#include "common/system_utils.h"
#include "util/EGLPlatformParameters.h"
#include "util/EGLWindow.h"
#include "util/OSWindow.h"
#include <stdint.h>
#include <string.h>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include "util/capture/frame_capture_test_utils.h"
constexpr char kResultTag[] = "*RESULT";
constexpr char kTracePath[] = ANGLE_CAPTURE_REPLAY_TEST_NAMES_PATH;
class CaptureReplayTests
{
public:
CaptureReplayTests()
{
// Load EGL library so we can initialize the display.
mEntryPointsLib.reset(
angle::OpenSharedLibrary(ANGLE_EGL_LIBRARY_NAME, angle::SearchType::ModuleDir));
mOSWindow = OSWindow::New();
mOSWindow->disableErrorMessageDialog();
}
~CaptureReplayTests()
{
EGLWindow::Delete(&mEGLWindow);
OSWindow::Delete(&mOSWindow);
}
bool initializeTest(const angle::TraceInfo &traceInfo)
{
if (!mOSWindow->initialize(traceInfo.name, traceInfo.drawSurfaceWidth,
traceInfo.drawSurfaceHeight))
{
return false;
}
mOSWindow->disableErrorMessageDialog();
mOSWindow->setVisible(true);
if (mEGLWindow && !mEGLWindow->isContextVersion(traceInfo.contextClientMajorVersion,
traceInfo.contextClientMinorVersion))
{
EGLWindow::Delete(&mEGLWindow);
mEGLWindow = nullptr;
}
if (!mEGLWindow)
{
mEGLWindow = EGLWindow::New(traceInfo.contextClientMajorVersion,
traceInfo.contextClientMinorVersion);
}
ConfigParameters configParams;
configParams.redBits = traceInfo.configRedBits;
configParams.greenBits = traceInfo.configGreenBits;
configParams.blueBits = traceInfo.configBlueBits;
configParams.alphaBits = traceInfo.configAlphaBits;
configParams.depthBits = traceInfo.configDepthBits;
configParams.stencilBits = traceInfo.configStencilBits;
configParams.clientArraysEnabled = traceInfo.areClientArraysEnabled;
configParams.bindGeneratesResource = traceInfo.isBindGeneratesResourcesEnabled;
configParams.webGLCompatibility = traceInfo.isWebGLCompatibilityEnabled;
configParams.robustResourceInit = traceInfo.isRobustResourceInitEnabled;
mPlatformParams.renderer = traceInfo.displayPlatformType;
mPlatformParams.deviceType = traceInfo.displayDeviceType;
mPlatformParams.forceInitShaderVariables = EGL_TRUE;
if (!mEGLWindow->initializeGL(mOSWindow, mEntryPointsLib.get(),
angle::GLESDriverType::AngleEGL, mPlatformParams,
configParams))
{
mOSWindow->destroy();
return false;
}
// Disable vsync
if (!mEGLWindow->setSwapInterval(0))
{
cleanupTest();
return false;
}
// Load trace
mTraceLibrary.reset(new angle::TraceLibrary(traceInfo.name));
if (!mTraceLibrary->valid())
{
std::cout << "Failed to load trace library: " << traceInfo.name << "\n";
return false;
}
if (traceInfo.isBinaryDataCompressed)
{
mTraceLibrary->setBinaryDataDecompressCallback(angle::DecompressBinaryData);
}
mTraceLibrary->setBinaryDataDir(ANGLE_CAPTURE_REPLAY_TEST_DATA_DIR);
mTraceLibrary->setupReplay();
return true;
}
void cleanupTest()
{
mTraceLibrary.reset(nullptr);
mEGLWindow->destroyGL();
mOSWindow->destroy();
}
void swap() { mEGLWindow->swap(); }
int runTest(const angle::TraceInfo &traceInfo)
{
if (!initializeTest(traceInfo))
{
return -1;
}
for (uint32_t frame = traceInfo.frameStart; frame <= traceInfo.frameEnd; frame++)
{
mTraceLibrary->replayFrame(frame);
const char *capturedSerializedState =
reinterpret_cast<const char *>(glGetString(GL_SERIALIZED_CONTEXT_STRING_ANGLE));
const char *replayedSerializedState = mTraceLibrary->getSerializedContextState(frame);
bool isEqual =
(capturedSerializedState && replayedSerializedState)
? compareSerializedContexts(replayedSerializedState, capturedSerializedState)
: (capturedSerializedState == replayedSerializedState);
// Swap always to allow RenderDoc/other tools to capture frames.
swap();
if (!isEqual)
{
std::ostringstream replayName;
replayName << traceInfo.name << "_ContextReplayed" << frame << ".json";
std::ofstream debugReplay(replayName.str());
debugReplay << (replayedSerializedState ? replayedSerializedState : "") << "\n";
std::ostringstream captureName;
captureName << traceInfo.name << "_ContextCaptured" << frame << ".json";
std::ofstream debugCapture(captureName.str());
debugCapture << (capturedSerializedState ? capturedSerializedState : "") << "\n";
cleanupTest();
return -1;
}
}
cleanupTest();
return 0;
}
int run()
{
std::string startingDirectory = angle::GetCWD().value();
// Set CWD to executable directory.
std::string exeDir = angle::GetExecutableDirectory();
if (!angle::SetCWD(exeDir.c_str()))
{
std::cout << "Unable to SetCWD to trace directory: " << exeDir << "\n";
return 1;
}
std::vector<std::string> traces;
if (!angle::LoadTraceNamesFromJSON(kTracePath, &traces))
{
std::cout << "Unable to load trace names from " << kTracePath << "\n";
return 1;
}
for (const std::string &trace : traces)
{
std::stringstream traceJsonPathStream;
traceJsonPathStream << ANGLE_CAPTURE_REPLAY_TEST_DATA_DIR << angle::GetPathSeparator()
<< trace << ".json";
std::string traceJsonPath = traceJsonPathStream.str();
int result = -1;
angle::TraceInfo traceInfo = {};
if (!angle::LoadTraceInfoFromJSON(trace, traceJsonPath, &traceInfo))
{
std::cout << "Unable to load trace data: " << traceJsonPath << "\n";
}
else
{
result = runTest(traceInfo);
}
std::cout << kResultTag << " " << trace << " " << result << "\n";
}
angle::SetCWD(startingDirectory.c_str());
return 0;
}
private:
bool compareSerializedContexts(const char *capturedSerializedContextState,
const char *replaySerializedContextState)
{
return !strcmp(replaySerializedContextState, capturedSerializedContextState);
}
OSWindow *mOSWindow = nullptr;
EGLWindow *mEGLWindow = nullptr;
EGLPlatformParameters mPlatformParams;
// Handle to the entry point binding library.
std::unique_ptr<angle::Library> mEntryPointsLib;
std::unique_ptr<angle::TraceLibrary> mTraceLibrary;
};
int main(int argc, char **argv)
{
CaptureReplayTests app;
return app.run();
}