mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +09:00
[Feat] (trace-replay): add Minecraft in-world fixture
This commit is contained in:
@@ -199,6 +199,27 @@ jobs:
|
|||||||
--fuzz-percent 20
|
--fuzz-percent 20
|
||||||
--timeout-seconds 180
|
--timeout-seconds 180
|
||||||
|| status=1;
|
|| status=1;
|
||||||
|
sh android-plugin/trace-replay-ci.sh
|
||||||
|
--apk-file "${apk_file}"
|
||||||
|
--package top.mobilegl.plugin.espryt.trace
|
||||||
|
--backend DirectGLES
|
||||||
|
--result-root android-retrace-result
|
||||||
|
--fixture-root android-retrace-fixture
|
||||||
|
--case minecraft-1.21.4-in-world
|
||||||
|
--trace-archive tools/trace_replay/fixtures/minecraft-1.21.4-in-world.tgz
|
||||||
|
--trace-file trace.trace
|
||||||
|
--golden tools/trace_replay/fixtures/minecraft-1.21.4-in-world.0004000686.png
|
||||||
|
--target-call 4000686
|
||||||
|
--width 854
|
||||||
|
--height 480
|
||||||
|
--tolerance 500
|
||||||
|
--crop-x 0
|
||||||
|
--crop-y 0
|
||||||
|
--crop-width 0
|
||||||
|
--crop-height 0
|
||||||
|
--fuzz-percent 20
|
||||||
|
--timeout-seconds 900
|
||||||
|
|| status=1;
|
||||||
mkdir -p android-retrace-result/status;
|
mkdir -p android-retrace-result/status;
|
||||||
echo "${status}" > android-retrace-result/status/DirectGLES.status;
|
echo "${status}" > android-retrace-result/status/DirectGLES.status;
|
||||||
exit 0
|
exit 0
|
||||||
@@ -280,6 +301,27 @@ jobs:
|
|||||||
--fuzz-percent 20
|
--fuzz-percent 20
|
||||||
--timeout-seconds 180
|
--timeout-seconds 180
|
||||||
|| status=1;
|
|| status=1;
|
||||||
|
sh android-plugin/trace-replay-ci.sh
|
||||||
|
--apk-file "${apk_file}"
|
||||||
|
--package top.mobilegl.plugin.magma.trace
|
||||||
|
--backend DirectVulkan
|
||||||
|
--result-root android-retrace-result
|
||||||
|
--fixture-root android-retrace-fixture
|
||||||
|
--case minecraft-1.21.4-in-world
|
||||||
|
--trace-archive tools/trace_replay/fixtures/minecraft-1.21.4-in-world.tgz
|
||||||
|
--trace-file trace.trace
|
||||||
|
--golden tools/trace_replay/fixtures/minecraft-1.21.4-in-world.0004000686.png
|
||||||
|
--target-call 4000686
|
||||||
|
--width 854
|
||||||
|
--height 480
|
||||||
|
--tolerance 500
|
||||||
|
--crop-x 0
|
||||||
|
--crop-y 0
|
||||||
|
--crop-width 0
|
||||||
|
--crop-height 0
|
||||||
|
--fuzz-percent 20
|
||||||
|
--timeout-seconds 900
|
||||||
|
|| status=1;
|
||||||
mkdir -p android-retrace-result/status;
|
mkdir -p android-retrace-result/status;
|
||||||
echo "${status}" > android-retrace-result/status/DirectVulkan.status;
|
echo "${status}" > android-retrace-result/status/DirectVulkan.status;
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <MG_State/EGLState/Core.h>
|
#include <MG_State/EGLState/Core.h>
|
||||||
#include <MG_Impl/GLImpl/Texture/ProxyTexture.h>
|
#include <MG_Impl/GLImpl/Texture/ProxyTexture.h>
|
||||||
#include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h>
|
#include <MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace MobileGL {
|
namespace MobileGL {
|
||||||
namespace {
|
namespace {
|
||||||
@@ -66,6 +67,9 @@ namespace MobileGL {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((destructor)) static void AutoDestroy() {
|
__attribute__((destructor)) static void AutoDestroy() {
|
||||||
|
if (std::getenv("MOBILEGL_TRACE_SKIP_AUTODESTROY") != nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include "apitrace_exit.hpp"
|
#include "apitrace_exit.hpp"
|
||||||
#include "png.h"
|
#include "png.h"
|
||||||
|
#include "trace_parser.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
@@ -113,6 +114,7 @@ std::string JsonEscape(const std::string& value) {
|
|||||||
bool LoadMobileGL(const Request& request, std::string& error) {
|
bool LoadMobileGL(const Request& request, std::string& error) {
|
||||||
setenv("MOBILEGL_BACKEND_TYPE", request.backend.c_str(), 1);
|
setenv("MOBILEGL_BACKEND_TYPE", request.backend.c_str(), 1);
|
||||||
setenv("MOBILEGL_TRACE_LIBRARY", request.mobileGlLibrary.c_str(), 1);
|
setenv("MOBILEGL_TRACE_LIBRARY", request.mobileGlLibrary.c_str(), 1);
|
||||||
|
setenv("MOBILEGL_TRACE_SKIP_AUTODESTROY", "1", 1);
|
||||||
|
|
||||||
void* handle = dlopen(request.mobileGlLibrary.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
void* handle = dlopen(request.mobileGlLibrary.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
@@ -345,9 +347,38 @@ std::string SnapshotPathForCall(const Request& request) {
|
|||||||
return request.outputDir + "/actual." + call + ".png";
|
return request.outputDir + "/actual." + call + ".png";
|
||||||
}
|
}
|
||||||
|
|
||||||
int RunRetraceMain(const Request& request) {
|
bool TargetCallSwapsRenderTarget(const Request& request, bool& swapsRenderTarget, std::string& error) {
|
||||||
|
trace::Parser parser;
|
||||||
|
if (!parser.open(request.tracePath.c_str())) {
|
||||||
|
error = "failed to open trace for target call inspection";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace::Call* call = nullptr;
|
||||||
|
while ((call = parser.parse_call()) != nullptr) {
|
||||||
|
const long long callNo = static_cast<long long>(call->no);
|
||||||
|
if (callNo == request.targetCall) {
|
||||||
|
swapsRenderTarget = (call->flags & trace::CALL_FLAG_SWAP_RENDERTARGET) != 0;
|
||||||
|
delete call;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (callNo > request.targetCall) {
|
||||||
|
delete call;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delete call;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream message;
|
||||||
|
message << "target_call " << request.targetCall << " was not found in trace";
|
||||||
|
error = message.str();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RunRetraceMain(const Request& request, bool usePresentDump) {
|
||||||
std::string prefix = request.outputDir + "/actual.";
|
std::string prefix = request.outputDir + "/actual.";
|
||||||
std::string callSet = std::to_string(request.targetCall);
|
const long long snapshotCall = usePresentDump ? request.targetCall + 1 : request.targetCall;
|
||||||
|
std::string callSet = std::to_string(snapshotCall);
|
||||||
|
|
||||||
std::string arg0 = "mobilegl-glretrace";
|
std::string arg0 = "mobilegl-glretrace";
|
||||||
std::string argBenchmark = "-b";
|
std::string argBenchmark = "-b";
|
||||||
@@ -374,11 +405,11 @@ int RunRetraceMain(const Request& request) {
|
|||||||
return MOBILEGL_APITRACE_RETRACE_MAIN(10, argv);
|
return MOBILEGL_APITRACE_RETRACE_MAIN(10, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunRetrace(const Request& request, Result& result) {
|
bool RunRetrace(const Request& request, bool usePresentDump, Result& result) {
|
||||||
int status = 0;
|
int status = 0;
|
||||||
try {
|
try {
|
||||||
ScopedFdRedirect redirect(request.outputDir + "/retrace.log");
|
ScopedFdRedirect redirect(request.outputDir + "/retrace.log");
|
||||||
status = RunRetraceMain(request);
|
status = RunRetraceMain(request, usePresentDump);
|
||||||
} catch (const MobileGLRetraceExit& retraceExit) {
|
} catch (const MobileGLRetraceExit& retraceExit) {
|
||||||
status = retraceExit.status;
|
status = retraceExit.status;
|
||||||
} catch (const std::exception& exception) {
|
} catch (const std::exception& exception) {
|
||||||
@@ -402,7 +433,7 @@ bool RunRetrace(const Request& request, Result& result) {
|
|||||||
std::string snapshotPath = SnapshotPathForCall(request);
|
std::string snapshotPath = SnapshotPathForCall(request);
|
||||||
const std::string presentPath = request.outputDir + "/present.ppm";
|
const std::string presentPath = request.outputDir + "/present.ppm";
|
||||||
const bool hasSnapshot = Exists(snapshotPath);
|
const bool hasSnapshot = Exists(snapshotPath);
|
||||||
const bool hasPresentDump = request.backend == "DirectVulkan" && Exists(presentPath);
|
const bool hasPresentDump = usePresentDump && Exists(presentPath);
|
||||||
if (!hasSnapshot && !hasPresentDump) {
|
if (!hasSnapshot && !hasPresentDump) {
|
||||||
result.statusCode = STATUS_RETRACE_FAILED;
|
result.statusCode = STATUS_RETRACE_FAILED;
|
||||||
result.message = "retrace completed but did not create expected snapshot: " + snapshotPath;
|
result.message = "retrace completed but did not create expected snapshot: " + snapshotPath;
|
||||||
@@ -415,7 +446,7 @@ bool RunRetrace(const Request& request, Result& result) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (request.backend == "DirectVulkan") {
|
if (usePresentDump) {
|
||||||
if (hasPresentDump) {
|
if (hasPresentDump) {
|
||||||
RgbaImage present;
|
RgbaImage present;
|
||||||
std::string imageError;
|
std::string imageError;
|
||||||
@@ -648,7 +679,17 @@ Result RunTraceReplay(const Request& request) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool usePresentDump = false;
|
||||||
if (request.backend == "DirectVulkan") {
|
if (request.backend == "DirectVulkan") {
|
||||||
|
std::string inspectError;
|
||||||
|
if (!TargetCallSwapsRenderTarget(request, usePresentDump, inspectError)) {
|
||||||
|
result.statusCode = STATUS_INVALID_ARGUMENT;
|
||||||
|
result.message = inspectError;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usePresentDump) {
|
||||||
std::string presentDumpPath = request.outputDir + "/present.ppm";
|
std::string presentDumpPath = request.outputDir + "/present.ppm";
|
||||||
std::string presentDumpCall = std::to_string(request.targetCall);
|
std::string presentDumpCall = std::to_string(request.targetCall);
|
||||||
setenv("MOBILEGL_PRESENT_DUMP_PATH", presentDumpPath.c_str(), 1);
|
setenv("MOBILEGL_PRESENT_DUMP_PATH", presentDumpPath.c_str(), 1);
|
||||||
@@ -670,7 +711,7 @@ Result RunTraceReplay(const Request& request) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RunRetrace(request, result)) {
|
if (!RunRetrace(request, usePresentDump, result)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -375,3 +375,13 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-main-menu
|
|||||||
HEIGHT 480
|
HEIGHT 480
|
||||||
TOLERANCE 500
|
TOLERANCE 500
|
||||||
FUZZ_PERCENT 20)
|
FUZZ_PERCENT 20)
|
||||||
|
|
||||||
|
add_trace_replay_test_for_backends(minecraft-1.21.4-in-world
|
||||||
|
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-in-world.tgz
|
||||||
|
TRACE_FILE trace.trace
|
||||||
|
GOLDEN ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-in-world.0004000686.png
|
||||||
|
TARGET_CALL 4000686
|
||||||
|
WIDTH 854
|
||||||
|
HEIGHT 480
|
||||||
|
TOLERANCE 500
|
||||||
|
FUZZ_PERCENT 20)
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ The bundled fixtures cover:
|
|||||||

|

|
||||||
- minecraft-1.21.4-main-menu: captured from Minecraft 1.21.4's main menu.
|
- minecraft-1.21.4-main-menu: captured from Minecraft 1.21.4's main menu.
|
||||||

|

|
||||||
|
- minecraft-1.21.4-in-world: captured from Minecraft 1.21.4 after entering a singleplayer world.
|
||||||
|

|
||||||
|
|
||||||
Build from the MobileGL repository root:
|
Build from the MobileGL repository root:
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 337 KiB |
Binary file not shown.
Reference in New Issue
Block a user