Run pspautotests under qemu for loongarch64 and riscv64

Only the IR JIT: it's the sole native backend these two have and the one
thing here that isn't shared code, and the x86-64 and arm64 runners
already cover all four backends. Every run costs emulated wall clock, so
the timeout goes up to match.

test.py grows a per-architecture known-failure list, selected with
--known-failures=<arch>, so this can guard against new breakage while the
four outstanding ones stay outstanding. Each entry carries its reason.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-21 15:36:49 -06:00
1 parent 46632812cd
commit 88b80011e4
2 files changed
+52

No files matched your search

+15
View File
@@ -409,6 +409,21 @@ jobs:
qemu-${{ matrix.extra }} -L /usr/${{ matrix.extra }}-linux-gnu \
build-${{ matrix.extra }}/PPSSPPUnitTest all
# Only the IR JIT - it's the sole native backend these two have, and the only thing here that
# isn't shared code. The interpreters are portable C++ that the x86-64 and arm64 runners
# already cover on all four backends, and every run costs emulated wall clock.
- name: Execute headless tests under qemu
if: matrix.extra == 'loongarch64' || matrix.extra == 'riscv64'
run: |
# test.py takes the newest build*/PPSSPPHeadless, so hand it one that runs the cross build
# under emulation. The wall clock is raised because everything is slower under qemu.
mkdir -p build-qemu
printf '#!/bin/bash\nexec qemu-%s -L /usr/%s-linux-gnu "$(dirname "$0")/../build-%s/PPSSPPHeadless" "$@"\n' \
'${{ matrix.extra }}' '${{ matrix.extra }}' '${{ matrix.extra }}' > build-qemu/PPSSPPHeadless
chmod +x build-qemu/PPSSPPHeadless
python3 test.py -g --graphics=software --cpu=jit-ir --timeout=60 \
--known-failures=${{ matrix.extra }}
- name: Package build
if: matrix.extra == 'test' || matrix.id == 'ios'
run: |
+37
View File
@@ -432,6 +432,30 @@ tests_good = [
# Broken tests
# -b flag runs these.
# Tests that don't pass yet on an architecture we can only reach through emulation. Pass
# --known-failures=<arch> to drop them from the run, so CI can still catch anything *new* breaking
# while these stay outstanding. Keep a reason next to each one, and delete entries as they're fixed
# rather than letting the list rot.
known_failures = {
"riscv64": [
# No flush-to-zero: the ISA has no control for it, so a denormal result survives where the
# PSP would have flushed it. Everything else in this test passes.
"cpu/fpu/fpu",
# The software renderer's output differs from the reference by the same amount on both of
# these architectures, despite them using completely different SIMD paths. Unexplained.
"gpu/clipping/homogeneous",
"gpu/commands/cull",
"gpu/primitives/triangles",
],
"loongarch64": [
"cpu/fpu/fpu",
"gpu/clipping/homogeneous",
"gpu/commands/cull",
"gpu/primitives/triangles",
],
}
tests_next = [
# These are the next tests up for fixing. These run by default.
"cpu/fpu/fcr",
@@ -628,10 +652,17 @@ def main():
tests = []
args = []
teamcity = False
skip_arch = None
for arg in sys.argv[1:]:
if arg == '--teamcity':
args.append(arg)
teamcity = True
elif arg.startswith('--known-failures='):
# Ours, not headless's - don't pass it through.
skip_arch = arg[len('--known-failures='):]
if skip_arch not in known_failures:
print("Unknown architecture for --known-failures: " + skip_arch)
sys.exit(1)
elif arg[0] == '-':
args.append(arg)
else:
@@ -651,6 +682,12 @@ def main():
elif '-m' in args:
tests = [i for i in tests_next + tests_good if i.startswith(tests[0])]
if skip_arch:
skipped = [t for t in tests if t in known_failures[skip_arch]]
tests = [t for t in tests if t not in known_failures[skip_arch]]
if skipped:
print("Skipping %d known failures on %s: %s" % (len(skipped), skip_arch, ", ".join(skipped)))
returncode = run_tests(tests, args)
if teamcity:
return 0