Skip to content

[QNN EP] Fix soc_model string name support - #736

Merged
qti-mbadnara merged 11 commits into
mainfrom
dev/qti-mbadnara/fix-mobile-invalid-config
Aug 19, 2026
Merged

qti-mbadnara merged 11 commits into
mainfrom
dev/qti-mbadnara/fix-mobile-invalid-config

Conversation

@qti-mbadnara

@qti-mbadnara qti-mbadnara commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Description

Extends the soc_model provider option to accept chip-family name strings (e.g. "SM8750", case-insensitive) in addition to numeric IDs, and adds missing HTP V79 architecture support for the SM8750 (Pakala) SoC.

Built on top of #707 with contributions from @quic-calvnguy


Motivation & Context

Issue: On Snapdragon SM8750P (soc_id=639), deviceCreate() fails with QNN_DEVICE_ERROR_INVALID_CONFIG when users pass soc_model="SM8750". The root cause is that ParseSocModel() calls std::stoi() directly, which throws std::invalid_argument on any non-integer string. The exception is caught and silently swallowed, soc_model falls back to QNN_SOC_MODEL_UNKNOWN (0), causing the QNN backend to attempt auto-detection of the SoC from hardware. On SM8750P, this auto-detection fails because soc_id=639 is not in QNN's internal lookup table, producing QNN_DEVICE_ERROR_INVALID_CONFIG.

Fix: ParseSocModel() now first attempts a name lookup via soc::SocModelFromName() before falling back to stoi(). A static map in soc_utils.cc covers entries from QNN/QnnTypes.h which have native HTP support. The name lookup is case-insensitive (ASCII uppercase, no locale dependency).

Why soc_model and not a new option: soc_model already flows directly into QnnHtpDevice_CustomConfig_t.socModel, which bypasses QNN's hardware auto-detection entirely. On Android, GetSocId() always returns 0 (it is Windows/PPTT-only), so users on Android have always had to set soc_model manually, string support makes this ergonomic without needing to look up the integer enum value.


Supported Configuration

Provider option Previously accepted Now also accepts
soc_model Numeric string (e.g. "69") Chip-family name string (e.g. "SM8750", case-insensitive)
htp_arch "68", "69", "73", "75", "81" "79" (HTP V79, SM8750)

Confirmed name-to-value mappings for common chips:

Chip name Qnn_SocModel_t value
SM8350 30
SM8450 36
SM8550 43
SM8650 57
SC8380XP 60
SM8750 69
SM8850 87

Full table in soc_utils.cc.


Unsupported Configuration

  • Unrecognized name strings (e.g. "FOOBAR") — fall back to QNN_SOC_MODEL_UNKNOWN (0) with a warning. No throw.
  • "SM8250" — not present in Qnn_SocModel_t; use numeric ID if needed.

@qti-mbadnara qti-mbadnara changed the title Dev/qti mbadnara/fix mobile invalid config [QNN EP] Fix soc_model string name support Aug 15, 2026
Comment thread onnxruntime/core/providers/qnn/soc_utils.cc

@quic-calvnguy quic-calvnguy left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM beyond a couple of nitpicks

Comment thread docs/execution_providers/QNN-ExecutionProvider.md Outdated
Comment thread onnxruntime/test/providers/qnn/unit/soc_utils_test.cc Outdated

