Skip to content

fix(hip): let the scaffold posture report -ENOSYS so its tests skip instead of failing - #1501

Closed
lusoris wants to merge 1 commit into
masterfrom
fix/hip-scaffold-enosys
Closed

lusoris wants to merge 1 commit into
masterfrom
fix/hip-scaffold-enosys

Conversation

@lusoris

@lusoris lusoris commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Summary

On an ordinary -Denable_hip=true build, four HIP parity tests failed where they were meant to skip. master (551d35a63) on ROCm 7.2.4 / gfx1036: 173 ok, 4 fail.

enable_hipcc defaults to false, so that build compiles the HIP host code but no device kernels. core/meson_options.txt documents the posture — extractors "fall back to -ENOSYS" — and every HIP parity test turns -ENOSYS into [skip: …] and passes. Two independent things broke that.

The extractor side

float_vif_hip.c and integer_psnr_hvs_hip.c wrote their scaffold path as:

int err = vmaf_hip_kernel_submit_pre_launch(&s->lc, s->ctx, NULL, 0, 0);
if (err != 0)
    return err;
return -ENOSYS;      /* unreachable */

The call passes rb == NULL, and rejecting a NULL rb is that helper's first statement, so it always returned -EINVAL and the -ENOSYS below was dead code. The extractor reported "invalid argument" where the contract promises "not implemented", the tests' skip branch never matched, and they failed. The call did nothing else — it returned before touching anything — so it is gone.

The test side

speed_temporal_hip returns -ENOSYS correctly, but from extract(), which surfaces through vmaf_read_pictures(): registration succeeds because only extract() knows there is no kernel. test_hip_speed_singular_parity.c checked -ENOSYS only at the vmaf_use_feature() site. Its own file header already claimed "the same skip contract as test_hip_speed_temporal_parity.c", and that sibling has always checked both sites — this one just never implemented the second.

How it was found

Not by inspection. AMD_LOG_LEVEL=1 showed no HIP API error, and the extractor's own six -EINVAL guards all log at ERROR and printed nothing at VMAF_LOG_LEVEL_DEBUG. Tagging every return -E* in the read path and the HIP runtime with its __LINE__ named the source in one run: core/src/hip/kernel_template.c, the lc == NULL || rb == NULL guard. The speed test's own error printed as -38, i.e. -ENOSYS — which is what pointed at the test rather than the extractor.

Verification

Both configurations, because a fix that makes tests skip has to be shown not to be hiding a real failure.

Build Master This branch
-Denable_hip=true (default, no kernels) 173 ok, 4 fail 177 ok, 0 fail
-Denable_hip=true -Denable_hipcc=true (real gfx1036 kernels) — 183 ok, 0 fail (2 expected fail, 1 unexpected pass)

The four now print explicitly what they did:

test_hip_psnr_hvs_parity         [skip: HIP extractor is a scaffold (-ENOSYS)]
test_hip_float_vif_parity        [skip: HIP scaffold ENOSYS on feed]
test_hip_speed_singular_parity   [skip: HIP scaffold ENOSYS on submit]

and with enable_hipcc=true the same four run against real kernels and pass, so the skip is a genuine "not built", not a silenced failure. Both edits are inside #ifndef HAVE_HIPCC / an err == -ENOSYS branch, so they are inert once kernels exist — the real-kernel run confirms that rather than asserting it.

The remaining test_hip_adm_parity unexpected pass and two expected fails in the real-kernel run are the stale should_fail markers PR #1493 removes, not this change.

praetorctl audit passes and the baseline tightens 1433 → 1415: deleting the dead call removed 18 findings. Re-recorded from a clean clone, branch verified. mkdocs build --strict exits 0; check-state-md-rows OK.

Type

  • fix — bug fix

Checklist

  • Commits follow Conventional Commits.
  • make format is green; pre-push hooks pass.
  • Unit tests pass — see the table, in both HIP configurations.
  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.
  • docs/state.md: row T-HIP-SCAFFOLD-ENOSYS-MASKED-2026-09-19 added as closed.

Deep-dive deliverables (ADR-0108)

  • Research digest — no digest needed: trivial. The diagnosis is three measurements, recorded in this description, ADR-1264 and the state row.
  • Decision matrix — ADR-1264 ## Alternatives considered, four options including relaxing the helper's NULL guard and marking the tests should_fail.
  • AGENTS.md invariant note — core/src/feature/hip/AGENTS.md, plus docs/rebase-notes.md.
  • Reproducer / smoke-test command — below.
  • CHANGELOG fragment — changelog.d/fixed/hip-scaffold-enosys.md.
  • Rebase note — docs/rebase-notes.md.

Reproducer

# The default posture: 4 failures on master, 0 here.
meson setup build core -Denable_cuda=false -Denable_sycl=false -Denable_hip=true
ninja -C build && meson test -C build --suite=fast

# With real kernels, to show the skip is not hiding anything (needs ROCm + hipcc):
meson setup build-hipcc core -Denable_cuda=false -Denable_sycl=false \
    -Denable_hip=true -Denable_hipcc=true
ninja -C build-hipcc && meson test -C build-hipcc --suite=fast

Rebase hazard

Both shapes come back easily, and docs/rebase-notes.md plus core/src/feature/hip/AGENTS.md name them: a scaffold path returns -ENOSYS directly and never calls a kernel-submit helper with placeholder arguments, and a HIP parity test checks -ENOSYS at both vmaf_use_feature() and vmaf_read_pictures(). Do not relax the helper's NULL rb guard to accommodate the old call — roughly twenty real callers depend on it.

…nstead of failing

enable_hipcc defaults to false, so an ordinary -Denable_hip=true build
compiles the HIP host code but no device kernels. meson_options.txt
documents that posture as reporting -ENOSYS, and every HIP parity test
turns -ENOSYS into a skip. Four of them failed instead, for two
independent reasons.

float_vif_hip.c and integer_psnr_hvs_hip.c wrote their scaffold path as
a call to vmaf_hip_kernel_submit_pre_launch() with a NULL readback
buffer, returning its error before falling through to -ENOSYS. Rejecting
a NULL rb is that helper's first statement, so the call always returned
-EINVAL and the -ENOSYS after it was unreachable. The call did nothing
else, so it is gone.

test_hip_speed_singular_parity.c recognised -ENOSYS only at the
vmaf_use_feature() site. speed_temporal_hip reports it from extract(),
which surfaces through vmaf_read_pictures(): registration succeeds
because only extract() knows there is no kernel. The file header already
claimed the same skip contract as test_hip_speed_temporal_parity.c,
which has always checked both sites; now this one does too.

Diagnosed by tagging every 'return -E*' in the read path and the HIP
runtime, which named core/src/hip/kernel_template.c's
'lc == NULL || rb == NULL' guard, and by printing the speed test's own
error, which was -38.

Default HIP fast suite goes from 173 ok / 4 fail to 177 ok / 0 fail,
each of the four printing an explicit skip marker. With
-Denable_hipcc=true the same four run against real gfx1036 kernels and
pass: 183 ok / 0 fail.
@lusoris

lusoris commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Absorbed into the integration train #1506, folded unchanged except where that PR's description says otherwise. This PR was green on its own; it and its three siblings kept knocking each other into conflict on docs/state.md and the generated ADR indexes every time one of them merged, so they land together.

@lusoris lusoris closed this Sep 19, 2026
@lusoris
lusoris deleted the fix/hip-scaffold-enosys branch October 6, 2026 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant