mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 14:18:31 +09:00
[Fix] (trace-replay): render DirectGLES replay onscreen by default
This commit is contained in:
@@ -38,6 +38,7 @@ crop_y optional compare crop y
|
|||||||
crop_width optional compare crop width
|
crop_width optional compare crop width
|
||||||
crop_height optional compare crop height
|
crop_height optional compare crop height
|
||||||
use_angle optional boolean; DirectGLES uses packaged ANGLE when true
|
use_angle optional boolean; DirectGLES uses packaged ANGLE when true
|
||||||
|
use_pbuffer optional boolean; DirectGLES uses an offscreen EGL pbuffer when true
|
||||||
angle_library_dir optional directory containing libEGL_angle.so and libGLESv2_angle.so; defaults to the APK native library directory
|
angle_library_dir optional directory containing libEGL_angle.so and libGLESv2_angle.so; defaults to the APK native library directory
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -46,10 +47,10 @@ Implementation notes:
|
|||||||
- The trace APK builds independently from FCL and can be launched with `adb shell am start`.
|
- The trace APK builds independently from FCL and can be launched with `adb shell am start`.
|
||||||
- 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` and `DirectVulkan` replay on the Activity `SurfaceView` by default. DirectGLES can still use the old offscreen EGL pbuffer path by passing `use_pbuffer=true`.
|
||||||
- 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.
|
- 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. Set `MOBILEGL_RETRACE_USE_PBUFFER=1` or pass `--use-pbuffer` to keep DirectGLES offscreen. 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`.
|
||||||
|
|
||||||
Example core-profile trace smoke command for a debug trace APK:
|
Example core-profile trace smoke command for a debug trace APK:
|
||||||
|
|
||||||
|
|||||||
@@ -814,6 +814,7 @@ bool WriteResultJson(const Request& request, const Result& result) {
|
|||||||
file << " \"ssim\": " << result.ssim << ",\n";
|
file << " \"ssim\": " << result.ssim << ",\n";
|
||||||
file << " \"ssimThreshold\": " << request.ssimThreshold << ",\n";
|
file << " \"ssimThreshold\": " << request.ssimThreshold << ",\n";
|
||||||
file << " \"useAngle\": " << (UseAngleForRequest(request) ? "true" : "false") << ",\n";
|
file << " \"useAngle\": " << (UseAngleForRequest(request) ? "true" : "false") << ",\n";
|
||||||
|
file << " \"usePbuffer\": " << (request.usePbuffer ? "true" : "false") << ",\n";
|
||||||
file << " \"mismatchPixels\": " << result.mismatchPixels << "\n";
|
file << " \"mismatchPixels\": " << result.mismatchPixels << "\n";
|
||||||
file << "}\n";
|
file << "}\n";
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ struct Request {
|
|||||||
int cropHeight = 0;
|
int cropHeight = 0;
|
||||||
double ssimThreshold = 0.99;
|
double ssimThreshold = 0.99;
|
||||||
bool useAngle = false;
|
bool useAngle = false;
|
||||||
|
bool usePbuffer = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Result {
|
struct Result {
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv*
|
|||||||
jint cropWidth,
|
jint cropWidth,
|
||||||
jint cropHeight,
|
jint cropHeight,
|
||||||
jstring angleLibraryDir,
|
jstring angleLibraryDir,
|
||||||
jboolean useAngle) {
|
jboolean useAngle,
|
||||||
|
jboolean usePbuffer) {
|
||||||
mobilegl_trace::Request request;
|
mobilegl_trace::Request request;
|
||||||
request.tracePath = ToString(env, tracePath);
|
request.tracePath = ToString(env, tracePath);
|
||||||
request.goldenPath = ToString(env, goldenPath);
|
request.goldenPath = ToString(env, goldenPath);
|
||||||
@@ -121,10 +122,13 @@ Java_top_mobilegl_plugin_trace_TraceReplayActivity_nativeRunTraceReplay(JNIEnv*
|
|||||||
request.cropWidth = cropWidth;
|
request.cropWidth = cropWidth;
|
||||||
request.cropHeight = cropHeight;
|
request.cropHeight = cropHeight;
|
||||||
request.useAngle = useAngle == JNI_TRUE;
|
request.useAngle = useAngle == JNI_TRUE;
|
||||||
|
request.usePbuffer = usePbuffer == JNI_TRUE;
|
||||||
|
|
||||||
ScopedTraceReplayState replayState;
|
ScopedTraceReplayState replayState;
|
||||||
mobilegl_trace_set_requested_size(request.width, request.height);
|
mobilegl_trace_set_requested_size(request.width, request.height);
|
||||||
const bool needsNativeWindow = request.backend == "DirectVulkan";
|
const bool needsNativeWindow =
|
||||||
|
request.backend == "DirectVulkan" ||
|
||||||
|
(request.backend == "DirectGLES" && !request.usePbuffer);
|
||||||
ANativeWindow *window = needsNativeWindow && surface != nullptr ? ANativeWindow_fromSurface(env, surface) : nullptr;
|
ANativeWindow *window = needsNativeWindow && surface != nullptr ? ANativeWindow_fromSurface(env, surface) : nullptr;
|
||||||
mobilegl_trace_set_native_window(window);
|
mobilegl_trace_set_native_window(window);
|
||||||
if (window != nullptr) {
|
if (window != nullptr) {
|
||||||
|
|||||||
+10
-4
@@ -112,7 +112,8 @@ public final class TraceReplayActivity extends Activity {
|
|||||||
request.cropWidth,
|
request.cropWidth,
|
||||||
request.cropHeight,
|
request.cropHeight,
|
||||||
request.angleLibraryDir,
|
request.angleLibraryDir,
|
||||||
request.useAngle
|
request.useAngle,
|
||||||
|
request.usePbuffer
|
||||||
);
|
);
|
||||||
Log.i(TAG, result.toString());
|
Log.i(TAG, result.toString());
|
||||||
TraceReplayResult finalResult = result;
|
TraceReplayResult finalResult = result;
|
||||||
@@ -140,7 +141,8 @@ public final class TraceReplayActivity extends Activity {
|
|||||||
int cropWidth,
|
int cropWidth,
|
||||||
int cropHeight,
|
int cropHeight,
|
||||||
String angleLibraryDir,
|
String angleLibraryDir,
|
||||||
boolean useAngle
|
boolean useAngle,
|
||||||
|
boolean usePbuffer
|
||||||
);
|
);
|
||||||
|
|
||||||
private static final class TraceReplayRequest {
|
private static final class TraceReplayRequest {
|
||||||
@@ -161,6 +163,7 @@ public final class TraceReplayActivity extends Activity {
|
|||||||
final int cropHeight;
|
final int cropHeight;
|
||||||
final String angleLibraryDir;
|
final String angleLibraryDir;
|
||||||
final boolean useAngle;
|
final boolean useAngle;
|
||||||
|
final boolean usePbuffer;
|
||||||
|
|
||||||
private TraceReplayRequest(
|
private TraceReplayRequest(
|
||||||
String tracePath,
|
String tracePath,
|
||||||
@@ -179,7 +182,8 @@ public final class TraceReplayActivity extends Activity {
|
|||||||
int cropWidth,
|
int cropWidth,
|
||||||
int cropHeight,
|
int cropHeight,
|
||||||
String angleLibraryDir,
|
String angleLibraryDir,
|
||||||
boolean useAngle
|
boolean useAngle,
|
||||||
|
boolean usePbuffer
|
||||||
) {
|
) {
|
||||||
this.tracePath = tracePath;
|
this.tracePath = tracePath;
|
||||||
this.goldenPath = goldenPath;
|
this.goldenPath = goldenPath;
|
||||||
@@ -198,6 +202,7 @@ public final class TraceReplayActivity extends Activity {
|
|||||||
this.cropHeight = cropHeight;
|
this.cropHeight = cropHeight;
|
||||||
this.angleLibraryDir = angleLibraryDir;
|
this.angleLibraryDir = angleLibraryDir;
|
||||||
this.useAngle = useAngle;
|
this.useAngle = useAngle;
|
||||||
|
this.usePbuffer = usePbuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TraceReplayRequest from(Intent intent, File filesDir, String nativeLibraryDir, String defaultBackend) {
|
static TraceReplayRequest from(Intent intent, File filesDir, String nativeLibraryDir, String defaultBackend) {
|
||||||
@@ -220,7 +225,8 @@ public final class TraceReplayActivity extends Activity {
|
|||||||
intent.getIntExtra("crop_width", 0),
|
intent.getIntExtra("crop_width", 0),
|
||||||
intent.getIntExtra("crop_height", 0),
|
intent.getIntExtra("crop_height", 0),
|
||||||
readString(intent, "angle_library_dir", nativeLibraryDir),
|
readString(intent, "angle_library_dir", nativeLibraryDir),
|
||||||
intent.getBooleanExtra("use_angle", false)
|
intent.getBooleanExtra("use_angle", false),
|
||||||
|
intent.getBooleanExtra("use_pbuffer", false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,13 @@ Usage:
|
|||||||
--crop-y N \
|
--crop-y N \
|
||||||
--crop-width N \
|
--crop-width N \
|
||||||
--crop-height N \
|
--crop-height N \
|
||||||
|
[--use-pbuffer] \
|
||||||
--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
|
||||||
instead of the device system GLES driver.
|
instead of the device system GLES driver.
|
||||||
|
Set MOBILEGL_RETRACE_USE_PBUFFER=1 or pass --use-pbuffer to run DirectGLES
|
||||||
|
against an offscreen EGL pbuffer instead of the Activity surface.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +75,7 @@ crop_x=""
|
|||||||
crop_y=""
|
crop_y=""
|
||||||
crop_width=""
|
crop_width=""
|
||||||
crop_height=""
|
crop_height=""
|
||||||
|
use_pbuffer=0
|
||||||
timeout_seconds=""
|
timeout_seconds=""
|
||||||
|
|
||||||
while [ "$#" -gt 0 ]; do
|
while [ "$#" -gt 0 ]; do
|
||||||
@@ -102,6 +106,7 @@ while [ "$#" -gt 0 ]; do
|
|||||||
--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 ;;
|
||||||
|
--use-pbuffer) use_pbuffer=1; shift 1 ;;
|
||||||
--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" ;;
|
||||||
@@ -201,6 +206,9 @@ run_retrace() {
|
|||||||
if [ "${MOBILEGL_RETRACE_USE_ANGLE:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then
|
if [ "${MOBILEGL_RETRACE_USE_ANGLE:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then
|
||||||
use_angle=1
|
use_angle=1
|
||||||
fi
|
fi
|
||||||
|
if [ "${MOBILEGL_RETRACE_USE_PBUFFER:-}" = "1" ] && [ "${backend}" = "DirectGLES" ]; then
|
||||||
|
use_pbuffer=1
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p "${result_dir}"
|
mkdir -p "${result_dir}"
|
||||||
"${ADB}" install -r "${apk_file}"
|
"${ADB}" install -r "${apk_file}"
|
||||||
@@ -217,6 +225,9 @@ run_retrace() {
|
|||||||
if [ "${use_angle}" -eq 1 ]; then
|
if [ "${use_angle}" -eq 1 ]; then
|
||||||
set -- "$@" --ez use_angle true
|
set -- "$@" --ez use_angle true
|
||||||
fi
|
fi
|
||||||
|
if [ "${use_pbuffer}" -eq 1 ] && [ "${backend}" = "DirectGLES" ]; then
|
||||||
|
set -- "$@" --ez use_pbuffer true
|
||||||
|
fi
|
||||||
set -- "$@" \
|
set -- "$@" \
|
||||||
--es output_dir "${app_dir}/output" \
|
--es output_dir "${app_dir}/output" \
|
||||||
--es diff_path "${app_dir}/output/${safe_case}-diff.png" \
|
--es diff_path "${app_dir}/output/${safe_case}-diff.png" \
|
||||||
|
|||||||
@@ -152,3 +152,5 @@ adb exec-out run-as $PKG cat files/trace-replay/output/openra-diff.png > openra-
|
|||||||
|
|
||||||
For the Vulkan backend, build and install `:app:assembleMagmaTraceDebug`, set
|
For the Vulkan backend, build and install `:app:assembleMagmaTraceDebug`, set
|
||||||
`PKG=top.mobilegl.plugin.magma.trace`, and pass `--es backend DirectVulkan`.
|
`PKG=top.mobilegl.plugin.magma.trace`, and pass `--es backend DirectVulkan`.
|
||||||
|
DirectGLES also renders to the Activity surface by default; pass
|
||||||
|
`--ez use_pbuffer true` to use the offscreen pbuffer path.
|
||||||
|
|||||||
Reference in New Issue
Block a user