Cycle 4 (LPF wd=8) closure: M1=100%, R=0.34, M4=+4.1%, PASS
Fourth daedalus-fourier kernel — VP9 8-tap inner loop filter wd=8 h_8_8 variant. Width extension of cycle 2's wd=4; completes VP9 inner-edge LPF coverage. Full cycle Phase 1-7 + M4'''' in one combined go (cycle compressed since incremental from cycle 2). Phase 5 review explicitly skipped (incremental ~30-line shader delta from cycle 2 + same geometry + cycle-2 RED-pattern checks still apply). Flagged in docs/k4_lpf8_phase4_7.md per dev_process.md "Skipping phases is a deliberate choice that should be flagged." Phase 6 v1 first-light: M1'''' 100.0000% bit-exact (65536/65536) first try. Shaderdb shows 231 inst, 4 hardware threads, 0 spills, 27 max-temps, 48 uniforms — compiler at the latency-hiding ceiling. Performance: M3'''' NEON (single-core) 52.382 Medge/s M2'''' QPU isolation 17.847 Medge/s R'''' 0.341 → ORANGE band 30fps floor margin 9.2x (isolation), 20.3x (mixed) M4'''' concurrent matrix: NEON 4-core 37.823 Medge/s <- baseline QPU only 14.867 Medge/s MIXED NEON-3 + QPU 39.389 Medge/s <- +4.1% PASS Verdict: YELLOW-via-M4'''' PASS. Deploy wd=8 LPF on QPU alongside cycle 2 wd=4. Combined VP9 inner-edge LPF coverage now complete. Cross-cycle LPF comparison: | | wd=4 (k2) | wd=8 (k4) | | M3 NEON | 48.3 | 52.4 | | M2 QPU iso | 19.6 | 17.8 | | R iso | 0.41 | 0.34 | | M4 delta | +6.9% | +4.1% | | 30fps mixed | 7.2x | 20.3x | | Verdict | GO QPU | GO QPU | NEW finding (Phase 9 lesson): NEON gets faster per edge as filter width grows (20.7 → 19.1 ns wd=4 → wd=8). The relative QPU loss grows with width. wd=16 would probably flip negative based on the trend line. Deployment recipe with cycle 4: IDCT 8x8 (k1) -> QPU (R=0.92, +7% mixed) LPF wd=4 (k2) -> QPU (R=0.41, +7% mixed) LPF wd=8 (k4) -> QPU (R=0.34, +4% mixed) MC 8h (k3) -> CPU (R=0.067, -19% mixed) Entropy -> CPU (structural) VP9 inner-edge LPF coverage complete. Project continues to higgs deployment plumbing or further kernels per user direction. New artifacts: - src/v3d_lpf_h_8_8.comp — GLSL shader - tests/vp9_lpf8_ref.c — standalone C ref - tests/bench_neon_lpf8.c — M1+M3 bench - tests/bench_v3d_lpf8.c — M1+M2 bench - tests/bench_concurrent_lpf8.c — M4 pthread bench - docs/k4_lpf8_phase1_3.md + phase4_7.md — combined cycle docs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Standalone bit-exact C reference for VP9 8-tap inner loop filter
|
||||
* (wd=8, horizontal, 8-pixel edge). Transcribed from FFmpeg's
|
||||
* libavcodec/vp9dsp_template.c loop_filter() function with wd=8
|
||||
* (vendored at external/ffmpeg-snapshot/). 8-bit pixels only.
|
||||
*
|
||||
* Differs from cycle 2's vp9_lpf_ref.c (wd=4) in:
|
||||
* - Adds flat8in test (6 abs comparisons) per row
|
||||
* - If flat8in passes, writes 6 pixels (p2 p1 p0 q0 q1 q2) per row
|
||||
* using 8-pixel-input flat filter
|
||||
* - Otherwise falls through to wd=4 hev/no-hev paths
|
||||
*
|
||||
* License: LGPL-2.1-or-later (matches upstream).
|
||||
* Spec: VP9 specification §8.8.1.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static inline int abs_i(int x) { return x < 0 ? -x : x; }
|
||||
static inline int clip_intp2_7(int x) { return x > 127 ? 127 : x < -128 ? -128 : x; }
|
||||
static inline uint8_t clip_u8(int x) { return (uint8_t)(x > 255 ? 255 : x < 0 ? 0 : x); }
|
||||
static inline int min_i(int a, int b) { return a < b ? a : b; }
|
||||
|
||||
/* wd=8 inner-edge horizontal LPF. 8 rows, neighborhood [-4..+3] cols. */
|
||||
void daedalus_vp9_loop_filter_h_8_8_ref(uint8_t *dst, ptrdiff_t stride,
|
||||
int E, int I, int H)
|
||||
{
|
||||
const int F = 1; /* 1 << (BIT_DEPTH - 8) for BIT_DEPTH=8 */
|
||||
|
||||
for (int i = 0; i < 8; i++, dst += stride) {
|
||||
int p3 = dst[-4], p2 = dst[-3], p1 = dst[-2], p0 = dst[-1];
|
||||
int q0 = dst[ 0], q1 = dst[+1], q2 = dst[+2], q3 = dst[+3];
|
||||
|
||||
int fm = abs_i(p3 - p2) <= I && abs_i(p2 - p1) <= I &&
|
||||
abs_i(p1 - p0) <= I && abs_i(q1 - q0) <= I &&
|
||||
abs_i(q2 - q1) <= I && abs_i(q3 - q2) <= I &&
|
||||
abs_i(p0 - q0) * 2 + (abs_i(p1 - q1) >> 1) <= E;
|
||||
if (!fm) continue;
|
||||
|
||||
int flat8in = abs_i(p3 - p0) <= F && abs_i(p2 - p0) <= F &&
|
||||
abs_i(p1 - p0) <= F && abs_i(q1 - q0) <= F &&
|
||||
abs_i(q2 - q0) <= F && abs_i(q3 - q0) <= F;
|
||||
|
||||
if (flat8in) {
|
||||
/* 8-pixel-input "inner flat" filter, 6 outputs. */
|
||||
dst[-3] = (uint8_t)((p3 + p3 + p3 + 2 * p2 + p1 + p0 + q0 + 4) >> 3);
|
||||
dst[-2] = (uint8_t)((p3 + p3 + p2 + 2 * p1 + p0 + q0 + q1 + 4) >> 3);
|
||||
dst[-1] = (uint8_t)((p3 + p2 + p1 + 2 * p0 + q0 + q1 + q2 + 4) >> 3);
|
||||
dst[ 0] = (uint8_t)((p2 + p1 + p0 + 2 * q0 + q1 + q2 + q3 + 4) >> 3);
|
||||
dst[+1] = (uint8_t)((p1 + p0 + q0 + 2 * q1 + q2 + q3 + q3 + 4) >> 3);
|
||||
dst[+2] = (uint8_t)((p0 + q0 + q1 + 2 * q2 + q3 + q3 + q3 + 4) >> 3);
|
||||
} else {
|
||||
/* Fall-through: same wd=4 hev/no-hev paths as cycle 2. */
|
||||
int hev = abs_i(p1 - p0) > H || abs_i(q1 - q0) > H;
|
||||
if (hev) {
|
||||
int f = clip_intp2_7(p1 - q1);
|
||||
f = clip_intp2_7(3 * (q0 - p0) + f);
|
||||
int f1 = min_i(f + 4, 127) >> 3;
|
||||
int f2 = min_i(f + 3, 127) >> 3;
|
||||
dst[-1] = clip_u8(p0 + f2);
|
||||
dst[ 0] = clip_u8(q0 - f1);
|
||||
} else {
|
||||
int f = clip_intp2_7(3 * (q0 - p0));
|
||||
int f1 = min_i(f + 4, 127) >> 3;
|
||||
int f2 = min_i(f + 3, 127) >> 3;
|
||||
dst[-1] = clip_u8(p0 + f2);
|
||||
dst[ 0] = clip_u8(q0 - f1);
|
||||
int fp = (f1 + 1) >> 1;
|
||||
dst[-2] = clip_u8(p1 + fp);
|
||||
dst[+1] = clip_u8(q1 - fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user