Skip to content

refactor(interop): re-vendor Pelorus at the commit whose conformance fixture reads with _fsopen (ADR-1113) - #2429

Merged
lusoris merged 3 commits into
masterfrom
refactor/pelorus-revendor-fsopen-fixture
Oct 7, 2026
Merged

lusoris merged 3 commits into
masterfrom
refactor/pelorus-revendor-fsopen-fixture

Conversation

@lusoris

@lusoris lusoris commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Summary

BLUF: stacked on #2424. VMAFx/pelorus #91 (fixing VMAFx/pelorus#90) reads the conformance fixture's files back through fixture_open_read(), _fsopen(path, "rb", _SH_DENYNO) on Windows, instead of the deprecated fopen() icx-cl reported twice in core/test/test_pelorus_interop.c (Windows MSVC+SYCL, job 112842753545). PELORUS_VENDOR_SHA moves to 11e183ec0aed and scripts/sync-pelorus-interop.sh --update re-renders the vendored files.

Type

  • refactor — no behaviour change

Checklist

  • Commits follow Conventional Commits.
  • Vendored files are rendered by the script, never edited by hand (ADR-1113).

Bug-status hygiene

Netflix golden-data gate

  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.

Deep-dive deliverables

  • Research digest — no digest needed: trivial re-pin.
  • Decision matrix — no alternatives: only-one-way fix (ADR-1113 forbids editing the mirror).
  • AGENTS.md invariant note — no rebase-sensitive invariants beyond ADR-1113's existing mirror rule.
  • Reproducer / smoke-test command — below.
  • CHANGELOG fragment — changelog.d/changed/pelorus-revendor-fsopen-fixture.md.
  • Rebase note — docs/rebase-notes.md.

Reproducer

scripts/sync-pelorus-interop.sh /path/to/pelorus   # a clone of VMAFx/pelorus that has 11e183e
python3 scripts/ci/run_meson_test.py -- -C <cpu build> test_pelorus_interop

#2426)

* ci: turn warnings into errors on the Windows MSVC legs that print none

scripts/ci/werror-args.sh gains an msvc mode that prints -Dwerror=true:
Meson makes that /WX on every cl.exe compile and -WX on every link.exe
link, and core/src/meson.build adds --Werror all-warnings to the nvcc
fatbins. Windows MSVC+CUDA, Windows ARM64 MSVC and Windows MSVC+CUDA
(full) call it from a bash step, because their configure steps run under
cmd. The icx-cl leg (Windows MSVC+SYCL) is not at zero yet and stays
listed in docs/development/ci.md. test_werror_args.py fails an MSVC leg
that is neither gated nor listed.

* docs(ci): record the MSVC gate's proof runs and the icx-cl leg's count

