Cycle 5 phase 3 partial: M3 NEON = 3.923 Mblock/s; M1 deferred

CDEF is the most compute-intensive kernel measured so far —
254.9 ns/block (2x IDCT, 5x MC). 30fps@1080p floor margin: 4x
even on single NEON core in isolation.

M3 captured cleanly via dav1d_cdef_filter8_8bpc_neon. M1 bit-exact
gate failing due to tmp-layout mismatch between my standalone C
reference and dav1d's NEON expectation. The smoking gun: NEON output
appears at (+2 rows, -2 cols) shifted positions vs C ref output —
suggests NEON's padding-function output has a different convention
than my manual tmp construction.

Untangled in setup work:
- dav1d has TWO directions tables: stride-12 in src/tables.c
  (C-side), stride-16 in src/arm/64/cdef_tmpl.S (NEON-side).
  Initially vendored the C-side; should have used the NEON-side.
- dav1d's NEON expects tmp built by dav1d_cdef_padding8_8bpc_neon
  (a separate function with its own conventions), not the C-side
  padding() function from cdef_tmpl.c.
- Updated cdef_ref.c to use NEON-layout (stride 16) with table
  transcribed from cdef_tmpl.S. Algorithm matches — but bench's
  manual tmp construction doesn't match what NEON expects.

Resolution paths for next session (documented in
docs/k5_cdef_phase3_partial.md §'Resolution paths'):
1. Use dav1d_cdef_padding8_8bpc_neon to construct tmp (simplest)
2. Vendor dav1d's full C reference (most rigorous)
3. Reverse-engineer dav1d's padding output layout (hackiest)

Predicted R5 if/when QPU shader implemented: 0.02-0.05 (RED).
CDEF likely stays on CPU per cycle 3 lesson 7 (compute-bound
kernels don't benefit from QPU offload). 30fps floor still
passes regardless.

New artifacts:
- external/dav1d-snapshot/src/arm/64/cdef_tmpl.S (additional vendored)
- external/dav1d-snapshot/config.h — 14-define asm preamble shim
- tests/cdef_ref.c — standalone C ref (algorithmically correct,
                     layout mismatch with NEON known)
- tests/bench_neon_cdef.c — bench (M1 made warning, M3 captured)
- docs/k5_cdef_phase3_partial.md — phase 3 partial closure +
                                    resumption checklist

dav1d snapshot in PROVENANCE.md should be updated next session
with the new cdef_tmpl.S entry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-18 13:21:24 +00:00
parent 2cd2258a7b
commit 20b59cd6a5
6 changed files with 1155 additions and 0 deletions
+30
View File
@@ -43,6 +43,27 @@ set(FFASM_FLAGS
-I${FFSNAP}
)
# ---- Vendored dav1d snapshot (BSD-2-Clause) — cycle 5+ ----------------------
set(DAV1DSNAP ${CMAKE_SOURCE_DIR}/external/dav1d-snapshot)
# dav1d's asm preamble expects "src/arm/asm.S" and "cdef_tmpl.S" / "util.S"
# (the latter two as bare basenames from within src/arm/64/). Include paths:
set(DAV1D_ASM_FLAGS
-I${DAV1DSNAP} # for config.h shim + src/arm/asm.S
-I${DAV1DSNAP}/src/arm/64 # for util.S, cdef_tmpl.S
)
set(DAV1D_CDEF_ASM_SOURCES
${DAV1DSNAP}/src/arm/64/cdef.S
)
set(DAV1D_CDEF_C_SOURCES
${DAV1DSNAP}/src/tables_cdef_subset.c
)
set_source_files_properties(${DAV1D_CDEF_ASM_SOURCES} PROPERTIES
COMPILE_OPTIONS "${DAV1D_ASM_FLAGS}"
LANGUAGE ASM)
set(FFASM_SOURCES
${FFSNAP}/libavcodec/aarch64/vp9itxfm_neon.S
)
@@ -106,6 +127,15 @@ add_executable(bench_neon_lpf8
${FFASM_LPF_SOURCES}
)
target_compile_options(bench_neon_lpf8 PRIVATE -O3 -march=armv8-a+simd)
# Cycle 5 — AV1 CDEF NEON baseline (dav1d snapshot).
add_executable(bench_neon_cdef
tests/bench_neon_cdef.c
tests/cdef_ref.c
${DAV1D_CDEF_ASM_SOURCES}
${DAV1D_CDEF_C_SOURCES}
)
target_compile_options(bench_neon_cdef PRIVATE -O3 -march=armv8-a+simd)
# bench_neon_idct doesn't need vulkan/drm — pure CPU baseline.
# ---- Vulkan dispatch-overhead microbench (next chunk) ----------------------