[Fix] (trace-replay): stabilize GL4ES OpenRA validation

This commit is contained in:
2026-06-15 22:27:39 +08:00
parent bc8109b695
commit 4c2c4cb565
4 changed files with 51 additions and 6 deletions
@@ -1665,8 +1665,15 @@ void main() {
MOBILEGL_ASSERT(m_vertexInputStateFactory != nullptr, "VertexInputStateFactory creation failed."); MOBILEGL_ASSERT(m_vertexInputStateFactory != nullptr, "VertexInputStateFactory creation failed.");
// Prime the first frame so Render() always targets an acquired swapchain image. // Prime the first frame so Render() always targets an acquired swapchain image.
VK_VERIFY(m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired), VkResult acquireResult =
"Initialize, WaitAndAcquireNextImage"); m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
if (acquireResult == VK_ERROR_OUT_OF_DATE_KHR || acquireResult == VK_SUBOPTIMAL_KHR) {
MGLOG_D("Initialize, vkAcquireNextImageKHR got %d, recreating swapchain", acquireResult);
RecreateSwapchain();
acquireResult =
m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired);
}
VK_VERIFY(acquireResult, "Initialize, WaitAndAcquireNextImage");
m_textureManager->BeginFrame(m_frameContext.GetCurrentFrameIndex()); m_textureManager->BeginFrame(m_frameContext.GetCurrentFrameIndex());
m_bufferManager.BeginFrame(m_frameContext.GetCurrentFrameIndex()); m_bufferManager.BeginFrame(m_frameContext.GetCurrentFrameIndex());
m_transientVertexIndexBufferSlicesThisFrame.clear(); m_transientVertexIndexBufferSlicesThisFrame.clear();
@@ -3,6 +3,8 @@ package top.mobilegl.plugin.trace;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
@@ -24,6 +26,7 @@ public final class TraceReplayActivity extends Activity {
private TextView statusView; private TextView statusView;
private TraceReplayRequest request; private TraceReplayRequest request;
private boolean started; private boolean started;
private final Handler mainHandler = new Handler(Looper.getMainLooper());
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -58,11 +61,12 @@ public final class TraceReplayActivity extends Activity {
holder.addCallback(new SurfaceHolder.Callback() { holder.addCallback(new SurfaceHolder.Callback() {
@Override @Override
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
scheduleReplay(holder);
} }
@Override @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
startReplay(holder); scheduleReplay(holder);
} }
@Override @Override
@@ -71,13 +75,21 @@ public final class TraceReplayActivity extends Activity {
}); });
} }
private void scheduleReplay(SurfaceHolder holder) {
mainHandler.postDelayed(() -> startReplay(holder), 250);
}
private void startReplay(SurfaceHolder holder) { private void startReplay(SurfaceHolder holder) {
if (started) { if (started) {
return; return;
} }
Surface surface = holder.getSurface();
if (surface == null || !surface.isValid()) {
return;
}
started = true; started = true;
statusView.setText("Running trace replay\n" + request.outputDir); statusView.setText("Running trace replay\n" + request.outputDir);
new Thread(() -> runRequest(request, holder.getSurface()), "MobileGLTraceReplay").start(); new Thread(() -> runRequest(request, surface), "MobileGLTraceReplay").start();
} }
private void runRequest(TraceReplayRequest request, Surface surface) { private void runRequest(TraceReplayRequest request, Surface surface) {
+22
View File
@@ -0,0 +1,22 @@
# GL4ES Trace Inventory
The GL4ES repository currently provides these apitrace fixtures under
`NG-GL4ES/NG-GL4ES/traces` with reference images under `NG-GL4ES/NG-GL4ES/refs`.
MobileGL's trace replay tests only use traces that exercise a core-profile style
OpenGL path. Compatibility/fixed-function traces are intentionally excluded.
| Trace | Status | Reason |
| --- | --- | --- |
| `openra` | Included | No fixed-function calls were detected in the trace scan, and it passes Linux replay on both `DirectGLES` and `DirectVulkan`. |
| `glsl_lighting` | Excluded | Uses compatibility matrix-stack calls (`glLoadIdentity`, `glPopMatrix`) and replays to a black image on MobileGL (`DirectGLES` mismatchPixels=30659 against the GL4ES reference). |
| `descent3` | Excluded | Uses fixed-function calls such as `glBegin`, `glEnd`, `glAlphaFunc`, `glOrtho`, and client arrays. |
| `foobillardplus` | Excluded | Uses display lists, matrix stack, material/fog state, and fixed-function client arrays. |
| `glxgears` | Excluded | Uses display lists, `glBegin`/`glEnd`, matrix stack, and material state. |
| `neverball` | Excluded | Uses display lists, `glBegin`/`glEnd`, fixed-function lighting/material state, clip planes, and matrix stack. |
| `pointsprite` | Excluded | Uses `glBegin`/`glEnd`, matrix stack, `glOrtho`, and fixed-function point state. |
| `stuntcarracer` | Excluded | Uses `glBegin`/`glEnd`, matrix stack, `glAlphaFunc`, and fixed-function client arrays. |
The scan is deliberately conservative: a trace is only added as a MobileGL
regression fixture after it replays and validates against its reference image on
Linux and Android. Traces that mainly test GL4ES compatibility behavior should
remain outside MobileGL core-profile CI.
+6 -2
View File
@@ -3,6 +3,10 @@
This directory builds a Linux command line replay runner for apitrace files. It is meant for CI coverage of MobileGL 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. 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.
Build from the MobileGL repository root: Build from the MobileGL repository root:
```sh ```sh
@@ -39,5 +43,5 @@ build-test/tools/trace_replay/mobilegl_trace_replay \
--fuzz-percent 20 --fuzz-percent 20
``` ```
The Linux runner loads MobileGL by path with `dlopen`. It uses an EGL pbuffer for `DirectGLES` and an X11 window The Linux runner loads MobileGL by path with `dlopen`. It uses an EGL pbuffer for `DirectGLES` and maps the pbuffer
surface for `DirectVulkan` so Magma can create a Vulkan swapchain under `xvfb-run` in CI. path to `VK_EXT_headless_surface` for `DirectVulkan`, so CI does not need an X11 or Wayland window.