daemon: link daedalus-fourier + log substrate availability at startup

First incremental step toward H.264 daemon-rewrite (daedalus-v4l2#11):
make the daedalus-fourier kernel library available to the daemon
process so subsequent patches can substitute its primitives
(IDCT 4×4, IDCT 8×8, luma vertical deblock, etc.) for libavcodec's
per-MB pixel math.

This patch does NOT yet dispatch any kernels.  It only:

  - Adds `pkg_check_modules(DAEDALUS_FOURIER REQUIRED daedalus-fourier)`
    to the daemon's CMakeLists, with explicit link ordering
    (libdaedalus_core.a must precede -lvulkan because the static
    archive references vulkan symbols and the linker resolves
    left-to-right).  We bypass IMPORTED_TARGET because pkg-config's
    Requires.private chain leaves CMake's dependency graph reordering
    the archive after -lvulkan, breaking the static link.

  - Calls daedalus_ctx_create_no_qpu() at daemon startup, logs the
    substrate-availability line, destroys the context at exit.
    no_qpu mode skips V3D Vulkan probe — proves linkage works
    without depending on shader-path resolution (which is a
    separate piece of work, since v3d_runner currently loads
    .spv files from cwd-relative paths and consumer would need
    a search path override).

Sample journal line:

  [2026-05-21 17:59:35.271 INFO] daedalus-fourier: linked, ctx alive
  (no_qpu mode; has_qpu=0)

Build-test verified on hertz (Pi 5 dev host) against an installed
copy of daedalus-fourier r35+gd87239d (from marfrit/daedalus-fourier
PR #1).  Binary links cleanly, --help prints, daemon mode opens
chardev (fails predictably on hertz which has no daedalus_v4l2
kmod; on higgs this is the existing working path).

Follow-up patches per daedalus-v4l2#11:

  1. Instrument the existing libavcodec decode path to count
     per-frame IDCT blocks / deblock edges / MC tiles so we have
     a baseline of what work the daemon dispatches for a typical
     YouTube H.264 stream.
  2. Substitute daedalus-fourier kernels one at a time, measuring
     CPU saved per substitution.
  3. Wire shader path resolution into daedalus_ctx_create() for
     the QPU substrate (V3D opportunistic helper paths).

Wire protocol unchanged.  DAEDALUS_PROTO_VERSION stays at 0.
This commit is contained in:
2026-05-21 18:00:46 +02:00
parent 5d8b4369e5
commit 88b2ebfaa9
2 changed files with 48 additions and 0 deletions
+24
View File
@@ -28,6 +28,20 @@ find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
libavformat libavcodec libavutil)
# daedalus-fourier — VC VII (V3D) + ARM NEON back-end kernel library.
# Linked statically. Today only the no-QPU smoke-test path is wired
# (a ctx_create_no_qpu at daemon startup, log-and-destroy at exit);
# follow-up patches (per daedalus-v4l2#11) substitute the
# `daedalus_recipe_dispatch_h264_*` family for libavcodec's per-MB
# pixel primitives, one cycle at a time.
#
# We bypass IMPORTED_TARGET and consume pkg-config's static variables
# (--static --libs path) directly so we control the link order:
# libdaedalus_core.a must precede -lvulkan because the static archive
# references vulkan symbols and the linker resolves left-to-right.
pkg_check_modules(DAEDALUS_FOURIER REQUIRED daedalus-fourier)
find_package(Vulkan REQUIRED)
add_executable(daedalus_v4l2_daemon
src/main.c
src/ffmpeg_loader.c
@@ -45,13 +59,23 @@ target_include_directories(daedalus_v4l2_daemon
src
${CMAKE_CURRENT_SOURCE_DIR}/../include
${FFMPEG_INCLUDE_DIRS}
${DAEDALUS_FOURIER_INCLUDE_DIRS}
)
# dl for dlopen, pthread for future threading work.
target_link_directories(daedalus_v4l2_daemon
PRIVATE
${DAEDALUS_FOURIER_LIBRARY_DIRS}
)
target_link_libraries(daedalus_v4l2_daemon
PRIVATE
dl
pthread
# Order matters: libdaedalus_core.a first (so its undefined
# vulkan symbols register), then -lvulkan to satisfy them.
${DAEDALUS_FOURIER_LIBRARIES}
Vulkan::Vulkan
)
install(TARGETS daedalus_v4l2_daemon
+24
View File
@@ -22,6 +22,8 @@
#include <libavutil/log.h>
#include <daedalus.h>
static volatile sig_atomic_t g_terminate = 0;
static void on_signal(int sig)
@@ -120,6 +122,26 @@ int main(int argc, char **argv)
/* Mute FFmpeg's own chattiness unless the user asked. */
fm.av_log_set_level(verbose ? AV_LOG_INFO : AV_LOG_WARNING);
/*
* Initialise daedalus-fourier early so we can log substrate
* availability up front. daedalus_ctx_create_no_qpu() skips
* the V3D Vulkan probe — we're not dispatching any kernels
* yet, this is just the linkage sanity check + a marker in the
* journal that the binary is wired against the right
* daedalus-fourier version. Future work (per daedalus-v4l2#11)
* promotes to daedalus_ctx_create() once shader-path resolution
* is wired through the public API.
*/
daedalus_ctx *df_ctx = daedalus_ctx_create_no_qpu();
if (df_ctx) {
log_info("daedalus-fourier: linked, ctx alive (no_qpu mode; "
"has_qpu=%d)",
daedalus_ctx_has_qpu(df_ctx));
} else {
log_warn("daedalus-fourier: ctx_create_no_qpu returned NULL "
"(out of memory?) — continuing without backend kernels");
}
int rc;
const char *cmd = argv[i++];
if (strcmp(cmd, "parse") == 0) {
@@ -132,6 +154,8 @@ int main(int argc, char **argv)
rc = 2;
}
if (df_ctx)
daedalus_ctx_destroy(df_ctx);
ffmpeg_loader_cleanup(&fm);
log_cleanup();
return rc;