Hi there! I've tried to modify your patch for the QCS6490 v68 platform without success.
I investigated that the QNN/QAIRT path (chraac fork) is blocked by unsigned PD firmware, but the upstream Hexagon backend (GGML_HEXAGON=ON) uses FastRPC directly with custom HVX/HMX kernels — it does NOT use QNN stub/skel at all. This means the unsigned PD blocker may not apply to the upstream path, since it compiles its own DSP code and loads it via FastRPC directly, not through the QNN SDK's transport layer.
I won't work on the patch of this fork for v68 anymore, but I created working upstream sync instructions.
Anyone can update the code - just paste it to you agent. Hope you can use it too, @chraac
Issue: QNN Backend API Compatibility + SoC Support for Recent Upstream
Summary
The dev-refactoring branch is ~1560 commits behind upstream/master. This causes:
- Build failures from upstream API changes in
ggml_backend_i and ggml_backend_buffer_i
- Missing model support (Qwen3.5, etc.) — upstream arch definitions not present
- Missing backend registration —
qnn not in ggml_backend_load_all_from_path() search list
This issue documents the changes needed to keep the QNN fork compatible with recent upstream.
1. Merge Upstream Master
The fork needs an upstream merge. Conflicts are minimal and mechanical:
Conflict Resolution for CMakeLists.txt
Keep both QNN deprecation warning AND CURL deprecation warning (upstream added new ones).
Conflict Resolution for ggml/src/ggml-backend-reg.cpp
Keep the QNN backend registration line. Upstream may add new backends (OpenVINO, virtgpu) — keep those too.
2. API Compatibility Patches
After merging upstream, these patches are needed for the QNN backend to compile:
Patch A: New op GGML_OP_GATED_DELTA_NET
Added in upstream, needs entries in 3 QNN tables:
File: ggml/src/ggml-qnn/qnn/backend-ops.cpp
false, // GGML_OP_SOLVE_TRI
+ false, // GGML_OP_GATED_DELTA_NET
File: ggml/src/ggml-qnn/qnn/op-config-caps.cpp
{}, // GGML_OP_SOLVE_TRI
+ {}, // GGML_OP_GATED_DELTA_NET
And in the same file, op constructors table:
nullptr, // GGML_OP_SOLVE_TRI
+ nullptr, // GGML_OP_GATED_DELTA_NET
Patch B: New 2D tensor fields in ggml_backend_i
Upstream added set_tensor_2d_async and get_tensor_2d_async to the interface struct.
File: ggml/src/ggml-qnn/qnn/ggml-qnn.cpp
/* .get_tensor_async = */ nullptr,
+ /* .set_tensor_2d_async = */ nullptr,
+ /* .get_tensor_2d_async = */ nullptr,
Patch C: New 2D tensor fields in ggml_backend_buffer_i
Upstream added set_tensor_2d and get_tensor_2d to the buffer interface struct.
File: ggml/src/ggml-qnn/qnn/ggml-qnn.cpp
/* .get_tensor = */ ggml_backend_qnn_buffer_get_tensor,
+ /* .set_tensor_2d = */ nullptr,
+ /* .get_tensor_2d = */ nullptr,
3. Backend Registration Fix
Upstream changed ggml_backend_load_all_from_path() to use a sorted search list. The QNN backend is missing from this list.
File: ggml/src/ggml-backend-reg.cpp — in ggml_backend_load_all_from_path(), add:
ggml_backend_load_best("qnn", silent, dir_path);
(Place it alongside other backends like "hexagon", "opencl", etc.)
4. Build System Fixes
POSITION_INDEPENDENT_CODE
The qnn-backend static library needs PIC for linking into the MODULE target:
File: ggml/src/ggml-qnn/qnn/CMakeLists.txt
set_target_properties(qnn-backend PROPERTIES POSITION_INDEPENDENT_CODE ON)
ggml-qnn-dl.cpp in CMakeLists
The dynamic loading support file must be included:
File: ggml/src/ggml-qnn/CMakeLists.txt
ggml_add_backend_library(ggml-qnn
../../include/ggml-qnn.h
ggml-qnn-dl.cpp # <-- add this line
)
5. SoC Model Fallback + Unsigned PD Support (Recommended)
For broader SoC compatibility (QCS6490/socModel=93 not in QNN SDK enum), enhance qnn_init() in qnn-lib.cpp:
5a: Enable unsigned module at init
// In qnn_init(), before load_system():
{
fastrpc_capability ctrl = {CDSP_DOMAIN_ID, UNSIGNED_PD_SUPPORT, 0};
typedef int (*remote_session_control_fn)(uint32_t, void*, uint32_t);
void * rpc_lib = dlopen("libcdsprpc.so", RTLD_NOW);
if (rpc_lib) {
auto fn = (remote_session_control_fn)dlsym(rpc_lib, "remote_session_control");
if (fn) {
fn(2 /* DSPRPC_CONTROL_UNSIGNED_MODULE */, &ctrl, sizeof(ctrl));
}
}
}
5b: SOC model fallback with unsigned PD config
Replace the single qnn_device_create() call with a loop trying multiple SoC configs:
uint32_t soc_models[] = {93, 29, 30, 31, 0}; // raw QCS6490, SM6350, SM8350, SM4350, none
const char *soc_names[] = {"raw93", "SM6350", "SM8350", "SM4350", "no-soc-config"};
for (int attempt = 0; attempt < 5 && !_qnn_device_handle; attempt++) {
const QnnDevice_Config_t *configs[3] = {nullptr};
int cc = 0;
// Arch config: HTP V68
configs[cc++]->option = QNN_DEVICE_CONFIG_OPTION_CUSTOM;
configs[cc++]->customConfig = &htp_arch_config;
if (attempt < 4) {
// SOC config for this attempt
configs[cc++]->option = QNN_DEVICE_CONFIG_OPTION_CUSTOM;
configs[cc++]->customConfig = &htp_soc_config;
}
// Unsigned PD config: useSignedProcessDomain = false
configs[cc++]->option = QNN_DEVICE_CONFIG_OPTION_CUSTOM;
configs[cc++]->customConfig = &htp_unsigned_pd_config;
qnn_device_create(_qnn_log_handle, configs, &_qnn_device_handle);
}
6. QAIRT SDK Version Note
QAIRT 2.42/2.43 reject socModel=93 (QCS6490) with INVALID_CONFIG. QAIRT 2.45+ recognizes QCS6490: "Detected Snapdragon SOC QCS6490 with 4 SOCs". The CMake config should document this requirement or detect available SDK versions.
Verification Checklist
After applying the above:
Hi there! I've tried to modify your patch for the QCS6490 v68 platform without success.
I investigated that the QNN/QAIRT path (chraac fork) is blocked by unsigned PD firmware, but the upstream Hexagon backend (GGML_HEXAGON=ON) uses FastRPC directly with custom HVX/HMX kernels — it does NOT use QNN stub/skel at all. This means the unsigned PD blocker may not apply to the upstream path, since it compiles its own DSP code and loads it via FastRPC directly, not through the QNN SDK's transport layer.
I won't work on the patch of this fork for v68 anymore, but I created working upstream sync instructions.
Anyone can update the code - just paste it to you agent. Hope you can use it too, @chraac
Issue: QNN Backend API Compatibility + SoC Support for Recent Upstream
Summary
The
dev-refactoringbranch is ~1560 commits behind upstream/master. This causes:ggml_backend_iandggml_backend_buffer_iqnnnot inggml_backend_load_all_from_path()search listThis issue documents the changes needed to keep the QNN fork compatible with recent upstream.
1. Merge Upstream Master
The fork needs an upstream merge. Conflicts are minimal and mechanical:
Conflict Resolution for
CMakeLists.txtKeep both QNN deprecation warning AND CURL deprecation warning (upstream added new ones).
Conflict Resolution for
ggml/src/ggml-backend-reg.cppKeep the QNN backend registration line. Upstream may add new backends (OpenVINO, virtgpu) — keep those too.
2. API Compatibility Patches
After merging upstream, these patches are needed for the QNN backend to compile:
Patch A: New op
GGML_OP_GATED_DELTA_NETAdded in upstream, needs entries in 3 QNN tables:
File:
ggml/src/ggml-qnn/qnn/backend-ops.cppfalse, // GGML_OP_SOLVE_TRI + false, // GGML_OP_GATED_DELTA_NETFile:
ggml/src/ggml-qnn/qnn/op-config-caps.cpp{}, // GGML_OP_SOLVE_TRI + {}, // GGML_OP_GATED_DELTA_NETAnd in the same file, op constructors table:
nullptr, // GGML_OP_SOLVE_TRI + nullptr, // GGML_OP_GATED_DELTA_NETPatch B: New 2D tensor fields in
ggml_backend_iUpstream added
set_tensor_2d_asyncandget_tensor_2d_asyncto the interface struct.File:
ggml/src/ggml-qnn/qnn/ggml-qnn.cppPatch C: New 2D tensor fields in
ggml_backend_buffer_iUpstream added
set_tensor_2dandget_tensor_2dto the buffer interface struct.File:
ggml/src/ggml-qnn/qnn/ggml-qnn.cpp3. Backend Registration Fix
Upstream changed
ggml_backend_load_all_from_path()to use a sorted search list. The QNN backend is missing from this list.File:
ggml/src/ggml-backend-reg.cpp— inggml_backend_load_all_from_path(), add:(Place it alongside other backends like "hexagon", "opencl", etc.)
4. Build System Fixes
POSITION_INDEPENDENT_CODE
The
qnn-backendstatic library needs PIC for linking into the MODULE target:File:
ggml/src/ggml-qnn/qnn/CMakeLists.txtggml-qnn-dl.cpp in CMakeLists
The dynamic loading support file must be included:
File:
ggml/src/ggml-qnn/CMakeLists.txt5. SoC Model Fallback + Unsigned PD Support (Recommended)
For broader SoC compatibility (QCS6490/socModel=93 not in QNN SDK enum), enhance
qnn_init()inqnn-lib.cpp:5a: Enable unsigned module at init
5b: SOC model fallback with unsigned PD config
Replace the single
qnn_device_create()call with a loop trying multiple SoC configs:6. QAIRT SDK Version Note
QAIRT 2.42/2.43 reject socModel=93 (QCS6490) with
INVALID_CONFIG. QAIRT 2.45+ recognizes QCS6490: "Detected Snapdragon SOC QCS6490 with 4 SOCs". The CMake config should document this requirement or detect available SDK versions.Verification Checklist
After applying the above:
cmakeconfigure succeedslibggml-qnn.soloads and registers correctlyqnn-npu: Hexagon NPU