From 329f30a0c94acc86761a18cfb0cb2aeb26f684f9 Mon Sep 17 00:00:00 2001 From: libretroadmin Date: Fri, 9 Oct 2026 08:35:56 +0200 Subject: [PATCH] Create the libretro GL presets once and run frametests on arm64 The GL contexts' CreateDrawContext made the thin3d presets and ContextReset made them again, leaking the first set on every context reset. Only ContextReset makes them now. The software renderer draws the same frame dumps on arm64 as on x86-64, so the frametests run on the arm64 runner too. b.sh --aarch64 and setup-cross.sh aarch64 give a headless build to run them under qemu locally. --- .github/workflows/build.yml | 10 +++--- b.sh | 5 +++ cmake/Toolchains/aarch64-linux-gnu.cmake | 44 ++++++++++++++++++++++++ cmake/scripts/setup-cross.sh | 18 ++++++---- libretro/LibretroGLContext.cpp | 1 - libretro/LibretroGLCoreContext.cpp | 1 - 6 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 cmake/Toolchains/aarch64-linux-gnu.cmake diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dff37d3725..e0b1687466 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -396,19 +396,17 @@ jobs: working-directory: ${{ env.GITHUB_WORKSPACE }} run: python3 test.py -g --graphics=vulkan --known-failures=vulkan - # x86-64 only: the reference images don't match what the software renderer produces on arm64, - # 23 of the 30 dumps differ there, one of them by an MSE of 100. That's a real difference and - # worth chasing, but it predates the arm64 runner - it just never had a CI job to show up in. + # Both Linux runners: the software renderer's x86-64 and arm64 JITs have to draw the same pixels. - name: Execute frametests - if: matrix.os == 'ubuntu-26.04' + if: runner.os == 'Linux' working-directory: ${{ env.GITHUB_WORKSPACE }} run: python3 frametests.py frametests/frametests.json --out-mode=failures - name: Upload frametest report uses: actions/upload-artifact@v7 - if: matrix.os == 'ubuntu-26.04' && always() + if: runner.os == 'Linux' && always() with: - name: frametest-report + name: frametest-report-${{ matrix.os }} path: frametests/out/ test-headless-alpine: diff --git a/b.sh b/b.sh index d3804f0fa9..0fab637f16 100755 --- a/b.sh +++ b/b.sh @@ -35,6 +35,11 @@ do TARGET_OS=loongarch64 CROSS_STUB_CC=loongarch64-linux-gnu-gcc-14 ;; + --aarch64) + CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/aarch64-linux-gnu.cmake -DHEADLESS=ON -DHEADLESS_CROSS=ON -DUSE_SYSTEM_LIBPNG=OFF -DUSE_SYSTEM_LIBSDL2=OFF ${CMAKE_ARGS}" + TARGET_OS=aarch64 + CROSS_STUB_CC=aarch64-linux-gnu-gcc-14 + ;; --riscv64) CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/riscv64-linux-gnu.cmake -DHEADLESS=ON -DHEADLESS_CROSS=ON -DUSE_SYSTEM_LIBPNG=OFF -DUSE_SYSTEM_LIBSDL2=OFF ${CMAKE_ARGS}" TARGET_OS=riscv64 diff --git a/cmake/Toolchains/aarch64-linux-gnu.cmake b/cmake/Toolchains/aarch64-linux-gnu.cmake new file mode 100644 index 0000000000..adff711c4b --- /dev/null +++ b/cmake/Toolchains/aarch64-linux-gnu.cmake @@ -0,0 +1,44 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc-14) +set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++-14) +set(CMAKE_ASM_COMPILER aarch64-linux-gnu-gcc-14) + +set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# No X11 in the sysroot; disable the X11 Vulkan path to avoid include-dir errors. +set(USING_X11_VULKAN OFF CACHE BOOL "" FORCE) + +# Use legacy GL preference so find_package(OpenGL) looks for a single libGL.so +# rather than the GLVND split (libOpenGL.so + libGLX.so), which we don't have. +# A stub libGL.so + GL headers must be present in the sysroot; they are placed +# there by cmake/scripts/setup-cross.sh (run once with sudo, or automatically +# by the CI install step). +set(OpenGL_GL_PREFERENCE LEGACY CACHE STRING "" FORCE) + +# b.sh also creates a stub in /stublibs/ as a local fallback so the +# linker can resolve GL/GLX calls from GLEW's static archive via PLT entries. +set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_BINARY_DIR}/stublibs" + CACHE STRING "" FORCE) + +# Allow CMake's compile-check programs to run via QEMU, if it's installed. +# Debian/Ubuntu ship the static binaries in qemu-user-static and the dynamic +# ones in qemu-user; either will do, so take whichever is present. +find_program(QEMU_AARCH64 NAMES qemu-aarch64-static qemu-aarch64) +if(QEMU_AARCH64) + # The /lib symlink is created by the setup script; without it, pass -L + # explicitly so QEMU can find the aarch64 dynamic linker. + if(EXISTS "/lib/ld-linux-aarch64.so.1") + set(CMAKE_CROSSCOMPILING_EMULATOR "${QEMU_AARCH64}" CACHE STRING "" FORCE) + else() + set(CMAKE_CROSSCOMPILING_EMULATOR + "${QEMU_AARCH64};-L;/usr/aarch64-linux-gnu" + CACHE STRING "" FORCE) + endif() +endif() diff --git a/cmake/scripts/setup-cross.sh b/cmake/scripts/setup-cross.sh index ea9b8df86b..b62794d991 100755 --- a/cmake/scripts/setup-cross.sh +++ b/cmake/scripts/setup-cross.sh @@ -2,13 +2,19 @@ # Sets up a cross-compilation environment for one of the headless-only targets. # Run once with sudo. After this, ./b.sh -- works on a fresh checkout. # -# Usage: sudo cmake/scripts/setup-cross.sh +# Usage: sudo cmake/scripts/setup-cross.sh set -e TARGET="$1" +LD_DIR=/lib64 case "$TARGET" in + aarch64) + TRIPLE=aarch64-linux-gnu + LD_SO=ld-linux-aarch64.so.1 + LD_DIR=/lib + ;; loongarch64) TRIPLE=loongarch64-linux-gnu LD_SO=ld-linux-loongarch-lp64d.so.1 @@ -18,7 +24,7 @@ case "$TARGET" in LD_SO=ld-linux-riscv64-lp64d.so.1 ;; *) - echo "Usage: sudo $0 " + echo "Usage: sudo $0 " exit 1 ;; esac @@ -84,13 +90,13 @@ echo " Installed to $SYSROOT/lib/libGL.so" # Without this, binfmt_misc can't find the target's dynamic linker. LD_LINUX=$SYSROOT/lib/$LD_SO if [ -f "$LD_LINUX" ]; then - mkdir -p /lib64 - ln -sf "$LD_LINUX" /lib64/$LD_SO - echo "Created /lib64/$LD_SO -> $LD_LINUX" + mkdir -p $LD_DIR + ln -sf "$LD_LINUX" $LD_DIR/$LD_SO + echo "Created $LD_DIR/$LD_SO -> $LD_LINUX" fi echo "" echo "Setup complete." echo "Build: ./b.sh --$TARGET" echo "Run: qemu-$TARGET -L $SYSROOT " -echo " (after setup the /lib64 symlink lets you run $TARGET binaries directly)" +echo " (after setup the $LD_DIR symlink lets you run $TARGET binaries directly)" diff --git a/libretro/LibretroGLContext.cpp b/libretro/LibretroGLContext.cpp index 3ac3765a97..48cfc1bba8 100644 --- a/libretro/LibretroGLContext.cpp +++ b/libretro/LibretroGLContext.cpp @@ -35,7 +35,6 @@ void LibretroGLContext::CreateDrawContext() { renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); - draw_->CreatePresets(); } void LibretroGLContext::DestroyDrawContext() { diff --git a/libretro/LibretroGLCoreContext.cpp b/libretro/LibretroGLCoreContext.cpp index de549e0380..7417a60434 100644 --- a/libretro/LibretroGLCoreContext.cpp +++ b/libretro/LibretroGLCoreContext.cpp @@ -37,7 +37,6 @@ void LibretroGLCoreContext::CreateDrawContext() { renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); renderManager_->SetInflightFrames(g_Config.iInflightFrames); SetGPUBackend(GPUBackend::OPENGL); - draw_->CreatePresets(); } void LibretroGLCoreContext::DestroyDrawContext() {