Skip to content

fix(qairt): name recognized dsp_arch values when device creation fails - #1259

Open
MAN$I VERMA (mansiverma897993) wants to merge 1 commit into
qualcomm:mainfrom
mansiverma897993:fix/dsp-arch-diagnostic
Open

fix(qairt): name recognized dsp_arch values when device creation fails#1259
MAN$I VERMA (mansiverma897993) wants to merge 1 commit into
qualcomm:mainfrom
mansiverma897993:fix/dsp-arch-diagnostic

Conversation

@mansiverma897993

@mansiverma897993 MAN$I VERMA (mansiverma897993) commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Fixes #1254.

A bundle whose htp_backend_ext_config.json specifies a dsp_arch this QAIRT release doesn't recognize (e.g. "v85") fails with a bare QNN error 1008, which reads as unsupported silicon.

This adds dsp_arch_diagnostic() to the qairt runtime utils: it scans the config (schema-agnostic walk) and produces a message naming the offending value and the recognized set (v68-v81). Both LLM and VLM create paths log it as a warning, and on pipeline-creation failure return PARAM_NOT_SUPPORTED with the diagnostic instead of the bare error.

Not a hard gate: a missing/unparseable config or a QAIRT that accepts the value changes nothing. Test report in the comment below.

@mansiverma897993

Copy link
Copy Markdown
Contributor Author

Test report (logic verification; no Snapdragon 8 Elite Gen 5 hardware on my side)

@Hahahaooovvv

zdc (Hahahaooovvv) commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Hi MAN$I VERMA (@mansiverma897993) , Compiled this branch for arm64-android-snapdragon-release (same toolchain image CI uses) and plugins/qairt/src/llm.cpp.o / vlm.cpp.o both fail — 20 errors each, e.g. error: no member named 'nlohmann' in the global namespace.

Root cause: qnn_runtime_utils.h's new #include "external/json.hpp" (standard nlohmann) collides with QAIRT's own vendored JSON fork (qnn-api/src/utils/detail/json.hpp, namespace renamed nlohmannqualla). Both headers guard identical macro names (NLOHMANN_JSON_NAMESPACE etc.) with the same include-guard idiom — whichever gets included first through llm.cpp's include chain (llm.h → llm_spec_loader.h → input_provider.h → graph.h → QnnApi.hpp → config/Config.hpp) locks the macros and breaks the other's type definitions.

Fix: use the qualla::json fork already used elsewhere in this codebase (e.g. core/src/llm/llm_spec_loader.cpp) instead of pulling in a second, conflicting JSON library:

--- a/sdk/plugins/qairt/include/qnn_runtime_utils.h
+++ b/sdk/plugins/qairt/include/qnn_runtime_utils.h
@@ -16,8 +16,8 @@
 #include <string>
 #include <vector>
 
-#include "external/json.hpp"
 #include "types.h"
