[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
width: 640
height: 480
tolerance: 3072
crop_x: 1
crop_y: 1
crop_width: 638
crop_height: 478
fuzz_percent: 20
timeout_seconds: 180
- name: minecraft-1.21.4-startup
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-startup.tgz
@@ -172,12 +170,10 @@ jobs:
target_call: 92195
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 180
- name: minecraft-1.21.4-main-menu
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-main-menu.tgz
@@ -186,12 +182,10 @@ jobs:
target_call: 481787
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 180
- name: minecraft-1.21.4-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-in-world.tgz
@@ -200,12 +194,10 @@ jobs:
target_call: 280000
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- name: minecraft-1.21.4-fabric-sodium-in-world
trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-sodium-in-world.tgz
@@ -214,12 +206,10 @@ jobs:
target_call: 923340
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 1800
- 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
@@ -228,12 +218,10 @@ jobs:
target_call: 110725
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -242,12 +230,10 @@ jobs:
target_call: 95322
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -256,12 +242,10 @@ jobs:
target_call: 141559
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -270,12 +254,10 @@ jobs:
target_call: 150023
width: 854
height: 480
tolerance: 8000
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -284,12 +266,10 @@ jobs:
target_call: 151297
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -298,12 +278,10 @@ jobs:
target_call: 146559
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -312,12 +290,10 @@ jobs:
target_call: 96143
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -327,12 +303,10 @@ jobs:
target_call: 153808
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -341,12 +315,10 @@ jobs:
target_call: 113511
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -355,12 +327,10 @@ jobs:
target_call: 125124
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
- 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
@@ -369,12 +339,10 @@ jobs:
target_call: 1173280
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 2400
- 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
@@ -383,12 +351,10 @@ jobs:
target_call: 1606997
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 2400
- 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
@@ -397,12 +363,10 @@ jobs:
target_call: 159866
width: 854
height: 480
tolerance: 4100
crop_x: 0
crop_y: 0
crop_width: 0
crop_height: 0
fuzz_percent: 20
timeout_seconds: 900
steps:
@@ -472,12 +436,11 @@ jobs:
--target-call "${{ matrix.case.target_call }}" \
--width "${{ matrix.case.width }}" \
--height "${{ matrix.case.height }}" \
--tolerance "${{ matrix.case.tolerance }}" \
--ssim-threshold "${{ matrix.case.ssim_threshold || '0.99' }}" \
--crop-x "${{ matrix.case.crop_x }}" \
--crop-y "${{ matrix.case.crop_y }}" \
--crop-width "${{ matrix.case.crop_width }}" \
--crop-height "${{ matrix.case.crop_height }}" \
--fuzz-percent "${{ matrix.case.fuzz_percent }}" \
--timeout-seconds "${{ matrix.case.timeout_seconds }}"
- 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
width optional replay surface width override
height optional replay surface height override
tolerance allowed mismatching pixel count after fuzz is applied
fuzz_percent per-channel fuzz percentage; default is 20
ssim_threshold minimum SSIM required to pass; default is 0.99
crop_x optional compare crop x
crop_y optional compare crop y
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 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.
- 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.
- 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 backend DirectGLES \
--el target_call 31249 \
--ei tolerance 0 \
--ei fuzz_percent 20
--es ssim_threshold 0.99
adb shell run-as top.mobilegl.plugin.espryt.trace cat files/trace-replay/output/result.json
```
@@ -14,6 +14,7 @@
#include <cstring>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>
#include <memory>
#include <sstream>
@@ -520,7 +521,6 @@ bool WriteDifferenceImage(const Result& result,
int y0,
int compareWidth,
int compareHeight,
int fuzz,
std::string& error) {
if (result.diffPath.empty()) {
return true;
@@ -548,7 +548,7 @@ bool WriteDifferenceImage(const Result& result,
ChannelValue(golden, imageX, imageY, 1));
int db = std::abs(ChannelValue(actual, 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() +
(static_cast<std::size_t>(imageY) * diff.width + imageX) * 4;
if (different) {
@@ -569,17 +569,71 @@ bool WriteDifferenceImage(const Result& result,
struct GoldenComparison {
std::string path;
RgbaImage image;
long long mismatchPixels = std::numeric_limits<long long>::max();
double ssim = -1.0;
long long mismatchPixels = 0;
int x0 = 0;
int y0 = 0;
int compareWidth = 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,
const RgbaImage& actual,
const std::string& goldenPath,
int fuzz,
GoldenComparison& comparison,
std::string& error) {
if (!Exists(goldenPath)) {
@@ -616,27 +670,28 @@ bool CompareAgainstOneGolden(const Request& request,
return false;
}
long long mismatch = 0;
long long exactMismatch = 0;
for (int y = 0; y < compareHeight; ++y) {
for (int x = 0; x < compareWidth; ++x) {
bool different = false;
for (unsigned c = 0; c < 3; ++c) {
int a = ChannelValue(actual, 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;
break;
}
}
if (different) {
++mismatch;
++exactMismatch;
}
}
}
comparison.path = goldenPath;
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.y0 = y0;
comparison.compareWidth = compareWidth;
@@ -659,6 +714,7 @@ bool CompareWithGolden(const Request& request, Result& result) {
result.passed = true;
result.statusCode = STATUS_OK;
result.message = "retrace completed; golden_path was not provided";
result.ssim = 1.0;
result.mismatchPixels = 0;
return true;
}
@@ -671,18 +727,17 @@ bool CompareWithGolden(const Request& request, Result& result) {
return false;
}
const int fuzz = std::max(0, std::min(100, request.fuzzPercent)) * 255 / 100;
GoldenComparison bestComparison;
std::string comparisonError;
bool hasComparison = false;
for (const auto& goldenPath : goldenPaths) {
GoldenComparison comparison;
std::string error;
if (!CompareAgainstOneGolden(request, actual, goldenPath, fuzz, comparison, error)) {
if (!CompareAgainstOneGolden(request, actual, goldenPath, comparison, error)) {
comparisonError = error;
continue;
}
if (!hasComparison || comparison.mismatchPixels < bestComparison.mismatchPixels) {
if (!hasComparison || comparison.ssim > bestComparison.ssim) {
bestComparison = std::move(comparison);
hasComparison = true;
}
@@ -696,20 +751,22 @@ bool CompareWithGolden(const Request& request, Result& result) {
std::string diffError;
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.message = diffError.empty() ? "failed to write diff PNG" : diffError;
return false;
}
result.ssim = bestComparison.ssim;
result.mismatchPixels = bestComparison.mismatchPixels;
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;
std::ostringstream message;
message << "retrace completed; mismatchPixels=" << bestComparison.mismatchPixels
<< ", tolerance=" << request.tolerance
<< ", fuzzPercent=" << request.fuzzPercent
message << std::fixed << std::setprecision(6)
<< "retrace completed; ssim=" << bestComparison.ssim
<< ", ssimThreshold=" << request.ssimThreshold
<< ", mismatchPixels=" << bestComparison.mismatchPixels
<< ", matchedGoldenPath=" << bestComparison.path;
result.message = message.str();
return result.passed;
@@ -753,8 +810,9 @@ bool WriteResultJson(const Request& request, const Result& result) {
file << " \"cropY\": " << request.cropY << ",\n";
file << " \"cropWidth\": " << request.cropWidth << ",\n";
file << " \"cropHeight\": " << request.cropHeight << ",\n";
file << " \"tolerance\": " << request.tolerance << ",\n";
file << " \"fuzzPercent\": " << request.fuzzPercent << ",\n";
file << std::fixed << std::setprecision(9);
file << " \"ssim\": " << result.ssim << ",\n";
file << " \"ssimThreshold\": " << request.ssimThreshold << ",\n";
file << " \"useAngle\": " << (UseAngleForRequest(request) ? "true" : "false") << ",\n";
file << " \"mismatchPixels\": " << result.mismatchPixels << "\n";
file << "}\n";
@@ -32,8 +32,7 @@ struct Request {
int cropY = 0;
int cropWidth = 0;
int cropHeight = 0;
int tolerance = 0;
int fuzzPercent = 20;
double ssimThreshold = 0.99;
bool useAngle = false;
};
@@ -45,6 +44,7 @@ struct Result {
std::string actualPath;
std::string diffPath;
std::string matchedGoldenPath;
double ssim = -1.0;
long long mismatchPixels = -1;
};
@@ -93,12 +93,11 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv*
jlong targetCall,
jint width,
jint height,
jint tolerance,
jdouble ssimThreshold,
jint cropX,
jint cropY,
jint cropWidth,
jint cropHeight,
jint fuzzPercent,
jstring angleLibraryDir,
jboolean useAngle) {
mobilegl_trace::Request request;
@@ -116,12 +115,11 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv*
request.targetCall = targetCall;
request.width = width;
request.height = height;
request.tolerance = tolerance;
request.ssimThreshold = ssimThreshold;
request.cropX = cropX;
request.cropY = cropY;
request.cropWidth = cropWidth;
request.cropHeight = cropHeight;
request.fuzzPercent = fuzzPercent;
request.useAngle = useAngle == JNI_TRUE;
ScopedTraceReplayState replayState;
@@ -106,12 +106,11 @@ public final class TraceReplayActivity extends Activity {
request.targetCall,
request.width,
request.height,
request.tolerance,
request.ssimThreshold,
request.cropX,
request.cropY,
request.cropWidth,
request.cropHeight,
request.fuzzPercent,
request.angleLibraryDir,
request.useAngle
);
@@ -135,12 +134,11 @@ public final class TraceReplayActivity extends Activity {
long targetCall,
int width,
int height,
int tolerance,
double ssimThreshold,
int cropX,
int cropY,
int cropWidth,
int cropHeight,
int fuzzPercent,
String angleLibraryDir,
boolean useAngle
);
@@ -156,12 +154,11 @@ public final class TraceReplayActivity extends Activity {
final long targetCall;
final int width;
final int height;
final int tolerance;
final double ssimThreshold;
final int cropX;
final int cropY;
final int cropWidth;
final int cropHeight;
final int fuzzPercent;
final String angleLibraryDir;
final boolean useAngle;
@@ -176,12 +173,11 @@ public final class TraceReplayActivity extends Activity {
long targetCall,
int width,
int height,
int tolerance,
double ssimThreshold,
int cropX,
int cropY,
int cropWidth,
int cropHeight,
int fuzzPercent,
String angleLibraryDir,
boolean useAngle
) {
@@ -195,12 +191,11 @@ public final class TraceReplayActivity extends Activity {
this.targetCall = targetCall;
this.width = width;
this.height = height;
this.tolerance = tolerance;
this.ssimThreshold = ssimThreshold;
this.cropX = cropX;
this.cropY = cropY;
this.cropWidth = cropWidth;
this.cropHeight = cropHeight;
this.fuzzPercent = fuzzPercent;
this.angleLibraryDir = angleLibraryDir;
this.useAngle = useAngle;
}
@@ -219,12 +214,11 @@ public final class TraceReplayActivity extends Activity {
intent.getLongExtra("target_call", -1L),
intent.getIntExtra("width", 0),
intent.getIntExtra("height", 0),
intent.getIntExtra("tolerance", 0),
readDouble(intent, "ssim_threshold", 0.99),
intent.getIntExtra("crop_x", 0),
intent.getIntExtra("crop_y", 0),
intent.getIntExtra("crop_width", 0),
intent.getIntExtra("crop_height", 0),
intent.getIntExtra("fuzz_percent", 20),
readString(intent, "angle_library_dir", nativeLibraryDir),
intent.getBooleanExtra("use_angle", false)
);
@@ -234,6 +228,18 @@ public final class TraceReplayActivity extends Activity {
String value = intent.getStringExtra(key);
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 {
+6 -11
View File
@@ -21,12 +21,11 @@ Usage:
--target-call N \
--width N \
--height N \
--tolerance N \
--ssim-threshold N \
--crop-x N \
--crop-y N \
--crop-width N \
--crop-height N \
--fuzz-percent N \
--timeout-seconds N
Set MOBILEGL_RETRACE_USE_ANGLE=1 to run DirectGLES replay with packaged ANGLE
@@ -68,12 +67,11 @@ alternate_golden_path=""
target_call=""
width=""
height=""
tolerance=""
ssim_threshold=""
crop_x=""
crop_y=""
crop_width=""
crop_height=""
fuzz_percent=""
timeout_seconds=""
while [ "$#" -gt 0 ]; do
@@ -99,12 +97,11 @@ while [ "$#" -gt 0 ]; do
--target-call) target_call="$(next_arg "$@")"; shift 2 ;;
--width) width="$(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-y) crop_y="$(next_arg "$@")"; shift 2 ;;
--crop-width) crop_width="$(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 ;;
-h|--help) usage; exit 0 ;;
*) die "unknown argument: $1" ;;
@@ -123,12 +120,11 @@ require_value "${golden_path}" "--golden"
require_value "${target_call}" "--target-call"
require_value "${width}" "--width"
require_value "${height}" "--height"
require_value "${tolerance}" "--tolerance"
require_value "${ssim_threshold}" "--ssim-threshold"
require_value "${crop_x}" "--crop-x"
require_value "${crop_y}" "--crop-y"
require_value "${crop_width}" "--crop-width"
require_value "${crop_height}" "--crop-height"
require_value "${fuzz_percent}" "--fuzz-percent"
require_value "${timeout_seconds}" "--timeout-seconds"
test -f "${apk_file}" || die "APK does not exist: ${apk_file}"
@@ -228,12 +224,11 @@ run_retrace() {
--el target_call "${target_call}" \
--ei width "${width}" \
--ei height "${height}" \
--ei tolerance "${tolerance}" \
--es ssim_threshold "${ssim_threshold}" \
--ei crop_x "${crop_x}" \
--ei crop_y "${crop_y}" \
--ei crop_width "${crop_width}" \
--ei crop_height "${crop_height}" \
--ei fuzz_percent "${fuzz_percent}"
--ei crop_height "${crop_height}"
"${ADB}" shell "$@"
app_exited=0
+23 -46
View File
@@ -273,12 +273,11 @@ function(add_trace_replay_test CASE_NAME BACKEND)
TARGET_CALL
WIDTH
HEIGHT
TOLERANCE
SSIM_THRESHOLD
CROP_X
CROP_Y
CROP_WIDTH
CROP_HEIGHT
FUZZ_PERCENT)
CROP_HEIGHT)
cmake_parse_arguments(TRACE_CASE "" "${oneValueArgs}" "" ${ARGN})
foreach(required TRACE_ARCHIVE GOLDEN TARGET_CALL WIDTH HEIGHT)
if(NOT TRACE_CASE_${required})
@@ -288,8 +287,8 @@ function(add_trace_replay_test CASE_NAME BACKEND)
if(NOT TRACE_CASE_TRACE_FILE)
set(TRACE_CASE_TRACE_FILE trace.trace)
endif()
if(NOT TRACE_CASE_TOLERANCE)
set(TRACE_CASE_TOLERANCE 0)
if(NOT TRACE_CASE_SSIM_THRESHOLD)
set(TRACE_CASE_SSIM_THRESHOLD 0.99)
endif()
if(NOT TRACE_CASE_CROP_X)
set(TRACE_CASE_CROP_X 0)
@@ -303,9 +302,6 @@ function(add_trace_replay_test CASE_NAME BACKEND)
if(NOT TRACE_CASE_CROP_HEIGHT)
set(TRACE_CASE_CROP_HEIGHT 0)
endif()
if(NOT TRACE_CASE_FUZZ_PERCENT)
set(TRACE_CASE_FUZZ_PERCENT 20)
endif()
add_test(
NAME MobileGLTraceReplay.${CASE_NAME}.${BACKEND}
COMMAND "${CMAKE_COMMAND}"
@@ -320,12 +316,11 @@ function(add_trace_replay_test CASE_NAME BACKEND)
-DTRACE_TARGET_CALL=${TRACE_CASE_TARGET_CALL}
-DTRACE_WIDTH=${TRACE_CASE_WIDTH}
-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_Y=${TRACE_CASE_CROP_Y}
-DTRACE_CROP_WIDTH=${TRACE_CASE_CROP_WIDTH}
-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_ARTIFACT_DIR=${CMAKE_CURRENT_BINARY_DIR}/${CASE_NAME}/actual-images
-P ${MOBILEGL_TRACE_ROOT}/run_trace_case.cmake)
@@ -350,12 +345,11 @@ add_trace_replay_test_for_backends(OpenRA
TARGET_CALL 31249
WIDTH 640
HEIGHT 480
TOLERANCE 3072
CROP_X 1
CROP_Y 1
CROP_WIDTH 638
CROP_HEIGHT 478
FUZZ_PERCENT 20)
)
add_trace_replay_test_for_backends(minecraft-1.21.4-startup
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
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -374,8 +367,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-main-menu
TARGET_CALL 481787
WIDTH 854
HEIGHT 480
TOLERANCE 4100
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
@@ -384,8 +376,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-in-world
TARGET_CALL 280000
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -394,8 +385,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-sodium-in-world
TARGET_CALL 923340
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -404,8 +394,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bsl-in-world
TARGET_CALL 110725
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -414,8 +403,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-makeup-ultrafast
TARGET_CALL 95322
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -424,8 +412,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-super-duper-vani
TARGET_CALL 141559
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -434,8 +421,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-sundial-lite-in-
TARGET_CALL 150023
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -444,8 +430,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-re
TARGET_CALL 151297
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -454,8 +439,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-complementary-un
TARGET_CALL 146559
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -464,8 +448,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-mellow-in-world
TARGET_CALL 96143
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -475,8 +458,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-nostalgia-in-wor
TARGET_CALL 153808
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -485,8 +467,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-bliss-in-world
TARGET_CALL 113511
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -495,8 +476,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-chocapic-v6-lite
TARGET_CALL 125124
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -505,8 +485,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-in-wo
TARGET_CALL 1173280
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -515,8 +494,7 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-iterationt-nodsa
TARGET_CALL 1606997
WIDTH 854
HEIGHT 480
TOLERANCE 4100
FUZZ_PERCENT 20)
)
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
@@ -525,5 +503,4 @@ add_trace_replay_test_for_backends(minecraft-1.21.4-fabric-iris-photon-v1.1-in-w
TARGET_CALL 159866
WIDTH 854
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-width 638 \
--crop-height 478 \
--tolerance 20 \
--fuzz-percent 20
--ssim-threshold 0.99
```
## Android device replay
@@ -140,8 +139,7 @@ adb shell am start -W -a top.mobilegl.plugin.TRACE_REPLAY \
--ei crop_y 1 \
--ei crop_width 638 \
--ei crop_height 478 \
--ei tolerance 20 \
--ei fuzz_percent 20
--es ssim_threshold 0.99
```
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()
endforeach()
if(NOT DEFINED TRACE_TOLERANCE OR "${TRACE_TOLERANCE}" STREQUAL "")
set(TRACE_TOLERANCE 0)
if(NOT DEFINED TRACE_SSIM_THRESHOLD OR "${TRACE_SSIM_THRESHOLD}" STREQUAL "")
set(TRACE_SSIM_THRESHOLD 0.99)
endif()
if(NOT DEFINED TRACE_CROP_X OR "${TRACE_CROP_X}" STREQUAL "")
set(TRACE_CROP_X 0)
@@ -19,9 +19,6 @@ endif()
if(NOT DEFINED TRACE_CROP_HEIGHT OR "${TRACE_CROP_HEIGHT}" STREQUAL "")
set(TRACE_CROP_HEIGHT 0)
endif()
if(NOT DEFINED TRACE_FUZZ_PERCENT OR "${TRACE_FUZZ_PERCENT}" STREQUAL "")
set(TRACE_FUZZ_PERCENT 20)
endif()
set(alternate_golden_args)
if(DEFINED TRACE_ALTERNATE_GOLDEN AND NOT "${TRACE_ALTERNATE_GOLDEN}" STREQUAL "")
list(APPEND alternate_golden_args --alternate-golden "${TRACE_ALTERNATE_GOLDEN}")
@@ -62,12 +59,11 @@ execute_process(
--target-call "${TRACE_TARGET_CALL}"
--width "${TRACE_WIDTH}"
--height "${TRACE_HEIGHT}"
--tolerance "${TRACE_TOLERANCE}"
--ssim-threshold "${TRACE_SSIM_THRESHOLD}"
--crop-x "${TRACE_CROP_X}"
--crop-y "${TRACE_CROP_Y}"
--crop-width "${TRACE_CROP_WIDTH}"
--crop-height "${TRACE_CROP_HEIGHT}"
--fuzz-percent "${TRACE_FUZZ_PERCENT}"
RESULT_VARIABLE replay_result
OUTPUT_VARIABLE replay_stdout
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,
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
test. Disable overlays and avoid tolerance/fuzz while localizing the first
divergent call unless the known golden already has small nondeterministic noise.
test. Disable overlays and use a strict SSIM threshold while localizing the
first divergent call unless the known golden already has small nondeterministic
noise.
## Prepare two replay environments
@@ -80,8 +81,7 @@ mkdir -p "$WORK/$CASE"
--target-call "$TARGET_CALL" \
--width "$WIDTH" \
--height "$HEIGHT" \
--tolerance 0 \
--fuzz-percent 0 > "$WORK/$CASE/target-retrace.log" 2>&1 || true
--ssim-threshold 1.0 > "$WORK/$CASE/target-retrace.log" 2>&1 || true
```
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.
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
continuing.
@@ -151,8 +151,7 @@ for call in 1000 1250 1430 1700; do
--target-call "$call" \
--width "$WIDTH" \
--height "$HEIGHT" \
--tolerance 0 \
--fuzz-percent 0 || true
--ssim-threshold 1.0 || true
done
```
@@ -173,8 +173,7 @@ add_trace_replay_test_for_backends(case-name
TARGET_CALL 0
WIDTH 854
HEIGHT 480
TOLERANCE 20
FUZZ_PERCENT 20)
SSIM_THRESHOLD 0.99)
```
Optional crop:
@@ -191,13 +190,13 @@ Optional crop:
Edit `.github/workflows/apk.yml` `TRACE_REPLAY_CASES`:
```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:
```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
@@ -236,12 +235,11 @@ cmake \
-DTRACE_TARGET_CALL="$TARGET_CALL" \
-DTRACE_WIDTH="$WIDTH" \
-DTRACE_HEIGHT="$HEIGHT" \
-DTRACE_TOLERANCE=20 \
-DTRACE_SSIM_THRESHOLD=0.99 \
-DTRACE_CROP_X=0 \
-DTRACE_CROP_Y=0 \
-DTRACE_CROP_WIDTH=0 \
-DTRACE_CROP_HEIGHT=0 \
-DTRACE_FUZZ_PERCENT=20 \
-DTRACE_OUTPUT_DIR="$WORK/$CASE/linux-DirectGLES" \
-DTRACE_ARTIFACT_DIR="$WORK/$CASE/linux-artifacts" \
-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" \
--width "$WIDTH" \
--height "$HEIGHT" \
--tolerance 20 \
--ssim-threshold 0.99 \
--crop-x 0 \
--crop-y 0 \
--crop-width 0 \
--crop-height 0 \
--fuzz-percent 20 \
--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"
<< " --width N Replay surface width override\n"
<< " --height N Replay surface height override\n"
<< " --tolerance N Allowed mismatch pixels\n"
<< " --fuzz-percent N Per-channel fuzz threshold, 0-100 (default: 20)\n"
<< " --ssim-threshold N Minimum SSIM required to pass (default: 0.99)\n"
<< " --crop-x N Compare crop x\n"
<< " --crop-y N Compare crop y\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;
}
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) {
request.backend = "DirectGLES";
request.fuzzPercent = 20;
for (int i = 1; i < argc; ++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;
} else if (arg == "--height") {
if (!ReadInt(argc, argv, i, request.height)) return false;
} else if (arg == "--tolerance") {
if (!ReadInt(argc, argv, i, request.tolerance)) return false;
} else if (arg == "--ssim-threshold") {
if (!ReadDouble(argc, argv, i, request.ssimThreshold)) return false;
} else if (arg == "--crop-x") {
if (!ReadInt(argc, argv, i, request.cropX)) return false;
} 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;
} else if (arg == "--crop-height") {
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") {
return false;
} else {