[Fix] (trace-replay): use SSIM for golden validation

This commit is contained in:
2026-06-23 21:26:55 +08:00
parent f0f6d1e5fa
commit 2f52264f01
14 changed files with 159 additions and 266 deletions
+1 -38
View File
@@ -158,12 +158,10 @@ jobs:
target_call: 31249 target_call: 31249
width: 640 width: 640
height: 480 height: 480
tolerance: 3072
crop_x: 1 crop_x: 1
crop_y: 1 crop_y: 1
crop_width: 638 crop_width: 638
crop_height: 478 crop_height: 478
fuzz_percent: 20
timeout_seconds: 180 timeout_seconds: 180
- name: minecraft-1.21.4-startup - name: minecraft-1.21.4-startup
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-startup.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-startup.tgz
@@ -172,12 +170,10 @@ jobs:
target_call: 92195 target_call: 92195
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 180 timeout_seconds: 180
- name: minecraft-1.21.4-main-menu - name: minecraft-1.21.4-main-menu
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-main-menu.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-main-menu.tgz
@@ -186,12 +182,10 @@ jobs:
target_call: 481787 target_call: 481787
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 180 timeout_seconds: 180
- name: minecraft-1.21.4-in-world - name: minecraft-1.21.4-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-in-world.tgz
@@ -200,12 +194,10 @@ jobs:
target_call: 280000 target_call: 280000
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-sodium-in-world - name: minecraft-1.21.4-fabric-sodium-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-sodium-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-sodium-in-world.tgz
@@ -214,12 +206,10 @@ jobs:
target_call: 923340 target_call: 923340
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 1800 timeout_seconds: 1800
- name: minecraft-1.21.4-fabric-iris-bsl-in-world - name: minecraft-1.21.4-fabric-iris-bsl-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.tgz
@@ -228,12 +218,10 @@ jobs:
target_call: 110725 target_call: 110725
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world - name: minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world.tgz
@@ -242,12 +230,10 @@ jobs:
target_call: 95322 target_call: 95322
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world - name: minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world.tgz
@@ -256,12 +242,10 @@ jobs:
target_call: 141559 target_call: 141559
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-sundial-lite-in-world - name: minecraft-1.21.4-fabric-iris-sundial-lite-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-sundial-lite-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-sundial-lite-in-world.tgz
@@ -270,12 +254,10 @@ jobs:
target_call: 150023 target_call: 150023
width: 854 width: 854
height: 480 height: 480
tolerance: 8000
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world - name: minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world.tgz
@@ -284,12 +266,10 @@ jobs:
target_call: 151297 target_call: 151297
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-complementary-unbound-in-world - name: minecraft-1.21.4-fabric-iris-complementary-unbound-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-unbound-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-complementary-unbound-in-world.tgz
@@ -298,12 +278,10 @@ jobs:
target_call: 146559 target_call: 146559
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-mellow-in-world - name: minecraft-1.21.4-fabric-iris-mellow-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-mellow-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-mellow-in-world.tgz
@@ -312,12 +290,10 @@ jobs:
target_call: 96143 target_call: 96143
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-nostalgia-in-world - name: minecraft-1.21.4-fabric-iris-nostalgia-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-nostalgia-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-nostalgia-in-world.tgz
@@ -327,12 +303,10 @@ jobs:
target_call: 153808 target_call: 153808
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-bliss-in-world - name: minecraft-1.21.4-fabric-iris-bliss-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bliss-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bliss-in-world.tgz
@@ -341,12 +315,10 @@ jobs:
target_call: 113511 target_call: 113511
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world - name: minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.tgz
@@ -355,12 +327,10 @@ jobs:
target_call: 125124 target_call: 125124
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
- name: minecraft-1.21.4-fabric-iris-iterationt-in-world - name: minecraft-1.21.4-fabric-iris-iterationt-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.tgz
@@ -369,12 +339,10 @@ jobs:
target_call: 1173280 target_call: 1173280
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 2400 timeout_seconds: 2400
- name: minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world - name: minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world.tgz
@@ -383,12 +351,10 @@ jobs:
target_call: 1606997 target_call: 1606997
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 2400 timeout_seconds: 2400
- name: minecraft-1.21.4-fabric-iris-photon-v1.1-in-world - name: minecraft-1.21.4-fabric-iris-photon-v1.1-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.1-in-world.tgz trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.1-in-world.tgz
@@ -397,12 +363,10 @@ jobs:
target_call: 159866 target_call: 159866
width: 854 width: 854
height: 480 height: 480
tolerance: 4100
crop_x: 0 crop_x: 0
crop_y: 0 crop_y: 0
crop_width: 0 crop_width: 0
crop_height: 0 crop_height: 0
fuzz_percent: 20
timeout_seconds: 900 timeout_seconds: 900
steps: steps:
@@ -472,12 +436,11 @@ jobs:
--target-call "${{ matrix.case.target_call }}" \ --target-call "${{ matrix.case.target_call }}" \
--width "${{ matrix.case.width }}" \ --width "${{ matrix.case.width }}" \
--height "${{ matrix.case.height }}" \ --height "${{ matrix.case.height }}" \
--tolerance "${{ matrix.case.tolerance }}" \ --ssim-threshold "${{ matrix.case.ssim_threshold || '0.99' }}" \
--crop-x "${{ matrix.case.crop_x }}" \ --crop-x "${{ matrix.case.crop_x }}" \
--crop-y "${{ matrix.case.crop_y }}" \ --crop-y "${{ matrix.case.crop_y }}" \
--crop-width "${{ matrix.case.crop_width }}" \ --crop-width "${{ matrix.case.crop_width }}" \
--crop-height "${{ matrix.case.crop_height }}" \ --crop-height "${{ matrix.case.crop_height }}" \
--fuzz-percent "${{ matrix.case.fuzz_percent }}" \
--timeout-seconds "${{ matrix.case.timeout_seconds }}" --timeout-seconds "${{ matrix.case.timeout_seconds }}"
- name: Collect emulator diagnostics - name: Collect emulator diagnostics
+3 -5
View File
@@ -32,8 +32,7 @@ target_frame target frame index, or -1
target_call target call number, or -1 target_call target call number, or -1
width optional replay surface width override width optional replay surface width override
height optional replay surface height override height optional replay surface height override
tolerance allowed mismatching pixel count after fuzz is applied ssim_threshold minimum SSIM required to pass; default is 0.99
fuzz_percent per-channel fuzz percentage; default is 20
crop_x optional compare crop x crop_x optional compare crop x
crop_y optional compare crop y crop_y optional compare crop y
crop_width optional compare crop width crop_width optional compare crop width
@@ -48,7 +47,7 @@ Implementation notes:
- The native runner validates inputs, sets `MOBILEGL_BACKEND_TYPE`, loads `libMobileGL.so`, runs apitrace GL retrace, writes `actual.png`, and writes `result.json`. - The native runner validates inputs, sets `MOBILEGL_BACKEND_TYPE`, loads `libMobileGL.so`, runs apitrace GL retrace, writes `actual.png`, and writes `result.json`.
- The runner uses a MobileGL-backed EGL window-system shim. GLX calls in PC traces are consumed by apitrace's GLX retrace frontend and mapped onto this EGL shim; the Android runner does not require or call a MobileGL GLX implementation. - The runner uses a MobileGL-backed EGL window-system shim. GLX calls in PC traces are consumed by apitrace's GLX retrace frontend and mapped onto this EGL shim; the Android runner does not require or call a MobileGL GLX implementation.
- `DirectGLES` replays on an EGL pbuffer by default, avoiding Android `SurfaceView` lifetime coupling. `DirectVulkan` still uses the Activity surface because it needs a native window-backed Vulkan swapchain. - `DirectGLES` replays on an EGL pbuffer by default, avoiding Android `SurfaceView` lifetime coupling. `DirectVulkan` still uses the Activity surface because it needs a native window-backed Vulkan swapchain.
- Golden comparison is implemented in native C++ with libpng RGBA decode. The Java Activity only passes arguments and displays the native result, so the replay/compare core is not tied to Android UI or Bitmap APIs and can be ported to Linux. - Golden comparison is implemented in native C++ with libpng RGBA decode and SSIM validation. The Java Activity only passes arguments and displays the native result, so the replay/compare core is not tied to Android UI or Bitmap APIs and can be ported to Linux.
- The plugin profile still excludes `libtrace_replay_runner.so`; normal plugin APK behavior is preserved. - The plugin profile still excludes `libtrace_replay_runner.so`; normal plugin APK behavior is preserved.
- Set `MOBILEGL_RETRACE_USE_ANGLE=1` when running `trace-replay-ci.sh` to pass `use_angle=true` for DirectGLES. The APK must include `libEGL_angle.so` and `libGLESv2_angle.so` under its x86_64 native libraries. The Activity passes Android's `nativeLibraryDir` to native code as `MOBILEGL_RETRACE_ANGLE_DIR`. - Set `MOBILEGL_RETRACE_USE_ANGLE=1` when running `trace-replay-ci.sh` to pass `use_angle=true` for DirectGLES. The APK must include `libEGL_angle.so` and `libGLESv2_angle.so` under its x86_64 native libraries. The Activity passes Android's `nativeLibraryDir` to native code as `MOBILEGL_RETRACE_ANGLE_DIR`.
@@ -68,7 +67,6 @@ adb shell am start -a top.mobilegl.plugin.TRACE_REPLAY \
--es diff_path /data/user/0/top.mobilegl.plugin.espryt.trace/files/trace-replay/output/app-diff.png \ --es diff_path /data/user/0/top.mobilegl.plugin.espryt.trace/files/trace-replay/output/app-diff.png \
--es backend DirectGLES \ --es backend DirectGLES \
--el target_call 31249 \ --el target_call 31249 \
--ei tolerance 0 \ --es ssim_threshold 0.99
--ei fuzz_percent 20
adb shell run-as top.mobilegl.plugin.espryt.trace cat files/trace-replay/output/result.json adb shell run-as top.mobilegl.plugin.espryt.trace cat files/trace-replay/output/result.json
``` ```
@@ -14,6 +14,7 @@
#include <cstring> #include <cstring>
#include <exception> #include <exception>
#include <fstream> #include <fstream>
#include <iomanip>
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
@@ -520,7 +521,6 @@ bool WriteDifferenceImage(const Result& result,
int y0, int y0,
int compareWidth, int compareWidth,
int compareHeight, int compareHeight,
int fuzz,
std::string& error) { std::string& error) {
if (result.diffPath.empty()) { if (result.diffPath.empty()) {
return true; return true;
@@ -548,7 +548,7 @@ bool WriteDifferenceImage(const Result& result,
ChannelValue(golden, imageX, imageY, 1)); ChannelValue(golden, imageX, imageY, 1));
int db = std::abs(ChannelValue(actual, imageX, imageY, 2) - int db = std::abs(ChannelValue(actual, imageX, imageY, 2) -
ChannelValue(golden, imageX, imageY, 2)); ChannelValue(golden, imageX, imageY, 2));
bool different = dr > fuzz || dg > fuzz || db > fuzz; bool different = dr != 0 || dg != 0 || db != 0;
std::uint8_t* dst = diff.pixels.data() + std::uint8_t* dst = diff.pixels.data() +
(static_cast<std::size_t>(imageY) * diff.width + imageX) * 4; (static_cast<std::size_t>(imageY) * diff.width + imageX) * 4;
if (different) { if (different) {
@@ -569,17 +569,71 @@ bool WriteDifferenceImage(const Result& result,
struct GoldenComparison { struct GoldenComparison {
std::string path; std::string path;
RgbaImage image; RgbaImage image;
long long mismatchPixels = std::numeric_limits<long long>::max(); double ssim = -1.0;
long long mismatchPixels = 0;
int x0 = 0; int x0 = 0;
int y0 = 0; int y0 = 0;
int compareWidth = 0; int compareWidth = 0;
int compareHeight = 0; int compareHeight = 0;
}; };
double ComputeChannelSsim(const RgbaImage& actual,
const RgbaImage& golden,
int x0,
int y0,
int compareWidth,
int compareHeight,
unsigned channel) {
const double count = static_cast<double>(compareWidth) * static_cast<double>(compareHeight);
double sumA = 0.0;
double sumG = 0.0;
double sumAA = 0.0;
double sumGG = 0.0;
double sumAG = 0.0;
for (int y = 0; y < compareHeight; ++y) {
for (int x = 0; x < compareWidth; ++x) {
const double a = ChannelValue(actual, x0 + x, y0 + y, channel);
const double g = ChannelValue(golden, x0 + x, y0 + y, channel);
sumA += a;
sumG += g;
sumAA += a * a;
sumGG += g * g;
sumAG += a * g;
}
}
const double meanA = sumA / count;
const double meanG = sumG / count;
const double varianceA = std::max(0.0, sumAA / count - meanA * meanA);
const double varianceG = std::max(0.0, sumGG / count - meanG * meanG);
const double covariance = sumAG / count - meanA * meanG;
constexpr double kC1 = 6.5025; // (0.01 * 255)^2
constexpr double kC2 = 58.5225; // (0.03 * 255)^2
const double luminance = (2.0 * meanA * meanG + kC1) /
(meanA * meanA + meanG * meanG + kC1);
const double contrastStructure = (2.0 * covariance + kC2) /
(varianceA + varianceG + kC2);
return luminance * contrastStructure;
}
double ComputeRgbSsim(const RgbaImage& actual,
const RgbaImage& golden,
int x0,
int y0,
int compareWidth,
int compareHeight) {
double sum = 0.0;
for (unsigned channel = 0; channel < 3; ++channel) {
sum += ComputeChannelSsim(actual, golden, x0, y0, compareWidth, compareHeight, channel);
}
return sum / 3.0;
}
bool CompareAgainstOneGolden(const Request& request, bool CompareAgainstOneGolden(const Request& request,
const RgbaImage& actual, const RgbaImage& actual,
const std::string& goldenPath, const std::string& goldenPath,
int fuzz,
GoldenComparison& comparison, GoldenComparison& comparison,
std::string& error) { std::string& error) {
if (!Exists(goldenPath)) { if (!Exists(goldenPath)) {
@@ -616,27 +670,28 @@ bool CompareAgainstOneGolden(const Request& request,
return false; return false;
} }
long long mismatch = 0; long long exactMismatch = 0;
for (int y = 0; y < compareHeight; ++y) { for (int y = 0; y < compareHeight; ++y) {
for (int x = 0; x < compareWidth; ++x) { for (int x = 0; x < compareWidth; ++x) {
bool different = false; bool different = false;
for (unsigned c = 0; c < 3; ++c) { for (unsigned c = 0; c < 3; ++c) {
int a = ChannelValue(actual, x0 + x, y0 + y, c); int a = ChannelValue(actual, x0 + x, y0 + y, c);
int g = ChannelValue(golden, x0 + x, y0 + y, c); int g = ChannelValue(golden, x0 + x, y0 + y, c);
if (std::abs(a - g) > fuzz) { if (a != g) {
different = true; different = true;
break; break;
} }
} }
if (different) { if (different) {
++mismatch; ++exactMismatch;
} }
} }
} }
comparison.path = goldenPath; comparison.path = goldenPath;
comparison.image = std::move(golden); comparison.image = std::move(golden);
comparison.mismatchPixels = mismatch; comparison.ssim = ComputeRgbSsim(actual, comparison.image, x0, y0, compareWidth, compareHeight);
comparison.mismatchPixels = exactMismatch;
comparison.x0 = x0; comparison.x0 = x0;
comparison.y0 = y0; comparison.y0 = y0;
comparison.compareWidth = compareWidth; comparison.compareWidth = compareWidth;
@@ -659,6 +714,7 @@ bool CompareWithGolden(const Request& request, Result& result) {
result.passed = true; result.passed = true;
result.statusCode = STATUS_OK; result.statusCode = STATUS_OK;
result.message = "retrace completed; golden_path was not provided"; result.message = "retrace completed; golden_path was not provided";
result.ssim = 1.0;
result.mismatchPixels = 0; result.mismatchPixels = 0;
return true; return true;
} }
@@ -671,18 +727,17 @@ bool CompareWithGolden(const Request& request, Result& result) {
return false; return false;
} }
const int fuzz = std::max(0, std::min(100, request.fuzzPercent)) * 255 / 100;
GoldenComparison bestComparison; GoldenComparison bestComparison;
std::string comparisonError; std::string comparisonError;
bool hasComparison = false; bool hasComparison = false;
for (const auto& goldenPath : goldenPaths) { for (const auto& goldenPath : goldenPaths) {
GoldenComparison comparison; GoldenComparison comparison;
std::string error; std::string error;
if (!CompareAgainstOneGolden(request, actual, goldenPath, fuzz, comparison, error)) { if (!CompareAgainstOneGolden(request, actual, goldenPath, comparison, error)) {
comparisonError = error; comparisonError = error;
continue; continue;
} }
if (!hasComparison || comparison.mismatchPixels < bestComparison.mismatchPixels) { if (!hasComparison || comparison.ssim > bestComparison.ssim) {
bestComparison = std::move(comparison); bestComparison = std::move(comparison);
hasComparison = true; hasComparison = true;
} }
@@ -696,20 +751,22 @@ bool CompareWithGolden(const Request& request, Result& result) {
std::string diffError; std::string diffError;
if (!WriteDifferenceImage(result, actual, bestComparison.image, bestComparison.x0, bestComparison.y0, if (!WriteDifferenceImage(result, actual, bestComparison.image, bestComparison.x0, bestComparison.y0,
bestComparison.compareWidth, bestComparison.compareHeight, fuzz, diffError)) { bestComparison.compareWidth, bestComparison.compareHeight, diffError)) {
result.statusCode = STATUS_IO_ERROR; result.statusCode = STATUS_IO_ERROR;
result.message = diffError.empty() ? "failed to write diff PNG" : diffError; result.message = diffError.empty() ? "failed to write diff PNG" : diffError;
return false; return false;
} }
result.ssim = bestComparison.ssim;
result.mismatchPixels = bestComparison.mismatchPixels; result.mismatchPixels = bestComparison.mismatchPixels;
result.matchedGoldenPath = bestComparison.path; result.matchedGoldenPath = bestComparison.path;
result.passed = bestComparison.mismatchPixels <= request.tolerance; result.passed = bestComparison.ssim >= request.ssimThreshold;
result.statusCode = result.passed ? STATUS_OK : STATUS_COMPARE_FAILED; result.statusCode = result.passed ? STATUS_OK : STATUS_COMPARE_FAILED;
std::ostringstream message; std::ostringstream message;
message << "retrace completed; mismatchPixels=" << bestComparison.mismatchPixels message << std::fixed << std::setprecision(6)
<< ", tolerance=" << request.tolerance << "retrace completed; ssim=" << bestComparison.ssim
<< ", fuzzPercent=" << request.fuzzPercent << ", ssimThreshold=" << request.ssimThreshold
<< ", mismatchPixels=" << bestComparison.mismatchPixels
<< ", matchedGoldenPath=" << bestComparison.path; << ", matchedGoldenPath=" << bestComparison.path;
result.message = message.str(); result.message = message.str();
return result.passed; return result.passed;
@@ -753,8 +810,9 @@ bool WriteResultJson(const Request& request, const Result& result) {
file << " \"cropY\": " << request.cropY << ",\n"; file << " \"cropY\": " << request.cropY << ",\n";
file << " \"cropWidth\": " << request.cropWidth << ",\n"; file << " \"cropWidth\": " << request.cropWidth << ",\n";
file << " \"cropHeight\": " << request.cropHeight << ",\n"; file << " \"cropHeight\": " << request.cropHeight << ",\n";
file << " \"tolerance\": " << request.tolerance << ",\n"; file << std::fixed << std::setprecision(9);
file << " \"fuzzPercent\": " << request.fuzzPercent << ",\n"; file << " \"ssim\": " << result.ssim << ",\n";
file << " \"ssimThreshold\": " << request.ssimThreshold << ",\n";
file << " \"useAngle\": " << (UseAngleForRequest(request) ? "true" : "false") << ",\n"; file << " \"useAngle\": " << (UseAngleForRequest(request) ? "true" : "false") << ",\n";
file << " \"mismatchPixels\": " << result.mismatchPixels << "\n"; file << " \"mismatchPixels\": " << result.mismatchPixels << "\n";
file << "}\n"; file << "}\n";
@@ -32,8 +32,7 @@ struct Request {
int cropY = 0; int cropY = 0;
int cropWidth = 0; int cropWidth = 0;
int cropHeight = 0; int cropHeight = 0;
int tolerance = 0; double ssimThreshold = 0.99;
int fuzzPercent = 20;
bool useAngle = false; bool useAngle = false;
}; };
@@ -45,6 +44,7 @@ struct Result {
std::string actualPath; std::string actualPath;
std::string diffPath; std::string diffPath;
std::string matchedGoldenPath; std::string matchedGoldenPath;
double ssim = -1.0;
long long mismatchPixels = -1; long long mismatchPixels = -1;
}; };
@@ -93,12 +93,11 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv*
jlong targetCall, jlong targetCall,
jint width, jint width,
jint height, jint height,
jint tolerance, jdouble ssimThreshold,
jint cropX, jint cropX,
jint cropY, jint cropY,
jint cropWidth, jint cropWidth,
jint cropHeight, jint cropHeight,
jint fuzzPercent,
jstring angleLibraryDir, jstring angleLibraryDir,
jboolean useAngle) { jboolean useAngle) {
mobilegl_trace::Request request; mobilegl_trace::Request request;
@@ -116,12 +115,11 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv*
request.targetCall = targetCall; request.targetCall = targetCall;
request.width = width; request.width = width;
request.height = height; request.height = height;
request.tolerance = tolerance; request.ssimThreshold = ssimThreshold;
request.cropX = cropX; request.cropX = cropX;
request.cropY = cropY; request.cropY = cropY;
request.cropWidth = cropWidth; request.cropWidth = cropWidth;
request.cropHeight = cropHeight; request.cropHeight = cropHeight;
request.fuzzPercent = fuzzPercent;
request.useAngle = useAngle == JNI_TRUE; request.useAngle = useAngle == JNI_TRUE;
ScopedTraceReplayState replayState; ScopedTraceReplayState replayState;
@@ -106,12 +106,11 @@ public final class TraceReplayActivity extends Activity {
request.targetCall, request.targetCall,
request.width, request.width,
request.height, request.height,
request.tolerance, request.ssimThreshold,
request.cropX, request.cropX,
request.cropY, request.cropY,
request.cropWidth, request.cropWidth,
request.cropHeight, request.cropHeight,
request.fuzzPercent,
request.angleLibraryDir, request.angleLibraryDir,
request.useAngle request.useAngle
); );
@@ -135,12 +134,11 @@ public final class TraceReplayActivity extends Activity {
long targetCall, long targetCall,
int width, int width,
int height, int height,
int tolerance, double ssimThreshold,
int cropX, int cropX,
int cropY, int cropY,
int cropWidth, int cropWidth,
int cropHeight, int cropHeight,
int fuzzPercent,
String angleLibraryDir, String angleLibraryDir,
boolean useAngle boolean useAngle
); );
@@ -156,12 +154,11 @@ public final class TraceReplayActivity extends Activity {
final long targetCall; final long targetCall;
final int width; final int width;
final int height; final int height;
final int tolerance; final double ssimThreshold;
final int cropX; final int cropX;
final int cropY; final int cropY;
final int cropWidth; final int cropWidth;
final int cropHeight; final int cropHeight;
final int fuzzPercent;
final String angleLibraryDir; final String angleLibraryDir;
final boolean useAngle; final boolean useAngle;
@@ -176,12 +173,11 @@ public final class TraceReplayActivity extends Activity {
long targetCall, long targetCall,
int width, int width,
int height, int height,
int tolerance, double ssimThreshold,
int cropX, int cropX,
int cropY, int cropY,
int cropWidth, int cropWidth,
int cropHeight, int cropHeight,
int fuzzPercent,
String angleLibraryDir, String angleLibraryDir,
boolean useAngle boolean useAngle
) { ) {
@@ -195,12 +191,11 @@ public final class TraceReplayActivity extends Activity {
this.targetCall = targetCall; this.targetCall = targetCall;
this.width = width; this.width = width;
this.height = height; this.height = height;
this.tolerance = tolerance; this.ssimThreshold = ssimThreshold;
this.cropX = cropX; this.cropX = cropX;
this.cropY = cropY; this.cropY = cropY;
this.cropWidth = cropWidth; this.cropWidth = cropWidth;
this.cropHeight = cropHeight; this.cropHeight = cropHeight;
this.fuzzPercent = fuzzPercent;
this.angleLibraryDir = angleLibraryDir; this.angleLibraryDir = angleLibraryDir;
this.useAngle = useAngle; this.useAngle = useAngle;
} }
@@ -219,12 +214,11 @@ public final class TraceReplayActivity extends Activity {
intent.getLongExtra("target_call", -1L), intent.getLongExtra("target_call", -1L),
intent.getIntExtra("width", 0), intent.getIntExtra("width", 0),
intent.getIntExtra("height", 0), intent.getIntExtra("height", 0),
intent.getIntExtra("tolerance", 0), readDouble(intent, "ssim_threshold", 0.99),
intent.getIntExtra("crop_x", 0), intent.getIntExtra("crop_x", 0),
intent.getIntExtra("crop_y", 0), intent.getIntExtra("crop_y", 0),
intent.getIntExtra("crop_width", 0), intent.getIntExtra("crop_width", 0),
intent.getIntExtra("crop_height", 0), intent.getIntExtra("crop_height", 0),
intent.getIntExtra("fuzz_percent", 20),
readString(intent, "angle_library_dir", nativeLibraryDir), readString(intent, "angle_library_dir", nativeLibraryDir),
intent.getBooleanExtra("use_angle", false) intent.getBooleanExtra("use_angle", false)
); );
@@ -234,6 +228,18 @@ public final class TraceReplayActivity extends Activity {
String value = intent.getStringExtra(key); String value = intent.getStringExtra(key);
return value == null ? fallback : value; return value == null ? fallback : value;
} }
private static double readDouble(Intent intent, String key, double fallback) {
String stringValue = intent.getStringExtra(key);
if (stringValue != null && !stringValue.isEmpty()) {
try {
return Double.parseDouble(stringValue);
} catch (NumberFormatException ignored) {
return fallback;
}
}
return intent.getDoubleExtra(key, fallback);
}
} }
public static final class TraceReplayResult { public static final class TraceReplayResult {
+6 -11
View File
@@ -21,12 +21,11 @@ Usage:
--target-call N \ --target-call N \
--width N \ --width N \
--height N \ --height N \
--tolerance N \ --ssim-threshold N \
--crop-x N \ --crop-x N \
--crop-y N \ --crop-y N \
--crop-width N \ --crop-width N \
--crop-height N \ --crop-height N \
--fuzz-percent N \
--timeout-seconds N --timeout-seconds N
Set MOBILEGL_RETRACE_USE_ANGLE=1 to run DirectGLES replay with packaged ANGLE Set MOBILEGL_RETRACE_USE_ANGLE=1 to run DirectGLES replay with packaged ANGLE
@@ -68,12 +67,11 @@ alternate_golden_path=""
target_call="" target_call=""
width="" width=""
height="" height=""
tolerance="" ssim_threshold=""
crop_x="" crop_x=""
crop_y="" crop_y=""
crop_width="" crop_width=""
crop_height="" crop_height=""
fuzz_percent=""
timeout_seconds="" timeout_seconds=""
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
@@ -99,12 +97,11 @@ while [ "$#" -gt 0 ]; do
--target-call) target_call="$(next_arg "$@")"; shift 2 ;; --target-call) target_call="$(next_arg "$@")"; shift 2 ;;
--width) width="$(next_arg "$@")"; shift 2 ;; --width) width="$(next_arg "$@")"; shift 2 ;;
--height) height="$(next_arg "$@")"; shift 2 ;; --height) height="$(next_arg "$@")"; shift 2 ;;
--tolerance) tolerance="$(next_arg "$@")"; shift 2 ;; --ssim-threshold) ssim_threshold="$(next_arg "$@")"; shift 2 ;;
--crop-x) crop_x="$(next_arg "$@")"; shift 2 ;; --crop-x) crop_x="$(next_arg "$@")"; shift 2 ;;
--crop-y) crop_y="$(next_arg "$@")"; shift 2 ;; --crop-y) crop_y="$(next_arg "$@")"; shift 2 ;;
--crop-width) crop_width="$(next_arg "$@")"; shift 2 ;; --crop-width) crop_width="$(next_arg "$@")"; shift 2 ;;
--crop-height) crop_height="$(next_arg "$@")"; shift 2 ;; --crop-height) crop_height="$(next_arg "$@")"; shift 2 ;;
--fuzz-percent) fuzz_percent="$(next_arg "$@")"; shift 2 ;;
--timeout-seconds) timeout_seconds="$(next_arg "$@")"; shift 2 ;; --timeout-seconds) timeout_seconds="$(next_arg "$@")"; shift 2 ;;
-h|--help) usage; exit 0 ;; -h|--help) usage; exit 0 ;;
*) die "unknown argument: $1" ;; *) die "unknown argument: $1" ;;
@@ -123,12 +120,11 @@ require_value "${golden_path}" "--golden"
require_value "${target_call}" "--target-call" require_value "${target_call}" "--target-call"
require_value "${width}" "--width" require_value "${width}" "--width"
require_value "${height}" "--height" require_value "${height}" "--height"
require_value "${tolerance}" "--tolerance" require_value "${ssim_threshold}" "--ssim-threshold"
require_value "${crop_x}" "--crop-x" require_value "${crop_x}" "--crop-x"
require_value "${crop_y}" "--crop-y" require_value "${crop_y}" "--crop-y"
require_value "${crop_width}" "--crop-width" require_value "${crop_width}" "--crop-width"
require_value "${crop_height}" "--crop-height" require_value "${crop_height}" "--crop-height"
require_value "${fuzz_percent}" "--fuzz-percent"
require_value "${timeout_seconds}" "--timeout-seconds" require_value "${timeout_seconds}" "--timeout-seconds"
test -f "${apk_file}" || die "APK does not exist: ${apk_file}" test -f "${apk_file}" || die "APK does not exist: ${apk_file}"
@@ -228,12 +224,11 @@ run_retrace() {
--el target_call "${target_call}" \ --el target_call "${target_call}" \
--ei width "${width}" \ --ei width "${width}" \
--ei height "${height}" \ --ei height "${height}" \
--ei tolerance "${tolerance}" \ --es ssim_threshold "${ssim_threshold}" \
--ei crop_x "${crop_x}" \ --ei crop_x "${crop_x}" \
--ei crop_y "${crop_y}" \ --ei crop_y "${crop_y}" \
--ei crop_width "${crop_width}" \ --ei crop_width "${crop_width}" \
--ei crop_height "${crop_height}" \ --ei crop_height "${crop_height}"
--ei fuzz_percent "${fuzz_percent}"
"${ADB}" shell "$@" "${ADB}" shell "$@"
app_exited=0 app_exited=0
+23 -46
View File
@@ -273,12 +273,11 @@ function(add_trace_replay_test CASE_NAME BACKEND)
TARGET_CALL TARGET_CALL
WIDTH WIDTH
HEIGHT HEIGHT
TOLERANCE SSIM_THRESHOLD
CROP_X CROP_X
CROP_Y CROP_Y
CROP_WIDTH CROP_WIDTH
CROP_HEIGHT CROP_HEIGHT)
FUZZ_PERCENT)
cmake_parse_arguments(TRACE_CASE "" "${oneValueArgs}" "" ${ARGN}) cmake_parse_arguments(TRACE_CASE "" "${oneValueArgs}" "" ${ARGN})
foreach(required TRACE_ARCHIVE GOLDEN TARGET_CALL WIDTH HEIGHT) foreach(required TRACE_ARCHIVE GOLDEN TARGET_CALL WIDTH HEIGHT)
if(NOT TRACE_CASE_${required}) if(NOT TRACE_CASE_${required})
@@ -288,8 +287,8 @@ function(add_trace_replay_test CASE_NAME BACKEND)
if(NOT TRACE_CASE_TRACE_FILE) if(NOT TRACE_CASE_TRACE_FILE)
set(TRACE_CASE_TRACE_FILE trace.trace) set(TRACE_CASE_TRACE_FILE trace.trace)
endif() endif()
if(NOT TRACE_CASE_TOLERANCE) if(NOT TRACE_CASE_SSIM_THRESHOLD)
set(TRACE_CASE_TOLERANCE 0) set(TRACE_CASE_SSIM_THRESHOLD 0.99)
endif() endif()
if(NOT TRACE_CASE_CROP_X) if(NOT TRACE_CASE_CROP_X)
set(TRACE_CASE_CROP_X 0) set(TRACE_CASE_CROP_X 0)
@@ -303,9 +302,6 @@ function(add_trace_replay_test CASE_NAME BACKEND)
if(NOT TRACE_CASE_CROP_HEIGHT) if(NOT TRACE_CASE_CROP_HEIGHT)
set(TRACE_CASE_CROP_HEIGHT 0) set(TRACE_CASE_CROP_HEIGHT 0)
endif() endif()
if(NOT TRACE_CASE_FUZZ_PERCENT)
set(TRACE_CASE_FUZZ_PERCENT 20)
endif()
add_test( add_test(
NAME MobileGLTraceReplay.${CASE_NAME}.${BACKEND} NAME MobileGLTraceReplay.${CASE_NAME}.${BACKEND}
COMMAND "${CMAKE_COMMAND}" COMMAND "${CMAKE_COMMAND}"
@@ -320,12 +316,11 @@ function(add_trace_replay_test CASE_NAME BACKEND)
-DTRACE_TARGET_CALL=${TRACE_CASE_TARGET_CALL} -DTRACE_TARGET_CALL=${TRACE_CASE_TARGET_CALL}
-DTRACE_WIDTH=${TRACE_CASE_WIDTH} -DTRACE_WIDTH=${TRACE_CASE_WIDTH}
-DTRACE_HEIGHT=${TRACE_CASE_HEIGHT} -DTRACE_HEIGHT=${TRACE_CASE_HEIGHT}
-DTRACE_TOLERANCE=${TRACE_CASE_TOLERANCE} -DTRACE_SSIM_THRESHOLD=${TRACE_CASE_SSIM_THRESHOLD}
-DTRACE_CROP_X=${TRACE_CASE_CROP_X} -DTRACE_CROP_X=${TRACE_CASE_CROP_X}
-DTRACE_CROP_Y=${TRACE_CASE_CROP_Y} -DTRACE_CROP_Y=${TRACE_CASE_CROP_Y}
-DTRACE_CROP_WIDTH=${TRACE_CASE_CROP_WIDTH} -DTRACE_CROP_WIDTH=${TRACE_CASE_CROP_WIDTH}
-DTRACE_CROP_HEIGHT=${TRACE_CASE_CROP_HEIGHT} -DTRACE_CROP_HEIGHT=${TRACE_CASE_CROP_HEIGHT}
-DTRACE_FUZZ_PERCENT=${TRACE_CASE_FUZZ_PERCENT}
-DTRACE_OUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}/${CASE_NAME}/${BACKEND} -DTRACE_OUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}/${CASE_NAME}/${BACKEND}
-DTRACE_ARTIFACT_DIR=${CMAKE_CURRENT_BINARY_DIR}/${CASE_NAME}/actual-images -DTRACE_ARTIFACT_DIR=${CMAKE_CURRENT_BINARY_DIR}/${CASE_NAME}/actual-images
-P ${MOBILEGL_TRACE_ROOT}/run_trace_case.cmake) -P ${MOBILEGL_TRACE_ROOT}/run_trace_case.cmake)
@@ -350,12 +345,11 @@ add_trace_replay_test_for_backends(OpenRA
TARGET_CALL 31249 TARGET_CALL 31249
WIDTH 640 WIDTH 640
HEIGHT 480 HEIGHT 480
TOLERANCE 3072
CROP_X 1 CROP_X 1
CROP_Y 1 CROP_Y 1
CROP_WIDTH 638 CROP_WIDTH 638
CROP_HEIGHT 478 CROP_HEIGHT 478
FUZZ_PERCENT 20) )
add_trace_replay_test_for_backends(minecraft-1.21.4-startup add_trace_replay_test_for_backends(minecraft-1.21.4-startup
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-startup.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-startup.tgz
@@ -364,8 +358,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-startup
TARGET_CALL 92195 TARGET_CALL 92195
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-main-menu add_trace_replay_test_for_backends(minecraft-1.21.4-main-menu
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-main-menu.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-main-menu.tgz
@@ -374,8 +367,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-main-menu
TARGET_CALL 481787 TARGET_CALL 481787
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-in-world 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_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-in-world.tgz
@@ -384,8 +376,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-in-world
TARGET_CALL 280000 TARGET_CALL 280000
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-sodium-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-sodium-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-sodium-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-sodium-in-world.tgz
@@ -394,8 +385,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-sodium-in-world
TARGET_CALL 923340 TARGET_CALL 923340
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bsl-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bsl-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.tgz
@@ -404,8 +394,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bsl-in-world
TARGET_CALL 110725 TARGET_CALL 110725
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-makeup-ultrafast-in-world.tgz
@@ -414,8 +403,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-makeup-ultrafast
TARGET_CALL 95322 TARGET_CALL 95322
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-super-duper-vanilla-in-world.tgz
@@ -424,8 +412,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-super-duper-vani
TARGET_CALL 141559 TARGET_CALL 141559
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-sundial-lite-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-sundial-lite-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-sundial-lite-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-sundial-lite-in-world.tgz
@@ -434,8 +421,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-sundial-lite-in-
TARGET_CALL 150023 TARGET_CALL 150023
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-complementary-reimagined-in-world.tgz
@@ -444,8 +430,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-re
TARGET_CALL 151297 TARGET_CALL 151297
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-unbound-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-unbound-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-complementary-unbound-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-complementary-unbound-in-world.tgz
@@ -454,8 +439,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-un
TARGET_CALL 146559 TARGET_CALL 146559
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-mellow-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-mellow-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-mellow-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-mellow-in-world.tgz
@@ -464,8 +448,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-mellow-in-world
TARGET_CALL 96143 TARGET_CALL 96143
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-nostalgia-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-nostalgia-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-nostalgia-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-nostalgia-in-world.tgz
@@ -475,8 +458,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-nostalgia-in-wor
TARGET_CALL 153808 TARGET_CALL 153808
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bliss-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bliss-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-bliss-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-bliss-in-world.tgz
@@ -485,8 +467,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bliss-in-world
TARGET_CALL 113511 TARGET_CALL 113511
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-chocapic-v6-lite-in-world.tgz
@@ -495,8 +476,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-chocapic-v6-lite
TARGET_CALL 125124 TARGET_CALL 125124
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-iterationt-in-world.tgz
@@ -505,8 +485,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-in-wo
TARGET_CALL 1173280 TARGET_CALL 1173280
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-iterationt-nodsa-in-world.tgz
@@ -515,8 +494,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-nodsa
TARGET_CALL 1606997 TARGET_CALL 1606997
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-photon-v1.1-in-world add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-photon-v1.1-in-world
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.1-in-world.tgz TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-fabric-iris-photon-v1.1-in-world.tgz
@@ -525,5 +503,4 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-photon-v1.1-in-w
TARGET_CALL 159866 TARGET_CALL 159866
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 4100 )
FUZZ_PERCENT 20)
+2 -4
View File
@@ -94,8 +94,7 @@ build-test/tools/trace_replay/mobilegl_trace_replay \
--crop-y 1 \ --crop-y 1 \
--crop-width 638 \ --crop-width 638 \
--crop-height 478 \ --crop-height 478 \
--tolerance 20 \ --ssim-threshold 0.99
--fuzz-percent 20
``` ```
## Android device replay ## Android device replay
@@ -140,8 +139,7 @@ adb shell am start -W -a top.mobilegl.plugin.TRACE_REPLAY \
--ei crop_y 1 \ --ei crop_y 1 \
--ei crop_width 638 \ --ei crop_width 638 \
--ei crop_height 478 \ --ei crop_height 478 \
--ei tolerance 20 \ --es ssim_threshold 0.99
--ei fuzz_percent 20
``` ```
Read back the result and images: Read back the result and images:
@@ -1,97 +0,0 @@
foreach(required TRACE_REPLAY_EXE MOBILEGL_LIBRARY OPENRA_TRACE_ARCHIVE OPENRA_GOLDEN OPENRA_OUTPUT_DIR OPENRA_BACKEND)
if(NOT DEFINED ${required} OR "${${required}}" STREQUAL "")
message(FATAL_ERROR "${required} is required")
endif()
endforeach()
if(EXISTS "${OPENRA_OUTPUT_DIR}")
file(REMOVE_RECURSE "${OPENRA_OUTPUT_DIR}")
endif()
file(MAKE_DIRECTORY "${OPENRA_OUTPUT_DIR}/input")
file(MAKE_DIRECTORY "${OPENRA_OUTPUT_DIR}/output")
execute_process(
COMMAND "${CMAKE_COMMAND}" -E tar xzf "${OPENRA_TRACE_ARCHIVE}"
WORKING_DIRECTORY "${OPENRA_OUTPUT_DIR}/input"
RESULT_VARIABLE extract_result
OUTPUT_VARIABLE extract_stdout
ERROR_VARIABLE extract_stderr)
if(NOT extract_result EQUAL 0)
message(STATUS "${extract_stdout}")
message(STATUS "${extract_stderr}")
message(FATAL_ERROR "failed to extract ${OPENRA_TRACE_ARCHIVE}")
endif()
set(openra_trace "${OPENRA_OUTPUT_DIR}/input/openra.trace")
if(NOT EXISTS "${openra_trace}")
message(FATAL_ERROR "extracted OpenRA trace was not found at ${openra_trace}")
endif()
execute_process(
COMMAND "${TRACE_REPLAY_EXE}"
--trace "${openra_trace}"
--golden "${OPENRA_GOLDEN}"
--output "${OPENRA_OUTPUT_DIR}/output"
--backend "${OPENRA_BACKEND}"
--mobilegl-library "${MOBILEGL_LIBRARY}"
--target-call 31249
--width 640
--height 480
--tolerance 20
--crop-x 1
--crop-y 1
--crop-width 638
--crop-height 478
--fuzz-percent 20
RESULT_VARIABLE replay_result
OUTPUT_VARIABLE replay_stdout
ERROR_VARIABLE replay_stderr)
message(STATUS "${replay_stdout}")
message(STATUS "${replay_stderr}")
set(retrace_log "${OPENRA_OUTPUT_DIR}/output/retrace.log")
set(mobilegl_log "${OPENRA_OUTPUT_DIR}/output/mobilegl.log")
if(EXISTS "${retrace_log}")
file(STRINGS "${retrace_log}" gl_identity_lines REGEX "MOBILEGL_TRACE_GL_")
foreach(line IN LISTS gl_identity_lines)
message(STATUS "${line}")
endforeach()
endif()
set(result_json "${OPENRA_OUTPUT_DIR}/output/result.json")
if(DEFINED OPENRA_ARTIFACT_DIR AND NOT "${OPENRA_ARTIFACT_DIR}" STREQUAL "")
file(MAKE_DIRECTORY "${OPENRA_ARTIFACT_DIR}")
set(actual_png "${OPENRA_OUTPUT_DIR}/output/actual.png")
if(EXISTS "${actual_png}")
file(COPY_FILE "${actual_png}" "${OPENRA_ARTIFACT_DIR}/openra-${OPENRA_BACKEND}-actual.png")
endif()
if(EXISTS "${result_json}")
file(COPY_FILE "${result_json}" "${OPENRA_ARTIFACT_DIR}/openra-${OPENRA_BACKEND}-result.json")
endif()
if(EXISTS "${retrace_log}")
file(COPY_FILE "${retrace_log}" "${OPENRA_ARTIFACT_DIR}/openra-${OPENRA_BACKEND}-retrace.log")
endif()
if(EXISTS "${mobilegl_log}")
file(COPY_FILE "${mobilegl_log}" "${OPENRA_ARTIFACT_DIR}/openra-${OPENRA_BACKEND}-mobilegl.log")
endif()
endif()
if(EXISTS "${result_json}")
file(READ "${result_json}" result_contents)
message(STATUS "${result_contents}")
else()
if(EXISTS "${retrace_log}")
file(READ "${retrace_log}" retrace_log_contents)
message(STATUS "${retrace_log_contents}")
endif()
if(EXISTS "${mobilegl_log}")
file(READ "${mobilegl_log}" mobilegl_log_contents)
message(STATUS "${mobilegl_log_contents}")
endif()
message(FATAL_ERROR "trace replay did not write ${result_json}")
endif()
if(NOT replay_result EQUAL 0)
message(FATAL_ERROR "OpenRA ${OPENRA_BACKEND} trace replay failed with status ${replay_result}")
endif()
+3 -7
View File
@@ -4,8 +4,8 @@ foreach(required TRACE_REPLAY_EXE MOBILEGL_LIBRARY TRACE_ARCHIVE TRACE_FILE TRAC
endif() endif()
endforeach() endforeach()
if(NOT DEFINED TRACE_TOLERANCE OR "${TRACE_TOLERANCE}" STREQUAL "") if(NOT DEFINED TRACE_SSIM_THRESHOLD OR "${TRACE_SSIM_THRESHOLD}" STREQUAL "")
set(TRACE_TOLERANCE 0) set(TRACE_SSIM_THRESHOLD 0.99)
endif() endif()
if(NOT DEFINED TRACE_CROP_X OR "${TRACE_CROP_X}" STREQUAL "") if(NOT DEFINED TRACE_CROP_X OR "${TRACE_CROP_X}" STREQUAL "")
set(TRACE_CROP_X 0) set(TRACE_CROP_X 0)
@@ -19,9 +19,6 @@ endif()
if(NOT DEFINED TRACE_CROP_HEIGHT OR "${TRACE_CROP_HEIGHT}" STREQUAL "") if(NOT DEFINED TRACE_CROP_HEIGHT OR "${TRACE_CROP_HEIGHT}" STREQUAL "")
set(TRACE_CROP_HEIGHT 0) set(TRACE_CROP_HEIGHT 0)
endif() endif()
if(NOT DEFINED TRACE_FUZZ_PERCENT OR "${TRACE_FUZZ_PERCENT}" STREQUAL "")
set(TRACE_FUZZ_PERCENT 20)
endif()
set(alternate_golden_args) set(alternate_golden_args)
if(DEFINED TRACE_ALTERNATE_GOLDEN AND NOT "${TRACE_ALTERNATE_GOLDEN}" STREQUAL "") if(DEFINED TRACE_ALTERNATE_GOLDEN AND NOT "${TRACE_ALTERNATE_GOLDEN}" STREQUAL "")
list(APPEND alternate_golden_args --alternate-golden "${TRACE_ALTERNATE_GOLDEN}") list(APPEND alternate_golden_args --alternate-golden "${TRACE_ALTERNATE_GOLDEN}")
@@ -62,12 +59,11 @@ execute_process(
--target-call "${TRACE_TARGET_CALL}" --target-call "${TRACE_TARGET_CALL}"
--width "${TRACE_WIDTH}" --width "${TRACE_WIDTH}"
--height "${TRACE_HEIGHT}" --height "${TRACE_HEIGHT}"
--tolerance "${TRACE_TOLERANCE}" --ssim-threshold "${TRACE_SSIM_THRESHOLD}"
--crop-x "${TRACE_CROP_X}" --crop-x "${TRACE_CROP_X}"
--crop-y "${TRACE_CROP_Y}" --crop-y "${TRACE_CROP_Y}"
--crop-width "${TRACE_CROP_WIDTH}" --crop-width "${TRACE_CROP_WIDTH}"
--crop-height "${TRACE_CROP_HEIGHT}" --crop-height "${TRACE_CROP_HEIGHT}"
--fuzz-percent "${TRACE_FUZZ_PERCENT}"
RESULT_VARIABLE replay_result RESULT_VARIABLE replay_result
OUTPUT_VARIABLE replay_stdout OUTPUT_VARIABLE replay_stdout
ERROR_VARIABLE replay_stderr) ERROR_VARIABLE replay_stderr)
@@ -40,8 +40,9 @@ The golden and target environments must use the same trace, surface size, target
call numbers, and comparison crop. They do not need to report the same GL vendor, call numbers, and comparison crop. They do not need to report the same GL vendor,
renderer, version, or extension set. The only requirement for the golden renderer, version, or extension set. The only requirement for the golden
environment is that it can replay the case and pass the fixture's golden image environment is that it can replay the case and pass the fixture's golden image
test. Disable overlays and avoid tolerance/fuzz while localizing the first test. Disable overlays and use a strict SSIM threshold while localizing the
divergent call unless the known golden already has small nondeterministic noise. first divergent call unless the known golden already has small nondeterministic
noise.
## Prepare two replay environments ## Prepare two replay environments
@@ -80,8 +81,7 @@ mkdir -p "$WORK/$CASE"
--target-call "$TARGET_CALL" \ --target-call "$TARGET_CALL" \
--width "$WIDTH" \ --width "$WIDTH" \
--height "$HEIGHT" \ --height "$HEIGHT" \
--tolerance 0 \ --ssim-threshold 1.0 > "$WORK/$CASE/target-retrace.log" 2>&1 || true
--fuzz-percent 0 > "$WORK/$CASE/target-retrace.log" 2>&1 || true
``` ```
Keep target GL identity lines such as `MOBILEGL_TRACE_GL_VENDOR`, Keep target GL identity lines such as `MOBILEGL_TRACE_GL_VENDOR`,
@@ -90,7 +90,7 @@ Keep target GL identity lines such as `MOBILEGL_TRACE_GL_VENDOR`,
reject a golden environment because its GL strings differ from the target. reject a golden environment because its GL strings differ from the target.
For Android, use `android-plugin/trace-replay-ci.sh` with the same trace, For Android, use `android-plugin/trace-replay-ci.sh` with the same trace,
golden, target call, width, height, crop, tolerance, and fuzz values. Pull golden, target call, width, height, crop, and SSIM threshold values. Pull
`result.json`, `actual.png`, `diff.png`, `retrace.log`, and `logcat.txt` before `result.json`, `actual.png`, `diff.png`, `retrace.log`, and `logcat.txt` before
continuing. continuing.
@@ -151,8 +151,7 @@ for call in 1000 1250 1430 1700; do
--target-call "$call" \ --target-call "$call" \
--width "$WIDTH" \ --width "$WIDTH" \
--height "$HEIGHT" \ --height "$HEIGHT" \
--tolerance 0 \ --ssim-threshold 1.0 || true
--fuzz-percent 0 || true
done done
``` ```
@@ -173,8 +173,7 @@ add_trace_replay_test_for_backends(case-name
TARGET_CALL 0 TARGET_CALL 0
WIDTH 854 WIDTH 854
HEIGHT 480 HEIGHT 480
TOLERANCE 20 SSIM_THRESHOLD 0.99)
FUZZ_PERCENT 20)
``` ```
Optional crop: Optional crop:
@@ -191,13 +190,13 @@ Optional crop:
Edit `.github/workflows/apk.yml` `TRACE_REPLAY_CASES`: Edit `.github/workflows/apk.yml` `TRACE_REPLAY_CASES`:
```text ```text
case-name|tools/trace_replay/fixtures/case-name.tgz|trace.trace|tools/trace_replay/fixtures/case-name.0000000000.png|0|854|480|20|0|0|0|0|20|900 case-name|tools/trace_replay/fixtures/case-name.tgz|trace.trace|tools/trace_replay/fixtures/case-name.0000000000.png|0|854|480|0.99|0|0|0|0|900
``` ```
Field order: Field order:
```text ```text
case|trace archive|trace file|golden|target call|width|height|tolerance|crop x|crop y|crop width|crop height|fuzz percent|timeout seconds case|trace archive|trace file|golden|target call|width|height|ssim threshold|crop x|crop y|crop width|crop height|timeout seconds
``` ```
Update `tools/trace_replay/README.md` with one fixture sentence and one golden Update `tools/trace_replay/README.md` with one fixture sentence and one golden
@@ -236,12 +235,11 @@ cmake \
-DTRACE_TARGET_CALL="$TARGET_CALL" \ -DTRACE_TARGET_CALL="$TARGET_CALL" \
-DTRACE_WIDTH="$WIDTH" \ -DTRACE_WIDTH="$WIDTH" \
-DTRACE_HEIGHT="$HEIGHT" \ -DTRACE_HEIGHT="$HEIGHT" \
-DTRACE_TOLERANCE=20 \ -DTRACE_SSIM_THRESHOLD=0.99 \
-DTRACE_CROP_X=0 \ -DTRACE_CROP_X=0 \
-DTRACE_CROP_Y=0 \ -DTRACE_CROP_Y=0 \
-DTRACE_CROP_WIDTH=0 \ -DTRACE_CROP_WIDTH=0 \
-DTRACE_CROP_HEIGHT=0 \ -DTRACE_CROP_HEIGHT=0 \
-DTRACE_FUZZ_PERCENT=20 \
-DTRACE_OUTPUT_DIR="$WORK/$CASE/linux-DirectGLES" \ -DTRACE_OUTPUT_DIR="$WORK/$CASE/linux-DirectGLES" \
-DTRACE_ARTIFACT_DIR="$WORK/$CASE/linux-artifacts" \ -DTRACE_ARTIFACT_DIR="$WORK/$CASE/linux-artifacts" \
-P "$REPO/tools/trace_replay/run_trace_case.cmake" -P "$REPO/tools/trace_replay/run_trace_case.cmake"
@@ -292,12 +290,11 @@ sh "$REPO/android-plugin/trace-replay-ci.sh" \
--target-call "$TARGET_CALL" \ --target-call "$TARGET_CALL" \
--width "$WIDTH" \ --width "$WIDTH" \
--height "$HEIGHT" \ --height "$HEIGHT" \
--tolerance 20 \ --ssim-threshold 0.99 \
--crop-x 0 \ --crop-x 0 \
--crop-y 0 \ --crop-y 0 \
--crop-width 0 \ --crop-width 0 \
--crop-height 0 \ --crop-height 0 \
--fuzz-percent 20 \
--timeout-seconds 900 --timeout-seconds 900
``` ```
+12 -7
View File
@@ -20,8 +20,7 @@ void PrintUsage(const char *argv0) {
<< " --mobilegl-library PATH libMobileGL.so path (default: libMobileGL.so)\n" << " --mobilegl-library PATH libMobileGL.so path (default: libMobileGL.so)\n"
<< " --width N Replay surface width override\n" << " --width N Replay surface width override\n"
<< " --height N Replay surface height override\n" << " --height N Replay surface height override\n"
<< " --tolerance N Allowed mismatch pixels\n" << " --ssim-threshold N Minimum SSIM required to pass (default: 0.99)\n"
<< " --fuzz-percent N Per-channel fuzz threshold, 0-100 (default: 20)\n"
<< " --crop-x N Compare crop x\n" << " --crop-x N Compare crop x\n"
<< " --crop-y N Compare crop y\n" << " --crop-y N Compare crop y\n"
<< " --crop-width N Compare crop width\n" << " --crop-width N Compare crop width\n"
@@ -55,9 +54,17 @@ bool ReadLongLong(int argc, char **argv, int &index, long long &out) {
return true; return true;
} }
bool ReadDouble(int argc, char **argv, int &index, double &out) {
std::string value;
if (!ReadValue(argc, argv, index, value)) {
return false;
}
out = std::strtod(value.c_str(), nullptr);
return true;
}
bool ParseArgs(int argc, char **argv, mobilegl_trace::Request &request) { bool ParseArgs(int argc, char **argv, mobilegl_trace::Request &request) {
request.backend = "DirectGLES"; request.backend = "DirectGLES";
request.fuzzPercent = 20;
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
const std::string arg = argv[i]; const std::string arg = argv[i];
@@ -87,8 +94,8 @@ bool ParseArgs(int argc, char **argv, mobilegl_trace::Request &request) {
if (!ReadInt(argc, argv, i, request.width)) return false; if (!ReadInt(argc, argv, i, request.width)) return false;
} else if (arg == "--height") { } else if (arg == "--height") {
if (!ReadInt(argc, argv, i, request.height)) return false; if (!ReadInt(argc, argv, i, request.height)) return false;
} else if (arg == "--tolerance") { } else if (arg == "--ssim-threshold") {
if (!ReadInt(argc, argv, i, request.tolerance)) return false; if (!ReadDouble(argc, argv, i, request.ssimThreshold)) return false;
} else if (arg == "--crop-x") { } else if (arg == "--crop-x") {
if (!ReadInt(argc, argv, i, request.cropX)) return false; if (!ReadInt(argc, argv, i, request.cropX)) return false;
} else if (arg == "--crop-y") { } else if (arg == "--crop-y") {
@@ -97,8 +104,6 @@ bool ParseArgs(int argc, char **argv, mobilegl_trace::Request &request) {
if (!ReadInt(argc, argv, i, request.cropWidth)) return false; if (!ReadInt(argc, argv, i, request.cropWidth)) return false;
} else if (arg == "--crop-height") { } else if (arg == "--crop-height") {
if (!ReadInt(argc, argv, i, request.cropHeight)) return false; if (!ReadInt(argc, argv, i, request.cropHeight)) return false;
} else if (arg == "--fuzz-percent") {
if (!ReadInt(argc, argv, i, request.fuzzPercent)) return false;
} else if (arg == "--help" || arg == "-h") { } else if (arg == "--help" || arg == "-h") {
return false; return false;
} else { } else {