fix: swap _v/_h dispatch fn selection — naming refers to filter direction not edge direction

This commit is contained in:
2026-05-25 23:18:17 +02:00
parent 92453d7019
commit e00a03c6f6
2 changed files with 49 additions and 10 deletions
+13 -7
View File
@@ -298,21 +298,27 @@ static int dispatch_deblock_pass(
uint8_t *, size_t, size_t, uint8_t *, size_t, size_t,
const daedalus_h264_deblock_meta *); const daedalus_h264_deblock_meta *);
/* daedalus-fourier kernel naming convention:
* _v = "v_loop_filter" — filter applied VERTICALLY across a
* HORIZONTAL edge. Use for our orient=1 (H edge).
* _h = "h_loop_filter" — filter applied HORIZONTALLY across a
* VERTICAL edge. Use for our orient=0 (V edge).
* The names refer to the FILTER DIRECTION, not the edge direction. */
deblock_dispatch_fn fn; deblock_dispatch_fn fn;
if (target_plane == 0) { if (target_plane == 0) {
if (target_orient == 0) if (target_orient == 0) /* V edge → h_loop_filter */
fn = target_bS_intra ? daedalus_dispatch_h264_deblock_luma_v_intra
: daedalus_dispatch_h264_deblock_luma_v;
else
fn = target_bS_intra ? daedalus_dispatch_h264_deblock_luma_h_intra fn = target_bS_intra ? daedalus_dispatch_h264_deblock_luma_h_intra
: daedalus_dispatch_h264_deblock_luma_h; : daedalus_dispatch_h264_deblock_luma_h;
else /* H edge → v_loop_filter */
fn = target_bS_intra ? daedalus_dispatch_h264_deblock_luma_v_intra
: daedalus_dispatch_h264_deblock_luma_v;
} else { } else {
if (target_orient == 0) if (target_orient == 0)
fn = target_bS_intra ? daedalus_dispatch_h264_deblock_chroma_v_intra
: daedalus_dispatch_h264_deblock_chroma_v;
else
fn = target_bS_intra ? daedalus_dispatch_h264_deblock_chroma_h_intra fn = target_bS_intra ? daedalus_dispatch_h264_deblock_chroma_h_intra
: daedalus_dispatch_h264_deblock_chroma_h; : daedalus_dispatch_h264_deblock_chroma_h;
else
fn = target_bS_intra ? daedalus_dispatch_h264_deblock_chroma_v_intra
: daedalus_dispatch_h264_deblock_chroma_v;
} }
return fn(dec->dctx, sub, scratch, stride, n, meta_scratch); return fn(dec->dctx, sub, scratch, stride, n, meta_scratch);
+36 -3
View File
@@ -105,28 +105,43 @@ static int build_mb_edges(int mb_x, int mb_y, int last_mb_x, int last_mb_y,
(e == 0) ? 4 : (int)(1 + xs64() % 3), (e == 0) ? 4 : (int)(1 + xs64() % 3),
/*boundary?*/ (e == 0 && mb_y == 0)); /*boundary?*/ (e == 0 && mb_y == 0));
/* V chroma Cb: 2 edges. */ /* V chroma Cb: 2 edges. Read DEBLOCK_CHROMA_MODE env at runtime:
* unset / "all" → both edges (current default test).
* "intra_only" → only bS=4 boundary edge.
* "none" → all chroma edges bS=0 (luma-only test).
* Lets us bisect substrate divergence without rebuilding. */
int chroma_intra_only = 0, chroma_none = 0;
const char *cm = getenv("DEBLOCK_CHROMA_MODE");
if (cm) {
if (!strcmp(cm, "intra_only")) chroma_intra_only = 1;
else if (!strcmp(cm, "none")) chroma_none = 1;
}
for (int e = 0; e < 2; e++) for (int e = 0; e < 2; e++)
EDGE(0, /*Cb*/1, e, EDGE(0, /*Cb*/1, e,
(e == 0) ? 4 : (int)(1 + xs64() % 3), (e == 0) ? 4 : (int)(1 + xs64() % 3),
(chroma_none) || (chroma_intra_only && e != 0) ||
(e == 0 && mb_x == 0)); (e == 0 && mb_x == 0));
/* H chroma Cb. */ /* H chroma Cb. */
for (int e = 0; e < 2; e++) for (int e = 0; e < 2; e++)
EDGE(1, 1, e, EDGE(1, 1, e,
(e == 0) ? 4 : (int)(1 + xs64() % 3), (e == 0) ? 4 : (int)(1 + xs64() % 3),
(chroma_none) || (chroma_intra_only && e != 0) ||
(e == 0 && mb_y == 0)); (e == 0 && mb_y == 0));
/* V chroma Cr. */ /* V chroma Cr. */
for (int e = 0; e < 2; e++) for (int e = 0; e < 2; e++)
EDGE(0, /*Cr*/2, e, EDGE(0, /*Cr*/2, e,
(e == 0) ? 4 : (int)(1 + xs64() % 3), (e == 0) ? 4 : (int)(1 + xs64() % 3),
(chroma_none) || (chroma_intra_only && e != 0) ||
(e == 0 && mb_x == 0)); (e == 0 && mb_x == 0));
/* H chroma Cr. */ /* H chroma Cr. */
for (int e = 0; e < 2; e++) for (int e = 0; e < 2; e++)
EDGE(1, 2, e, EDGE(1, 2, e,
(e == 0) ? 4 : (int)(1 + xs64() % 3), (e == 0) ? 4 : (int)(1 + xs64() % 3),
(chroma_none) || (chroma_intra_only && e != 0) ||
(e == 0 && mb_y == 0)); (e == 0 && mb_y == 0));
#undef EDGE #undef EDGE
@@ -246,12 +261,30 @@ int main(int argc, char **argv)
/* Check 1: CPU vs QPU byte-exact. */ /* Check 1: CPU vs QPU byte-exact. */
size_t y_diffs = 0, uv_diffs = 0; size_t y_diffs = 0, uv_diffs = 0;
size_t y_first = (size_t) -1, uv_first = (size_t) -1;
for (size_t i = 0; i < y_size; i++) for (size_t i = 0; i < y_size; i++)
if (out_cpu_y[i] != out_qpu_y[i]) y_diffs++; if (out_cpu_y[i] != out_qpu_y[i]) {
if (y_first == (size_t) -1) y_first = i;
y_diffs++;
}
for (size_t i = 0; i < uv_size; i++) for (size_t i = 0; i < uv_size; i++)
if (out_cpu_uv[i] != out_qpu_uv[i]) uv_diffs++; if (out_cpu_uv[i] != out_qpu_uv[i]) {
if (uv_first == (size_t) -1) uv_first = i;
uv_diffs++;
}
printf("CPU vs QPU: Y diff %zu/%zu, UV diff %zu/%zu\n", printf("CPU vs QPU: Y diff %zu/%zu, UV diff %zu/%zu\n",
y_diffs, y_size, uv_diffs, uv_size); y_diffs, y_size, uv_diffs, uv_size);
if (uv_diffs && uv_first != (size_t)-1) {
size_t chroma_w = (size_t) width; /* NV12 UV row pitch = width */
size_t row = uv_first / chroma_w;
size_t col = uv_first % chroma_w;
size_t mb_x = col / 16; /* NV12 interleaved Cb/Cr; 2 chroma px per pair → 8 chroma cols / MB but 16 NV12 bytes */
size_t mb_y = row / 8;
printf(" first UV diff at byte %zu (row %zu col %zu) -> MB(%zu,%zu) chroma_%s offset (%zu,%zu)\n",
uv_first, row, col, mb_x, mb_y,
(col & 1) ? "Cr" : "Cb", row % 8, (col % 16) / 2);
printf(" CPU=%u QPU=%u\n", out_cpu_uv[uv_first], out_qpu_uv[uv_first]);
}
if (y_diffs != 0 || uv_diffs != 0) { if (y_diffs != 0 || uv_diffs != 0) {
fprintf(stderr, "FAIL: CPU and QPU outputs differ — dispatch wiring broken\n"); fprintf(stderr, "FAIL: CPU and QPU outputs differ — dispatch wiring broken\n");
return 1; return 1;