Withheld after an 8 Elite Gen 5 report where the app stuck on 'Loading
models'. What made that fatal was not the binaries -- profiling on a real
S26 Ultra shows fan2d_v81 and nsfwq2_v81 loading and executing correctly and
faster than v79 -- but that ffpipe picked a tier by file presence and had NO
recovery if those contexts would not run.
0.3.0 walks the chain and accepts a tier only after it has actually executed
a model, so a v81 part that cannot run v81 now falls back to v73 by itself.
The tier and the fallback belong in the same release.
⚠ An 8 Elite Gen 5 still on 0.2.x has no fallback. The release notes say to
update before downloading.
Add nsfwq2: the quantised gate, recalibrated for the correct input range
facefusion 3.8.2 normalises nsfw_2 with mean 0.5 / std 0.5, i.e. [-1,1]. The
app fed it [0,1] from the gate's first release, which moves the decision
statistic by -1.15 on average against a 0.25 threshold. Corrected in 0.2.2.
The quantised gate's encodings are calibrated FOR that range, so the old file
and the new app do not mix. A new filename makes that impossible to hit by
accident rather than merely unlikely: 0.2.2 asks for nsfwq2_, does not find
nsfwq_, and reports the gate missing instead of silently mis-scoring.
Both are hosted in each tier ON PURPOSE. 0.2.1 needs nsfwq_ and 0.2.2 needs
nsfwq2_; dropping the old one would brick a 0.2.1 install that re-downloads.
It costs 6.6 MB per tier until 0.2.1 is out of the field.
v79 is untouched -- it runs the fp32 gate, which takes no calibration, so only
the input handed to it changed.
Withhold the v81 tier -- it fails to initialise on real 8 Elite Gen 5
Reported: the app sits on 'Loading models', then a minute later says the
content check could not run. That message means contentScore returned NaN,
and ffjni returns NaN when g_pipe is null -- i.e. Pipeline::init FAILED.
Not a gate misjudgement; the pipeline never came up.
The v81 context binaries have never been executed on v81 silicon; every
check was made by rebuilding at v79 and comparing. Before today a v81 part
resolved v81->v73 and ran the v73 build, which worked. Removing the tier
restores exactly that until the cause is known.
Files stay hosted under `v81_withheld` so this is one commit to undo.
Add the ncnn/Vulkan preview set (roadmap 6) -- NOT used by any shipped app
Six graphs converted with pnnx for the non-Qualcomm backend: yoloface, 2dfan4,
arcface, hyperswap, the nsfw_2 content gate, and gpen. fp16 storage, 576 MB.
Recorded in manifest.json under `ncnn_preview`, deliberately NOT under `tiers`:
the app picks a tier by name from its chain (v81/v79/v73/v68), so a sibling key is
inert to every build in the field and cannot be selected by accident.
Accuracy on device against the ONNX host reference, real tensors:
yoloface fp32 64.40 fp16 56.24 vulkan 55.67
fan2d fp32 29.68 fp16 29.36 vulkan 29.63
arcface fp32 53.27 fp16 34.78 vulkan 41.75
hyperswap fp32 76.98 fp16 52.18 vulkan 58.00
nsfw fp32 70.53 fp16 46.72 vulkan 22.01
gpen fp32 56.87 fp16 15.85 vulkan 15.81
gpen is the outlier: fp16 STORAGE breaks it (fp32 arithmetic over fp16 storage is
equally bad), and Vulkan is wrong even with every fp16 path off. It needs fp32
activations, and on the GPU it does not work at all yet.
Publish the v81 tier, and the 9.5x face enhancer for every tier
v81 (8 Elite Gen 5): six binaries, 311.6 MB. Until now a v81 part resolved the
chain v81,v73,v68, found no v81 tier published, and correctly downloaded v73 --
so it ran the 8 Gen 2 build. The gate is nsfwq_, not nsfw_: the fp32 context does
not build for v81 (no properties registered for q::QNN_Gelu), so v81 takes the
quantised gate exactly as the tiers below v79 do.
gpen replaced in all four tiers, ~3.3 MB smaller each. The enhancer went 23.35 ms
to 2.45 ms per face by collapsing 18 StyleGAN blur blocks into one grouped conv
each -- the graph had been moving 2.59 bytes through Transpose for every byte it
computed. Deploy SNR is unchanged at 38.2 dB.
One commit so the manifest is never live against files that are not.