Summary
SM8845 doesn't appear in any of LiteRT's Qualcomm SoC lists, but it ships in real consumer devices (Snapdragon 8s Gen 4 — kernel soc_id=685, QNN SDK socModel=97, Hexagon v81). I'm trying to run a LiteRT-compiled NPU graph on one, and the only workable target in SocModel is SM8850 (same v81 arch). That path runs into err = 1002 (QNN_CONTEXT_ERROR_MEM_ALLOC_FAIL) / Skel failed to process context binary on all 4 PDs at runtime, even with very small cache_length.
I'd like to confirm:
- Is
SM8845 intentionally unsupported, or just not added yet?
- If a user wants to add it locally, what is the complete list of places that need to change?
- Beyond the enum/table edits, does the AOT compiler bake any per-SoC PerfSetting / cluster-topology info into the context binary that would make compiling-for-
SM8850-and-running-on-SM8845 fundamentally incompatible?
Environment
|
|
| LiteRT |
main branch, snapshot ~2026-05-19 |
| QAIRT SDK |
2.46.0.260424 |
| Host |
Linux x86_64, NDK r28b cross-compile |
| Device |
ro.product.model=PLR110, ro.soc.model=SM8845, kernel /sys/devices/soc0/soc_id=685, Hexagon v81 |
| Build |
cmake --preset android-arm64 for the runtime, aot_compile(target=SocModel.SM8850) for the model |
| Model |
Gemma 4 E2B, dynamic_wi4_afp32 recipe (W4 weights), various cache_length |
What's in the codebase today
SM8845 is absent from every list I could find:
-
litert/python/aot/vendors/qualcomm/target.py — SocModel enum stops at SM8850:
class SocModel(StrEnum):
ALL = "ALL"
SA8255 = "SA8255"
SA8295 = "SA8295"
SM8350 = "SM8350"
SM8450 = "SM8450"
SM8550 = "SM8550"
SM8650 = "SM8650"
SM8750 = "SM8750"
SM8850 = "SM8850"
# TODO(weiyiw): Generate this from supported_soc.csv.
-
litert/vendors/qualcomm/core/schema/soc_table.h — C++ SnapdragonModel enum has SM8850 = 87 but no SM8845.
-
litert/vendors/qualcomm/core/schema/soc_table.cc — kSocInfos[] has no SM8845 entry.
-
litert/vendors/qualcomm/supported_soc.csv — no SM8845 row.
-
litert/vendors/qualcomm/compiler/qnn_compiler_plugin_test.cc and litert/vendors/qualcomm/qnn_backend_test/test_utils.h — test fixtures hardcode {"SM8650", "SM8750", "SM8850"}.
For reference, SM8845's QNN SDK socModel enum value is 97. It isn't in the QAIRT 2.46 QnnTypes.h header, but the SDK runtime recognizes it — the QAIRT Python utility qti/aisw/tools/core/utilities/devices/android/android_device_constants.py has the kernel-id-to-name mapping "685": "SM8845", and ExecuTorch PR pytorch/executorch#16500 explicitly defines SM8845 = 97 # v81.
What I tried, and what fails
1. Compile for SocModel.SM8850, runtime-patch the binary
Since SM8845 isn't in the enum, I picked the closest v81 target:
aot_lib.aot_compile(
'extracted/Section2_prefill_decode.tflite',
output_dir='compiled_sm8850',
target=[qnn_target.Target(qnn_target.SocModel.SM8850)],
)
I then ASCII-replaced SM8850 → SM8845 in the resulting .tflite (works for the SoC name string, but obviously can't change SDK enum values that are stored as integers in the QNN context binary).
I also locally added SM8845 = 97 to SnapdragonModel, and added a kSocInfos[] entry with DspArch::V81 and vtcm_size_in_mb = 8, so that runtime FindSocInfo() succeeds. After this, dispatch correctly logs:
INFO: [Qnn] Initializing QNN backend for SoC model: SM8845
2. PD context allocation fails
The DSP skel then rejects the context binary on all 4 protection domains:
QnnDsp <E> Skel failed to process context binary.
QnnDsp <E> Context create from binary failed for deviceId 0 coreId 0 pdId 0 for context 1, err 5005
QnnDsp <E> Context 1 failed on pd 0
... (same for pdId 2, 3, 1) ...
QnnDsp <E> Failed to find available PD for contextId 1 on deviceId 0 coreId 0
with context size estimate 2159091712
QnnDsp <E> context create from binary failed on contextId 1, err = 1002
ERROR: [qnn_manager.cc:600] Failed to create QNN context: 1002
3. Shrinking the model does not help
I suspected this was pure context-size pressure, so I rebuilt the model with progressively smaller cache_length:
cache_length |
Quantization |
Disk size (compiled .tflite) |
Runtime context size |
Result |
| 4096 |
W4 (dynamic_wi4_afp32) |
1.13 GB |
4.00 GB |
❌ err 1002 on all 4 PDs |
| 1280 |
W4 |
1.13 GB |
2.47 GB |
❌ err 1002 on all 4 PDs |
| 512 |
W4 |
1.13 GB |
2.06 GB |
❌ err 1002 on all 4 PDs |
Even cache_length=512 (smallest realistic LLM context) fails identically with 5005 / 1002 on all PDs. That makes me suspect this isn't just memory size — the skel may be rejecting the binary because the PerfSetting / cluster-topology baked at compile time (for SM8850) doesn't match the SM8845 hardware.
Questions
-
Is SM8845 planned to be added? It's a shipping consumer device (Snapdragon 8s Gen 4). Skipping it while supporting both the older SM8750 and the newer flagship SM8850 feels intentional but unexplained — is it gated on QAIRT 2.50+ exposing enum 97 in QnnTypes.h?
-
What is the complete set of places to add an SoC? Beyond the four files listed above (target.py, soc_table.{h,cc}, supported_soc.csv), does the aot_compile flow generate or consume any per-SoC PerfSetting / .conf artifacts (cluster topology, HVX thread count, PMU template) that need updates? Is there any hidden hardcoding inside qnn-context-binary-generator invocation paths that depends on the SoC?
-
# TODO(weiyiw): Generate this from supported_soc.csv. — what's the planned single-source-of-truth design here? Right now supported_soc.csv is hand-curated but the Python SocModel enum and C++ SnapdragonModel enum are independent and hand-edited, which makes user-side additions error-prone.
-
Is 5005 / 1002 on all 4 PDs most likely (a) SoC PerfSetting mismatch from compiling for SM8850, (b) actual PD memory pressure where the SM8845 PD limit really is below ~2 GB, or (c) something else? Any diagnostic guidance (e.g. how to extract the embedded PerfSetting from a compiled context binary to confirm cluster topology) would be very helpful.
Repro
# 1. Build LiteRT runtime for android-arm64
cmake --preset android-arm64
cmake --build cmake_build_android_arm64 -j
# 2. Export Gemma 4 E2B with W4 at any cache_length
python -m litert_torch.generative.export_hf.export \
--model=google/gemma-4-E2B \
--output_dir=./out \
--prefill_lengths=[128] \
--cache_length=512 \
--externalize_embedder=True \
--quantization_recipe=dynamic_wi4_afp32
# 3. AOT-compile for SM8850 (closest available v81 target)
python -c "
from ai_edge_litert.aot import aot_compile as aot_lib
from ai_edge_litert.aot.vendors.qualcomm import target as qnn_target
aot_lib.aot_compile('Section2_prefill_decode.tflite',
output_dir='compiled_sm8850',
target=[qnn_target.Target(qnn_target.SocModel.SM8850)])
"
# 4. Push to an SM8845 device with QAIRT 2.46 v81 runtime libs and run_model
# 5. Observe err 1002 on all 4 PDs even with cache_length=512.
What would unblock me
A concrete answer to whether (a) SM8845 is a one-line-per-file addition I can do myself, or (b) it needs deeper compiler-side support that only the LiteRT maintainers can add. If (b), even a rough pointer to the relevant files / commits would let me plan around it.
Thanks!
Summary
SM8845doesn't appear in any of LiteRT's Qualcomm SoC lists, but it ships in real consumer devices (Snapdragon 8s Gen 4 — kernelsoc_id=685, QNN SDKsocModel=97, Hexagon v81). I'm trying to run a LiteRT-compiled NPU graph on one, and the only workable target inSocModelisSM8850(same v81 arch). That path runs intoerr = 1002 (QNN_CONTEXT_ERROR_MEM_ALLOC_FAIL)/Skel failed to process context binaryon all 4 PDs at runtime, even with very smallcache_length.I'd like to confirm:
SM8845intentionally unsupported, or just not added yet?SM8850-and-running-on-SM8845fundamentally incompatible?Environment
mainbranch, snapshot ~2026-05-19ro.product.model=PLR110,ro.soc.model=SM8845, kernel/sys/devices/soc0/soc_id=685, Hexagon v81cmake --preset android-arm64for the runtime,aot_compile(target=SocModel.SM8850)for the modeldynamic_wi4_afp32recipe (W4 weights), variouscache_lengthWhat's in the codebase today
SM8845is absent from every list I could find:litert/python/aot/vendors/qualcomm/target.py—SocModelenum stops atSM8850:litert/vendors/qualcomm/core/schema/soc_table.h— C++SnapdragonModelenum hasSM8850 = 87but noSM8845.litert/vendors/qualcomm/core/schema/soc_table.cc—kSocInfos[]has noSM8845entry.litert/vendors/qualcomm/supported_soc.csv— noSM8845row.litert/vendors/qualcomm/compiler/qnn_compiler_plugin_test.ccandlitert/vendors/qualcomm/qnn_backend_test/test_utils.h— test fixtures hardcode{"SM8650", "SM8750", "SM8850"}.For reference,
SM8845's QNN SDKsocModelenum value is97. It isn't in the QAIRT 2.46QnnTypes.hheader, but the SDK runtime recognizes it — the QAIRT Python utilityqti/aisw/tools/core/utilities/devices/android/android_device_constants.pyhas the kernel-id-to-name mapping"685": "SM8845", and ExecuTorch PR pytorch/executorch#16500 explicitly definesSM8845 = 97 # v81.What I tried, and what fails
1. Compile for
SocModel.SM8850, runtime-patch the binarySince
SM8845isn't in the enum, I picked the closest v81 target:I then ASCII-replaced
SM8850→SM8845in the resulting.tflite(works for the SoC name string, but obviously can't change SDK enum values that are stored as integers in the QNN context binary).I also locally added
SM8845 = 97toSnapdragonModel, and added akSocInfos[]entry withDspArch::V81andvtcm_size_in_mb = 8, so that runtimeFindSocInfo()succeeds. After this, dispatch correctly logs:2. PD context allocation fails
The DSP skel then rejects the context binary on all 4 protection domains:
3. Shrinking the model does not help
I suspected this was pure context-size pressure, so I rebuilt the model with progressively smaller
cache_length:cache_lengthdynamic_wi4_afp32)err 1002on all 4 PDserr 1002on all 4 PDserr 1002on all 4 PDsEven
cache_length=512(smallest realistic LLM context) fails identically with5005 / 1002on all PDs. That makes me suspect this isn't just memory size — the skel may be rejecting the binary because the PerfSetting / cluster-topology baked at compile time (forSM8850) doesn't match theSM8845hardware.Questions
Is
SM8845planned to be added? It's a shipping consumer device (Snapdragon 8s Gen 4). Skipping it while supporting both the olderSM8750and the newer flagshipSM8850feels intentional but unexplained — is it gated on QAIRT 2.50+ exposing enum97inQnnTypes.h?What is the complete set of places to add an SoC? Beyond the four files listed above (
target.py,soc_table.{h,cc},supported_soc.csv), does theaot_compileflow generate or consume any per-SoC PerfSetting /.confartifacts (cluster topology, HVX thread count, PMU template) that need updates? Is there any hidden hardcoding insideqnn-context-binary-generatorinvocation paths that depends on the SoC?# TODO(weiyiw): Generate this from supported_soc.csv.— what's the planned single-source-of-truth design here? Right nowsupported_soc.csvis hand-curated but the PythonSocModelenum and C++SnapdragonModelenum are independent and hand-edited, which makes user-side additions error-prone.Is
5005 / 1002on all 4 PDs most likely (a) SoC PerfSetting mismatch from compiling forSM8850, (b) actual PD memory pressure where theSM8845PD limit really is below ~2 GB, or (c) something else? Any diagnostic guidance (e.g. how to extract the embedded PerfSetting from a compiled context binary to confirm cluster topology) would be very helpful.Repro
What would unblock me
A concrete answer to whether (a)
SM8845is a one-line-per-file addition I can do myself, or (b) it needs deeper compiler-side support that only the LiteRT maintainers can add. If (b), even a rough pointer to the relevant files / commits would let me plan around it.Thanks!