h264: V3D shaders for the 4 single-axis quarter-pel qpel variants #32

Merged
marfrit merged 1 commits from noether/v3d-shader-h264-qpel-quarter-axis into main 2026-05-25 17:09:01 +00:00
Owner

mc10 (¼-H), mc30 (¾-H), mc01 (¼-V), mc03 (¾-V). Each is the half-pel filter + 1 L2 rounded-average line against an integer-source pixel. ~45-line shaders each.

CMake foreach for SPV rules. dispatch_h264_qpel_axis_qpu helper shares plumbing across all 4 (axis flag selects src_max). Macros collapse ~200 LOC of boilerplate.

All 4 tests PASS 2048/2048 bytes bit-exact via QPU substrate. Recipe table flips MC{10,30,01,03} CPU→QPU.

Qpel QPU coverage: 3 half-pel anchors + 4 single-axis quarter-pel = 7 of 15 useful put_ positions. Remaining 8 are diagonals (each composes 2 anchors via L2).

mc10 (¼-H), mc30 (¾-H), mc01 (¼-V), mc03 (¾-V). Each is the half-pel filter + 1 L2 rounded-average line against an integer-source pixel. ~45-line shaders each. CMake foreach for SPV rules. `dispatch_h264_qpel_axis_qpu` helper shares plumbing across all 4 (axis flag selects src_max). Macros collapse ~200 LOC of boilerplate. **All 4 tests PASS 2048/2048 bytes bit-exact** via QPU substrate. Recipe table flips MC{10,30,01,03} CPU→QPU. Qpel QPU coverage: 3 half-pel anchors + 4 single-axis quarter-pel = **7 of 15 useful put_ positions**. Remaining 8 are diagonals (each composes 2 anchors via L2).
marfrit added 1 commit 2026-05-25 17:04:28 +00:00
mc10 (¼-H), mc30 (¾-H), mc01 (¼-V), mc03 (¾-V).  Each is the
corresponding half-pel filter (mc20 or mc02) with one extra L2
rounded-average step against an integer-source pixel at the tail:

  mc10[r,c] = avg(clip255(mc20(s)), s[r,   c   ])
  mc30[r,c] = avg(clip255(mc20(s)), s[r,   c+1])
  mc01[r,c] = avg(clip255(mc02(s)), s[r,   c  ])
  mc03[r,c] = avg(clip255(mc02(s)), s[r+1, c  ])

Each shader is ~45 lines (mc20-/mc02-pattern + 1 L2 line).

CMake foreach loop generates the 4 SPV compile rules.  Dispatch
helper `dispatch_h264_qpel_axis_qpu` shares plumbing across all 4
(axis flag selects src_max bounds: H reads cols -2..+10, V reads
rows -2..+10).  DEFINE_QPEL_AXIS_QPU + DEFINE_QPEL_DISPATCH_QPU
macros collapse ~200 LOC of boilerplate.

Recipe table flips DAEDALUS_KERNEL_H264_QPEL_MC{10,30,01,03} from
CPU to QPU.

Verified on hertz:

  $ ./build/test_api_h264 | grep "qpel mc[01230]"
    H.264 qpel mc10: 2048/2048 bytes bit-exact (100.0000%)
    H.264 qpel mc30: 2048/2048 bytes bit-exact (100.0000%)
    H.264 qpel mc01: 2048/2048 bytes bit-exact (100.0000%)
    H.264 qpel mc03: 2048/2048 bytes bit-exact (100.0000%)
    (+ mc20/mc02/mc22 anchors from previous PRs)

Qpel QPU coverage:

  put_  mc20 ✓  mc02 ✓  mc22 ✓                                  (3 anchors)
        mc10 ✓  mc30 ✓  mc01 ✓  mc03 ✓                          (4 quarter-axis, THIS PR)
        mc11/12/13/21/23/31/32/33 — CPU NEON                    (8 diagonals)
  avg_  all 15 positions — CPU NEON

7 of 15 useful put_ positions now on QPU.  The 8 diagonals each
compose two half-pel results via L2; can land via dedicated kernels
or by chaining existing anchor dispatches (the latter would need
the L2 step as a fourth dispatch — probably cheaper to write
dedicated 8x diagonal shaders).
marfrit merged commit 224f4be9e2 into main 2026-05-25 17:09:01 +00:00
marfrit deleted branch noether/v3d-shader-h264-qpel-quarter-axis 2026-05-25 17:09:01 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marfrit/daedalus-fourier#32