diff --git a/tools/cts/README.md b/tools/cts/README.md index a843261a..acce48aa 100644 --- a/tools/cts/README.md +++ b/tools/cts/README.md @@ -9,7 +9,8 @@ This directory contains three supported paths: `skills/wgl-gl-cts-on-mobilegl/SKILL.md`. - Desktop Linux x64 / MobileGL EGL: `scripts/run_cts_local.py` against the `mobilegl-desktop` VK-GL-CTS target, documented in "Desktop Linux workflow" - below. This is the path that needs no device and no GPU. + below and in `skills/linux-gl-cts-on-mobilegl/SKILL.md`. This is the path that + needs no device and no GPU. Windows prerequisites are Git, Python 3.9+, CMake, Visual Studio 2022's Desktop C++ workload, and a Vulkan SDK visible to CMake. DirectVulkan also needs a diff --git a/tools/cts/skills/README.md b/tools/cts/skills/README.md index 82bc6930..1e590d1b 100644 --- a/tools/cts/skills/README.md +++ b/tools/cts/skills/README.md @@ -17,3 +17,4 @@ Each skill is a self-contained package, matching the layout used by | --- | --- | | [gl-cts-on-mobilegl](gl-cts-on-mobilegl/SKILL.md) | Build VK-GL-CTS `glcts` as a standalone Android arm64 binary against MobileGL's own EGL, run KHR-GL33, and report a per-backend OpenGL 3.3 core conformance rate. | | [wgl-gl-cts-on-mobilegl](wgl-gl-cts-on-mobilegl/SKILL.md) | Build MobileGL's Windows x64 WGL drop-in, run GL30-GL46 core CTS against DirectGLES and DirectVulkan, resume safely, and emit validated reports. | +| [linux-gl-cts-on-mobilegl](linux-gl-cts-on-mobilegl/SKILL.md) | Build `glcts` as a desktop Linux host binary against MobileGL, run any CTS group headlessly with no GPU, and report Espryt and Magma separately. The path to reach for while iterating on a fix. | diff --git a/tools/cts/skills/linux-gl-cts-on-mobilegl/SKILL.md b/tools/cts/skills/linux-gl-cts-on-mobilegl/SKILL.md new file mode 100644 index 00000000..f151b9cd --- /dev/null +++ b/tools/cts/skills/linux-gl-cts-on-mobilegl/SKILL.md @@ -0,0 +1,159 @@ +--- +name: linux-gl-cts-on-mobilegl +description: Run the Khronos OpenGL CTS (VK-GL-CTS glcts) against MobileGL on desktop Linux with no GPU and no device, and report a per-backend conformance rate for Espryt (DirectGLES) and Magma (DirectVulkan). Use when measuring or iterating on the conformance of one test group, when a fix needs a before/after number, or when neither an Android device nor a Windows GPU box is available. +--- + +# OpenGL CTS on MobileGL (desktop Linux) + +## Overview + +`glcts` is built as an ordinary x86-64 host executable that reaches OpenGL only +through `libMobileGL.so`, using the `mobilegl-desktop` VK-GL-CTS target and the +`tcu::Platform` port in `tools/cts/platform/`. Nothing links `libGL` or `libEGL`, +so a result is unambiguously MobileGL's. + +Both backends run headless on software rendering, so this needs no GPU at all: + +- **Espryt** (`DirectGLES`) drives Mesa's OpenGL ES through the system EGL. +- **Magma** (`DirectVulkan`) runs on lavapipe, whose `VK_EXT_headless_surface` + is what the desktop platform port's pbuffer path requires. + +Always report the two backends **separately**. They are different +implementations of the same front end, they fail different cases, and a single +combined number hides which one a change moved. + +## Prerequisites + +```sh +sudo apt-get install -y ninja-build cmake libvulkan-dev \ + libegl1-mesa-dev libgles2-mesa-dev mesa-vulkan-drivers +``` + +`mesa-vulkan-drivers` is what installs lavapipe; without it DirectVulkan has no +ICD and `eglInitialize` fails inside the backend. A C++23 toolchain is required +(GCC 13+, or Clang 20+ — Clang 18 defines `__cpp_concepts` as 201907L, which +switches libstdc++'s `` off and the build fails in +`MG_Util/ShaderTranspiler/Types.h`). + +```sh +export MG= +export CTS= +``` + +## Step 1 — build libMobileGL.so + +```sh +git -C "$MG" submodule update --init --recursive +python3 "$MG/3rdparty/glslang/update_glslang_sources.py" # SPIRV-Tools; ENABLE_OPT is forced on + +cmake -S "$MG" -B "$MG/build-linux" -G Ninja -DCMAKE_BUILD_TYPE=Release \ + -DMOBILEGL_BUILD_TEST=OFF -DMOBILEGL_BUILD_BENCHMARK=OFF \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache +cmake --build "$MG/build-linux" --parallel "$(nproc)" +``` + +Add `-DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=FALSE` when iterating. The +Release configuration turns LTO on, which makes every relink cost minutes for no +behavioural difference; a conformance number is identical either way. + +## Step 2 — get VK-GL-CTS and build glcts + +Use a release tag so the mustpass list, and therefore the reported rate, is +citable. + +```sh +git -C "$CTS" checkout opengl-cts-4.6.8.1 +python3 "$CTS/external/fetch_sources.py" + +python3 "$MG/tools/cts/scripts/sync_to_cts.py" "$CTS" +git -C "$CTS" apply "$MG/tools/cts/patches/0001-fbo-color-texture-attachment.patch" + +cmake -S "$CTS" -B "$CTS/build-cts" -G Ninja -DDEQP_TARGET=mobilegl-desktop \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache +ninja -C "$CTS/build-cts" glcts +``` + +Confirm the configure output says `*** Using MobileGL desktop target`. Budget a +couple of hours for the `glcts` link on a small machine; it is a one-time cost +that ccache makes cheap afterwards. + +If `fetch_sources.py` dies with `HTTP Error 403` it is an egress policy blocking +the GitHub archive downloads (zlib, libpng), not a broken checkout: `git clone` +still works, so clone the package at the tag the script pins into +`external//src` by hand — for libpng also copy +`scripts/pnglibconf.h.prebuilt` to `src/pnglibconf.h`, which is what the +script's post-extract step does. + +## Step 3 — run, once per backend + +```sh +cd "$MG" +for BACKEND in DirectGLES DirectVulkan; do + python3 tools/cts/scripts/run_cts_local.py --backend "$BACKEND" \ + --glcts "$CTS/build-cts/external/openglcts/modules/glcts" \ + --lib build-linux/libMobileGL.so \ + --caselist cases.txt --outdir "runs/${BACKEND}" \ + --env EGL_PLATFORM=surfaceless + python3 tools/cts/scripts/qpa_report.py "runs/${BACKEND}" --label "$BACKEND" +done +``` + +`cases.txt` is any subset of a mustpass list. For one group, filter the list +rather than running the whole suite: + +```sh +grep direct_state_access \ + "$CTS"/external/openglcts/data/gl_cts/data/mustpass/gl/khronos_mustpass/main/gl45-main.txt \ + > cases.txt +``` + +`run_cts_local.py` re-invokes `glcts` with only the cases that have no result +yet, so a crash costs one case rather than the run, and it records the case that +was open when the process died as `Crash`. `qpa_report.py` scores `Pass`, +`NotSupported` and the warning statuses as non-failures, the way Khronos scores +a submission, and reports the strict `Pass`-only rate alongside. + +## Required flags, and why + +| Flag | Why it is not optional | +| --- | --- | +| `--env EGL_PLATFORM=surfaceless` | For DirectGLES. With no `/dev/dri` node Mesa's EGL fails `eglInitialize` on the default display, and MobileGL surfaces that as `EGL_BAD_ALLOC` out of `eglCreatePbufferSurface` — which points at the wrong call entirely. Harmless for DirectVulkan, so pass it to both. | +| `--deqp-surface-type=fbo` (the runner's default) | DirectVulkan reads back zeros from the **default** framebuffer. dEQP verifies nearly everything through `glReadPixels`, so rendering to the surface scores Magma near zero for a reason unrelated to conformance. Use it for both backends so the two numbers stay comparable. | +| `--deqp-terminate-on-device-lost=disable` (supplied by the runner) | Its default calls `glGetGraphicsResetStatus()` after every case. That is GL 4.5 / `KHR_robustness`, absent from what MobileGL exports, so the pointer is null and the process segfaults on the first case. | + +## What this environment does and does not tell you + +Reproducible here, and MobileGL's own rather than a driver quirk: + +- DirectVulkan's default-framebuffer readback returns zeros; a user FBO, + renderbuffer- or texture-attached, is correct on both backends. This is the + same defect the Android runs work around, so it can be debugged without a + phone. + +Different from a real GPU, so do not read conformance into it: + +- lavapipe supports renderbuffer formats Adreno reports as unsupported, so the + Android runs see `NotSupported` where these do not, and vice versa. +- Backend limits differ. `GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT` is 16 on llvmpipe + and on lavapipe; a device that reports 1 will not exercise the same paths. +- Everything is a software rasterizer, so a case that fails only under real + timing or real tiling will not fail here. + +## Reference results: KHR-GL45.direct_state_access + +`opengl-cts-4.6.8.1`, the 371 `direct_state_access` cases of the `gl45-main` +mustpass list, Mesa 25.2.8, `--deqp-surface-type=fbo`. + +| backend | renderer | conformance | strict Pass | Fail | InternalError | Crash | +| --- | --- | ---: | ---: | ---: | ---: | ---: | +| DirectGLES | Espryt | **74.66%** | 67.12% | 86 | 8 | 0 | +| DirectVulkan | Magma | **73.05%** | 72.78% | 89 | 8 | 3 | + +## Contents + + platform/tcuMobileGLPlatform.{cpp,hpp} dEQP tcu::Platform for MobileGL + targets/mobilegl-desktop.cmake VK-GL-CTS target (-DDEQP_TARGET=mobilegl-desktop) + scripts/sync_to_cts.py inject the port into a CTS checkout + scripts/run_cts_local.py crash-resuming local-host runner + scripts/qpa_report.py .qpa -> conformance rate diff --git a/tools/cts/skills/linux-gl-cts-on-mobilegl/agents/openai.yaml b/tools/cts/skills/linux-gl-cts-on-mobilegl/agents/openai.yaml new file mode 100644 index 00000000..2deb57ae --- /dev/null +++ b/tools/cts/skills/linux-gl-cts-on-mobilegl/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "OpenGL CTS on MobileGL (desktop Linux)" + short_description: "Run VK-GL-CTS glcts against MobileGL headlessly and report Espryt and Magma separately" + default_prompt: "Use $linux-gl-cts-on-mobilegl to run the selected OpenGL CTS group against MobileGL on this Linux host and report the conformance rate for DirectGLES (Espryt) and DirectVulkan (Magma) separately."