[Feat] (trace-replay): add Minecraft startup trace

This commit is contained in:
2026-06-16 12:22:27 +08:00
parent 24372c8558
commit 0dc3a0916e
7 changed files with 229 additions and 31 deletions
+11 -14
View File
@@ -267,20 +267,20 @@ jobs:
working-directory: build-retrace
run: |
set +e
ctest -V -R MobileGLTraceReplay.OpenRA.DirectGLES
ctest -V -R 'MobileGLTraceReplay\..*\.DirectGLES'
status=$?
mkdir -p tools/trace_replay/openra
echo "${status}" > tools/trace_replay/openra/DirectGLES.status
mkdir -p tools/trace_replay/status
echo "${status}" > tools/trace_replay/status/DirectGLES.status
exit 0
- name: Retrace and validate Magma (DirectVulkan)
working-directory: build-retrace
run: |
set +e
ctest -V -R MobileGLTraceReplay.OpenRA.DirectVulkan
ctest -V -R 'MobileGLTraceReplay\..*\.DirectVulkan'
status=$?
mkdir -p tools/trace_replay/openra
echo "${status}" > tools/trace_replay/openra/DirectVulkan.status
mkdir -p tools/trace_replay/status
echo "${status}" > tools/trace_replay/status/DirectVulkan.status
exit 0
- name: Upload actual image
@@ -289,20 +289,17 @@ jobs:
with:
name: retrace-result
path: |
build-retrace/tools/trace_replay/openra/actual-images/openra-DirectGLES-actual.png
build-retrace/tools/trace_replay/openra/actual-images/openra-DirectVulkan-actual.png
build-retrace/tools/trace_replay/openra/actual-images/*.json
build-retrace/tools/trace_replay/openra/actual-images/*.log
build-retrace/tools/trace_replay/openra/*.status
build-retrace/tools/trace_replay/openra/*/output/**
build-retrace/tools/trace_replay/*/actual-images/**
build-retrace/tools/trace_replay/*/*/output/**
build-retrace/tools/trace_replay/status/*.status
if-no-files-found: warn
- name: Check retrace results
if: always()
working-directory: build-retrace
run: |
direct_gles_status="$(cat tools/trace_replay/openra/DirectGLES.status 2>/dev/null || echo 1)"
direct_vulkan_status="$(cat tools/trace_replay/openra/DirectVulkan.status 2>/dev/null || echo 1)"
direct_gles_status="$(cat tools/trace_replay/status/DirectGLES.status 2>/dev/null || echo 1)"
direct_vulkan_status="$(cat tools/trace_replay/status/DirectVulkan.status 2>/dev/null || echo 1)"
echo "DirectGLES status: ${direct_gles_status}"
echo "DirectVulkan status: ${direct_vulkan_status}"
if [ "${direct_gles_status}" -ne 0 ] || [ "${direct_vulkan_status}" -ne 0 ]; then
+1
View File
@@ -22,3 +22,4 @@ MobileGL/MG*/cmake-build*
/android-plugin/.gradle
/android-plugin/build
/android-plugin/app/build
tools/trace_replay/work/
+90 -12
View File
@@ -264,26 +264,104 @@ else()
endif()
enable_testing()
function(add_openra_trace_replay_test BACKEND)
function(add_trace_replay_test CASE_NAME BACKEND)
set(oneValueArgs
TRACE_ARCHIVE
TRACE_FILE
GOLDEN
TARGET_CALL
WIDTH
HEIGHT
TOLERANCE
CROP_X
CROP_Y
CROP_WIDTH
CROP_HEIGHT
FUZZ_PERCENT)
cmake_parse_arguments(TRACE_CASE "" "${oneValueArgs}" "" ${ARGN})
foreach(required TRACE_ARCHIVE GOLDEN TARGET_CALL WIDTH HEIGHT)
if(NOT TRACE_CASE_${required})
message(FATAL_ERROR "${required} is required for ${CASE_NAME}")
endif()
endforeach()
if(NOT TRACE_CASE_TRACE_FILE)
set(TRACE_CASE_TRACE_FILE trace.trace)
endif()
if(NOT TRACE_CASE_TOLERANCE)
set(TRACE_CASE_TOLERANCE 0)
endif()
if(NOT TRACE_CASE_CROP_X)
set(TRACE_CASE_CROP_X 0)
endif()
if(NOT TRACE_CASE_CROP_Y)
set(TRACE_CASE_CROP_Y 0)
endif()
if(NOT TRACE_CASE_CROP_WIDTH)
set(TRACE_CASE_CROP_WIDTH 0)
endif()
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.OpenRA.${BACKEND}
NAME MobileGLTraceReplay.${CASE_NAME}.${BACKEND}
COMMAND "${CMAKE_COMMAND}"
-DTRACE_REPLAY_EXE=$<TARGET_FILE:mobilegl_trace_replay>
-DMOBILEGL_LIBRARY=${mobilegl_trace_replay_mobilegl_library}
-DOPENRA_TRACE_ARCHIVE=${MOBILEGL_TRACE_ROOT}/fixtures/openra.tgz
-DOPENRA_GOLDEN=${MOBILEGL_TRACE_ROOT}/fixtures/openra.0000031249.png
-DOPENRA_BACKEND=${BACKEND}
-DOPENRA_OUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}/openra/${BACKEND}
-DOPENRA_ARTIFACT_DIR=${CMAKE_CURRENT_BINARY_DIR}/openra/actual-images
-P ${MOBILEGL_TRACE_ROOT}/run_openra_replay.cmake)
-DTRACE_CASE_NAME=${CASE_NAME}
-DTRACE_ARCHIVE=${TRACE_CASE_TRACE_ARCHIVE}
-DTRACE_FILE=${TRACE_CASE_TRACE_FILE}
-DTRACE_GOLDEN=${TRACE_CASE_GOLDEN}
-DTRACE_BACKEND=${BACKEND}
-DTRACE_TARGET_CALL=${TRACE_CASE_TARGET_CALL}
-DTRACE_WIDTH=${TRACE_CASE_WIDTH}
-DTRACE_HEIGHT=${TRACE_CASE_HEIGHT}
-DTRACE_TOLERANCE=${TRACE_CASE_TOLERANCE}
-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)
if(BACKEND STREQUAL "DirectGLES")
set_tests_properties(MobileGLTraceReplay.OpenRA.${BACKEND} PROPERTIES
set_tests_properties(MobileGLTraceReplay.${CASE_NAME}.${BACKEND} PROPERTIES
ENVIRONMENT "EGL_PLATFORM=surfaceless;LIBGL_ALWAYS_SOFTWARE=1;MESA_GL_VERSION_OVERRIDE=3.3;MESA_GLSL_VERSION_OVERRIDE=330")
else()
set_tests_properties(MobileGLTraceReplay.OpenRA.${BACKEND} PROPERTIES
set_tests_properties(MobileGLTraceReplay.${CASE_NAME}.${BACKEND} PROPERTIES
ENVIRONMENT "LIBGL_ALWAYS_SOFTWARE=1;MESA_GL_VERSION_OVERRIDE=3.3;MESA_GLSL_VERSION_OVERRIDE=330")
endif()
endfunction()
add_openra_trace_replay_test(DirectGLES)
add_openra_trace_replay_test(DirectVulkan)
function(add_trace_replay_test_for_backends CASE_NAME)
add_trace_replay_test(${CASE_NAME} DirectGLES ${ARGN})
add_trace_replay_test(${CASE_NAME} DirectVulkan ${ARGN})
endfunction()
add_trace_replay_test_for_backends(OpenRA
TRACE_ARCHIVE ${MOBILEGL_TRACE_ROOT}/fixtures/openra.tgz
TRACE_FILE openra.trace
GOLDEN ${MOBILEGL_TRACE_ROOT}/fixtures/openra.0000031249.png
TARGET_CALL 31249
WIDTH 640
HEIGHT 480
TOLERANCE 20
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
TRACE_FILE trace.trace
GOLDEN ${MOBILEGL_TRACE_ROOT}/fixtures/minecraft-1.21.4-startup.0000092195.png
TARGET_CALL 92195
WIDTH 854
HEIGHT 480
TOLERANCE 20
FUZZ_PERCENT 20)
+11 -5
View File
@@ -3,9 +3,12 @@
This directory builds a Linux command line replay runner for apitrace files. It is meant for CI coverage of MobileGL
without Android, APK packaging, FCL, or plugin runtime dependencies.
The bundled `openra` fixture comes from GL4ES' apitrace corpus. See
[GL4ES_TRACES.md](GL4ES_TRACES.md) for the current inventory and the traces that
were rejected because they rely on compatibility/fixed-function OpenGL.
The bundled fixtures cover:
- `OpenRA`: sourced from GL4ES' apitrace corpus. See [GL4ES_TRACES.md](GL4ES_TRACES.md) for the current inventory and
traces rejected because they rely on compatibility/fixed-function OpenGL.
- `minecraft-1.21.4-startup`: captured from Minecraft 1.21.4's Mojang Studios startup screen. The fixture is trimmed
to call 92195, immediately after the startup screen draw into Minecraft's offscreen framebuffer.
Build from the MobileGL repository root:
@@ -17,10 +20,10 @@ cmake -S . -B build-test -G Ninja \
cmake --build build-test
```
Run the OpenRA fixture test:
Run the fixture tests:
```sh
ctest --test-dir build-test -V -R MobileGLTraceReplay.OpenRA
ctest --test-dir build-test -V -R 'MobileGLTraceReplay\.'
```
Run the CLI directly:
@@ -43,5 +46,8 @@ build-test/tools/trace_replay/mobilegl_trace_replay \
--fuzz-percent 20
```
The Minecraft startup fixture uses `tools/trace_replay/fixtures/minecraft-1.21.4-startup.tgz`, golden image
`minecraft-1.21.4-startup.0000092195.png`, `--target-call 92195`, `--width 854`, and `--height 480`.
The Linux runner loads MobileGL by path with `dlopen`. It uses an EGL pbuffer for `DirectGLES` and maps the pbuffer
path to `VK_EXT_headless_surface` for `DirectVulkan`, so CI does not need an X11 or Wayland window.
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

+116
View File
@@ -0,0 +1,116 @@
foreach(required TRACE_REPLAY_EXE MOBILEGL_LIBRARY TRACE_ARCHIVE TRACE_FILE TRACE_GOLDEN TRACE_OUTPUT_DIR TRACE_BACKEND TRACE_CASE_NAME TRACE_TARGET_CALL TRACE_WIDTH TRACE_HEIGHT)
if(NOT DEFINED ${required} OR "${${required}}" STREQUAL "")
message(FATAL_ERROR "${required} is required")
endif()
endforeach()
if(NOT DEFINED TRACE_TOLERANCE OR "${TRACE_TOLERANCE}" STREQUAL "")
set(TRACE_TOLERANCE 0)
endif()
if(NOT DEFINED TRACE_CROP_X OR "${TRACE_CROP_X}" STREQUAL "")
set(TRACE_CROP_X 0)
endif()
if(NOT DEFINED TRACE_CROP_Y OR "${TRACE_CROP_Y}" STREQUAL "")
set(TRACE_CROP_Y 0)
endif()
if(NOT DEFINED TRACE_CROP_WIDTH OR "${TRACE_CROP_WIDTH}" STREQUAL "")
set(TRACE_CROP_WIDTH 0)
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()
if(EXISTS "${TRACE_OUTPUT_DIR}")
file(REMOVE_RECURSE "${TRACE_OUTPUT_DIR}")
endif()
file(MAKE_DIRECTORY "${TRACE_OUTPUT_DIR}/input")
file(MAKE_DIRECTORY "${TRACE_OUTPUT_DIR}/output")
execute_process(
COMMAND "${CMAKE_COMMAND}" -E tar xzf "${TRACE_ARCHIVE}"
WORKING_DIRECTORY "${TRACE_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 ${TRACE_ARCHIVE}")
endif()
set(trace_path "${TRACE_OUTPUT_DIR}/input/${TRACE_FILE}")
if(NOT EXISTS "${trace_path}")
message(FATAL_ERROR "extracted trace was not found at ${trace_path}")
endif()
execute_process(
COMMAND "${TRACE_REPLAY_EXE}"
--trace "${trace_path}"
--golden "${TRACE_GOLDEN}"
--output "${TRACE_OUTPUT_DIR}/output"
--backend "${TRACE_BACKEND}"
--mobilegl-library "${MOBILEGL_LIBRARY}"
--target-call "${TRACE_TARGET_CALL}"
--width "${TRACE_WIDTH}"
--height "${TRACE_HEIGHT}"
--tolerance "${TRACE_TOLERANCE}"
--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)
message(STATUS "${replay_stdout}")
message(STATUS "${replay_stderr}")
set(retrace_log "${TRACE_OUTPUT_DIR}/output/retrace.log")
set(mobilegl_log "${TRACE_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 "${TRACE_OUTPUT_DIR}/output/result.json")
if(DEFINED TRACE_ARTIFACT_DIR AND NOT "${TRACE_ARTIFACT_DIR}" STREQUAL "")
file(MAKE_DIRECTORY "${TRACE_ARTIFACT_DIR}")
set(actual_png "${TRACE_OUTPUT_DIR}/output/actual.png")
if(EXISTS "${actual_png}")
file(COPY_FILE "${actual_png}" "${TRACE_ARTIFACT_DIR}/${TRACE_CASE_NAME}-${TRACE_BACKEND}-actual.png")
endif()
if(EXISTS "${result_json}")
file(COPY_FILE "${result_json}" "${TRACE_ARTIFACT_DIR}/${TRACE_CASE_NAME}-${TRACE_BACKEND}-result.json")
endif()
if(EXISTS "${retrace_log}")
file(COPY_FILE "${retrace_log}" "${TRACE_ARTIFACT_DIR}/${TRACE_CASE_NAME}-${TRACE_BACKEND}-retrace.log")
endif()
if(EXISTS "${mobilegl_log}")
file(COPY_FILE "${mobilegl_log}" "${TRACE_ARTIFACT_DIR}/${TRACE_CASE_NAME}-${TRACE_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 "${TRACE_CASE_NAME} ${TRACE_BACKEND} trace replay failed with status ${replay_result}")
endif()