+#include "utils/detail/json.hpp"
 
 namespace geniex::qairt::runtime {
 
@@ -48,16 +48,16 @@ inline std::optional<std::string> dsp_arch_diagnostic(const std::string& htp_con
     if (!file.is_open()) {
         return std::nullopt;
     }
-    const nlohmann::json root = nlohmann::json::parse(file, nullptr, /*allow_exceptions=*/false);
+    const qualla::json root = qualla::json::parse(file, nullptr, /*allow_exceptions=*/false);
     if (root.is_discarded()) {
         return std::nullopt;
     }
 
     // Exporters nest dsp_arch differently, so walk the whole document.
-    std::vector<std::string>           unrecognized;
-    std::vector<const nlohmann::json*> stack{&root};
+    std::vector<std::string>         unrecognized;
+    std::vector<const qualla::json*> stack{&root};
     while (!stack.empty()) {
-        const nlohmann::json* node = stack.back();
+        const qualla::json* node = stack.back();
         stack.pop_back();
         if (node->is_object()) {
             for (auto it = node->begin(); it != node->end(); ++it) {

With this change, compiles clean and verified end-to-end on a real Snapdragon 8 Elite Gen 5 (SM8850) device via QDC: patched htp_backend_ext_config.json to dsp_arch: "v85" and confirmed the WARN fires with the expected message, and pipeline creation fails with PARAM_NOT_SUPPORTED (code -100016) instead of the bare 1008. Control run with the original v81 value shows no false-positive diagnostic.

@mansiverma897993

Copy link
Copy Markdown
Contributor Author

Hi MAN$I VERMA (MAN$I VERMA (@mansiverma897993)) , Compiled this branch for arm64-android-snapdragon-release (same toolchain image CI uses) and plugins/qairt/src/llm.cpp.o / vlm.cpp.o both fail — 20 errors each, e.g. error: no member named 'nlohmann' in the global namespace.

Root cause: qnn_runtime_utils.h's new #include "external/json.hpp" (standard nlohmann) collides with QAIRT's own vendored JSON fork (qnn-api/src/utils/detail/json.hpp, namespace renamed nlohmannqualla). Both headers guard identical macro names (NLOHMANN_JSON_NAMESPACE etc.) with the same include-guard idiom — whichever gets included first through llm.cpp's include chain (llm.h → llm_spec_loader.h → input_provider.h → graph.h → QnnApi.hpp → config/Config.hpp) locks the macros and breaks the other's type definitions.

Fix: use the qualla::json fork already used elsewhere in this codebase (e.g. core/src/llm/llm_spec_loader.cpp) instead of pulling in a second, conflicting JSON library:

--- a/sdk/plugins/qairt/include/qnn_runtime_utils.h
+++ b/sdk/plugins/qairt/include/qnn_runtime_utils.h
@@ -16,8 +16,8 @@
 #include <string>
 #include <vector>
 
-#include "external/json.hpp"
 #include "types.h"
+#include "utils/detail/json.hpp"
 
 namespace geniex::qairt::runtime {
 
@@ -48,16 +48,16 @@ inline std::optional<std::string> dsp_arch_diagnostic(const std::string& htp_con
     if (!file.is_open()) {
         return std::nullopt;
     }
-    const nlohmann::json root = nlohmann::json::parse(file, nullptr, /*allow_exceptions=*/false);
+    const qualla::json root = qualla::json::parse(file, nullptr, /*allow_exceptions=*/false);
     if (root.is_discarded()) {
         return std::nullopt;
     }
 
     // Exporters nest dsp_arch differently, so walk the whole document.
-    std::vector<std::string>           unrecognized;
-    std::vector<const nlohmann::json*> stack{&root};
+    std::vector<std::string>         unrecognized;
+    std::vector<const qualla::json*> stack{&root};
     while (!stack.empty()) {
-        const nlohmann::json* node = stack.back();
+        const qualla::json* node = stack.back();
         stack.pop_back();
         if (node->is_object()) {
             for (auto it = node->begin(); it != node->end(); ++it) {

With this change, compiles clean and verified end-to-end on a real Snapdragon 8 Elite Gen 5 (SM8850) device via QDC: patched htp_backend_ext_config.json to dsp_arch: "v85" and confirmed the WARN fires with the expected message, and pipeline creation fails with PARAM_NOT_SUPPORTED (code -100016) instead of the bare 1008. Control run with the original v81 value shows no false-positive diagnostic.

Thanks zdc (@Hahahaooovvv) for the detailed root-cause and the diff! Applied it as suggested switched to the vendored qualla::json (utils/detail/json.hpp) and dropped the conflicting nlohmann include. Verified llm.cpp / vlm.cpp now compile clean with the same include chain that broke before. Force-pushed to the branch, ready for another look.

A bundle whose htp_backend_ext_config.json specifies a dsp_arch this
QAIRT release does not recognize (e.g. "v85") fails with a bare QNN
error 1008, which reads as unsupported silicon. Validate the config
up front and, when pipeline creation fails, log which dsp_arch was
unrecognized and which values are supported, returning
PARAM_NOT_SUPPORTED instead of MODEL_LOAD. Not a hard gate: a QAIRT
that accepts the value still loads normally.

Fixes qualcomm#1254

Signed-off-by: mansiverma897993 <vmansi756@gmail.com>
@mansiverma897993

Copy link
Copy Markdown
Contributor Author

zdc (@Hahahaooovvv) RemiliaForever (@RemiliaForever) CI fails resolved: rebased onto the latest main, and all CI runs (QC Preflight, PR Check, zizmor) are fresh on commit dbefb8b. Code is verified against current main (vendored qualla::json, PARAM_NOT_SUPPORTED). Please Approve and run the checks so they can pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

QAIRT: unrecognized dsp_arch (e.g. v85) fails with bare error 1008 instead of naming supported values

2 participants