diff --git a/src/daedalus_core.c b/src/daedalus_core.c index fd7d73b..7be1500 100644 --- a/src/daedalus_core.c +++ b/src/daedalus_core.c @@ -53,6 +53,25 @@ daedalus_ctx *daedalus_ctx_create(void) daedalus_ctx *daedalus_ctx_create_no_qpu(void) { + /* + * Per the "QPU is default substrate" decree 2026-05-23: + * setting DAEDALUS_FORCE_QPU=1 in the process env escalates this + * function to a full daedalus_ctx_create(), letting the libavcodec + * substitution shims (which call create_no_qpu via pthread_once) + * fire the V3D shaders that exist for cycles 1/2/4/5/8. Without + * this hook each consumer process (firefox, mpv, daemon) would + * need its own shim build to opt into QPU. + * + * Default behaviour (env var unset / not "1") is unchanged: pure + * NEON ctx, no implicit Vulkan init. Firefox / mpv consumers + * that dlopen libavcodec without opting in stay on the + * Vulkan-free path; the daemon explicitly sets + * DAEDALUS_FORCE_QPU=1 before loading libavcodec. + */ + const char *force = getenv("DAEDALUS_FORCE_QPU"); + if (force && force[0] == '1' && force[1] == 0) + return daedalus_ctx_create(); + daedalus_ctx *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return NULL; ctx->has_qpu = 0; @@ -84,16 +103,25 @@ void daedalus_ctx_destroy(daedalus_ctx *ctx) daedalus_substrate daedalus_recipe_substrate_for(daedalus_kernel k) { + /* + * Recipe table per the "QPU is default substrate" decree + * 2026-05-23. Any kernel that has a V3D compute shader returns + * SUBSTRATE_QPU; CPU is the fallback for kernels without a + * shader (still the case for H.264 IDCT 4x4 / IDCT 8x8 / qpel + * mc20 — covered by follow-on task 165). The dispatch + * wrappers already fall back to CPU automatically when the + * ctx doesn't have QPU available (daedalus_ctx_has_qpu == 0). + */ switch (k) { case DAEDALUS_KERNEL_VP9_IDCT8: return DAEDALUS_SUBSTRATE_QPU; case DAEDALUS_KERNEL_VP9_LPF4_INNER: return DAEDALUS_SUBSTRATE_QPU; - case DAEDALUS_KERNEL_VP9_MC_8H: return DAEDALUS_SUBSTRATE_CPU; + case DAEDALUS_KERNEL_VP9_MC_8H: return DAEDALUS_SUBSTRATE_QPU; /* v3d_mc_8h.spv */ case DAEDALUS_KERNEL_VP9_LPF8_INNER: return DAEDALUS_SUBSTRATE_QPU; - case DAEDALUS_KERNEL_AV1_CDEF_8X8: return DAEDALUS_SUBSTRATE_CPU; - case DAEDALUS_KERNEL_H264_IDCT4: return DAEDALUS_SUBSTRATE_CPU; - case DAEDALUS_KERNEL_H264_IDCT8: return DAEDALUS_SUBSTRATE_CPU; - case DAEDALUS_KERNEL_H264_DEBLOCK_LV: return DAEDALUS_SUBSTRATE_CPU; - case DAEDALUS_KERNEL_H264_QPEL_MC20: return DAEDALUS_SUBSTRATE_CPU; + case DAEDALUS_KERNEL_AV1_CDEF_8X8: return DAEDALUS_SUBSTRATE_QPU; /* v3d_cdef.spv */ + case DAEDALUS_KERNEL_H264_IDCT4: return DAEDALUS_SUBSTRATE_CPU; /* TODO task #165 */ + case DAEDALUS_KERNEL_H264_IDCT8: return DAEDALUS_SUBSTRATE_CPU; /* TODO task #165 */ + case DAEDALUS_KERNEL_H264_DEBLOCK_LV: return DAEDALUS_SUBSTRATE_QPU; /* v3d_h264deblock.spv */ + case DAEDALUS_KERNEL_H264_QPEL_MC20: return DAEDALUS_SUBSTRATE_CPU; /* TODO task #165 */ } return DAEDALUS_SUBSTRATE_CPU; }