whisper.rn 0.4.0-rc.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/README.md +5 -1
  2. package/android/build.gradle +12 -3
  3. package/android/src/main/CMakeLists.txt +44 -13
  4. package/android/src/main/java/com/rnwhisper/AudioUtils.java +27 -12
  5. package/android/src/main/java/com/rnwhisper/RNWhisper.java +75 -34
  6. package/android/src/main/java/com/rnwhisper/WhisperContext.java +53 -38
  7. package/android/src/main/jni.cpp +38 -1
  8. package/android/src/main/jniLibs/arm64-v8a/librnwhisper.so +0 -0
  9. package/android/src/main/jniLibs/arm64-v8a/librnwhisper_v8fp16_va_2.so +0 -0
  10. package/android/src/main/jniLibs/armeabi-v7a/librnwhisper.so +0 -0
  11. package/android/src/main/jniLibs/armeabi-v7a/librnwhisper_vfpv4.so +0 -0
  12. package/android/src/main/jniLibs/x86_64/librnwhisper.so +0 -0
  13. package/android/src/main/jniLibs/x86_64/librnwhisper_x86_64.so +0 -0
  14. package/android/src/newarch/java/com/rnwhisper/RNWhisperModule.java +10 -0
  15. package/android/src/oldarch/java/com/rnwhisper/RNWhisperModule.java +10 -0
  16. package/cpp/coreml/whisper-compat.h +10 -0
  17. package/cpp/coreml/whisper-compat.m +35 -0
  18. package/cpp/coreml/whisper-decoder-impl.h +27 -15
  19. package/cpp/coreml/whisper-decoder-impl.m +36 -10
  20. package/cpp/coreml/whisper-encoder-impl.h +21 -9
  21. package/cpp/coreml/whisper-encoder-impl.m +29 -3
  22. package/cpp/ggml-alloc.c +727 -517
  23. package/cpp/ggml-alloc.h +47 -65
  24. package/cpp/ggml-backend-impl.h +196 -57
  25. package/cpp/ggml-backend-reg.cpp +591 -0
  26. package/cpp/ggml-backend.cpp +2016 -0
  27. package/cpp/ggml-backend.h +234 -89
  28. package/cpp/ggml-common.h +1861 -0
  29. package/cpp/ggml-cpp.h +39 -0
  30. package/cpp/ggml-cpu/amx/amx.cpp +221 -0
  31. package/cpp/ggml-cpu/amx/amx.h +8 -0
  32. package/cpp/ggml-cpu/amx/common.h +91 -0
  33. package/cpp/ggml-cpu/amx/mmq.cpp +2511 -0
  34. package/cpp/ggml-cpu/amx/mmq.h +10 -0
  35. package/cpp/ggml-cpu/arch/arm/cpu-feats.cpp +94 -0
  36. package/cpp/ggml-cpu/arch/arm/quants.c +4113 -0
  37. package/cpp/ggml-cpu/arch/arm/repack.cpp +2162 -0
  38. package/cpp/ggml-cpu/arch/x86/cpu-feats.cpp +327 -0
  39. package/cpp/ggml-cpu/arch/x86/quants.c +4310 -0
  40. package/cpp/ggml-cpu/arch/x86/repack.cpp +3284 -0
  41. package/cpp/ggml-cpu/arch-fallback.h +184 -0
  42. package/cpp/ggml-cpu/binary-ops.cpp +158 -0
  43. package/cpp/ggml-cpu/binary-ops.h +16 -0
  44. package/cpp/ggml-cpu/common.h +72 -0
  45. package/cpp/ggml-cpu/ggml-cpu-impl.h +511 -0
  46. package/cpp/ggml-cpu/ggml-cpu.c +3473 -0
  47. package/cpp/ggml-cpu/ggml-cpu.cpp +671 -0
  48. package/cpp/ggml-cpu/ops.cpp +9085 -0
  49. package/cpp/ggml-cpu/ops.h +111 -0
  50. package/cpp/ggml-cpu/quants.c +1157 -0
  51. package/cpp/ggml-cpu/quants.h +89 -0
  52. package/cpp/ggml-cpu/repack.cpp +1570 -0
  53. package/cpp/ggml-cpu/repack.h +98 -0
  54. package/cpp/ggml-cpu/simd-mappings.h +1006 -0
  55. package/cpp/ggml-cpu/traits.cpp +36 -0
  56. package/cpp/ggml-cpu/traits.h +38 -0
  57. package/cpp/ggml-cpu/unary-ops.cpp +186 -0
  58. package/cpp/ggml-cpu/unary-ops.h +28 -0
  59. package/cpp/ggml-cpu/vec.cpp +321 -0
  60. package/cpp/ggml-cpu/vec.h +973 -0
  61. package/cpp/ggml-cpu.h +143 -0
  62. package/cpp/ggml-impl.h +525 -168
  63. package/cpp/ggml-metal-impl.h +622 -0
  64. package/cpp/ggml-metal.h +16 -14
  65. package/cpp/ggml-metal.m +5289 -1859
  66. package/cpp/ggml-opt.cpp +1037 -0
  67. package/cpp/ggml-opt.h +237 -0
  68. package/cpp/ggml-quants.c +2916 -6877
  69. package/cpp/ggml-quants.h +87 -249
  70. package/cpp/ggml-threading.cpp +12 -0
  71. package/cpp/ggml-threading.h +14 -0
  72. package/cpp/ggml-whisper-sim.metallib +0 -0
  73. package/cpp/ggml-whisper.metallib +0 -0
  74. package/cpp/ggml.c +3293 -16770
  75. package/cpp/ggml.h +778 -835
  76. package/cpp/gguf.cpp +1347 -0
  77. package/cpp/gguf.h +202 -0
  78. package/cpp/rn-whisper.cpp +84 -0
  79. package/cpp/rn-whisper.h +2 -0
  80. package/cpp/whisper-arch.h +197 -0
  81. package/cpp/whisper.cpp +3240 -944
  82. package/cpp/whisper.h +144 -31
  83. package/ios/CMakeLists.txt +95 -0
  84. package/ios/RNWhisper.h +5 -0
  85. package/ios/RNWhisper.mm +124 -37
  86. package/ios/RNWhisperAudioUtils.h +1 -0
  87. package/ios/RNWhisperAudioUtils.m +24 -13
  88. package/ios/RNWhisperContext.h +8 -2
  89. package/ios/RNWhisperContext.mm +42 -8
  90. package/ios/rnwhisper.xcframework/Info.plist +74 -0
  91. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-alloc.h +76 -0
  92. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-backend-impl.h +255 -0
  93. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-backend.h +354 -0
  94. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-common.h +1861 -0
  95. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-cpp.h +39 -0
  96. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-cpu.h +143 -0
  97. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-impl.h +603 -0
  98. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-metal-impl.h +622 -0
  99. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-metal.h +66 -0
  100. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-opt.h +237 -0
  101. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-quants.h +100 -0
  102. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml-threading.h +14 -0
  103. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/ggml.h +2221 -0
  104. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/gguf.h +202 -0
  105. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/rn-audioutils.h +14 -0
  106. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/rn-whisper-log.h +11 -0
  107. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/rn-whisper.h +52 -0
  108. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/whisper-arch.h +197 -0
  109. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Headers/whisper.h +739 -0
  110. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/Info.plist +0 -0
  111. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/ggml-whisper.metallib +0 -0
  112. package/ios/rnwhisper.xcframework/ios-arm64/rnwhisper.framework/rnwhisper +0 -0
  113. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-alloc.h +76 -0
  114. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-backend-impl.h +255 -0
  115. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-backend.h +354 -0
  116. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-common.h +1861 -0
  117. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-cpp.h +39 -0
  118. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-cpu.h +143 -0
  119. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-impl.h +603 -0
  120. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-metal-impl.h +622 -0
  121. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-metal.h +66 -0
  122. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-opt.h +237 -0
  123. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-quants.h +100 -0
  124. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-threading.h +14 -0
  125. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml.h +2221 -0
  126. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/gguf.h +202 -0
  127. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/rn-audioutils.h +14 -0
  128. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/rn-whisper-log.h +11 -0
  129. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/rn-whisper.h +52 -0
  130. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/whisper-arch.h +197 -0
  131. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Headers/whisper.h +739 -0
  132. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/Info.plist +0 -0
  133. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/_CodeSignature/CodeResources +101 -0
  134. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/ggml-whisper-sim.metallib +0 -0
  135. package/ios/rnwhisper.xcframework/ios-arm64_x86_64-simulator/rnwhisper.framework/rnwhisper +0 -0
  136. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-alloc.h +76 -0
  137. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-backend-impl.h +255 -0
  138. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-backend.h +354 -0
  139. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-common.h +1861 -0
  140. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-cpp.h +39 -0
  141. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-cpu.h +143 -0
  142. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-impl.h +603 -0
  143. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-metal-impl.h +622 -0
  144. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-metal.h +66 -0
  145. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-opt.h +237 -0
  146. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-quants.h +100 -0
  147. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml-threading.h +14 -0
  148. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/ggml.h +2221 -0
  149. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/gguf.h +202 -0
  150. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/rn-audioutils.h +14 -0
  151. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/rn-whisper-log.h +11 -0
  152. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/rn-whisper.h +52 -0
  153. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/whisper-arch.h +197 -0
  154. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Headers/whisper.h +739 -0
  155. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/Info.plist +0 -0
  156. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/ggml-whisper.metallib +0 -0
  157. package/ios/rnwhisper.xcframework/tvos-arm64/rnwhisper.framework/rnwhisper +0 -0
  158. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-alloc.h +76 -0
  159. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-backend-impl.h +255 -0
  160. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-backend.h +354 -0
  161. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-common.h +1861 -0
  162. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-cpp.h +39 -0
  163. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-cpu.h +143 -0
  164. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-impl.h +603 -0
  165. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-metal-impl.h +622 -0
  166. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-metal.h +66 -0
  167. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-opt.h +237 -0
  168. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-quants.h +100 -0
  169. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml-threading.h +14 -0
  170. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/ggml.h +2221 -0
  171. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/gguf.h +202 -0
  172. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/rn-audioutils.h +14 -0
  173. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/rn-whisper-log.h +11 -0
  174. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/rn-whisper.h +52 -0
  175. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/whisper-arch.h +197 -0
  176. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Headers/whisper.h +739 -0
  177. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/Info.plist +0 -0
  178. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/_CodeSignature/CodeResources +101 -0
  179. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/ggml-whisper-sim.metallib +0 -0
  180. package/ios/rnwhisper.xcframework/tvos-arm64_x86_64-simulator/rnwhisper.framework/rnwhisper +0 -0
  181. package/jest/mock.js +14 -1
  182. package/lib/commonjs/NativeRNWhisper.js.map +1 -1
  183. package/lib/commonjs/index.js +48 -19
  184. package/lib/commonjs/index.js.map +1 -1
  185. package/lib/commonjs/version.json +1 -1
  186. package/lib/module/NativeRNWhisper.js.map +1 -1
  187. package/lib/module/index.js +48 -19
  188. package/lib/module/index.js.map +1 -1
  189. package/lib/module/version.json +1 -1
  190. package/lib/typescript/NativeRNWhisper.d.ts +6 -3
  191. package/lib/typescript/NativeRNWhisper.d.ts.map +1 -1
  192. package/lib/typescript/index.d.ts +25 -3
  193. package/lib/typescript/index.d.ts.map +1 -1
  194. package/package.json +15 -10
  195. package/src/NativeRNWhisper.ts +12 -3
  196. package/src/index.ts +63 -24
  197. package/src/version.json +1 -1
  198. package/whisper-rn.podspec +18 -18
  199. package/cpp/README.md +0 -4
  200. package/cpp/ggml-backend.c +0 -1718
  201. package/cpp/ggml-metal-whisper.metal +0 -5820
