h264: V3D shader for deblock_luma_h — first QPU port since cycle 9 #28
Reference in New Issue
Block a user
Delete Branch "noether/v3d-shader-h264-deblock-luma-h"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ports cycle 8's v3d_h264deblock.comp (V edge) to H orientation. Same algorithm, transposed access pattern (lane→row instead of lane→col; pix[±N] instead of pix[±N*stride]).
Recipe table flipped DAEDALUS_KERNEL_H264_DEBLOCK_LH from CPU to QPU. CMake plumbing for the new SPV; daedalus_ctx gets a parallel pipeline pair for the H variant.
Test result on hertz:
H.264 deblock luma h: 1024/1024 bytes bit-exact (100.0000%)— recipe substrate now reports 2 (QPU).QPU coverage for the H.264 8-bit 4:2:0 deblock matrix: luma_v ✓ (cycle 8), luma_h ✓ (this PR). chroma + intra variants stay CPU NEON (smaller tiles, less critical).
Downstream: marfrit-packages 0008 patch (which substitutes H264DSPContext.h_loop_filter_luma → daedalus) was previously NEON-by-recipe; will automatically become QPU-by-recipe once consumers initialise daedalus with a QPU-capable context.
Ports cycle 8's v3d_h264deblock.comp (V edge, horizontal across a row) to the H orientation (V edge, horizontal across a column). Same algorithm, transposed access pattern: V variant: lane → column, reads/writes pix[±N*stride] (vertical I/O) H variant: lane → row, reads/writes pix[±N] (horizontal I/O) WG geometry unchanged: 256 invocations, 16 edges/WG, 16 lanes/edge. Lane-in-edge interpretation flips: column-index for V → row-index for H. tc0 segment math unchanged (one tc0 byte per 4 lanes). dst_max calculation flips: V used dst_off + 3*stride + 16 (cols), H uses dst_off + 15*stride + 4 (rows). Recipe table: DAEDALUS_KERNEL_H264_DEBLOCK_LH = QPU (was CPU). AUTO dispatch now picks QPU for the H edge as well as the V edge. CPU NEON path stays as the explicit-SUBSTRATE_CPU + has_qpu=0 fallback. Verified on hertz (Pi 5 / V3D 7.1): $ ./build/test_api_h264 | grep luma_h H264_DEBLOCK_LH recipe substrate: 2 (was 1 — flipped to QPU) H.264 deblock luma h: 1024/1024 bytes bit-exact (100.0000%) Bit-exact against the C reference (h264_h_loop_filter_luma_ref) on 8 tiles × 8 cols × 16 rows of random input. Same correctness gate as the cycle 8 V shader. CMake plumbing: glslang rule for v3d_h264deblock_h.comp; new SPV added to daedalus_shaders ALL list + install rule. daedalus_ctx gains a parallel h264deblock_h_pipe_ready / h264deblock_h_pipe pair (can't share with V because pipelines bind a specific SPIR-V module at create time). What this changes for the substitution arc: PR #97's 0008-h264- deblock-luma-h substitution patch already plumbed daedalus_recipe_dispatch_h264_deblock_luma_h through libavcodec. That path was NEON-by-recipe; with this PR it becomes QPU-by-recipe (unless the libavcodec ctx is no-QPU per daedalus_ctx_create_no_qpu, in which case it stays NEON — same shape as cycle 8's V shader). Coverage state for H.264 8-bit 4:2:0 deblock kernels (QPU shaders): luma_v ✓ cycle 8 ✓ now luma_h — ✓ THIS PR chroma_v/h — (CPU NEON; smaller tiles, lower-priority) *_intra (4) — (CPU NEON; less common)