Files
2ff8f419cb ci: run the GPU tests on lavapipe on Linux and fail if they skip (#7975)
The Linux runner has no GPU, so the GPU tests ran on Mesa llvmpipe over
GL, which can't render Rgba32Float: 57 GPU checks (50 GPU parity, 3
canvas, 2 adjustment preview parity, 2 effect-map recovery) returned
early and passed without comparing anything. A new step after Test
installs mesa-vulkan-drivers and runs the nextest `gpu` group on
lavapipe (Vulkan), reusing Test's build, and fails unless the parity
tests report the Vulkan backend and no test printed a skip.

No code change: photocraft's tests take whatever adapter wgpu returns,
software adapters included. Follows the CI half of lightcraft#1148.

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:44:13 +01:00

68 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""Run the configured GPU group on lavapipe without silently losing comparisons."""
import glob
import os
from pathlib import Path
import re
import subprocess
import sys
import tempfile
import tomllib
def gpu_filter(config):
filters = [row['filter'] for row in config['profile']['default']['overrides']
if row.get('test-group') == 'gpu']
if not filters:
raise ValueError('nextest GPU group has no filters')
return ' | '.join(f'({value})' for value in filters)
def validate_log(lines):
vulkan = False
rejected = []
for line in lines:
vulkan |= 'GPU parity backend: Vulkan' in line
# Authored skips, not nextest's summary of ignored/filtered-out tests.
if re.search(r'\bskipping\b|\bno (?:GPU )?adapter\b', line):
rejected.append(line.rstrip())
if 'SKIP ' in line and not (
('SKIP gpu timing:' in line and 'is a software adapter' in line)
or 'SKIP the comparison: this GPU finishes' in line
or 'SKIP the sum: this refresh still fit one command buffer' in line
):
rejected.append(line.rstrip())
if not vulkan:
rejected.append('GPU parity tests did not report the Vulkan backend')
return rejected
def main():
root = Path(__file__).resolve().parents[1]
with (root / '.config/nextest.toml').open('rb') as source:
selected = gpu_filter(tomllib.load(source))
icds = sorted(glob.glob('/usr/share/vulkan/icd.d/lvp_icd*.json'))
if not icds:
raise RuntimeError('Install mesa-vulkan-drivers and libvulkan1 before this check')
env = dict(os.environ, WGPU_BACKEND='vulkan', VK_ICD_FILENAMES=os.pathsep.join(icds))
command = ['cargo', 'nextest', 'run', '--profile', 'ci', '--workspace', '--locked',
'--features', 'heif', '--lib', '--bins', '--tests', '-E', selected,
'--success-output', 'immediate', '--color', 'never']
# Stream output and keep it on disk, rather than buffering every successful test in memory.
with tempfile.TemporaryFile(mode='w+t') as log:
with subprocess.Popen(command, cwd=root, env=env, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, text=True) as process:
for line in process.stdout:
sys.stdout.write(line)
log.write(line)
result = process.wait()
log.seek(0)
errors = validate_log(log)
for error in errors:
print(f'::error::{error}', file=sys.stderr)
return result if result else int(bool(errors))
if __name__ == '__main__':
sys.exit(main())