From 4c2c4cb56523d0fc229fe658d088956dd1f5b58b Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Mon, 15 Jun 2026 22:27:39 +0800 Subject: [PATCH] [Fix] (trace-replay): stabilize GL4ES OpenRA validation --- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 11 ++++++++-- .../plugin/trace/TraceReplayActivity.java | 16 ++++++++++++-- tools/trace_replay/GL4ES_TRACES.md | 22 +++++++++++++++++++ tools/trace_replay/README.md | 8 +++++-- 4 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 tools/trace_replay/GL4ES_TRACES.md diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index b093cf1e..d371ba41 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -1665,8 +1665,15 @@ void main() { MOBILEGL_ASSERT(m_vertexInputStateFactory != nullptr, "VertexInputStateFactory creation failed."); // Prime the first frame so Render() always targets an acquired swapchain image. - VK_VERIFY(m_frameContext.WaitAndAcquireNextImage(m_device, m_swapchainObject.GetHandle(), m_imageIndexAcquired), - "Initialize, WaitAndAcquireNextImage"); + VkResult acquireResult = + 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_bufferManager.BeginFrame(m_frameContext.GetCurrentFrameIndex()); m_transientVertexIndexBufferSlicesThisFrame.clear(); diff --git a/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java b/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java index 231bdad6..4040e20d 100644 --- a/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java +++ b/android-plugin/app/src/trace/java/top/mobilegl/plugin/trace/TraceReplayActivity.java @@ -3,6 +3,8 @@ package top.mobilegl.plugin.trace; import android.app.Activity; import android.content.Intent; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; @@ -24,6 +26,7 @@ public final class TraceReplayActivity extends Activity { private TextView statusView; private TraceReplayRequest request; private boolean started; + private final Handler mainHandler = new Handler(Looper.getMainLooper()); @Override protected void onCreate(Bundle savedInstanceState) { @@ -58,11 +61,12 @@ public final class TraceReplayActivity extends Activity { holder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { + scheduleReplay(holder); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - startReplay(holder); + scheduleReplay(holder); } @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) { if (started) { return; } + Surface surface = holder.getSurface(); + if (surface == null || !surface.isValid()) { + return; + } started = true; 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) { diff --git a/tools/trace_replay/GL4ES_TRACES.md b/tools/trace_replay/GL4ES_TRACES.md new file mode 100644 index 00000000..5844cfce --- /dev/null +++ b/tools/trace_replay/GL4ES_TRACES.md @@ -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. diff --git a/tools/trace_replay/README.md b/tools/trace_replay/README.md index 5b238817..fd0ff226 100644 --- a/tools/trace_replay/README.md +++ b/tools/trace_replay/README.md @@ -3,6 +3,10 @@ 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. + Build from the MobileGL repository root: ```sh @@ -39,5 +43,5 @@ build-test/tools/trace_replay/mobilegl_trace_replay \ --fuzz-percent 20 ``` -The Linux runner loads MobileGL by path with `dlopen`. It uses an EGL pbuffer for `DirectGLES` and an X11 window -surface for `DirectVulkan` so Magma can create a Vulkan swapchain under `xvfb-run` in CI. +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.