Skip to main content

virtio_accel_hexagon/
lib.rs

1//! Qualcomm Hexagon NPU backend for `virtio-accel`.
2//!
3//! The portable portion validates TOSA 1.0 artifacts and creates a provider-local, fixed binding
4//! and operation plan. Native modules are compiled only for Windows ARM64 when a complete public
5//! QAIRT/QNN SDK is detected. SDK-free hosts retain that portable code and a constructor that
6//! reports the unavailable runtime without importing Qualcomm dependencies into portable crates.
7
8#![cfg_attr(not(va_hexagon), forbid(unsafe_code))]
9
10mod lower;
11
12pub use lower::{
13    HEXAGON_TOSA_CAPABILITY, HEXAGON_TOSA_INTEGER_CAPABILITY, HEXAGON_TOSA_INTEGER_TARGET,
14    HEXAGON_TOSA_TARGET, LoweringError, supports_tosa_dtype, supports_tosa_operator,
15};
16
17use virtio_accel_tosa::CapabilityDescriptor;
18#[cfg(not(va_hexagon))]
19use virtio_accel_tosa::TosaCapabilityProvider;
20
21#[cfg(va_hexagon)]
22const TOSA_CAPABILITIES: &[CapabilityDescriptor] =
23    &[HEXAGON_TOSA_CAPABILITY, HEXAGON_TOSA_INTEGER_CAPABILITY];
24#[cfg(not(va_hexagon))]
25const TOSA_CAPABILITIES: &[CapabilityDescriptor] = &[];
26
27/// Native QNN runtime and ABI version validated by the initial backend tier.
28pub const TESTED_QAIRT_RELEASE: &str = "2.49.0.260730";
29
30/// Conservative program-residency charge until QNN publishes a finite graph allocation bound.
31pub const REQUIRED_RESIDENT_BYTES: u64 = u64::MAX;
32
33/// Failure to initialize a Qualcomm Hexagon backend instance.
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
35pub enum InitError {
36    /// The crate was built without a complete QAIRT/QNN development runtime.
37    RuntimeUnavailable,
38    /// The loaded QNN interface is outside the validated API range.
39    IncompatibleRuntime,
40    /// The HTP backend or its device could not be created.
41    DeviceUnavailable,
42}
43
44impl core::fmt::Display for InitError {
45    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46        write!(formatter, "{self:?}")
47    }
48}
49
50impl std::error::Error for InitError {}
51
52#[allow(unsafe_code)]
53#[cfg(va_hexagon)]
54mod ffi;
55#[allow(unsafe_code)]
56#[cfg(va_hexagon)]
57mod native;
58#[cfg(va_hexagon)]
59pub use native::HexagonAccelerator;
60#[cfg(va_hexagon)]
61pub use native::{
62    HexagonBuffer, HexagonContext, HexagonEvent, HexagonProgram, HexagonQueue, QnnRuntimeInfo,
63};
64
65/// Placeholder that keeps workspace consumers portable when no complete QNN SDK was detected.
66#[cfg(not(va_hexagon))]
67#[derive(Clone, Copy, Debug, Default)]
68pub struct HexagonAccelerator;
69
70#[cfg(not(va_hexagon))]
71impl HexagonAccelerator {
72    /// Report that the native QNN build requirements were not detected.
73    pub fn new() -> Result<Self, InitError> {
74        Err(InitError::RuntimeUnavailable)
75    }
76
77    /// Report that the native QNN build requirements were not detected.
78    pub fn available_devices() -> Result<Vec<String>, InitError> {
79        Err(InitError::RuntimeUnavailable)
80    }
81}
82
83#[cfg(not(va_hexagon))]
84impl TosaCapabilityProvider for HexagonAccelerator {
85    fn tosa_capabilities(&self) -> &'static [CapabilityDescriptor] {
86        TOSA_CAPABILITIES
87    }
88}
89
90#[cfg(all(test, not(va_hexagon)))]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn sdk_free_constructor_is_explicitly_unavailable() {
96        assert!(matches!(
97            HexagonAccelerator::new(),
98            Err(InitError::RuntimeUnavailable)
99        ));
100        assert!(matches!(
101            HexagonAccelerator::available_devices(),
102            Err(InitError::RuntimeUnavailable)
103        ));
104    }
105}