The planted C4305 failed all three gated legs as C2220, the planted linker directive the x64 and ARM64 links as LNK1218, and the gate commit passed them with no warning in the logs. Windows MSVC+SYCL printed 4,361 warnings on the gate commit; the state row and docs/development/ci.md list what is left.
…852) (#2199)

* feat(api): implement the VMAFx core API on the engine (RC4 WP2, ADR-1852)

A program can now score videos through vmafx/*.h alone. The definition
(core/api/vmafx.toml, ABI 0.1.1 per ADR-1897) gains contexts with a log
callback and options, option sets, extractor / model / model-set
registration, imported scores, feature resolution (ADR-1359), frame
retention, refcounted models and model sets with the SHA-256 of the bytes
as loaded, the CPU device, host frames allocated or borrowed without a
copy, submission and flush, and synchronous per-frame and pooled scores
for features, models and model sets. Errors also name the kind of subject
and the function; an input struct below its introduction size is the new
VMAFX_E_ABI.

The implementation in core/src/vmafx/ calls the engine through
vmaf_engine_* entry points: the bodies of 14 more libvmaf functions are
renamed in core/src/libvmaf.c and the libvmaf names forward to them until
the compat layer generates them as shims. A context with a log callback
gets the engine messages of its calls through a per-thread sink in
core/src/log.cpp and never changes the process log level. A frame
reference is one count of the engine picture's counter, so one frame is
scored by several contexts without a copy (ADR-1880). ADR-1906 records
these rules.

Scores equal the libvmaf calls bit for bit: test_vmafx_bitexact compares
every feature and model score, per frame and pooled with every method, of
the golden pair, both checkerboards and the 10-bit sparks pair for
vmaf_v1.0.16_3d0h and vmaf_v0.6.1. New tests cover every function's
success, named failures and NULL error path, struct size negotiation,
logging, lifetimes under ASan and UBSan, and SHA-256; each was shown
failing on a planted defect.

Two generator fixes for WP1 (requests/WP1-2): Python records keep to_c()
when they gain pointer fields, and the generator tests no longer assume
the definition's ABI version or function set.

Found on the way: a model set scored per frame and then pooled over that
frame fails in libvmaf too (T-MODEL-SET-SCORE-NOT-IDEMPOTENT-2026-10-05).

* refactor(api): bring the VMAFx core API sources and tests to zero clang-tidy findings

The cpu lane measured 33 findings in the files of the core API commit
(dev container, clang-tidy 22.1.8). The VMAFx log level and pixel format
reach the engine through explicit mappings instead of enum casts; pointer
offsets in the SHA-256 code are computed in size_t; the model file reader
cannot reach malloc(0) on any analysed path; the held-reference array is
cast from realloc explicitly.

The tests compare doubles through their integer bits instead of memcmp,
take the model and fixture directories from Meson at build time instead
of getenv, release their clip buffers on every path, and test functions
over the branch threshold are split into smaller ones. A source contract
test (test_gpu_float_ssim_auto_scale_contract) now reads the
vmaf_engine_* bodies the libvmaf entry points forward to.

vmafx_device_create() and the two registration functions assert the state
their checks established, so every fork-added function of 20 lines or
more carries an assert (assertion-density gate).

* feat(api): route every message of a VMAFx context to its log callback (ADR-1906)

The maintainer chose full routing for RC4 (ADR-1906, now Accepted): a
context with a log callback receives every message the library raises
for it, worker threads included, and nothing of it reaches the process
log.

Each job the engine runs on a worker thread now captures the log sink of
the call that submitted it and installs it while it runs
(ThreadDataBatch.log_sink in core/src/libvmaf.c, vmaf_log_thread_sink()
in core/src/log.cpp); core/src/thread_pool.c is unchanged. The error
prints of the float ADM, SSIM, MS-SSIM, motion and VIF code went to
stdout and now go through vmaf_log(). A model belongs to no context:
VmafxModelConfig gains log_level, log_callback and log_user, and a load
routes its messages there. VmafxLogCallback moves to vmafx/types.h and
documents that it runs on library threads, possibly several at once.

The engine's init no longer sets the process log level;
vmafx_context_create() sets it for a context without a callback only, so
a context with a callback never writes it. A ThreadSanitizer run of the
new test found that the level itself is a plain global every init writes
while vmaf_log() reads it on all threads; that is a master defect and its
fix is master PR #2207 (T-LOG-LEVEL-GLOBAL-DATA-RACE-2026-10-06), which
this branch gets on its rebase.

test_vmafx_log_routing covers a message raised on a worker thread with
n_threads = 4, two contexts on two threads in a deterministic
interleaving and concurrently with worker threads, the process log of a
context without a callback, and a model load. Planted defects (no job
sink, a process-wide sink, a model load without its sink, a plain
context that leaves the process level) each fail it; with #2207's atomic
level applied TSan reports nothing in 8 runs. A source contract
(test_engine_log_routing_contract.py) refuses a direct stdout / stderr
write in core/src outside a declared exception table.

* ci(tidy): measure the translation units of the VMAFx core API (WP2) in the cpu lane

The clang-tidy coverage rule on master requires every tracked translation
unit to be read by a lane. The new and touched units of this pull request
were measured in the dev container (scripts/dev/tidy-lane.sh --write
--only ... cpu, clang-tidy 22.1.8): 0 findings, 0 uncited NOLINT; they join
the cpu lane's measured sources.

* fix(api): emit no bare `return None` in the generated Python binding

Master's hooks now lint bindings/python/ with the pinned ruff, whose RET501
rewrites a method that returns `None` as its only value. The generated
binding of WP2 had three such methods, so a commit that stages
bindings/python/vmafx/_api.py came out of the hooks changed and the
generated-file check would then fail. The generator leaves the `return`
out when a method returns `None`; the binding is otherwise unchanged.

* test(api): count one direct write in metal/common.mm after master's Metal cleanup

The routing contract holds an exact count per file. Master's Metal host cleanup (#2222) left one device-listing write in core/src/metal/common.mm where the contract counted two; the count follows, so a new write still fails the test.

* chore(api): regenerate the generated files after the rebase onto master

* docs: regenerate the indexes and the citation map after rebasing
…fixture reads with _fsopen (ADR-1113) (#2429)

* refactor(interop): re-vendor Pelorus at the commit whose conformance fixture reads with _fsopen (ADR-1113)

VMAFx/pelorus #91 (fixing #90) reads the fixture files back through fixture_open_read(), _fsopen(..., _SH_DENYNO) on Windows, instead of the deprecated fopen() icx-cl reported twice in test_pelorus_interop.c. PELORUS_VENDOR_SHA moves to 11e183ec0aed and --update re-renders the vendored files; the drift check passes.
@lusoris
lusoris force-pushed the refactor/pelorus-revendor-fsopen-fixture branch from ffd44b1 to f7ddee7 Compare October 7, 2026 17:12
@lusoris
lusoris merged commit f7ddee7 into master Oct 7, 2026
9 of 36 checks passed
@lusoris
lusoris deleted the refactor/pelorus-revendor-fsopen-fixture branch October 7, 2026 17:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:refactor Internal refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant