Authors with no merged pull requests can have 1 open, with at least 1
merged 20, and from 20 merged there is no limit. Reopening a pull
request runs the check again.
Co-Authored-By: Claude <noreply@anthropic.com>
No job saved its ccache, so every build restored a day-old cache and
recompiled about half the tree (971/2038 hits). Main push builds now
save it, and they no longer cancel each other, so one finishes and
refreshes it. Pull request builds still only restore, so PR code never
writes the shared cache.
macOS has no counterpart to userfaultfd write-protect or
MEM_WRITE_WATCH, so GuestWriteWatch had no backend there and the driver
re-read every guest buffer on each use.
The macOS backend write-protects watched pages. The first write to a
page faults, the SIGBUS/SIGSEGV handler records the page and restores
its protection, and Collect reports the recorded pages and protects
them again. A page is protected before its record is cleared, under the
lock the handler takes, so a write that lands in between is recorded.
The lock hands out turns in order: an unfair one starved writers under
Rosetta.
The protection is real, which adds three entry points:
- GuestWriteWatchBeginHostWrite/EndHostWrite lift it around a system
call that writes guest memory, which would otherwise fail with
EFAULT. GuestArena::HostWrite calls them, as it calls the Windows
equivalent.
- GuestWriteWatchProtectionChanged tells the watch the protection given
to watched pages by mprotect or a new mapping.
- GuestWriteWatchProtection reports that protection, since a watched
page is read-only between a collection and the next write.
Register keeps the recorded protection of a page it already watches:
read from the kernel it would be the watch's own read-only protection,
and the page would never be watched again.
The tests build without the prx libraries and run natively and through
Rosetta.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Install lavapipe on Linux release builds and set ANYPS5_REQUIRE_VULKAN and GALLIUM_OVERRIDE_CPU_CAPS for ctest so GPU execution tests run instead of skipping. Scope SSL_CERT_FILE to Windows winlibs download and CMake configure steps only so Linux FFmpeg fetch is not broken. Leave release ctest as a single strict run.
Check out the repo when labeling open PRs so actions/labeler reads .github/labeler.yml locally instead of fetching it from the API once per pull request.
GitHub refreshes merge_commit_sha only when the pull request's branch
changes, so a manual build could test the pull request against a main
from days earlier. Each job now checks out main as it is when the build
starts and merges the pull request head into it.
gh label create exits non-zero for a label that already exists, and the
step runs with bash -e, so the first existing unforced label stopped the
job. Skip labels that already exist, keeping hand-set colors.
Fixes#2320
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Linux job reports "100% tests passed out of 371" with 20 agc_driver execution tests skipped
(llvmpipe reports subgroup size 8, so the tests that need a wider wave exit 77), and the Windows
job reports "100% tests passed, 0 tests failed out of 368" with 143 skipped - the runner has no
Vulkan driver and ANYPS5_REQUIRE_VULKAN is not set there, so 143 of the 147 GPU execution tests
silently do not run. ctest counts a skip as a pass, so neither job notices when the set grows.
Add tools/check_skips.py. It reads the file ctest writes with --output-junit and fails when a test
skips for a reason that is not expected:
- linux: a skip is expected only when the test's own output reports that the device's subgroups
are too narrow for it, so adding a wave32 test does not need the rule edited;
- windows: any agc_driver test, since the runner has no driver for them, while a skip of anything
else fails.
Both jobs now pass --output-junit and run the check after ctest. The JUnit file needs no
redirection, so the console output stays visible and no pipe can hide a failing ctest.
Verified here with the CI command and the CI device (lavapipe, subgroup 8): the real run reports
20 skipped, all expected; a 21st wave32 test skipping for the same reason passes; a skip whose
reason is something else exits 1; a file with 143 agc_driver skips passes with --job windows and
one non-agc skip in it exits 1.
A test executable can be declared with add_test_executable and never
registered with add_test. It is then built and never run, and ctest
reports a full pass over what it knows, so nothing in CI says so.
Measured on main, five test executables are in this state: the driver's
mesh and recorder tests, the guest formatting tests, the video out flip
tests and the BDA device tests.
tools/check_test_registration.py compares the test executables CMake
builds, read from the build graph, against the add_test calls in the
generated CTestTestfile.cmake files, which are written at configure time
and so do not depend on the build having finished. It fails on a test
executable that nothing runs, and records those five by name so the job
stays green until they are dealt with.
Both jobs run it right after configure, before anything is built.
CI configures without ANYPS5_ENABLE_SPIRV_TOOLS, so the shader recompiler never validates or
optimizes the SPIR-V it emits - Recompiler.cpp guards the ValidateAndOptimizeSpirv call on that
macro - and the shader tests lose the blocks that exercise it:
- ShaderMemory.cpp guards five blocks on the macro, including three expectFailure cases that are
the only coverage for rejecting invalid SPIR-V and for rejecting an unsupported Vulkan or SPIR-V
target.
- SpirvOptimizer.cpp includes the SPIRV-Tools headers, so the file is not built at all.
- README.md gives the Spirv-Tools validation as how the recompiler is known to produce valid
SPIR-V, and no job exercises it.
Add the flag to CONFIGURE. Verified with the CI command and the CI device (lavapipe, subgroup 8,
ANYPS5_REQUIRE_VULKAN=1, GALLIUM_OVERRIDE_CPU_CAPS=avx): the full suite passes 371/371 with the
flag on, with the same 20 skips, and agc_shader_memory passes.
SPIRV-Tools is a submodule built from source, so this adds build time to the job. I have not
measured how much; if it is too much, the flag can go on one job instead of the shared CONFIGURE.
agc_driver_vopc_compare failed on every Linux runner with an
AVX512-FP16 Xeon (Sapphire, Emerald and Granite Rapids) and passed on
AMD EPYC and Ice Lake runners. Ubuntu 24.04's lavapipe compiles with
LLVM 20.1.2, which on these CPUs merges a masked fcmp ult/uge on half
vectors with the same compare of swapped operands, so v_cmp_nle_f16,
v_cmp_nlt_f16 and v_cmpx_nle_f16 return the result of their mirror.
The recompiler's SPIR-V is the same on every device and correct.
GALLIUM_OVERRIDE_CPU_CAPS=avx keeps LLVM off AVX-512, so every runner
compiles the tests the same way.
MixPrecision and SdwaDestination dispatch hand-assembled RDNA through the
recompiler and compare every lane with a CPU model, but were never in ctest.
Move them to tests/execution/, which is globbed into one test per file with
the same target names, so new execution tests add a file and no CMake lines.
They exit 77 (skipped) when the host has no Vulkan device; the Linux runner
installs lavapipe and sets ANYPS5_REQUIRE_VULKAN=1 so they cannot skip there.
Co-Authored-By: Claude <noreply@anthropic.com>
WinLibs puts its own cmake.exe (4.3, OpenSSL) first in PATH and ships no
CA certificates, so file(DOWNLOAD) of the FFmpeg package failed with
curl error 60. SSL_CERT_FILE points it at the bundle of Git for Windows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Feat/provide release
Added a release workflow for v* tags: build Windows and Linux, run tests, and publish only if both platforms are successful. The release contains PRX archives, relinker executables, and documentation from docs/user. The build cache is reused.
- `prx-windows-v0.1.0.zip`
- `prx-windows-v0.1.0.tar.gz`
- `prx-linux-v0.1.0.zip`
- `prx-linux-v0.1.0.tar.gz`
- `relinker-v0.1.0.exe`
- `relinker-v0.1.0`
- `COMPATIBILITY.md`
- `INPUT_MAPPING.md`