[Docs] (trace-replay): add trace fixture authoring guide

This commit is contained in:
2026-06-20 10:51:36 +08:00
parent 1a2f867ba9
commit d219ac3f6f
@@ -0,0 +1,327 @@
# Trace fixture authoring
## Variables
```sh
export REPO="$PWD"
export WORK="$PWD/.trace-work"
export CASE="case-name"
export WIDTH=854
export HEIGHT=480
export TARGET_CALL=0
```
## Prerequisites
```sh
git clone --recursive <mobilegl-repo-url> MobileGL
cd MobileGL
git lfs install
git lfs pull
```
Install:
- CMake
- Ninja
- C++ compiler
- Python 3
- Mesa OpenGL/EGL runtime
- Vulkan loader and ICD for `DirectVulkan`
- Pillow or ImageMagick for alpha cleanup
- Android SDK, Android NDK, JDK, Gradle, and `adb` for Android replay
## Build apitrace
```sh
cmake -S "$REPO/3rdparty/apitrace" -B "$WORK/build-apitrace" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DENABLE_GUI=OFF
cmake --build "$WORK/build-apitrace" --target apitrace glretrace --parallel
export APITRACE="$(find "$WORK/build-apitrace" -type f -name apitrace -perm -111 | head -n 1)"
export GLRETRACE="$(find "$WORK/build-apitrace" -type f -name glretrace -perm -111 | head -n 1)"
test -n "$APITRACE"
test -n "$GLRETRACE"
```
On Windows, set `APITRACE` and `GLRETRACE` to the corresponding `.exe` files.
## Prepare the capture
- Set the target window size to `WIDTH` x `HEIGHT`.
- Disable unintended overlays, frame counters, notifications, and launcher UI.
- Fix language, resource packs, mods, shader pack, world seed, time, weather,
player position, camera direction, FOV, GUI scale, and render distance.
- Trace the final OpenGL process, not the launcher.
- For Minecraft, document version, mod loader, mods, shader pack, language,
world, time, and camera setup.
## Capture
```sh
mkdir -p "$WORK/$CASE"
"$APITRACE" trace --api=gl \
--output "$WORK/$CASE/full.trace" \
-- <application-command> <application-args>
```
For Java:
```sh
"$APITRACE" trace --api=gl \
--output "$WORK/$CASE/full.trace" \
-- "$JAVA_EXE" <jvm-args> <main-class-or-jar> <game-args>
```
Keep `full.trace` until both backends are validated.
## Select target call
```sh
mkdir -p "$WORK/$CASE/probe"
for call in $(seq "$START_CALL" "$STEP_CALL" "$END_CALL"); do
"$APITRACE" replay --headless \
--snapshot-prefix "$WORK/$CASE/probe/$CASE." \
--snapshot="$call" \
--call-nos \
"$WORK/$CASE/full.trace" || true
done
```
Inspect the PNGs and set:
```sh
export TARGET_CALL=<chosen-call-number>
```
## Trim and package
```sh
"$APITRACE" trim \
--calls="$TARGET_CALL" \
--output "$WORK/$CASE/trace.trace" \
"$WORK/$CASE/full.trace"
```
## Generate golden
Generate the golden from the trimmed trace:
```sh
mkdir -p "$WORK/$CASE/golden"
"$APITRACE" replay --headless \
--snapshot-prefix "$WORK/$CASE/golden/$CASE." \
--snapshot="$TARGET_CALL" \
--call-nos \
"$WORK/$CASE/trace.trace"
GOLDEN_SRC="$WORK/$CASE/golden/$CASE.$(printf '%010d' "$TARGET_CALL").png"
```
Remove unintended alpha:
```sh
python3 - "$GOLDEN_SRC" "$WORK/$CASE/$CASE.$(printf '%010d' "$TARGET_CALL").png" <<'PY'
import sys
from PIL import Image
src, dst = sys.argv[1], sys.argv[2]
img = Image.open(src).convert("RGBA")
bg = Image.new("RGBA", img.size, (0, 0, 0, 255))
bg.alpha_composite(img)
bg.convert("RGB").save(dst)
PY
```
Or copy directly:
```sh
cp "$GOLDEN_SRC" "$WORK/$CASE/$CASE.$(printf '%010d' "$TARGET_CALL").png"
```
Package:
```sh
mkdir -p "$WORK/$CASE/archive"
cp "$WORK/$CASE/trace.trace" "$WORK/$CASE/archive/trace.trace"
tar -czf "$REPO/tools/trace_replay/fixtures/$CASE.tgz" \
-C "$WORK/$CASE/archive" trace.trace
cp "$WORK/$CASE/$CASE.$(printf '%010d' "$TARGET_CALL").png" \
"$REPO/tools/trace_replay/fixtures/"
```
Track with Git LFS:
```sh
git lfs track "tools/trace_replay/fixtures/*.tgz"
git lfs track "tools/trace_replay/fixtures/*.png"
git add .gitattributes tools/trace_replay/fixtures/$CASE.tgz \
tools/trace_replay/fixtures/$CASE.$(printf '%010d' "$TARGET_CALL").png
git lfs status
```
## Register Linux replay
Edit `tools/trace_replay/CMakeLists.txt`:
```cmake
add_trace_replay_test_for_backends(case-name
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/case-name.tgz
TRACE_FILE trace.trace
GOLDEN ${MOBILEGL_TRACE_ROOT}/fixtures/case-name.0000000000.png
TARGET_CALL 0
WIDTH 854
HEIGHT 480
TOLERANCE 20
FUZZ_PERCENT 20)
```
Optional crop:
```cmake
CROP_X 1
CROP_Y 1
CROP_WIDTH 852
CROP_HEIGHT 478
```
## Register Android replay
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
```
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
```
Update `tools/trace_replay/README.md` with one fixture sentence and one golden
image link.
## Validate on Linux
```sh
cmake -S "$REPO" -B "$WORK/build-linux" -G Ninja \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DMOBILEGL_BUILD_TEST=ON \
-DMOBILEGL_BUILD_BENCHMARK=OFF \
-DMOBILEGL_BUILD_TRACE_REPLAY=ON \
-DMOBILEGL_LOG_ACTIVE_LEVEL=MOBILEGL_LOG_LEVEL_INFO
cmake --build "$WORK/build-linux" --target mobilegl_trace_replay --parallel
```
Run the registered case:
```sh
ctest --test-dir "$WORK/build-linux/tools/trace_replay" -V \
-R "MobileGLTraceReplay\\.$CASE\\."
```
Run one backend manually:
```sh
cmake \
-DTRACE_REPLAY_EXE="$WORK/build-linux/tools/trace_replay/mobilegl_trace_replay" \
-DMOBILEGL_LIBRARY="$WORK/build-linux/libMobileGL.so" \
-DTRACE_CASE_NAME="$CASE" \
-DTRACE_ARCHIVE="$REPO/tools/trace_replay/fixtures/$CASE.tgz" \
-DTRACE_FILE=trace.trace \
-DTRACE_GOLDEN="$REPO/tools/trace_replay/fixtures/$CASE.$(printf '%010d' "$TARGET_CALL").png" \
-DTRACE_BACKEND=DirectGLES \
-DTRACE_TARGET_CALL="$TARGET_CALL" \
-DTRACE_WIDTH="$WIDTH" \
-DTRACE_HEIGHT="$HEIGHT" \
-DTRACE_TOLERANCE=20 \
-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"
```
DirectGLES CI env:
```sh
export EGL_PLATFORM=surfaceless
export LIBGL_ALWAYS_SOFTWARE=1
export MESA_GL_VERSION_OVERRIDE=3.3
export MESA_GLSL_VERSION_OVERRIDE=330
```
DirectVulkan check:
```sh
vulkaninfo | grep -E 'deviceName|VK_EXT_headless_surface'
```
## Validate on Android
Build trace APKs:
```sh
gradle --no-daemon -p "$REPO/android-plugin" \
:app:assembleEsprytTraceRelease \
:app:assembleMagmaTraceRelease \
-Pmobilegl.abis=all \
-Pmobilegl.debuggableRelease=true \
-Pmobilegl.logLevel=MOBILEGL_LOG_LEVEL_INFO \
--parallel
```
Run DirectGLES:
```sh
sh "$REPO/android-plugin/trace-replay-ci.sh" \
--apk-file "$REPO/android-plugin/app/build/outputs/apk/esprytTrace/release/MobileGL-EsprytTrace-release.apk" \
--package top.mobilegl.plugin.espryt.trace \
--backend DirectGLES \
--result-root "$WORK/$CASE/android-result" \
--fixture-root "$WORK/$CASE/android-fixture" \
--case "$CASE" \
--trace-archive "$REPO/tools/trace_replay/fixtures/$CASE.tgz" \
--trace-file trace.trace \
--golden "$REPO/tools/trace_replay/fixtures/$CASE.$(printf '%010d' "$TARGET_CALL").png" \
--target-call "$TARGET_CALL" \
--width "$WIDTH" \
--height "$HEIGHT" \
--tolerance 20 \
--crop-x 0 \
--crop-y 0 \
--crop-width 0 \
--crop-height 0 \
--fuzz-percent 20 \
--timeout-seconds 900
```
Run DirectVulkan with:
- APK: `MobileGL-MagmaTrace-release.apk`
- package: `top.mobilegl.plugin.magma.trace`
- backend: `DirectVulkan`
Inspect:
- `$WORK/$CASE/android-result/$CASE-DirectGLES/result.json`
- `$WORK/$CASE/android-result/$CASE-DirectGLES/$CASE-DirectGLES-actual.png`
- `$WORK/$CASE/android-result/$CASE-DirectGLES/$CASE-DirectGLES-diff.png`
- `$WORK/$CASE/android-result/$CASE-DirectGLES/retrace.log`
- `$WORK/$CASE/android-result/$CASE-DirectGLES/logcat.txt`
## Checklist
- Golden matches the committed trace and target call.
- Archive contains only `trace.trace`.
- Both Linux backends pass before Linux CI registration.
- Both Android backends pass before APK CI registration.
- `actual.png` and `case-diff.png` are inspected.
- Fixture `.tgz` and `.png` files are tracked by Git LFS.
- No build output, extracted trace directory, temporary report, or debug text is
staged.