Repository navigation
Lift the Qwen3.5 Android Vulkan restriction on ggml 0.28.0+ runtimes (#948) - #1800
Merged
Merged
Conversation
…8.0+ (#948) llama.cpp #30106 (ggml 0.28.0, llamadart-native v0.8.0) fixed the Vulkan small-matmul tile defect behind #948. The service now reads ggml_version() and applies the Qwen3.5 restriction only to older or unversioned runtimes. Qwen3.5 on Android Vulkan keeps actual-placement KQV offload and the eight-token prompt cap as a speed default.
Its image encoder on these Mali GPUs is unvalidated on every runtime. The rule reads the loaded model's architecture and treats an unreadable one as Qwen3.5; the Qwen3.5-0.8B file-name rule is unchanged.
State that Vulkan text matched the CPU exactly and embeddings by cosine, qualify the chat app's projector note, and correct the ggml version read comment.
leehack
marked this pull request as ready for review
November 8, 2026 14:51
This was referenced Nov 8, 2026
Contributor
|
Chat app preview removed for |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
0.28.0or newer. The small-matmul tile defect behind Android llama.cpp Vulkan on Pixel 9 Pro (Mali-G715): wrong output for prompts over ~32 tokens, then abort under a grammar #948 was fixed upstream in ggml-org/llama.cpp#30106; every bundled runtime from llamadart-nativev0.8.0(8642541b, ggml0.28.0) on has it, and the pinnedv0.9.0reports ggml0.29.0.ggml_version()once and keeps the full restriction (refusals, capability probes, fail-closed missing architecture) when the version is below0.28.0, unparsable, or not exported.0.27.0spans commits before and after #30106, so it counts as unfixed. The ggml version is the release number of the component that carries the fix; a llama.cpp commit hash inllama_dart_build_identitycannot be ordered, and no native capability flag exists.microBatchSizeunset keeps the 8-token prompt cap. The cap is now documented as a speed default (Pixel 9 Pro: about 44 tok/s capped against 27-29 at 32 or 512); explicit sizes run uncapped.general.architecture(an unreadable one counts as Qwen3.5), not the file name. The Qwen3.5-0.8B file-name rule (shouldForceCpuProjectorForAndroid) is unchanged, so the device-tested 0.8B path behaves as before.pixel_qwen35_guard_test.dart,PIXEL_QWEN35_GUARD.md) is marked retired: its bound nativev0.8.0-2has ggml0.28.0, so its refusal cells now fail by design.Production-readiness scope
microBatchSizeabove 8, image/audio prompts (image encoder on the CPU on small-tile GPUs), every speculative strategy and embeddings; capability probes report them.0.28.0(native release override or custom build) keeps the restriction:microBatchSize > 8throwsLlamaUnsupportedExceptionbefore context creation, and media, speculation and embeddings throw before evaluation, naming ggml0.28.0/ llamadart-nativev0.8.0and Android llama.cpp Vulkan on Pixel 9 Pro (Mali-G715): wrong output for prompts over ~32 tokens, then abort under a grammar #948.Completeness checklist
PR type guidance
Test Plan
dart run tool/prepare_workspace.dartdart format --output=none --set-exit-if-changed .dart analyzedart run tool/testing/check_platform_boundaries.dartdart test -p vm -j 1 --exclude-tags local-only— 11544 pass, 129 skipped, 6 env-only failures (windows_registry_qualification_test, needspwsh) on990a36aaadart test -p chrome --exclude-tags local-only— 4630 pass, 1 skipped (on0921339ed; the later commits are VM-only service code, tests and docs)coverage-lib— 93.51% (32944/35231) on0921339ed;vulkan_device_probe.dart80/85flutter test test test_vmand the Chrome chat-app set (pass),flutter analyzeinexample/chat_app,validation_coverage_test,package_skills_test,check_released_changelog_sections_test, docs site build (pass), and the FTL device runs below. Rerun on the new head: format, analyze, platform boundaries,qwen35_vulkan_restriction_testandvulkan_device_probe_test(82 pass), the tooling tests, the chat app VM and Chrome sets andflutter analyze.Matrix Evidence
root-vm990a36aaawindows_registry_qualification_testfailures needpwsh(env-only, same asmain)root-chromecoverage-lib{}reports from model-less local-only files removed beforeformat_lcovandroid-arm64-device-smoke(with model load/generation)caimanAPI 35 (Mali-G715, subgroup 16), Qwen3.5-0.8B Q4_0 + mmproj F16, Vulkan 25/25 layersmatrix-20gdqfruugqqn; journalbypass:false; Dart logggml 0.29.0 has the Vulkan small matmul tile fix; 10/10 text outputs identical to the CPU (raw strings), embedding cosine 0.99987/0.99984, no typed errorsandroid-arm64-device-smoke(same harness)pantherAPI 33 (Mali-G710, subgroup 16)matrix-3qsokm5qfa3ha;bypass:false;ggml 0.29.0 has the Vulkan small matmul tile fix; 10/10 text outputs identical to the CPU (raw strings), embedding cosine 0.99982/0.99977, CLIP on CPU, no typed errorsDevice runs used the build of
0921339ed. The later projector rule does not change the 0.8B path they exercised, since the file-name rule already kept that projector on the CPU, so they were not repeated.|
chat-app-micro-batch-sweep| sweep default/explicit sizes | N/A | N/A | already run with the restriction bypassed on Pixel 9 Pro (v0.9.0 and v0.8.0-3, #948 comment); this PR's production path is the bypass's path, and the follow-up harness above covers it without the bypass ||
high-risk-exact-head-independent-qa| exact-head audit | fresh Claude Opus auditor session | ACCEPT | full audit atfe3c4c575/ce8ddf674, delta re-audit at990a36aaa/d53971eef; see below ||
structured-output-adversarial| parsers/grammar | N/A | N/A | no parser, grammar or template change; grammar/tool calls on Vulkan covered by the #948 device runs ||
release-metadata-verification| release docs pins | N/A | N/A | no pins or install snippets changed ||
litert-lm-*,web-*,webgpu-*,gemma4-*, iOS/macOS/Linux/Windows runtime rows | other runtimes | N/A | N/A | behavior changes only on Android with actual Vulkan placement.generationCapabilities,supportsVisionandsupportsAudioread the ggml version once per service on every platform (it returns null on Windows, where the default asset lacksggml_version), but the result only matters for an Android Vulkan model |Review Notes
990a36aaa. Previous head: 34 pass, 9 skipped, 0 fail onfe3c4c575(first attempt: one Linux VM failure inmodel_download_manager_io_concurrency_test"two processes sharing a cache root", unrelated to this PR, passing locally; the failed jobs passed on rerun)High-risk regression review
backendRuntime)fe3c4c575/ce8ddf674, delta re-audit at exact head990a36aaa/ based53971eef. Threshold: fix 459a1ba5 is in ggml 0.27.0 and an ancestor of the 0.28.0 bump (v0.7.0=0.27.0, v0.8.0=0.28.0, v0.9.0=0.29.0); unknown or unparsable versions fail closed. Older-runtime refusals are unchanged apart from wording, now pinned by tests; the projector rule is the only mtmd path. 31 mutants: survivors are equivalent or more conservative, plus M35, now killed (M16, M19, M23, M35b-d re-killed at the delta). Delta: lib logic and PR diff identical against the new base (remerge-diff empty), Speak with Chatterbox and Pocket TTS, with predefined voices #1792 TTS paths unaffected (166 tests), doc fixes accurate. Suites: VM 11535 pass (6 env-only pwsh failures), coverage-lib 93.54%, chat app 689 VM / 132 Chrome. FTLmatrix-226337fgaz7n6(Pixel 9 Pro, Mali-G715, no bypass): 10/10 CPU-vs-Vulkan text exact, embedding cosine 0.99987/0.99984, projector on CPU. Readiness CLI (high_risk_readiness.dart, exact head and base): exit 2unverifiedPrerequisites, evidence internally consistent.990a36aaa/d53971eef. origin/main was merged twice with merge commits (c21d46e7ffor Speak with LFM3-Audio and Soprano through the native model-type opt-in #1791,c4b3404cdfor Speak with Chatterbox and Pocket TTS, with predefined voices #1792), both without textual conflicts. Speak with LFM3-Audio and Soprano through the native model-type opt-in #1791 and Speak with Chatterbox and Pocket TTS, with predefined voices #1792 change TTS code inllama_cpp_service.dartand docs in separate hunks; Speak with Chatterbox and Pocket TTS, with predefined voices #1792 adds no projector path, and TTS projectors keep their placement because the CPU rule matches onlyqwen35or an unreadable architecture on small-tile Android Vulkan.qwen35_vulkan_restriction_test.dart; disabling the projector rule, applying it to every model, or dropping the unreadable-architecture case fails its projector placement tests; changing the older-runtime refusal wording fails the exact-message test. The device runs used no bypass define (journalbypass:false) and logged the probe result.