@@ -0,0 +1,591 @@
1
+ #include "ggml-backend-impl.h"
2
+ #include "ggml-backend.h"
3
+ #include "ggml-impl.h"
4
+ #include <algorithm>
5
+ #include <cstring>
6
+ #include <filesystem>
7
+ #include <memory>
8
+ #include <string>
9
+ #include <type_traits>
10
+ #include <vector>
11
+ #include <cctype>
12
+
13
+ #ifdef _WIN32
14
+ # define WIN32_LEAN_AND_MEAN
15
+ # ifndef NOMINMAX
16
+ # define NOMINMAX
17
+ # endif
18
+ # include <windows.h>
19
+ #elif defined(__APPLE__)
20
+ # include <mach-o/dyld.h>
21
+ # include <dlfcn.h>
22
+ #else
23
+ # include <dlfcn.h>
24
+ # include <unistd.h>
25
+ #endif
26
+
27
+ // Backend registry
28
+ #ifdef WSP_GGML_USE_CPU
29
+ #include "ggml-cpu.h"
30
+ #endif
31
+
32
+ #ifdef WSP_GGML_USE_CUDA
33
+ #include "ggml-cuda.h"
34
+ #endif
35
+
36
+ #ifdef WSP_GGML_USE_METAL
37
+ #include "ggml-metal.h"
38
+ #endif
39
+
40
+ #ifdef WSP_GGML_USE_SYCL
41
+ #include "ggml-sycl.h"
42
+ #endif
43
+
44
+ #ifdef WSP_GGML_USE_VULKAN
45
+ #include "ggml-vulkan.h"
46
+ #endif
47
+
48
+ #ifdef WSP_GGML_USE_OPENCL
49
+ #include "ggml-opencl.h"
50
+ #endif
51
+
52
+ #ifdef WSP_GGML_USE_BLAS
53
+ #include "ggml-blas.h"
54
+ #endif
55
+
56
+ #ifdef WSP_GGML_USE_RPC
57
+ #include "ggml-rpc.h"
58
+ #endif
59
+
60
+ #ifdef WSP_GGML_USE_CANN
61
+ #include "ggml-cann.h"
62
+ #endif
63
+
64
+ #ifdef WSP_GGML_USE_KOMPUTE
65
+ #include "ggml-kompute.h"
66
+ #endif
67
+
68
+ // disable C++17 deprecation warning for std::codecvt_utf8
69
+ #if defined(__clang__)
70
+ # pragma clang diagnostic push
71
+ # pragma clang diagnostic ignored "-Wdeprecated-declarations"
72
+ #elif defined(__GNUC__)
73
+ # pragma GCC diagnostic push
74
+ # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
75
+ #endif
76
+
77
+ namespace fs = std::filesystem;
78
+
79
+ static std::string path_str(const fs::path & path) {
80
+ std::string u8path;
81
+ try {
82
+ #if defined(__cpp_lib_char8_t)
83
+ // C++20 and later: u8string() returns std::u8string
84
+ std::u8string u8str = path.u8string();
85
+ u8path = std::string(reinterpret_cast<const char*>(u8str.c_str()));
86
+ #else
87
+ // C++17: u8string() returns std::string
88
+ u8path = path.u8string();
89
+ #endif
90
+ } catch (...) {
91
+ }
92
+ return u8path;
93
+ }
94
+
95
+ #if defined(__clang__)
96
+ # pragma clang diagnostic pop
97
+ #elif defined(__GNUC__)
98
+ # pragma GCC diagnostic pop
99
+ #endif
100
+
101
+ #ifdef _WIN32
102
+
103
+ using dl_handle = std::remove_pointer_t<HMODULE>;
104
+
105
+ struct dl_handle_deleter {
106
+ void operator()(HMODULE handle) {
107
+ FreeLibrary(handle);
108
+ }
109
+ };
110
+
111
+ static dl_handle * dl_load_library(const fs::path & path) {
112
+ // suppress error dialogs for missing DLLs
113
+ DWORD old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
114
+ SetErrorMode(old_mode | SEM_FAILCRITICALERRORS);
115
+
116
+ HMODULE handle = LoadLibraryW(path.wstring().c_str());
117
+
118
+ SetErrorMode(old_mode);
119
+
120
+ return handle;
121
+ }
122
+
123
+ static void * dl_get_sym(dl_handle * handle, const char * name) {
124
+ DWORD old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
125
+ SetErrorMode(old_mode | SEM_FAILCRITICALERRORS);
126
+
127
+ void * p = (void *) GetProcAddress(handle, name);
128
+
129
+ SetErrorMode(old_mode);
130
+
131
+ return p;
132
+ }
133
+
134
+ #else
135
+
136
+ using dl_handle = void;
137
+
138
+ struct dl_handle_deleter {
139
+ void operator()(void * handle) {
140
+ dlclose(handle);
141
+ }
142
+ };
143
+
144
+ static void * dl_load_library(const fs::path & path) {
145
+ dl_handle * handle = dlopen(path.string().c_str(), RTLD_NOW | RTLD_LOCAL);
146
+
147
+ return handle;
148
+ }
149
+
150
+ static void * dl_get_sym(dl_handle * handle, const char * name) {
151
+ return dlsym(handle, name);
152
+ }
153
+
154
+ #endif
155
+
156
+ using dl_handle_ptr = std::unique_ptr<dl_handle, dl_handle_deleter>;
157
+
158
+ struct wsp_ggml_backend_reg_entry {
159
+ wsp_ggml_backend_reg_t reg;
160
+ dl_handle_ptr handle;
161
+ };
162
+
163
+ struct wsp_ggml_backend_registry {
164
+ std::vector<wsp_ggml_backend_reg_entry> backends;
165
+ std::vector<wsp_ggml_backend_dev_t> devices;
166
+
167
+ wsp_ggml_backend_registry() {
168
+ #ifdef WSP_GGML_USE_CUDA
169
+ register_backend(wsp_ggml_backend_cuda_reg());
170
+ #endif
171
+ #ifdef WSP_GGML_USE_METAL
172
+ register_backend(wsp_ggml_backend_metal_reg());
173
+ #endif
174
+ #ifdef WSP_GGML_USE_SYCL
175
+ register_backend(wsp_ggml_backend_sycl_reg());
176
+ #endif
177
+ #ifdef WSP_GGML_USE_VULKAN
178
+ register_backend(wsp_ggml_backend_vk_reg());
179
+ #endif
180
+ #ifdef WSP_GGML_USE_OPENCL
181
+ register_backend(wsp_ggml_backend_opencl_reg());
182
+ #endif
183
+ #ifdef WSP_GGML_USE_CANN
184
+ register_backend(wsp_ggml_backend_cann_reg());
185
+ #endif
186
+ #ifdef WSP_GGML_USE_BLAS
187
+ register_backend(wsp_ggml_backend_blas_reg());
188
+ #endif
189
+ #ifdef WSP_GGML_USE_RPC
190
+ register_backend(wsp_ggml_backend_rpc_reg());
191
+ #endif
192
+ #ifdef WSP_GGML_USE_KOMPUTE
193
+ register_backend(wsp_ggml_backend_kompute_reg());
194
+ #endif
195
+ #ifdef WSP_GGML_USE_CPU
196
+ register_backend(wsp_ggml_backend_cpu_reg());
197
+ #endif
198
+ }
199
+
200
+ ~wsp_ggml_backend_registry() {
201
+ // FIXME: backends cannot be safely unloaded without a function to destroy all the backend resources,
202
+ // since backend threads may still be running and accessing resources from the dynamic library
203
+ for (auto & entry : backends) {
204
+ if (entry.handle) {
205
+ entry.handle.release(); // NOLINT
206
+ }
207
+ }
208
+ }
209
+
210
+ void register_backend(wsp_ggml_backend_reg_t reg, dl_handle_ptr handle = nullptr) {
211
+ if (!reg) {
212
+ return;
213
+ }
214
+
215
+ #ifndef NDEBUG
216
+ WSP_GGML_LOG_DEBUG("%s: registered backend %s (%zu devices)\n",
217
+ __func__, wsp_ggml_backend_reg_name(reg), wsp_ggml_backend_reg_dev_count(reg));
218
+ #endif
219
+ backends.push_back({ reg, std::move(handle) });
220
+ for (size_t i = 0; i < wsp_ggml_backend_reg_dev_count(reg); i++) {
221
+ register_device(wsp_ggml_backend_reg_dev_get(reg, i));
222
+ }
223
+ }
224
+
225
+ void register_device(wsp_ggml_backend_dev_t device) {
226
+ #ifndef NDEBUG
227
+ WSP_GGML_LOG_DEBUG("%s: registered device %s (%s)\n", __func__, wsp_ggml_backend_dev_name(device), wsp_ggml_backend_dev_description(device));
228
+ #endif
229
+ devices.push_back(device);
230
+ }
231
+
232
+ wsp_ggml_backend_reg_t load_backend(const fs::path & path, bool silent) {
233
+ dl_handle_ptr handle { dl_load_library(path) };
234
+ if (!handle) {
235
+ if (!silent) {
236
+ WSP_GGML_LOG_ERROR("%s: failed to load %s\n", __func__, path_str(path).c_str());
237
+ }
238
+ return nullptr;
239
+ }
240
+
241
+ auto score_fn = (wsp_ggml_backend_score_t) dl_get_sym(handle.get(), "wsp_ggml_backend_score");
242
+ if (score_fn && score_fn() == 0) {
243
+ if (!silent) {
244
+ WSP_GGML_LOG_INFO("%s: backend %s is not supported on this system\n", __func__, path_str(path).c_str());
245
+ }
246
+ return nullptr;
247
+ }
248
+
249
+ auto backend_init_fn = (wsp_ggml_backend_init_t) dl_get_sym(handle.get(), "wsp_ggml_backend_init");
250
+ if (!backend_init_fn) {
251
+ if (!silent) {
252
+ WSP_GGML_LOG_ERROR("%s: failed to find wsp_ggml_backend_init in %s\n", __func__, path_str(path).c_str());
253
+ }
254
+ return nullptr;
255
+ }
256
+
257
+ wsp_ggml_backend_reg_t reg = backend_init_fn();
258
+ if (!reg || reg->api_version != WSP_GGML_BACKEND_API_VERSION) {
259
+ if (!silent) {
260
+ if (!reg) {
261
+ WSP_GGML_LOG_ERROR("%s: failed to initialize backend from %s: wsp_ggml_backend_init returned NULL\n",
262
+ __func__, path_str(path).c_str());
263
+ } else {
264
+ WSP_GGML_LOG_ERROR("%s: failed to initialize backend from %s: incompatible API version (backend: %d, current: %d)\n",
265
+ __func__, path_str(path).c_str(), reg->api_version, WSP_GGML_BACKEND_API_VERSION);
266
+ }
267
+ }
268
+ return nullptr;
269
+ }
270
+
271
+ WSP_GGML_LOG_INFO("%s: loaded %s backend from %s\n", __func__, wsp_ggml_backend_reg_name(reg), path_str(path).c_str());
272
+
273
+ register_backend(reg, std::move(handle));
274
+
275
+ return reg;
276
+ }
277
+
278
+ void unload_backend(wsp_ggml_backend_reg_t reg, bool silent) {
279
+ auto it = std::find_if(backends.begin(), backends.end(),
280
+ [reg](const wsp_ggml_backend_reg_entry & entry) { return entry.reg == reg; });
281
+
282
+ if (it == backends.end()) {
283
+ if (!silent) {
284
+ WSP_GGML_LOG_ERROR("%s: backend not found\n", __func__);
285
+ }
286
+ return;
287
+ }
288
+
289
+ if (!silent) {
290
+ WSP_GGML_LOG_DEBUG("%s: unloading %s backend\n", __func__, wsp_ggml_backend_reg_name(reg));
291
+ }
292
+
293
+ // remove devices
294
+ devices.erase(
295
+ std::remove_if(devices.begin(), devices.end(),
296
+ [reg](wsp_ggml_backend_dev_t dev) { return wsp_ggml_backend_dev_backend_reg(dev) == reg; }),
297
+ devices.end());
298
+
299
+ // remove backend
300
+ backends.erase(it);
301
+ }
302
+ };
303
+
304
+ static wsp_ggml_backend_registry & get_reg() {
305
+ static wsp_ggml_backend_registry reg;
306
+ return reg;
307
+ }
308
+
309
+ // Internal API
310
+ void wsp_ggml_backend_register(wsp_ggml_backend_reg_t reg) {
311
+ get_reg().register_backend(reg);
312
+ }
313
+
314
+ void wsp_ggml_backend_device_register(wsp_ggml_backend_dev_t device) {
315
+ get_reg().register_device(device);
316
+ }
317
+
318
+ // Backend (reg) enumeration
319
+ static bool striequals(const char * a, const char * b) {
320
+ for (; *a && *b; a++, b++) {
321
+ if (std::tolower(*a) != std::tolower(*b)) {
322
+ return false;
323
+ }
324
+ }
325
+ return *a == *b;
326
+ }
327
+
328
+ size_t wsp_ggml_backend_reg_count() {
329
+ return get_reg().backends.size();
330
+ }
331
+
332
+ wsp_ggml_backend_reg_t wsp_ggml_backend_reg_get(size_t index) {
333
+ WSP_GGML_ASSERT(index < wsp_ggml_backend_reg_count());
334
+ return get_reg().backends[index].reg;
335
+ }
336
+
337
+ wsp_ggml_backend_reg_t wsp_ggml_backend_reg_by_name(const char * name) {
338
+ for (size_t i = 0; i < wsp_ggml_backend_reg_count(); i++) {
339
+ wsp_ggml_backend_reg_t reg = wsp_ggml_backend_reg_get(i);
340
+ if (striequals(wsp_ggml_backend_reg_name(reg), name)) {
341
+ return reg;
342
+ }
343
+ }
344
+ return nullptr;
345
+ }
346
+
347
+ // Device enumeration
348
+ size_t wsp_ggml_backend_dev_count() {
349
+ return get_reg().devices.size();
350
+ }
351
+
352
+ wsp_ggml_backend_dev_t wsp_ggml_backend_dev_get(size_t index) {
353
+ WSP_GGML_ASSERT(index < wsp_ggml_backend_dev_count());
354
+ return get_reg().devices[index];
355
+ }
356
+
357
+ wsp_ggml_backend_dev_t wsp_ggml_backend_dev_by_name(const char * name) {
358
+ for (size_t i = 0; i < wsp_ggml_backend_dev_count(); i++) {
359
+ wsp_ggml_backend_dev_t dev = wsp_ggml_backend_dev_get(i);
360
+ if (striequals(wsp_ggml_backend_dev_name(dev), name)) {
361
+ return dev;
362
+ }
363
+ }
364
+ return nullptr;
365
+ }
366
+
367
+ wsp_ggml_backend_dev_t wsp_ggml_backend_dev_by_type(enum wsp_ggml_backend_dev_type type) {
368
+ for (size_t i = 0; i < wsp_ggml_backend_dev_count(); i++) {
369
+ wsp_ggml_backend_dev_t dev = wsp_ggml_backend_dev_get(i);
370
+ if (wsp_ggml_backend_dev_type(dev) == type) {
371
+ return dev;
372
+ }
373
+ }
374
+ return nullptr;
375
+ }
376
+
377
+ // Convenience functions
378
+ wsp_ggml_backend_t wsp_ggml_backend_init_by_name(const char * name, const char * params) {
379
+ wsp_ggml_backend_dev_t dev = wsp_ggml_backend_dev_by_name(name);
380
+ if (!dev) {
381
+ return nullptr;
382
+ }
383
+ return wsp_ggml_backend_dev_init(dev, params);
384
+ }
385
+
386
+ wsp_ggml_backend_t wsp_ggml_backend_init_by_type(enum wsp_ggml_backend_dev_type type, const char * params) {
387
+ wsp_ggml_backend_dev_t dev = wsp_ggml_backend_dev_by_type(type);
388
+ if (!dev) {
389
+ return nullptr;
390
+ }
391
+ return wsp_ggml_backend_dev_init(dev, params);
392
+ }
393
+
394
+ wsp_ggml_backend_t wsp_ggml_backend_init_best(void) {
395
+ wsp_ggml_backend_dev_t dev = wsp_ggml_backend_dev_by_type(WSP_GGML_BACKEND_DEVICE_TYPE_GPU);
396
+ if (!dev) {
397
+ dev = wsp_ggml_backend_dev_by_type(WSP_GGML_BACKEND_DEVICE_TYPE_CPU);
398
+ }
399
+ if (!dev) {
400
+ return nullptr;
401
+ }
402
+ return wsp_ggml_backend_dev_init(dev, nullptr);
403
+ }
404
+
405
+ // Dynamic loading
406
+ wsp_ggml_backend_reg_t wsp_ggml_backend_load(const char * path) {
407
+ return get_reg().load_backend(path, false);
408
+ }
409
+
410
+ void wsp_ggml_backend_unload(wsp_ggml_backend_reg_t reg) {
411
+ get_reg().unload_backend(reg, true);
412
+ }
413
+
414
+ static fs::path get_executable_path() {
415
+ #if defined(__APPLE__)
416
+ // get executable path
417
+ std::vector<char> path;
418
+ uint32_t size;
419
+ while (true) {
420
+ size = path.size();
421
+ if (_NSGetExecutablePath(path.data(), &size) == 0) {
422
+ break;
423
+ }
424
+ path.resize(size);
425
+ }
426
+ std::string base_path(path.data(), size);
427
+ // remove executable name
428
+ auto last_slash = base_path.find_last_of('/');
429
+ if (last_slash != std::string::npos) {
430
+ base_path = base_path.substr(0, last_slash);
431
+ }
432
+ return base_path + "/";
433
+ #elif defined(__linux__) || defined(__FreeBSD__)
434
+ std::string base_path = ".";
435
+ std::vector<char> path(1024);
436
+ while (true) {
437
+ // get executable path
438
+ # if defined(__linux__)
439
+ ssize_t len = readlink("/proc/self/exe", path.data(), path.size());
440
+ # elif defined(__FreeBSD__)
441
+ ssize_t len = readlink("/proc/curproc/file", path.data(), path.size());
442
+ # endif
443
+ if (len == -1) {
444
+ break;
445
+ }
446
+ if (len < (ssize_t) path.size()) {
447
+ base_path = std::string(path.data(), len);
448
+ // remove executable name
449
+ auto last_slash = base_path.find_last_of('/');
450
+ if (last_slash != std::string::npos) {
451
+ base_path = base_path.substr(0, last_slash);
452
+ }
453
+ break;
454
+ }
455
+ path.resize(path.size() * 2);
456
+ }
457
+
458
+ return base_path + "/";
459
+ #elif defined(_WIN32)
460
+ std::vector<wchar_t> path(MAX_PATH);
461
+ DWORD len = GetModuleFileNameW(NULL, path.data(), path.size());
462
+ if (len == 0) {
463
+ return {};
464
+ }
465
+ std::wstring base_path(path.data(), len);
466
+ // remove executable name
467
+ auto last_slash = base_path.find_last_of('\\');
468
+ if (last_slash != std::string::npos) {
469
+ base_path = base_path.substr(0, last_slash);
470
+ }
471
+ return base_path + L"\\";
472
+ #else
473
+ return {};
474
+ #endif
475
+ }
476
+
477
+ static fs::path backend_filename_prefix() {
478
+ #ifdef _WIN32
479
+ return fs::u8path("ggml-");
480
+ #else
481
+ return fs::u8path("libggml-");
482
+ #endif
483
+ }
484
+
485
+ static fs::path backend_filename_extension() {
486
+ #ifdef _WIN32
487
+ return fs::u8path(".dll");
488
+ #else
489
+ return fs::u8path(".so");
490
+ #endif
491
+ }
492
+
493
+ static wsp_ggml_backend_reg_t wsp_ggml_backend_load_best(const char * name, bool silent, const char * user_search_path) {
494
+ // enumerate all the files that match [lib]ggml-name-*.[so|dll] in the search paths
495
+ const fs::path name_path = fs::u8path(name);
496
+ const fs::path file_prefix = backend_filename_prefix().native() + name_path.native() + fs::u8path("-").native();
497
+ const fs::path file_extension = backend_filename_extension();
498
+
499
+ std::vector<fs::path> search_paths;
500
+ if (user_search_path == nullptr) {
501
+ // default search paths: executable directory, current directory
502
+ search_paths.push_back(get_executable_path());
503
+ search_paths.push_back(fs::current_path());
504
+ } else {
505
+ search_paths.push_back(fs::u8path(user_search_path));
506
+ }
507
+
508
+ int best_score = 0;
509
+ fs::path best_path;
510
+
511
+ for (const auto & search_path : search_paths) {
512
+ if (!fs::exists(search_path)) {
513
+ WSP_GGML_LOG_DEBUG("%s: search path %s does not exist\n", __func__, path_str(search_path).c_str());
514
+ continue;
515
+ }
516
+ fs::directory_iterator dir_it(search_path, fs::directory_options::skip_permission_denied);
517
+ for (const auto & entry : dir_it) {
518
+ if (entry.is_regular_file()) {
519
+ auto filename = entry.path().filename();
520
+ auto ext = entry.path().extension();
521
+ if (filename.native().find(file_prefix) == 0 && ext == file_extension) {
522
+ dl_handle_ptr handle { dl_load_library(entry) };
523
+ if (!handle && !silent) {
524
+ WSP_GGML_LOG_ERROR("%s: failed to load %s\n", __func__, path_str(entry.path()).c_str());
525
+ }
526
+ if (handle) {
527
+ auto score_fn = (wsp_ggml_backend_score_t) dl_get_sym(handle.get(), "wsp_ggml_backend_score");
528
+ if (score_fn) {
529
+ int s = score_fn();
530
+ #ifndef NDEBUG
531
+ WSP_GGML_LOG_DEBUG("%s: %s score: %d\n", __func__, path_str(entry.path()).c_str(), s);
532
+ #endif
533
+ if (s > best_score) {
534
+ best_score = s;
535
+ best_path = entry.path();
536
+ }
537
+ } else {
538
+ if (!silent) {
539
+ WSP_GGML_LOG_INFO("%s: failed to find wsp_ggml_backend_score in %s\n", __func__, path_str(entry.path()).c_str());
540
+ }
541
+ }
542
+ }
543
+ }
544
+ }
545
+ }
546
+ }
547
+
548
+ if (best_score == 0) {
549
+ // try to load the base backend
550
+ for (const auto & search_path : search_paths) {
551
+ fs::path filename = backend_filename_prefix().native() + name_path.native() + backend_filename_extension().native();
552
+ fs::path path = search_path / filename;
553
+ if (fs::exists(path)) {
554
+ return get_reg().load_backend(path, silent);
555
+ }
556
+ }
557
+ return nullptr;
558
+ }
559
+
560
+ return get_reg().load_backend(best_path, silent);
561
+ }
562
+
563
+ void wsp_ggml_backend_load_all() {
564
+ wsp_ggml_backend_load_all_from_path(nullptr);
565
+ }
566
+
567
+ void wsp_ggml_backend_load_all_from_path(const char * dir_path) {
568
+ #ifdef NDEBUG
569
+ bool silent = true;
570
+ #else
571
+ bool silent = false;
572
+ #endif
573
+
574
+ wsp_ggml_backend_load_best("blas", silent, dir_path);
575
+ wsp_ggml_backend_load_best("cann", silent, dir_path);
576
+ wsp_ggml_backend_load_best("cuda", silent, dir_path);
577
+ wsp_ggml_backend_load_best("hip", silent, dir_path);
578
+ wsp_ggml_backend_load_best("kompute", silent, dir_path);
579
+ wsp_ggml_backend_load_best("metal", silent, dir_path);
580
+ wsp_ggml_backend_load_best("rpc", silent, dir_path);
581
+ wsp_ggml_backend_load_best("sycl", silent, dir_path);
582
+ wsp_ggml_backend_load_best("vulkan", silent, dir_path);
583
+ wsp_ggml_backend_load_best("opencl", silent, dir_path);
584
+ wsp_ggml_backend_load_best("musa", silent, dir_path);
585
+ wsp_ggml_backend_load_best("cpu", silent, dir_path);
586
+ // check the environment variable WSP_GGML_BACKEND_PATH to load an out-of-tree backend
587
+ const char * backend_path = std::getenv("WSP_GGML_BACKEND_PATH");
588
+ if (backend_path) {
589
+ wsp_ggml_backend_load(backend_path);
590
+ }
591
+ }