@minfhong-qti minfhong-qti left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a more motivation-based question.
I think qnn-net-run / qnn-context-binary-generator do not support specifying SoC name. In addition, I believe the enum type Qnn_SocModel_t has stopped updating (and I guess it's probably why your map misses Glymur).
Couldn't we ask user to check for QNN doc and map by themselves? And we can save the effort of maintaining the map.

Comment thread onnxruntime/core/providers/qnn/soc_utils.cc
@ivaylo681-dev

Copy link
Copy Markdown

Feedback from building this locally (PR #736 branch, Android + --use_qnn static_lib + --build_java)
Wanted to share a few build-system issues hit while compiling this locally to validate the fix on-device:

  1. onnxruntime_unittests.cmake generates a malformed cmake -E copy when --use_qnn static_lib is used
    cmake
    if(onnxruntime_USE_QNN)
    add_custom_command(TARGET onnxruntime_providers_qnn POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy ${QNN_LIB_FILES} ${JAVA_NATIVE_TEST_DIR})
    endif()
    QNN_LIB_FILES is apparently only populated for shared_lib mode. In static_lib mode it's empty, producing cmake -E copy with no source argument, which crashes the build (CMake Error: cmake version ..., prints usage instead of copying). Worked around locally by commenting out this block, but presumably needs a guard like if(onnxruntime_USE_QNN AND QNN_LIB_FILES).
  2. --skip_submodule_sync isn't forwarded to the nested ExternalProject build
    In cmake/external/onnxruntime_prebuilt.cmake, the generated ORT_BUILD_COMMAND list never includes --skip_submodule_sync, even when the top-level build.sh invocation passes it. Since the ort_core source fetched via this mechanism isn't a git repository, the nested build.py unconditionally runs git submodule sync --recursive and crashes with fatal: not a git repository. No existing top-level flag avoids this. Worked around by manually adding list(APPEND ORT_BUILD_COMMAND --skip_submodule_sync) locally.
  3. QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE version guard doesn't match the real SDK
    cpp
    // QNN_HTP_GRAPH_CONFIG_OPTION_FP16_CLAMP_OVERFLOW is available from QNN API 2.38
    // (QAIRT 2.49).
    #if QNN_API_VERSION_MAJOR > 2 || (QNN_API_VERSION_MAJOR == 2 && QNN_API_VERSION_MINOR >= 38)
    #define QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE
    #endif
    This evaluates true against the actual, current QAIRT 2.49.0.260730 SDK, but fp16ClampOverflow/QNN_HTP_GRAPH_CONFIG_OPTION_FP16_CLAMP_OVERFLOW don't exist in that SDK's real headers — compile fails. Worked around by disabling the #define locally; the version check likely needs tightening (maybe a later QAIRT point release than what's currently public).
  4. Runtime observation: this is now purely a Qualcomm SoC-table issue, nothing left on the ORT side. I will put the description in [Mobile] QNN EP: QNN_DEVICE_ERROR_INVALID_CONFIG on Snapdragon 8 Elite (SM8750P, soc_id=639) — device creation fails regardless of provider_options, onnxruntime-android-qnn #715 (comment)

@qti-mbadnara

Copy link
Copy Markdown
Collaborator Author

Feedback from building this locally (PR #736 branch, Android + --use_qnn static_lib + --build_java) Wanted to share a few build-system issues hit while compiling this locally to validate the fix on-device:

  1. onnxruntime_unittests.cmake generates a malformed cmake -E copy when --use_qnn static_lib is used
    cmake
    if(onnxruntime_USE_QNN)
    add_custom_command(TARGET onnxruntime_providers_qnn POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy ${QNN_LIB_FILES} ${JAVA_NATIVE_TEST_DIR})
    endif()
    QNN_LIB_FILES is apparently only populated for shared_lib mode. In static_lib mode it's empty, producing cmake -E copy with no source argument, which crashes the build (CMake Error: cmake version ..., prints usage instead of copying). Worked around locally by commenting out this block, but presumably needs a guard like if(onnxruntime_USE_QNN AND QNN_LIB_FILES).
  2. --skip_submodule_sync isn't forwarded to the nested ExternalProject build
    In cmake/external/onnxruntime_prebuilt.cmake, the generated ORT_BUILD_COMMAND list never includes --skip_submodule_sync, even when the top-level build.sh invocation passes it. Since the ort_core source fetched via this mechanism isn't a git repository, the nested build.py unconditionally runs git submodule sync --recursive and crashes with fatal: not a git repository. No existing top-level flag avoids this. Worked around by manually adding list(APPEND ORT_BUILD_COMMAND --skip_submodule_sync) locally.
  3. QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE version guard doesn't match the real SDK
    cpp
    // QNN_HTP_GRAPH_CONFIG_OPTION_FP16_CLAMP_OVERFLOW is available from QNN API 2.38
    // (QAIRT 2.49).
    #if QNN_API_VERSION_MAJOR > 2 || (QNN_API_VERSION_MAJOR == 2 && QNN_API_VERSION_MINOR >= 38)
    #define QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE
    #endif
    This evaluates true against the actual, current QAIRT 2.49.0.260730 SDK, but fp16ClampOverflow/QNN_HTP_GRAPH_CONFIG_OPTION_FP16_CLAMP_OVERFLOW don't exist in that SDK's real headers — compile fails. Worked around by disabling the #define locally; the version check likely needs tightening (maybe a later QAIRT point release than what's currently public).
  4. Runtime observation: this is now purely a Qualcomm SoC-table issue, nothing left on the ORT side. I will put the description in [Mobile] QNN EP: QNN_DEVICE_ERROR_INVALID_CONFIG on Snapdragon 8 Elite (SM8750P, soc_id=639) — device creation fails regardless of provider_options, onnxruntime-android-qnn #715 (comment)

Thanks for the feedback @ivaylo681-dev

Will fix 1) and 2) as a separate PR. @huaychou Can you investigate the issue reported for QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE and make a fix if necessary. Thanks!

@qti-mbadnara

Copy link
Copy Markdown
Collaborator Author

This is a more motivation-based question. I think qnn-net-run / qnn-context-binary-generator do not support specifying SoC name. In addition, I believe the enum type Qnn_SocModel_t has stopped updating (and I guess it's probably why your map misses Glymur). Couldn't we ask user to check for QNN doc and map by themselves? And we can save the effort of maintaining the map.

Yeahh I agree with you, have updated the same in the documentation. Let me know if any other changes might be needed

@qti-mbadnara

Copy link
Copy Markdown
Collaborator Author

Feedback from building this locally (PR #736 branch, Android + --use_qnn static_lib + --build_java) Wanted to share a few build-system issues hit while compiling this locally to validate the fix on-device:

  1. onnxruntime_unittests.cmake generates a malformed cmake -E copy when --use_qnn static_lib is used
    cmake
    if(onnxruntime_USE_QNN)
    add_custom_command(TARGET onnxruntime_providers_qnn POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy ${QNN_LIB_FILES} ${JAVA_NATIVE_TEST_DIR})
    endif()
    QNN_LIB_FILES is apparently only populated for shared_lib mode. In static_lib mode it's empty, producing cmake -E copy with no source argument, which crashes the build (CMake Error: cmake version ..., prints usage instead of copying). Worked around locally by commenting out this block, but presumably needs a guard like if(onnxruntime_USE_QNN AND QNN_LIB_FILES).
  2. --skip_submodule_sync isn't forwarded to the nested ExternalProject build
    In cmake/external/onnxruntime_prebuilt.cmake, the generated ORT_BUILD_COMMAND list never includes --skip_submodule_sync, even when the top-level build.sh invocation passes it. Since the ort_core source fetched via this mechanism isn't a git repository, the nested build.py unconditionally runs git submodule sync --recursive and crashes with fatal: not a git repository. No existing top-level flag avoids this. Worked around by manually adding list(APPEND ORT_BUILD_COMMAND --skip_submodule_sync) locally.
  3. QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE version guard doesn't match the real SDK
    cpp
    // QNN_HTP_GRAPH_CONFIG_OPTION_FP16_CLAMP_OVERFLOW is available from QNN API 2.38
    // (QAIRT 2.49).
    #if QNN_API_VERSION_MAJOR > 2 || (QNN_API_VERSION_MAJOR == 2 && QNN_API_VERSION_MINOR >= 38)
    #define QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE
    #endif
    This evaluates true against the actual, current QAIRT 2.49.0.260730 SDK, but fp16ClampOverflow/QNN_HTP_GRAPH_CONFIG_OPTION_FP16_CLAMP_OVERFLOW don't exist in that SDK's real headers — compile fails. Worked around by disabling the #define locally; the version check likely needs tightening (maybe a later QAIRT point release than what's currently public).
  4. Runtime observation: this is now purely a Qualcomm SoC-table issue, nothing left on the ORT side. I will put the description in [Mobile] QNN EP: QNN_DEVICE_ERROR_INVALID_CONFIG on Snapdragon 8 Elite (SM8750P, soc_id=639) — device creation fails regardless of provider_options, onnxruntime-android-qnn #715 (comment)

Thanks for the feedback @ivaylo681-dev

Will fix 1) and 2) as a separate PR. @huaychou Can you investigate the issue reported for QNN_HTP_FP16_CLAMP_OVERFLOW_AVAILABLE and make a fix if necessary. Thanks!

@ivaylo681-dev #744 fixes the first two issues reported!

@qti-mbadnara
qti-mbadnara enabled auto-merge (squash) August 19, 2026 21:03
@qti-mbadnara
qti-mbadnara merged commit 6c768be into main Aug 19, 2026
139 of 141 checks passed
@qti-mbadnara
qti-mbadnara deleted the dev/qti-mbadnara/fix-mobile-invalid-config branch August 19, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

5 participants