whispercpp 1.3.6 → 1.3.8

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 (965) hide show
  1. checksums.yaml +4 -4
  2. data/.document +3 -0
  3. data/.rdoc_options +2 -0
  4. data/README.md +43 -9
  5. data/Rakefile +18 -3
  6. data/ext/dependencies.rb +10 -4
  7. data/ext/dependencies_for_windows.rb +17 -0
  8. data/ext/extconf.rb +20 -8
  9. data/ext/options.rb +54 -14
  10. data/ext/options_for_windows.rb +51 -0
  11. data/ext/ruby_whisper.c +35 -42
  12. data/ext/ruby_whisper.h +141 -0
  13. data/ext/ruby_whisper_context.c +157 -29
  14. data/ext/ruby_whisper_log_queue.c +180 -0
  15. data/ext/ruby_whisper_log_settable.h +46 -0
  16. data/ext/ruby_whisper_parakeet.c +49 -0
  17. data/ext/ruby_whisper_parakeet_context.c +304 -0
  18. data/ext/ruby_whisper_parakeet_context_params.c +117 -0
  19. data/ext/ruby_whisper_parakeet_model.c +84 -0
  20. data/ext/ruby_whisper_parakeet_params.c +548 -0
  21. data/ext/ruby_whisper_parakeet_segment.c +157 -0
  22. data/ext/ruby_whisper_parakeet_token.c +188 -0
  23. data/ext/ruby_whisper_parakeet_transcribe.cpp +58 -0
  24. data/ext/ruby_whisper_params.c +265 -73
  25. data/ext/ruby_whisper_segment.c +6 -6
  26. data/ext/ruby_whisper_transcribe.cpp +23 -15
  27. data/ext/ruby_whisper_vad_context.c +30 -10
  28. data/ext/ruby_whisper_vad_context_detect.cpp +8 -9
  29. data/ext/ruby_whisper_vad_params.c +4 -4
  30. data/ext/ruby_whisper_vad_segment.c +2 -2
  31. data/ext/sources/CMakeLists.txt +42 -3
  32. data/ext/sources/CMakePresets.json +95 -0
  33. data/ext/sources/cmake/parakeet-config.cmake.in +30 -0
  34. data/ext/sources/cmake/parakeet.pc.in +10 -0
  35. data/ext/sources/cmake/whisper.pc.in +2 -2
  36. data/ext/sources/examples/CMakeLists.txt +4 -2
  37. data/ext/sources/examples/bench/bench.cpp +1 -1
  38. data/ext/sources/examples/cli/cli.cpp +52 -10
  39. data/ext/sources/examples/common-ggml.cpp +4 -0
  40. data/ext/sources/examples/common-whisper.cpp +139 -67
  41. data/ext/sources/examples/common-whisper.h +11 -0
  42. data/ext/sources/examples/ffmpeg-transcode.cpp +211 -341
  43. data/ext/sources/examples/parakeet-cli/CMakeLists.txt +8 -0
  44. data/ext/sources/examples/parakeet-cli/parakeet-cli.cpp +243 -0
  45. data/ext/sources/examples/parakeet-quantize/CMakeLists.txt +7 -0
  46. data/ext/sources/examples/parakeet-quantize/parakeet-quantize.cpp +230 -0
  47. data/ext/sources/examples/server/server.cpp +199 -163
  48. data/ext/sources/examples/vad-speech-segments/speech.cpp +3 -2
  49. data/ext/sources/ggml/CMakeLists.txt +21 -14
  50. data/ext/sources/ggml/cmake/FindNCCL.cmake +36 -0
  51. data/ext/sources/ggml/cmake/ggml-config.cmake.in +12 -2
  52. data/ext/sources/ggml/include/ggml-alloc.h +1 -0
  53. data/ext/sources/ggml/include/ggml-backend.h +72 -10
  54. data/ext/sources/ggml/include/ggml-cuda.h +2 -2
  55. data/ext/sources/ggml/include/ggml-rpc.h +3 -3
  56. data/ext/sources/ggml/include/ggml-sycl.h +8 -0
  57. data/ext/sources/ggml/include/ggml.h +103 -9
  58. data/ext/sources/ggml/include/gguf.h +10 -2
  59. data/ext/sources/ggml/src/CMakeLists.txt +30 -6
  60. data/ext/sources/ggml/src/ggml-alloc.c +5 -1
  61. data/ext/sources/ggml/src/ggml-backend-impl.h +22 -2
  62. data/ext/sources/ggml/src/ggml-backend-meta.cpp +2266 -0
  63. data/ext/sources/ggml/src/ggml-backend-reg.cpp +12 -0
  64. data/ext/sources/ggml/src/ggml-backend.cpp +110 -9
  65. data/ext/sources/ggml/src/ggml-blas/ggml-blas.cpp +4 -0
  66. data/ext/sources/ggml/src/ggml-cann/aclnn_ops.cpp +672 -257
  67. data/ext/sources/ggml/src/ggml-cann/aclnn_ops.h +71 -0
  68. data/ext/sources/ggml/src/ggml-cann/common.h +20 -10
  69. data/ext/sources/ggml/src/ggml-cann/ggml-cann.cpp +211 -30
  70. data/ext/sources/ggml/src/ggml-common.h +24 -2
  71. data/ext/sources/ggml/src/ggml-cpu/CMakeLists.txt +59 -30
  72. data/ext/sources/ggml/src/ggml-cpu/amx/amx.cpp +2 -0
  73. data/ext/sources/ggml/src/ggml-cpu/amx/mmq.cpp +21 -22
  74. data/ext/sources/ggml/src/ggml-cpu/arch/arm/quants.c +194 -11
  75. data/ext/sources/ggml/src/ggml-cpu/arch/arm/repack.cpp +65 -0
  76. data/ext/sources/ggml/src/ggml-cpu/arch/loongarch/quants.c +151 -1
  77. data/ext/sources/ggml/src/ggml-cpu/arch/powerpc/quants.c +0 -1
  78. data/ext/sources/ggml/src/ggml-cpu/arch/riscv/quants.c +4279 -1292
  79. data/ext/sources/ggml/src/ggml-cpu/arch/riscv/repack.cpp +5 -35
  80. data/ext/sources/ggml/src/ggml-cpu/arch/s390/quants.c +0 -1
  81. data/ext/sources/ggml/src/ggml-cpu/arch/wasm/quants.c +72 -1
  82. data/ext/sources/ggml/src/ggml-cpu/arch/x86/quants.c +319 -31
  83. data/ext/sources/ggml/src/ggml-cpu/arch/x86/repack.cpp +1 -1
  84. data/ext/sources/ggml/src/ggml-cpu/arch-fallback.h +12 -2
  85. data/ext/sources/ggml/src/ggml-cpu/cmake/FindSMTIME.cmake +32 -0
  86. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu-impl.h +10 -0
  87. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu.c +109 -5
  88. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu.cpp +2 -0
  89. data/ext/sources/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp +146 -134
  90. data/ext/sources/ggml/src/ggml-cpu/llamafile/sgemm.cpp +107 -82
  91. data/ext/sources/ggml/src/ggml-cpu/ops.cpp +501 -119
  92. data/ext/sources/ggml/src/ggml-cpu/ops.h +3 -0
  93. data/ext/sources/ggml/src/ggml-cpu/quants.c +106 -0
  94. data/ext/sources/ggml/src/ggml-cpu/quants.h +6 -0
  95. data/ext/sources/ggml/src/ggml-cpu/repack.cpp +3 -0
  96. data/ext/sources/ggml/src/ggml-cpu/simd-gemm.h +91 -1
  97. data/ext/sources/ggml/src/ggml-cpu/simd-mappings.h +14 -16
  98. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime.cpp +1402 -687
  99. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime.h +8 -0
  100. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime1_kernels.cpp +597 -2766
  101. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime2_kernels.cpp +5768 -0
  102. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime_env.cpp +320 -0
  103. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime_env.h +55 -0
  104. data/ext/sources/ggml/src/ggml-cpu/spacemit/ime_kernels.h +182 -19
  105. data/ext/sources/ggml/src/ggml-cpu/spacemit/repack.cpp +1795 -0
  106. data/ext/sources/ggml/src/ggml-cpu/spacemit/repack.h +14 -0
  107. data/ext/sources/ggml/src/ggml-cpu/spacemit/rvv_kernels.cpp +3178 -0
  108. data/ext/sources/ggml/src/ggml-cpu/spacemit/rvv_kernels.h +95 -0
  109. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_barrier.h +34 -0
  110. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_mem_pool.cpp +760 -0
  111. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_mem_pool.h +32 -0
  112. data/ext/sources/ggml/src/ggml-cpu/spacemit/spine_tcm.h +409 -0
  113. data/ext/sources/ggml/src/ggml-cpu/vec.cpp +39 -55
  114. data/ext/sources/ggml/src/ggml-cpu/vec.h +225 -240
  115. data/ext/sources/ggml/src/ggml-cuda/CMakeLists.txt +17 -7
  116. data/ext/sources/ggml/src/ggml-cuda/allreduce.cu +971 -0
  117. data/ext/sources/ggml/src/ggml-cuda/allreduce.cuh +29 -0
  118. data/ext/sources/ggml/src/ggml-cuda/argsort.cu +62 -26
  119. data/ext/sources/ggml/src/ggml-cuda/binbcast.cu +134 -64
  120. data/ext/sources/ggml/src/ggml-cuda/binbcast.cuh +1 -0
  121. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cu +81 -0
  122. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cuh +3 -0
  123. data/ext/sources/ggml/src/ggml-cuda/common.cuh +246 -28
  124. data/ext/sources/ggml/src/ggml-cuda/concat.cu +134 -116
  125. data/ext/sources/ggml/src/ggml-cuda/conv-transpose-1d.cu +14 -12
  126. data/ext/sources/ggml/src/ggml-cuda/conv2d-transpose.cu +45 -21
  127. data/ext/sources/ggml/src/ggml-cuda/conv2d-transpose.cuh +1 -0
  128. data/ext/sources/ggml/src/ggml-cuda/convert.cu +139 -34
  129. data/ext/sources/ggml/src/ggml-cuda/convert.cuh +10 -0
  130. data/ext/sources/ggml/src/ggml-cuda/cpy.cu +88 -29
  131. data/ext/sources/ggml/src/ggml-cuda/dequantize.cuh +22 -0
  132. data/ext/sources/ggml/src/ggml-cuda/fattn-common.cuh +287 -49
  133. data/ext/sources/ggml/src/ggml-cuda/fattn-mma-f16.cuh +335 -130
  134. data/ext/sources/ggml/src/ggml-cuda/fattn-tile.cu +12 -0
  135. data/ext/sources/ggml/src/ggml-cuda/fattn-tile.cuh +127 -24
  136. data/ext/sources/ggml/src/ggml-cuda/fattn-vec.cuh +40 -15
  137. data/ext/sources/ggml/src/ggml-cuda/fattn-wmma-f16.cu +18 -9
  138. data/ext/sources/ggml/src/ggml-cuda/fattn.cu +169 -60
  139. data/ext/sources/ggml/src/ggml-cuda/fattn.cuh +2 -0
  140. data/ext/sources/ggml/src/ggml-cuda/fwht.cu +101 -0
  141. data/ext/sources/ggml/src/ggml-cuda/fwht.cuh +4 -0
  142. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cu +109 -45
  143. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cuh +10 -0
  144. data/ext/sources/ggml/src/ggml-cuda/getrows.cu +48 -23
  145. data/ext/sources/ggml/src/ggml-cuda/ggml-cuda.cu +2034 -2104
  146. data/ext/sources/ggml/src/ggml-cuda/im2col.cu +32 -29
  147. data/ext/sources/ggml/src/ggml-cuda/mean.cu +4 -2
  148. data/ext/sources/ggml/src/ggml-cuda/mma.cuh +242 -195
  149. data/ext/sources/ggml/src/ggml-cuda/mmf.cuh +3 -3
  150. data/ext/sources/ggml/src/ggml-cuda/mmq.cu +25 -12
  151. data/ext/sources/ggml/src/ggml-cuda/mmq.cuh +502 -423
  152. data/ext/sources/ggml/src/ggml-cuda/mmvf.cu +19 -12
  153. data/ext/sources/ggml/src/ggml-cuda/mmvq.cu +562 -97
  154. data/ext/sources/ggml/src/ggml-cuda/mmvq.cuh +6 -1
  155. data/ext/sources/ggml/src/ggml-cuda/norm.cu +36 -10
  156. data/ext/sources/ggml/src/ggml-cuda/out-prod.cu +66 -7
  157. data/ext/sources/ggml/src/ggml-cuda/quantize.cu +133 -26
  158. data/ext/sources/ggml/src/ggml-cuda/quantize.cuh +1 -1
  159. data/ext/sources/ggml/src/ggml-cuda/reduce_rows.cuh +5 -1
  160. data/ext/sources/ggml/src/ggml-cuda/rope.cu +11 -4
  161. data/ext/sources/ggml/src/ggml-cuda/scale.cu +4 -1
  162. data/ext/sources/ggml/src/ggml-cuda/set-rows.cu +78 -10
  163. data/ext/sources/ggml/src/ggml-cuda/snake.cu +72 -0
  164. data/ext/sources/ggml/src/ggml-cuda/snake.cuh +8 -0
  165. data/ext/sources/ggml/src/ggml-cuda/softcap.cu +4 -1
  166. data/ext/sources/ggml/src/ggml-cuda/ssm-conv.cu +45 -13
  167. data/ext/sources/ggml/src/ggml-cuda/ssm-conv.cuh +1 -1
  168. data/ext/sources/ggml/src/ggml-cuda/ssm-scan.cu +40 -18
  169. data/ext/sources/ggml/src/ggml-cuda/sumrows.cu +8 -4
  170. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_16.cu +1 -0
  171. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_32.cu +1 -0
  172. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_8.cu +2 -0
  173. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu +1 -0
  174. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_4.cu +1 -0
  175. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_16.cu +1 -0
  176. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_32.cu +1 -0
  177. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_4.cu +1 -0
  178. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_8.cu +2 -0
  179. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu +1 -0
  180. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_16.cu +1 -0
  181. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu +1 -0
  182. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_4.cu +1 -0
  183. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_8.cu +2 -0
  184. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu +1 -0
  185. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_4.cu +1 -0
  186. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_8.cu +2 -0
  187. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq192-dv128.cu +5 -0
  188. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq320-dv256.cu +5 -0
  189. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq512-dv512.cu +5 -0
  190. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-bf16.cu +7 -0
  191. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-f16.cu +7 -0
  192. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_0.cu +7 -0
  193. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_1.cu +7 -0
  194. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_0.cu +7 -0
  195. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_1.cu +7 -0
  196. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q8_0.cu +7 -0
  197. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-bf16.cu +7 -0
  198. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-bf16.cu +7 -0
  199. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-bf16.cu +7 -0
  200. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-bf16.cu +7 -0
  201. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-bf16.cu +7 -0
  202. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-bf16.cu +7 -0
  203. data/ext/sources/ggml/src/ggml-cuda/template-instances/mmq-instance-nvfp4.cu +5 -0
  204. data/ext/sources/ggml/src/ggml-cuda/template-instances/mmq-instance-q1_0.cu +5 -0
  205. data/ext/sources/ggml/src/ggml-cuda/top-k.cu +5 -4
  206. data/ext/sources/ggml/src/ggml-cuda/topk-moe.cu +33 -24
  207. data/ext/sources/ggml/src/ggml-cuda/unary.cu +31 -2
  208. data/ext/sources/ggml/src/ggml-cuda/unary.cuh +2 -0
  209. data/ext/sources/ggml/src/ggml-cuda/vecdotq.cuh +80 -0
  210. data/ext/sources/ggml/src/ggml-cuda/vendors/cuda.h +7 -2
  211. data/ext/sources/ggml/src/ggml-cuda/vendors/hip.h +23 -4
  212. data/ext/sources/ggml/src/ggml-cuda/vendors/musa.h +4 -0
  213. data/ext/sources/ggml/src/ggml-hexagon/CMakeLists.txt +1 -5
  214. data/ext/sources/ggml/src/ggml-hexagon/ggml-hexagon.cpp +2788 -1762
  215. data/ext/sources/ggml/src/ggml-hexagon/htp/CMakeLists.txt +13 -4
  216. data/ext/sources/ggml/src/ggml-hexagon/htp/act-ops.c +53 -84
  217. data/ext/sources/ggml/src/ggml-hexagon/htp/argsort-ops.c +25 -12
  218. data/ext/sources/ggml/src/ggml-hexagon/htp/binary-ops.c +165 -184
  219. data/ext/sources/ggml/src/ggml-hexagon/htp/cmake-toolchain.cmake +17 -19
  220. data/ext/sources/ggml/src/ggml-hexagon/htp/concat-ops.c +277 -0
  221. data/ext/sources/ggml/src/ggml-hexagon/htp/cpy-ops.c +170 -127
  222. data/ext/sources/ggml/src/ggml-hexagon/htp/cumsum-ops.c +270 -0
  223. data/ext/sources/ggml/src/ggml-hexagon/htp/diag-ops.c +216 -0
  224. data/ext/sources/ggml/src/ggml-hexagon/htp/fill-ops.c +123 -0
  225. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.c +1774 -396
  226. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.h +303 -0
  227. data/ext/sources/ggml/src/ggml-hexagon/htp/gated-delta-net-ops.c +1148 -0
  228. data/ext/sources/ggml/src/ggml-hexagon/htp/get-rows-ops.c +148 -42
  229. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-common.h +80 -0
  230. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dma.c +2 -2
  231. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dma.h +255 -62
  232. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dump.h +9 -0
  233. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-profile.h +64 -0
  234. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-utils.h +25 -21
  235. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-fa-kernels.h +555 -0
  236. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-mm-kernels-tiled.h +1303 -0
  237. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.c +167 -0
  238. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.h +157 -0
  239. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-utils.h +222 -0
  240. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ctx.h +104 -13
  241. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ops.h +222 -57
  242. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-vtcm.h +19 -0
  243. data/ext/sources/ggml/src/ggml-hexagon/htp/htp_iface.idl +10 -3
  244. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-base.h +78 -26
  245. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-copy.h +27 -10
  246. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-div.h +63 -23
  247. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-exp.h +48 -8
  248. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-fa-kernels.h +232 -0
  249. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-flash-attn.h +47 -0
  250. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-log.h +65 -0
  251. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-flat.h +1511 -0
  252. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-tiled.h +1200 -0
  253. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-pow.h +42 -0
  254. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-repl.h +74 -0
  255. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-sigmoid.h +40 -0
  256. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-sin-cos.h +90 -0
  257. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-utils.h +5 -8
  258. data/ext/sources/ggml/src/ggml-hexagon/htp/main.c +625 -816
  259. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.c +3052 -2166
  260. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.h +650 -0
  261. data/ext/sources/ggml/src/ggml-hexagon/htp/pad-ops.c +547 -0
  262. data/ext/sources/ggml/src/ggml-hexagon/htp/repeat-ops.c +148 -0
  263. data/ext/sources/ggml/src/ggml-hexagon/htp/rope-ops.c +337 -106
  264. data/ext/sources/ggml/src/ggml-hexagon/htp/set-rows-ops.c +59 -37
  265. data/ext/sources/ggml/src/ggml-hexagon/htp/softmax-ops.c +121 -133
  266. data/ext/sources/ggml/src/ggml-hexagon/htp/solve-tri-ops.c +267 -0
  267. data/ext/sources/ggml/src/ggml-hexagon/htp/ssm-conv.c +245 -151
  268. data/ext/sources/ggml/src/ggml-hexagon/htp/sum-rows-ops.c +6 -6
  269. data/ext/sources/ggml/src/ggml-hexagon/htp/unary-ops.c +719 -45
  270. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.c +15 -3
  271. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.h +8 -0
  272. data/ext/sources/ggml/src/ggml-hexagon/htp-opnode.h +390 -0
  273. data/ext/sources/ggml/src/ggml-hexagon/libggml-htp.inf +3 -5
  274. data/ext/sources/ggml/src/ggml-hip/CMakeLists.txt +27 -9
  275. data/ext/sources/ggml/src/ggml-impl.h +6 -1
  276. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.cpp +207 -18
  277. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.h +36 -2
  278. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.m +186 -29
  279. data/ext/sources/ggml/src/ggml-metal/ggml-metal-impl.h +118 -0
  280. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.cpp +322 -21
  281. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.h +4 -0
  282. data/ext/sources/ggml/src/ggml-metal/ggml-metal.cpp +39 -26
  283. data/ext/sources/ggml/src/ggml-metal/ggml-metal.metal +1226 -467
  284. data/ext/sources/ggml/src/ggml-musa/CMakeLists.txt +5 -6
  285. data/ext/sources/ggml/src/ggml-opencl/CMakeLists.txt +67 -5
  286. data/ext/sources/ggml/src/ggml-opencl/fa_tune.h +92 -0
  287. data/ext/sources/ggml/src/ggml-opencl/ggml-opencl.cpp +16290 -6246
  288. data/ext/sources/ggml/src/ggml-opencl/kernels/concat.cl +67 -0
  289. data/ext/sources/ggml/src/ggml-opencl/kernels/cpy.cl +59 -0
  290. data/ext/sources/ggml/src/ggml-opencl/kernels/cvt.cl +1997 -92
  291. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f16.cl +81 -41
  292. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32.cl +88 -39
  293. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_f16.cl +1995 -96
  294. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q4_0.cl +1615 -0
  295. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q8_0.cl +1486 -0
  296. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_pre_f16.cl +156 -0
  297. data/ext/sources/ggml/src/ggml-opencl/kernels/gated_delta_net.cl +249 -0
  298. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32_ns.cl +374 -0
  299. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_0_f32_ns.cl +324 -0
  300. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_1_f32_ns.cl +326 -0
  301. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_k_f32_ns.cl +348 -0
  302. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_0_f32_ns.cl +328 -0
  303. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_1_f32_ns.cl +330 -0
  304. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_k_f32_ns.cl +356 -0
  305. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q6_k_f32_ns.cl +335 -0
  306. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_iq4_nl_f32.cl +150 -0
  307. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q1_0_f32.cl +94 -0
  308. data/ext/sources/ggml/src/ggml-opencl/kernels/{mul_mat_Ab_Bi_8x4.cl → gemm_noshuffle_q4_0_f32.cl} +1 -1
  309. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q4_k_f32.cl +172 -0
  310. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_0_f32.cl +131 -0
  311. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_1_f32.cl +134 -0
  312. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q5_k_f32.cl +176 -0
  313. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q6_k_f32.cl +140 -0
  314. data/ext/sources/ggml/src/ggml-opencl/kernels/{mul_mm_q8_0_f32_8x4.cl → gemm_noshuffle_q8_0_f32.cl} +1 -1
  315. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_xmem_f16_f32_os8.cl +233 -0
  316. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_mxfp4_f32_ns.cl +165 -0
  317. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q4_0_f32_ns.cl +120 -0
  318. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q4_1_f32_ns.cl +123 -0
  319. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q4_k_f32_ns.cl +155 -0
  320. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q5_0_f32_ns.cl +123 -0
  321. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q5_1_f32_ns.cl +125 -0
  322. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q5_k_f32_ns.cl +160 -0
  323. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_moe_q6_k_f32_ns.cl +141 -0
  324. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_iq4_nl_f32.cl +302 -0
  325. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q1_0_f32.cl +121 -0
  326. data/ext/sources/ggml/src/ggml-opencl/kernels/{gemv_noshuffle_general.cl → gemv_noshuffle_q4_0_f32.cl} +5 -5
  327. data/ext/sources/ggml/src/ggml-opencl/kernels/{gemv_noshuffle.cl → gemv_noshuffle_q4_0_f32_spec.cl} +5 -5
  328. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q4_k_f32.cl +318 -0
  329. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_0_f32.cl +291 -0
  330. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_1_f32.cl +294 -0
  331. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q5_k_f32.cl +326 -0
  332. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q6_k_f32.cl +293 -0
  333. data/ext/sources/ggml/src/ggml-opencl/kernels/{gemv_noshuffle_general_q8_0_f32.cl → gemv_noshuffle_q8_0_f32.cl} +1 -1
  334. data/ext/sources/ggml/src/ggml-opencl/kernels/get_rows.cl +15 -9
  335. data/ext/sources/ggml/src/ggml-opencl/kernels/moe_reorder_b.cl +30 -0
  336. data/ext/sources/ggml/src/ggml-opencl/kernels/moe_sort_by_expert.cl +82 -0
  337. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_iq4_nl_f32_l4_lm.cl +171 -0
  338. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q1_0_f32_l4_lm.cl +156 -0
  339. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q4_k_f32_l4_lm.cl +179 -0
  340. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q5_0_f32_l4_lm.cl +173 -0
  341. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q5_1_f32_l4_lm.cl +175 -0
  342. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q5_k_f32_l4_lm.cl +192 -0
  343. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +1149 -0
  344. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_iq4_nl_f32.cl +164 -0
  345. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_iq4_nl_f32_flat.cl +202 -0
  346. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32.cl +141 -0
  347. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32_flat.cl +190 -0
  348. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32_flat.cl +196 -0
  349. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_0_f32.cl +241 -0
  350. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_0_f32_flat.cl +243 -0
  351. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_1_f32.cl +243 -0
  352. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_1_f32_flat.cl +247 -0
  353. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_k_f32.cl +187 -0
  354. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q5_k_f32_flat.cl +203 -0
  355. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q6_k_f32_flat.cl +48 -64
  356. data/ext/sources/ggml/src/ggml-opencl/kernels/norm.cl +5 -2
  357. data/ext/sources/ggml/src/ggml-opencl/kernels/set_rows.cl +500 -0
  358. data/ext/sources/ggml/src/ggml-opencl/libdl.h +79 -0
  359. data/ext/sources/ggml/src/ggml-openvino/.clang-format +0 -5
  360. data/ext/sources/ggml/src/ggml-openvino/CMakeLists.txt +2 -4
  361. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.cpp +740 -127
  362. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.h +76 -23
  363. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.cpp +75 -14
  364. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.h +29 -8
  365. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino.cpp +339 -69
  366. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.cpp +330 -192
  367. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.h +10 -4
  368. data/ext/sources/ggml/src/ggml-openvino/openvino/decoder.h +56 -16
  369. data/ext/sources/ggml/src/ggml-openvino/openvino/frontend.h +1 -1
  370. data/ext/sources/ggml/src/ggml-openvino/openvino/input_model.h +4 -4
  371. data/ext/sources/ggml/src/ggml-openvino/openvino/node_context.h +94 -37
  372. data/ext/sources/ggml/src/ggml-openvino/openvino/op/add_id.cpp +76 -0
  373. data/ext/sources/ggml/src/ggml-openvino/openvino/op/argsort.cpp +47 -0
  374. data/ext/sources/ggml/src/ggml-openvino/openvino/op/clamp.cpp +33 -0
  375. data/ext/sources/ggml/src/ggml-openvino/openvino/op/concat.cpp +48 -0
  376. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cont.cpp +8 -16
  377. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cpy.cpp +14 -1
  378. data/ext/sources/ggml/src/ggml-openvino/openvino/op/div.cpp +146 -0
  379. data/ext/sources/ggml/src/ggml-openvino/openvino/op/flash_attn_ext.cpp +108 -21
  380. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.cpp +282 -0
  381. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.hpp +65 -0
  382. data/ext/sources/ggml/src/ggml-openvino/openvino/op/get_rows.cpp +2 -9
  383. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_geglu.cpp +21 -7
  384. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_swiglu.cpp +41 -8
  385. data/ext/sources/ggml/src/ggml-openvino/openvino/op/im2col.cpp +120 -0
  386. data/ext/sources/ggml/src/ggml-openvino/openvino/op/l2_norm.cpp +44 -0
  387. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mul_mat_id.cpp +226 -0
  388. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mulmat.cpp +19 -9
  389. data/ext/sources/ggml/src/ggml-openvino/openvino/op/norm.cpp +58 -0
  390. data/ext/sources/ggml/src/ggml-openvino/openvino/op/pad.cpp +95 -0
  391. data/ext/sources/ggml/src/ggml-openvino/openvino/op/permute.cpp +58 -13
  392. data/ext/sources/ggml/src/ggml-openvino/openvino/op/repeat.cpp +74 -0
  393. data/ext/sources/ggml/src/ggml-openvino/openvino/op/reshape.cpp +13 -6
  394. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rms_norm.cpp +1 -1
  395. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rope.cpp +161 -39
  396. data/ext/sources/ggml/src/ggml-openvino/openvino/op/set_rows.cpp +3 -3
  397. data/ext/sources/ggml/src/ggml-openvino/openvino/op/softmax.cpp +126 -49
  398. data/ext/sources/ggml/src/ggml-openvino/openvino/op/ssm_conv.cpp +59 -0
  399. data/ext/sources/ggml/src/ggml-openvino/openvino/op/sum_rows.cpp +27 -0
  400. data/ext/sources/ggml/src/ggml-openvino/openvino/op/transpose.cpp +32 -1
  401. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_silu.cpp +1 -1
  402. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_softplus.cpp +38 -0
  403. data/ext/sources/ggml/src/ggml-openvino/openvino/op/view.cpp +90 -25
  404. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.cpp +41 -22
  405. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.h +18 -4
  406. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/mark_decompression_convert_constant_folding.h +1 -1
  407. data/ext/sources/ggml/src/ggml-openvino/openvino/rt_info/weightless_caching_attributes.hpp +41 -0
  408. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.cpp +70 -43
  409. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.h +5 -4
  410. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.cpp +612 -36
  411. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.h +29 -26
  412. data/ext/sources/ggml/src/ggml-openvino/utils.cpp +460 -114
  413. data/ext/sources/ggml/src/ggml-openvino/utils.h +32 -9
  414. data/ext/sources/ggml/src/ggml-opt.cpp +1 -0
  415. data/ext/sources/ggml/src/ggml-quants.c +365 -114
  416. data/ext/sources/ggml/src/ggml-quants.h +6 -0
  417. data/ext/sources/ggml/src/ggml-rpc/CMakeLists.txt +24 -0
  418. data/ext/sources/ggml/src/ggml-rpc/ggml-rpc.cpp +167 -311
  419. data/ext/sources/ggml/src/ggml-rpc/transport.cpp +683 -0
  420. data/ext/sources/ggml/src/ggml-rpc/transport.h +34 -0
  421. data/ext/sources/ggml/src/ggml-sycl/CMakeLists.txt +50 -4
  422. data/ext/sources/ggml/src/ggml-sycl/add-id.cpp +1 -1
  423. data/ext/sources/ggml/src/ggml-sycl/backend.hpp +5 -1
  424. data/ext/sources/ggml/src/ggml-sycl/binbcast.cpp +12 -0
  425. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.cpp +102 -0
  426. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.hpp +8 -0
  427. data/ext/sources/ggml/src/ggml-sycl/common.cpp +72 -2
  428. data/ext/sources/ggml/src/ggml-sycl/common.hpp +59 -2
  429. data/ext/sources/ggml/src/ggml-sycl/concat.cpp +21 -1
  430. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.cpp +158 -0
  431. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.hpp +10 -0
  432. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.cpp +125 -0
  433. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.hpp +10 -0
  434. data/ext/sources/ggml/src/ggml-sycl/conv2d.cpp +150 -0
  435. data/ext/sources/ggml/src/ggml-sycl/conv2d.hpp +10 -0
  436. data/ext/sources/ggml/src/ggml-sycl/conv3d.cpp +224 -0
  437. data/ext/sources/ggml/src/ggml-sycl/conv3d.hpp +8 -0
  438. data/ext/sources/ggml/src/ggml-sycl/convert.cpp +121 -13
  439. data/ext/sources/ggml/src/ggml-sycl/convert.hpp +9 -0
  440. data/ext/sources/ggml/src/ggml-sycl/cpy.cpp +706 -0
  441. data/ext/sources/ggml/src/ggml-sycl/cpy.hpp +281 -0
  442. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.cpp +255 -0
  443. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.hpp +7 -0
  444. data/ext/sources/ggml/src/ggml-sycl/cumsum.cpp +148 -0
  445. data/ext/sources/ggml/src/ggml-sycl/cumsum.hpp +5 -0
  446. data/ext/sources/ggml/src/ggml-sycl/dequantize.hpp +678 -0
  447. data/ext/sources/ggml/src/ggml-sycl/diag.cpp +67 -0
  448. data/ext/sources/ggml/src/ggml-sycl/diag.hpp +5 -0
  449. data/ext/sources/ggml/src/ggml-sycl/dmmv.cpp +997 -244
  450. data/ext/sources/ggml/src/ggml-sycl/dpct/helper.hpp +15 -7
  451. data/ext/sources/ggml/src/ggml-sycl/element_wise.cpp +215 -204
  452. data/ext/sources/ggml/src/ggml-sycl/element_wise.hpp +2 -2
  453. data/ext/sources/ggml/src/ggml-sycl/fattn-buffers.cpp +56 -0
  454. data/ext/sources/ggml/src/ggml-sycl/fattn-buffers.hpp +63 -0
  455. data/ext/sources/ggml/src/ggml-sycl/fattn-common.hpp +7 -5
  456. data/ext/sources/ggml/src/ggml-sycl/fattn-tile.cpp +4 -0
  457. data/ext/sources/ggml/src/ggml-sycl/fattn-tile.hpp +76 -168
  458. data/ext/sources/ggml/src/ggml-sycl/fattn-vec.hpp +7 -0
  459. data/ext/sources/ggml/src/ggml-sycl/fattn.cpp +3 -1
  460. data/ext/sources/ggml/src/ggml-sycl/fill.cpp +55 -0
  461. data/ext/sources/ggml/src/ggml-sycl/fill.hpp +5 -0
  462. data/ext/sources/ggml/src/ggml-sycl/gated_delta_net.cpp +69 -31
  463. data/ext/sources/ggml/src/ggml-sycl/gated_delta_net.hpp +1 -0
  464. data/ext/sources/ggml/src/ggml-sycl/gemm.hpp +3 -0
  465. data/ext/sources/ggml/src/ggml-sycl/getrows.cpp +79 -3
  466. data/ext/sources/ggml/src/ggml-sycl/ggml-sycl.cpp +1758 -455
  467. data/ext/sources/ggml/src/ggml-sycl/im2col.cpp +353 -89
  468. data/ext/sources/ggml/src/ggml-sycl/im2col.hpp +5 -3
  469. data/ext/sources/ggml/src/ggml-sycl/mmvq.cpp +1542 -39
  470. data/ext/sources/ggml/src/ggml-sycl/mmvq.hpp +33 -0
  471. data/ext/sources/ggml/src/ggml-sycl/norm.cpp +103 -49
  472. data/ext/sources/ggml/src/ggml-sycl/outprod.cpp +45 -9
  473. data/ext/sources/ggml/src/ggml-sycl/pad.cpp +27 -27
  474. data/ext/sources/ggml/src/ggml-sycl/pool.cpp +185 -0
  475. data/ext/sources/ggml/src/ggml-sycl/pool.hpp +22 -0
  476. data/ext/sources/ggml/src/ggml-sycl/presets.hpp +3 -1
  477. data/ext/sources/ggml/src/ggml-sycl/quants.hpp +71 -0
  478. data/ext/sources/ggml/src/ggml-sycl/set_rows.cpp +17 -3
  479. data/ext/sources/ggml/src/ggml-sycl/softmax.cpp +9 -10
  480. data/ext/sources/ggml/src/ggml-sycl/solve_tri.cpp +172 -0
  481. data/ext/sources/ggml/src/ggml-sycl/solve_tri.hpp +8 -0
  482. data/ext/sources/ggml/src/ggml-sycl/ssm_conv.cpp +6 -1
  483. data/ext/sources/ggml/src/ggml-sycl/ssm_scan.cpp +156 -0
  484. data/ext/sources/ggml/src/ggml-sycl/ssm_scan.hpp +5 -0
  485. data/ext/sources/ggml/src/ggml-sycl/sycl_hw.cpp +62 -10
  486. data/ext/sources/ggml/src/ggml-sycl/sycl_hw.hpp +18 -6
  487. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-tile-instance-dkq512-dv512.cpp +6 -0
  488. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-f16.cpp +1 -0
  489. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q4_0.cpp +1 -0
  490. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q4_1.cpp +1 -0
  491. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q5_0.cpp +1 -0
  492. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q5_1.cpp +1 -0
  493. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-f16-q8_0.cpp +1 -0
  494. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-f16.cpp +1 -0
  495. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q4_0.cpp +1 -0
  496. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q4_1.cpp +1 -0
  497. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q5_0.cpp +1 -0
  498. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q5_1.cpp +1 -0
  499. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_0-q8_0.cpp +1 -0
  500. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-f16.cpp +1 -0
  501. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q4_0.cpp +1 -0
  502. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q4_1.cpp +1 -0
  503. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q5_0.cpp +1 -0
  504. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q5_1.cpp +1 -0
  505. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q4_1-q8_0.cpp +1 -0
  506. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-f16.cpp +1 -0
  507. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q4_0.cpp +1 -0
  508. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q4_1.cpp +1 -0
  509. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q5_0.cpp +1 -0
  510. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q5_1.cpp +1 -0
  511. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_0-q8_0.cpp +1 -0
  512. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-f16.cpp +1 -0
  513. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q4_0.cpp +1 -0
  514. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q4_1.cpp +1 -0
  515. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q5_0.cpp +1 -0
  516. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q5_1.cpp +1 -0
  517. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q5_1-q8_0.cpp +1 -0
  518. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-f16.cpp +1 -0
  519. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q4_0.cpp +1 -0
  520. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q4_1.cpp +1 -0
  521. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q5_0.cpp +1 -0
  522. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q5_1.cpp +1 -0
  523. data/ext/sources/ggml/src/ggml-sycl/template-instances/fattn-vec-instance-q8_0-q8_0.cpp +1 -0
  524. data/ext/sources/ggml/src/ggml-sycl/type.hpp +112 -0
  525. data/ext/sources/ggml/src/ggml-sycl/upscale.cpp +410 -0
  526. data/ext/sources/ggml/src/ggml-sycl/upscale.hpp +9 -0
  527. data/ext/sources/ggml/src/ggml-sycl/vecdotq.hpp +242 -45
  528. data/ext/sources/ggml/src/ggml-virtgpu/ggml-backend-buffer.cpp +4 -0
  529. data/ext/sources/ggml/src/ggml-virtgpu/ggml-backend-device.cpp +2 -0
  530. data/ext/sources/ggml/src/ggml-virtgpu/ggml-backend.cpp +2 -0
  531. data/ext/sources/ggml/src/ggml-virtgpu/virtgpu-shm.cpp +1 -0
  532. data/ext/sources/ggml/src/ggml-virtgpu/virtgpu.cpp +1 -0
  533. data/ext/sources/ggml/src/ggml-virtgpu/virtgpu.h +0 -2
  534. data/ext/sources/ggml/src/ggml-vulkan/CMakeLists.txt +16 -0
  535. data/ext/sources/ggml/src/ggml-vulkan/ggml-vulkan.cpp +2843 -700
  536. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt +4 -0
  537. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp +61 -0
  538. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp +6 -2
  539. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +146 -13
  540. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp +431 -0
  541. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/copy.comp +3 -1
  542. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp +1 -1
  543. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp +25 -1
  544. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl +88 -0
  545. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl +643 -1
  546. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_nvfp4.comp +32 -0
  547. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q1_0.comp +29 -0
  548. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/diag.comp +3 -4
  549. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/dot_product_funcs.glsl +27 -0
  550. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/coopmat2_decode_vector.comp +7 -0
  551. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn.comp +198 -48
  552. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_base.glsl +60 -59
  553. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm1.comp +116 -113
  554. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm2.comp +122 -31
  555. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_dequant.glsl +131 -0
  556. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_mmq_funcs.glsl +203 -0
  557. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/fwht.comp +115 -0
  558. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gated_delta_net.comp +125 -64
  559. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/generic_binary_head.glsl +0 -1
  560. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.glsl +21 -19
  561. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/get_rows_back.comp +25 -0
  562. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_head.glsl +29 -1
  563. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_main.glsl +17 -11
  564. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/im2col.comp +76 -54
  565. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/im2col_3d.comp +0 -1
  566. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/l2_norm.comp +4 -7
  567. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/log.comp +0 -1
  568. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec.comp +122 -27
  569. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iface.glsl +6 -6
  570. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp +1 -1
  571. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q4_k.comp +1 -1
  572. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q5_k.comp +1 -1
  573. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq.comp +22 -24
  574. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq_funcs.glsl +88 -55
  575. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp +42 -40
  576. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_cm2.comp +49 -15
  577. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_funcs.glsl +222 -171
  578. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_funcs.glsl +8 -8
  579. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_shmem_types.glsl +24 -9
  580. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/multi_add.comp +0 -1
  581. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/norm.comp +10 -10
  582. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/repeat_back.comp +3 -3
  583. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/roll.comp +3 -3
  584. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rope_funcs.glsl +5 -2
  585. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rope_head.glsl +0 -1
  586. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rope_params.glsl +3 -2
  587. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/snake.comp +49 -0
  588. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/ssm_conv.comp +11 -1
  589. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tri.comp +3 -4
  590. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/types.glsl +79 -2
  591. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/unary.comp +168 -0
  592. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +282 -211
  593. data/ext/sources/ggml/src/ggml-webgpu/CMakeLists.txt +5 -2
  594. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp +2209 -283
  595. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu.cpp +2618 -1416
  596. data/ext/sources/ggml/src/ggml-webgpu/pre_wgsl.hpp +37 -7
  597. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/add_id.wgsl +64 -0
  598. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/binary.wgsl +8 -7
  599. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl +90 -95
  600. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/concat.wgsl +19 -1
  601. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/conv2d.wgsl +165 -0
  602. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/{cpy.tmpl.wgsl → cpy.wgsl} +25 -50
  603. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn.wgsl +107 -184
  604. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_quant_staging.tmpl +124 -0
  605. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_tile.wgsl +397 -0
  606. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_blk.wgsl +101 -0
  607. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_reduce.wgsl +84 -0
  608. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_split.wgsl +619 -0
  609. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/gated_delta_net.wgsl +149 -0
  610. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/get_rows.wgsl +204 -78
  611. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/glu.wgsl +155 -0
  612. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/im2col.wgsl +101 -0
  613. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_decls.tmpl +805 -526
  614. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id.wgsl +195 -0
  615. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_gather.wgsl +52 -0
  616. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_vec.wgsl +154 -0
  617. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_reg_tile.wgsl +8 -6
  618. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_subgroup_matrix.wgsl +5 -1
  619. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl +90 -413
  620. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_acc.tmpl +1553 -0
  621. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_q_acc.tmpl +297 -0
  622. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/quant_inner_loops.tmpl +21 -0
  623. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/quantize_q8.wgsl +178 -0
  624. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/rms_norm_mul.wgsl +152 -0
  625. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/{rope.tmpl.wgsl → rope.wgsl} +71 -142
  626. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/row_norm.wgsl +153 -0
  627. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/scale.wgsl +6 -4
  628. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/set.wgsl +109 -0
  629. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/set_rows.wgsl +2 -3
  630. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/set_rows_quant.wgsl +224 -0
  631. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/{soft_max.tmpl.wgsl → soft_max.wgsl} +106 -206
  632. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/solve_tri.wgsl +121 -0
  633. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/ssm_conv.wgsl +65 -0
  634. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/ssm_scan.wgsl +193 -0
  635. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/unary.wgsl +68 -48
  636. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/upscale.wgsl +240 -0
  637. data/ext/sources/ggml/src/ggml-zdnn/ggml-zdnn.cpp +18 -14
  638. data/ext/sources/ggml/src/ggml-zendnn/CMakeLists.txt +1 -1
  639. data/ext/sources/ggml/src/ggml-zendnn/ggml-zendnn.cpp +244 -10
  640. data/ext/sources/ggml/src/ggml.c +146 -42
  641. data/ext/sources/ggml/src/gguf.cpp +173 -28
  642. data/ext/sources/include/parakeet.h +342 -0
  643. data/ext/sources/include/whisper.h +31 -0
  644. data/ext/sources/media/matmul.png +0 -0
  645. data/ext/sources/src/CMakeLists.txt +23 -0
  646. data/ext/sources/src/parakeet-arch.h +188 -0
  647. data/ext/sources/src/parakeet.cpp +3838 -0
  648. data/ext/sources/src/whisper.cpp +220 -26
  649. data/extsources.rb +26 -10
  650. data/lib/whisper/log_settable.rb +33 -0
  651. data/lib/whisper/model/uri.rb +13 -8
  652. data/lib/whisper/output.rb +74 -0
  653. data/sig/whisper.rbs +417 -62
  654. data/test/helper.rb +2 -0
  655. data/test/jfk_reader/jfk_reader.c +50 -7
  656. data/test/test_callback.rb +1 -0
  657. data/test/test_package.rb +6 -5
  658. data/test/test_parakeet.rb +28 -0
  659. data/test/test_parakeet_callback.rb +107 -0
  660. data/test/test_parakeet_context.rb +116 -0
  661. data/test/test_parakeet_context_params.rb +24 -0
  662. data/test/test_parakeet_model.rb +21 -0
  663. data/test/test_parakeet_params.rb +78 -0
  664. data/test/test_parakeet_segment.rb +42 -0
  665. data/test/test_parakeet_token.rb +73 -0
  666. data/test/test_params.rb +2 -0
  667. data/test/test_vad.rb +9 -0
  668. data/test/test_vad_context.rb +2 -2
  669. data/test/test_vad_segment.rb +1 -1
  670. data/test/test_whisper.rb +24 -6
  671. data/whispercpp.gemspec +2 -2
  672. metadata +263 -304
  673. data/ext/sources/bindings/javascript/CMakeLists.txt +0 -41
  674. data/ext/sources/bindings/javascript/emscripten.cpp +0 -93
  675. data/ext/sources/bindings/javascript/libwhisper.worker.js +0 -1
  676. data/ext/sources/bindings/javascript/package.json +0 -26
  677. data/ext/sources/bindings/javascript/whisper.js +0 -19
  678. data/ext/sources/examples/addon.node/CMakeLists.txt +0 -31
  679. data/ext/sources/examples/addon.node/__test__/whisper.spec.js +0 -133
  680. data/ext/sources/examples/addon.node/addon.cpp +0 -557
  681. data/ext/sources/examples/addon.node/index.js +0 -59
  682. data/ext/sources/examples/addon.node/package.json +0 -16
  683. data/ext/sources/examples/addon.node/vad-example.js +0 -132
  684. data/ext/sources/examples/bench.wasm/CMakeLists.txt +0 -49
  685. data/ext/sources/examples/bench.wasm/emscripten.cpp +0 -87
  686. data/ext/sources/examples/bench.wasm/index-tmpl.html +0 -285
  687. data/ext/sources/examples/coi-serviceworker.js +0 -146
  688. data/ext/sources/examples/command/CMakeLists.txt +0 -10
  689. data/ext/sources/examples/command/command.cpp +0 -802
  690. data/ext/sources/examples/command/commands.txt +0 -9
  691. data/ext/sources/examples/command.wasm/CMakeLists.txt +0 -50
  692. data/ext/sources/examples/command.wasm/emscripten.cpp +0 -327
  693. data/ext/sources/examples/command.wasm/index-tmpl.html +0 -415
  694. data/ext/sources/examples/generate-karaoke.sh +0 -57
  695. data/ext/sources/examples/helpers.js +0 -191
  696. data/ext/sources/examples/livestream.sh +0 -112
  697. data/ext/sources/examples/lsp/CMakeLists.txt +0 -10
  698. data/ext/sources/examples/lsp/lsp.cpp +0 -471
  699. data/ext/sources/examples/lsp/whisper.vim +0 -362
  700. data/ext/sources/examples/python/test_whisper_processor.py +0 -7
  701. data/ext/sources/examples/python/whisper_processor.py +0 -54
  702. data/ext/sources/examples/server/bench.js +0 -29
  703. data/ext/sources/examples/server.py +0 -120
  704. data/ext/sources/examples/stream/CMakeLists.txt +0 -10
  705. data/ext/sources/examples/stream/stream.cpp +0 -437
  706. data/ext/sources/examples/stream.wasm/CMakeLists.txt +0 -49
  707. data/ext/sources/examples/stream.wasm/emscripten.cpp +0 -216
  708. data/ext/sources/examples/stream.wasm/index-tmpl.html +0 -491
  709. data/ext/sources/examples/sycl/CMakeLists.txt +0 -9
  710. data/ext/sources/examples/sycl/build.sh +0 -22
  711. data/ext/sources/examples/sycl/ls-sycl-device.cpp +0 -11
  712. data/ext/sources/examples/sycl/run-whisper.sh +0 -17
  713. data/ext/sources/examples/talk-llama/CMakeLists.txt +0 -48
  714. data/ext/sources/examples/talk-llama/eleven-labs.py +0 -80
  715. data/ext/sources/examples/talk-llama/llama-adapter.cpp +0 -488
  716. data/ext/sources/examples/talk-llama/llama-adapter.h +0 -89
  717. data/ext/sources/examples/talk-llama/llama-arch.cpp +0 -2877
  718. data/ext/sources/examples/talk-llama/llama-arch.h +0 -628
  719. data/ext/sources/examples/talk-llama/llama-batch.cpp +0 -919
  720. data/ext/sources/examples/talk-llama/llama-batch.h +0 -173
  721. data/ext/sources/examples/talk-llama/llama-chat.cpp +0 -896
  722. data/ext/sources/examples/talk-llama/llama-chat.h +0 -71
  723. data/ext/sources/examples/talk-llama/llama-context.cpp +0 -3633
  724. data/ext/sources/examples/talk-llama/llama-context.h +0 -359
  725. data/ext/sources/examples/talk-llama/llama-cparams.cpp +0 -5
  726. data/ext/sources/examples/talk-llama/llama-cparams.h +0 -47
  727. data/ext/sources/examples/talk-llama/llama-ext.h +0 -12
  728. data/ext/sources/examples/talk-llama/llama-grammar.cpp +0 -1464
  729. data/ext/sources/examples/talk-llama/llama-grammar.h +0 -194
  730. data/ext/sources/examples/talk-llama/llama-graph.cpp +0 -2735
  731. data/ext/sources/examples/talk-llama/llama-graph.h +0 -1031
  732. data/ext/sources/examples/talk-llama/llama-hparams.cpp +0 -258
  733. data/ext/sources/examples/talk-llama/llama-hparams.h +0 -353
  734. data/ext/sources/examples/talk-llama/llama-impl.cpp +0 -171
  735. data/ext/sources/examples/talk-llama/llama-impl.h +0 -75
  736. data/ext/sources/examples/talk-llama/llama-io.cpp +0 -15
  737. data/ext/sources/examples/talk-llama/llama-io.h +0 -35
  738. data/ext/sources/examples/talk-llama/llama-kv-cache-iswa.cpp +0 -330
  739. data/ext/sources/examples/talk-llama/llama-kv-cache-iswa.h +0 -137
  740. data/ext/sources/examples/talk-llama/llama-kv-cache.cpp +0 -2285
  741. data/ext/sources/examples/talk-llama/llama-kv-cache.h +0 -389
  742. data/ext/sources/examples/talk-llama/llama-kv-cells.h +0 -533
  743. data/ext/sources/examples/talk-llama/llama-memory-hybrid-iswa.cpp +0 -275
  744. data/ext/sources/examples/talk-llama/llama-memory-hybrid-iswa.h +0 -140
  745. data/ext/sources/examples/talk-llama/llama-memory-hybrid.cpp +0 -268
  746. data/ext/sources/examples/talk-llama/llama-memory-hybrid.h +0 -139
  747. data/ext/sources/examples/talk-llama/llama-memory-recurrent.cpp +0 -1165
  748. data/ext/sources/examples/talk-llama/llama-memory-recurrent.h +0 -182
  749. data/ext/sources/examples/talk-llama/llama-memory.cpp +0 -59
  750. data/ext/sources/examples/talk-llama/llama-memory.h +0 -122
  751. data/ext/sources/examples/talk-llama/llama-mmap.cpp +0 -752
  752. data/ext/sources/examples/talk-llama/llama-mmap.h +0 -73
  753. data/ext/sources/examples/talk-llama/llama-model-loader.cpp +0 -1655
  754. data/ext/sources/examples/talk-llama/llama-model-loader.h +0 -206
  755. data/ext/sources/examples/talk-llama/llama-model-saver.cpp +0 -299
  756. data/ext/sources/examples/talk-llama/llama-model-saver.h +0 -40
  757. data/ext/sources/examples/talk-llama/llama-model.cpp +0 -9056
  758. data/ext/sources/examples/talk-llama/llama-model.h +0 -597
  759. data/ext/sources/examples/talk-llama/llama-quant.cpp +0 -1304
  760. data/ext/sources/examples/talk-llama/llama-quant.h +0 -1
  761. data/ext/sources/examples/talk-llama/llama-sampler.cpp +0 -3885
  762. data/ext/sources/examples/talk-llama/llama-sampler.h +0 -42
  763. data/ext/sources/examples/talk-llama/llama-vocab.cpp +0 -3970
  764. data/ext/sources/examples/talk-llama/llama-vocab.h +0 -187
  765. data/ext/sources/examples/talk-llama/llama.cpp +0 -1194
  766. data/ext/sources/examples/talk-llama/llama.h +0 -1573
  767. data/ext/sources/examples/talk-llama/models/afmoe.cpp +0 -190
  768. data/ext/sources/examples/talk-llama/models/apertus.cpp +0 -125
  769. data/ext/sources/examples/talk-llama/models/arcee.cpp +0 -135
  770. data/ext/sources/examples/talk-llama/models/arctic.cpp +0 -137
  771. data/ext/sources/examples/talk-llama/models/arwkv7.cpp +0 -86
  772. data/ext/sources/examples/talk-llama/models/baichuan.cpp +0 -123
  773. data/ext/sources/examples/talk-llama/models/bailingmoe.cpp +0 -143
  774. data/ext/sources/examples/talk-llama/models/bailingmoe2.cpp +0 -133
  775. data/ext/sources/examples/talk-llama/models/bert.cpp +0 -184
  776. data/ext/sources/examples/talk-llama/models/bitnet.cpp +0 -145
  777. data/ext/sources/examples/talk-llama/models/bloom.cpp +0 -101
  778. data/ext/sources/examples/talk-llama/models/chameleon.cpp +0 -178
  779. data/ext/sources/examples/talk-llama/models/chatglm.cpp +0 -132
  780. data/ext/sources/examples/talk-llama/models/codeshell.cpp +0 -111
  781. data/ext/sources/examples/talk-llama/models/cogvlm.cpp +0 -102
  782. data/ext/sources/examples/talk-llama/models/cohere2-iswa.cpp +0 -134
  783. data/ext/sources/examples/talk-llama/models/command-r.cpp +0 -122
  784. data/ext/sources/examples/talk-llama/models/dbrx.cpp +0 -122
  785. data/ext/sources/examples/talk-llama/models/deci.cpp +0 -135
  786. data/ext/sources/examples/talk-llama/models/deepseek.cpp +0 -142
  787. data/ext/sources/examples/talk-llama/models/deepseek2.cpp +0 -262
  788. data/ext/sources/examples/talk-llama/models/delta-net-base.cpp +0 -445
  789. data/ext/sources/examples/talk-llama/models/dots1.cpp +0 -132
  790. data/ext/sources/examples/talk-llama/models/dream.cpp +0 -105
  791. data/ext/sources/examples/talk-llama/models/ernie4-5-moe.cpp +0 -148
  792. data/ext/sources/examples/talk-llama/models/ernie4-5.cpp +0 -110
  793. data/ext/sources/examples/talk-llama/models/eurobert.cpp +0 -97
  794. data/ext/sources/examples/talk-llama/models/exaone-moe.cpp +0 -145
  795. data/ext/sources/examples/talk-llama/models/exaone.cpp +0 -114
  796. data/ext/sources/examples/talk-llama/models/exaone4.cpp +0 -123
  797. data/ext/sources/examples/talk-llama/models/falcon-h1.cpp +0 -111
  798. data/ext/sources/examples/talk-llama/models/falcon.cpp +0 -120
  799. data/ext/sources/examples/talk-llama/models/gemma-embedding.cpp +0 -116
  800. data/ext/sources/examples/talk-llama/models/gemma.cpp +0 -112
  801. data/ext/sources/examples/talk-llama/models/gemma2-iswa.cpp +0 -128
  802. data/ext/sources/examples/talk-llama/models/gemma3.cpp +0 -155
  803. data/ext/sources/examples/talk-llama/models/gemma3n-iswa.cpp +0 -384
  804. data/ext/sources/examples/talk-llama/models/glm4-moe.cpp +0 -170
  805. data/ext/sources/examples/talk-llama/models/glm4.cpp +0 -157
  806. data/ext/sources/examples/talk-llama/models/gpt2.cpp +0 -105
  807. data/ext/sources/examples/talk-llama/models/gptneox.cpp +0 -144
  808. data/ext/sources/examples/talk-llama/models/granite-hybrid.cpp +0 -195
  809. data/ext/sources/examples/talk-llama/models/granite.cpp +0 -210
  810. data/ext/sources/examples/talk-llama/models/grok.cpp +0 -159
  811. data/ext/sources/examples/talk-llama/models/grovemoe.cpp +0 -139
  812. data/ext/sources/examples/talk-llama/models/hunyuan-dense.cpp +0 -132
  813. data/ext/sources/examples/talk-llama/models/hunyuan-moe.cpp +0 -153
  814. data/ext/sources/examples/talk-llama/models/internlm2.cpp +0 -120
  815. data/ext/sources/examples/talk-llama/models/jais.cpp +0 -86
  816. data/ext/sources/examples/talk-llama/models/jais2.cpp +0 -123
  817. data/ext/sources/examples/talk-llama/models/jamba.cpp +0 -106
  818. data/ext/sources/examples/talk-llama/models/kimi-linear.cpp +0 -381
  819. data/ext/sources/examples/talk-llama/models/lfm2.cpp +0 -196
  820. data/ext/sources/examples/talk-llama/models/llada-moe.cpp +0 -122
  821. data/ext/sources/examples/talk-llama/models/llada.cpp +0 -99
  822. data/ext/sources/examples/talk-llama/models/llama-iswa.cpp +0 -178
  823. data/ext/sources/examples/talk-llama/models/llama.cpp +0 -175
  824. data/ext/sources/examples/talk-llama/models/maincoder.cpp +0 -117
  825. data/ext/sources/examples/talk-llama/models/mamba-base.cpp +0 -289
  826. data/ext/sources/examples/talk-llama/models/mamba.cpp +0 -54
  827. data/ext/sources/examples/talk-llama/models/mimo2-iswa.cpp +0 -129
  828. data/ext/sources/examples/talk-llama/models/minicpm3.cpp +0 -200
  829. data/ext/sources/examples/talk-llama/models/minimax-m2.cpp +0 -123
  830. data/ext/sources/examples/talk-llama/models/mistral3.cpp +0 -160
  831. data/ext/sources/examples/talk-llama/models/models.h +0 -704
  832. data/ext/sources/examples/talk-llama/models/modern-bert.cpp +0 -109
  833. data/ext/sources/examples/talk-llama/models/mpt.cpp +0 -126
  834. data/ext/sources/examples/talk-llama/models/nemotron-h.cpp +0 -162
  835. data/ext/sources/examples/talk-llama/models/nemotron.cpp +0 -122
  836. data/ext/sources/examples/talk-llama/models/neo-bert.cpp +0 -104
  837. data/ext/sources/examples/talk-llama/models/olmo.cpp +0 -121
  838. data/ext/sources/examples/talk-llama/models/olmo2.cpp +0 -150
  839. data/ext/sources/examples/talk-llama/models/olmoe.cpp +0 -124
  840. data/ext/sources/examples/talk-llama/models/openai-moe-iswa.cpp +0 -127
  841. data/ext/sources/examples/talk-llama/models/openelm.cpp +0 -124
  842. data/ext/sources/examples/talk-llama/models/orion.cpp +0 -123
  843. data/ext/sources/examples/talk-llama/models/paddleocr.cpp +0 -122
  844. data/ext/sources/examples/talk-llama/models/pangu-embedded.cpp +0 -121
  845. data/ext/sources/examples/talk-llama/models/phi2.cpp +0 -121
  846. data/ext/sources/examples/talk-llama/models/phi3.cpp +0 -152
  847. data/ext/sources/examples/talk-llama/models/plamo.cpp +0 -110
  848. data/ext/sources/examples/talk-llama/models/plamo2.cpp +0 -320
  849. data/ext/sources/examples/talk-llama/models/plamo3.cpp +0 -128
  850. data/ext/sources/examples/talk-llama/models/plm.cpp +0 -169
  851. data/ext/sources/examples/talk-llama/models/qwen.cpp +0 -108
  852. data/ext/sources/examples/talk-llama/models/qwen2.cpp +0 -126
  853. data/ext/sources/examples/talk-llama/models/qwen2moe.cpp +0 -151
  854. data/ext/sources/examples/talk-llama/models/qwen2vl.cpp +0 -117
  855. data/ext/sources/examples/talk-llama/models/qwen3.cpp +0 -120
  856. data/ext/sources/examples/talk-llama/models/qwen35.cpp +0 -381
  857. data/ext/sources/examples/talk-llama/models/qwen35moe.cpp +0 -422
  858. data/ext/sources/examples/talk-llama/models/qwen3moe.cpp +0 -131
  859. data/ext/sources/examples/talk-llama/models/qwen3next.cpp +0 -525
  860. data/ext/sources/examples/talk-llama/models/qwen3vl-moe.cpp +0 -140
  861. data/ext/sources/examples/talk-llama/models/qwen3vl.cpp +0 -132
  862. data/ext/sources/examples/talk-llama/models/refact.cpp +0 -94
  863. data/ext/sources/examples/talk-llama/models/rnd1.cpp +0 -126
  864. data/ext/sources/examples/talk-llama/models/rwkv6-base.cpp +0 -164
  865. data/ext/sources/examples/talk-llama/models/rwkv6.cpp +0 -94
  866. data/ext/sources/examples/talk-llama/models/rwkv6qwen2.cpp +0 -86
  867. data/ext/sources/examples/talk-llama/models/rwkv7-base.cpp +0 -137
  868. data/ext/sources/examples/talk-llama/models/rwkv7.cpp +0 -90
  869. data/ext/sources/examples/talk-llama/models/seed-oss.cpp +0 -124
  870. data/ext/sources/examples/talk-llama/models/smallthinker.cpp +0 -126
  871. data/ext/sources/examples/talk-llama/models/smollm3.cpp +0 -128
  872. data/ext/sources/examples/talk-llama/models/stablelm.cpp +0 -146
  873. data/ext/sources/examples/talk-llama/models/starcoder.cpp +0 -100
  874. data/ext/sources/examples/talk-llama/models/starcoder2.cpp +0 -121
  875. data/ext/sources/examples/talk-llama/models/step35-iswa.cpp +0 -165
  876. data/ext/sources/examples/talk-llama/models/t5-dec.cpp +0 -166
  877. data/ext/sources/examples/talk-llama/models/t5-enc.cpp +0 -96
  878. data/ext/sources/examples/talk-llama/models/wavtokenizer-dec.cpp +0 -149
  879. data/ext/sources/examples/talk-llama/models/xverse.cpp +0 -108
  880. data/ext/sources/examples/talk-llama/prompts/talk-alpaca.txt +0 -23
  881. data/ext/sources/examples/talk-llama/speak +0 -40
  882. data/ext/sources/examples/talk-llama/speak.bat +0 -1
  883. data/ext/sources/examples/talk-llama/speak.ps1 +0 -14
  884. data/ext/sources/examples/talk-llama/talk-llama.cpp +0 -813
  885. data/ext/sources/examples/talk-llama/unicode-data.cpp +0 -7034
  886. data/ext/sources/examples/talk-llama/unicode-data.h +0 -20
  887. data/ext/sources/examples/talk-llama/unicode.cpp +0 -1103
  888. data/ext/sources/examples/talk-llama/unicode.h +0 -111
  889. data/ext/sources/examples/wchess/CMakeLists.txt +0 -10
  890. data/ext/sources/examples/wchess/libwchess/CMakeLists.txt +0 -19
  891. data/ext/sources/examples/wchess/libwchess/Chessboard.cpp +0 -803
  892. data/ext/sources/examples/wchess/libwchess/Chessboard.h +0 -33
  893. data/ext/sources/examples/wchess/libwchess/WChess.cpp +0 -193
  894. data/ext/sources/examples/wchess/libwchess/WChess.h +0 -63
  895. data/ext/sources/examples/wchess/libwchess/test-chessboard.cpp +0 -117
  896. data/ext/sources/examples/wchess/wchess.cmd/CMakeLists.txt +0 -8
  897. data/ext/sources/examples/wchess/wchess.cmd/wchess.cmd.cpp +0 -253
  898. data/ext/sources/examples/whisper.wasm/CMakeLists.txt +0 -50
  899. data/ext/sources/examples/whisper.wasm/emscripten.cpp +0 -118
  900. data/ext/sources/examples/whisper.wasm/index-tmpl.html +0 -659
  901. data/ext/sources/ggml/src/ggml-cuda/template-instances/generate_cu_files.py +0 -99
  902. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-msg.h +0 -155
  903. data/ext/sources/ggml/src/ggml-hexagon/op-desc.h +0 -153
  904. data/ext/sources/ggml/src/ggml-opencl/kernels/embed_kernel.py +0 -26
  905. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/eliminate_zp.cpp +0 -123
  906. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/eliminate_zp.h +0 -17
  907. data/ext/sources/ggml/src/ggml-virtgpu/regenerate_remoting.py +0 -333
  908. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/abs.comp +0 -21
  909. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/ceil.comp +0 -22
  910. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/clamp.comp +0 -17
  911. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/cos.comp +0 -17
  912. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/elu.comp +0 -27
  913. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/exp.comp +0 -21
  914. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/floor.comp +0 -22
  915. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu.comp +0 -25
  916. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_erf.comp +0 -39
  917. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_quick.comp +0 -23
  918. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardsigmoid.comp +0 -22
  919. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardswish.comp +0 -22
  920. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/leaky_relu.comp +0 -22
  921. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/neg.comp +0 -20
  922. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/relu.comp +0 -21
  923. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/round.comp +0 -29
  924. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/rte.glsl +0 -5
  925. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sgn.comp +0 -21
  926. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sigmoid.comp +0 -20
  927. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/silu.comp +0 -22
  928. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sin.comp +0 -17
  929. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/softplus.comp +0 -23
  930. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sqrt.comp +0 -17
  931. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/square.comp +0 -17
  932. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/step.comp +0 -22
  933. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tanh.comp +0 -20
  934. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/trunc.comp +0 -22
  935. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/xielu.comp +0 -35
  936. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/embed_wgsl.py +0 -182
  937. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/glu.tmpl.wgsl +0 -323
  938. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat.wgsl +0 -718
  939. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/rms_norm.wgsl +0 -123
  940. data/ext/sources/tests/CMakeLists.txt +0 -112
  941. data/ext/sources/tests/earnings21/eval.mk +0 -58
  942. data/ext/sources/tests/earnings21/eval.py +0 -68
  943. data/ext/sources/tests/earnings21/normalizers/__init__.py +0 -2
  944. data/ext/sources/tests/earnings21/normalizers/basic.py +0 -80
  945. data/ext/sources/tests/earnings21/normalizers/english.json +0 -1741
  946. data/ext/sources/tests/earnings21/normalizers/english.py +0 -550
  947. data/ext/sources/tests/earnings21/requirements.txt +0 -6
  948. data/ext/sources/tests/en-0-ref.txt +0 -1
  949. data/ext/sources/tests/en-1-ref.txt +0 -1
  950. data/ext/sources/tests/en-2-ref.txt +0 -1
  951. data/ext/sources/tests/es-0-ref.txt +0 -1
  952. data/ext/sources/tests/librispeech/eval.mk +0 -39
  953. data/ext/sources/tests/librispeech/eval.py +0 -47
  954. data/ext/sources/tests/librispeech/normalizers/__init__.py +0 -2
  955. data/ext/sources/tests/librispeech/normalizers/basic.py +0 -80
  956. data/ext/sources/tests/librispeech/normalizers/english.json +0 -1741
  957. data/ext/sources/tests/librispeech/normalizers/english.py +0 -550
  958. data/ext/sources/tests/librispeech/requirements.txt +0 -6
  959. data/ext/sources/tests/run-tests.sh +0 -130
  960. data/ext/sources/tests/test-c.c +0 -3
  961. data/ext/sources/tests/test-vad-full.cpp +0 -56
  962. data/ext/sources/tests/test-vad.cpp +0 -83
  963. data/ext/sources/tests/test-whisper.js +0 -58
  964. data/lib/whisper/context.rb +0 -15
  965. data/lib/whisper/segment.rb +0 -58
@@ -1,6 +1,7 @@
1
1
  #ifndef GGML_WEBGPU_SHADER_LIB_HPP
2
2
  #define GGML_WEBGPU_SHADER_LIB_HPP
3
3
 
4
+ #include "ggml-impl.h"
4
5
  #include "ggml-wgsl-shaders.hpp"
5
6
  #include "ggml.h"
6
7
  #include "pre_wgsl.hpp"
@@ -17,6 +18,9 @@
17
18
  #define GGML_WEBGPU_F32_SIZE_BYTES 4
18
19
  #define GGML_WEBGPU_I32_SIZE_BYTES 4
19
20
  #define GGML_WEBGPU_FLASH_ATTN_PREFERRED_KV_SG_TILES 8u
21
+ #define GGML_WEBGPU_FLASH_ATTN_VEC_MAX_SEQ_LEN 20u
22
+ #define GGML_WEBGPU_FLASH_ATTN_VEC_MAX_KV_TILE 32u
23
+ #define GGML_WEBGPU_FLASH_ATTN_TILE_MAX_KV_TILE 64u
20
24
  #define GGML_WEBGPU_FLASH_ATTN_PREFERRED_WG_SIZE 128u
21
25
  // Matches GGML_PAD(..., 256) in src/llama-context.cpp for KV cache sizing.
22
26
  #define GGML_WEBGPU_KV_SEQ_PAD 256u
@@ -26,38 +30,32 @@
26
30
  // Matrix multiplication parameters
27
31
 
28
32
  // Register tiling parameters
29
- #define WEBGPU_MUL_MAT_TILE_M 8
30
- #define WEBGPU_MUL_MAT_TILE_N 8
31
- #define WEBGPU_MUL_MAT_WG_SIZE_M 8
32
- #define WEBGPU_MUL_MAT_WG_SIZE_N 8
33
- #define WEBGPU_MUL_MAT_TILE_K 32
33
+ #define WEBGPU_MUL_MAT_TILE_M 4
34
+ #define WEBGPU_MUL_MAT_TILE_N 4
35
+ #define WEBGPU_MUL_MAT_WG_SIZE_M 8
36
+ #define WEBGPU_MUL_MAT_WG_SIZE_N 8
37
+ #define WEBGPU_MUL_MAT_REG_TILE_K_FLOAT 8
38
+ #define WEBGPU_MUL_MAT_REG_TILE_K_QUANT 32
34
39
 
35
40
  // Subgroup matrix parameters
36
41
  // The number of subgroups in the M dimension
37
- #define WEBGPU_MUL_MAT_SUBGROUP_M 2
42
+ #define WEBGPU_MUL_MAT_SUBGROUP_M 2
38
43
  // The number of subgroups in the N dimension
39
- #define WEBGPU_MUL_MAT_SUBGROUP_N 2
44
+ #define WEBGPU_MUL_MAT_SUBGROUP_N 4
40
45
  // The number of subgroup matrices each subgroup accumulates over
41
- #define WEBGPU_MUL_MAT_SUBGROUP_MATRIX_M 4
42
- #define WEBGPU_MUL_MAT_SUBGROUP_MATRIX_N 2
46
+ #define WEBGPU_MUL_MAT_SUBGROUP_MATRIX_M 4
47
+ #define WEBGPU_MUL_MAT_SUBGROUP_MATRIX_N 2
48
+ #define WEBGPU_MUL_MAT_SUBGROUP_TILE_K_FLOAT 32
49
+ #define WEBGPU_MUL_MAT_SUBGROUP_TILE_K_QUANT 32
43
50
 
44
51
  // Matrix-vector multiplication parameters
45
52
  #define WEBGPU_MUL_MAT_VEC_WG_SIZE 256
46
53
 
47
- // Must be multiple of 4 to work with vectorized paths, and must divide
48
- // mul_mat_vec wg size
49
- #define WEBGPU_MUL_MAT_VEC_FLOAT_OUTPUTS_PER_WG 64
50
- #define WEBGPU_MUL_MAT_VEC_FLOAT_TILE_K 256
54
+ #define WEBGPU_MUL_MAT_VEC_FLOAT_OUTPUTS_PER_WG 4
55
+ #define WEBGPU_MUL_MAT_VEC_LEGACY_Q_OUTPUTS_PER_WG 4
56
+ #define WEBGPU_MUL_MAT_VEC_K_Q_OUTPUTS_PER_WG 4
51
57
 
52
- #define WEBGPU_MUL_MAT_VEC_LEGACY_Q_OUTPUTS_PER_WG 64
53
- #define WEBGPU_MUL_MAT_VEC_LEGACY_Q_TILE_K 256
54
-
55
- // Requires 32 threads per output (wg_size/outputs_per_wg == 32)
56
- #define WEBGPU_MUL_MAT_VEC_K_Q_OUTPUTS_PER_WG 8
57
- // Requires at least two (and multiple of 2) k-quant blocks per tile
58
- #define WEBGPU_MUL_MAT_VEC_K_Q_TILE_K 512
59
-
60
- // default size for legacy matrix multiplication
58
+ // default size for reg-tile matrix multiplication
61
59
  #define WEBGPU_MUL_MAT_WG_SIZE 256
62
60
 
63
61
  // Same hash combine function as in boost
@@ -65,24 +63,41 @@ template <typename T> inline void ggml_webgpu_hash_combine(size_t & seed, const
65
63
  seed ^= std::hash<T>{}(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
66
64
  }
67
65
 
66
+ // Calculates base address of a tensor ignoring the fake base pointer
67
+ inline uintptr_t ggml_webgpu_tensor_addr(const ggml_tensor * tensor) {
68
+ const ggml_tensor * base_tensor = tensor->view_src ? tensor->view_src : tensor;
69
+ return (uintptr_t) base_tensor->data + tensor->view_offs;
70
+ }
71
+
72
+ inline bool ggml_webgpu_tensor_equal(const ggml_tensor * a, const ggml_tensor * b) {
73
+ return a->buffer == b->buffer && ggml_webgpu_tensor_addr(a) == ggml_webgpu_tensor_addr(b);
74
+ }
75
+
76
+ inline bool ggml_webgpu_tensor_overlap(const ggml_tensor * a, const ggml_tensor * b) {
77
+ return a->buffer == b->buffer && ggml_webgpu_tensor_addr(a) < ggml_webgpu_tensor_addr(b) + ggml_nbytes(b) &&
78
+ ggml_webgpu_tensor_addr(b) < ggml_webgpu_tensor_addr(a) + ggml_nbytes(a);
79
+ }
80
+
68
81
  struct ggml_webgpu_shader_lib_context {
69
82
  ggml_tensor * src0;
70
83
  ggml_tensor * src1;
71
84
  ggml_tensor * src2;
72
85
  ggml_tensor * src3;
73
86
  ggml_tensor * src4;
87
+ ggml_tensor * src5;
74
88
  ggml_tensor * dst;
75
89
 
76
- uint32_t max_wg_size;
77
- size_t wg_mem_limit_bytes = 0;
78
- bool inplace = false;
79
- bool overlap = false;
80
- bool src_overlap = false;
81
- bool supports_subgroup_matrix = false;
82
- uint32_t sg_mat_m = 0;
83
- uint32_t sg_mat_n = 0;
84
- uint32_t sg_mat_k = 0;
85
- uint32_t max_subgroup_size = 0;
90
+ uint32_t max_wg_size;
91
+ size_t wg_mem_limit_bytes = 0;
92
+ bool supports_subgroups = false;
93
+ bool supports_subgroup_matrix = false;
94
+ uint32_t sg_mat_m = 0;
95
+ uint32_t sg_mat_n = 0;
96
+ uint32_t sg_mat_k = 0;
97
+ uint32_t min_subgroup_size = 0;
98
+ uint32_t max_subgroup_size = 0;
99
+ bool supports_dot_product = false;
100
+ std::string vendor;
86
101
  };
87
102
 
88
103
  struct webgpu_pipeline {
@@ -93,6 +108,51 @@ struct webgpu_pipeline {
93
108
 
94
109
  struct ggml_webgpu_generic_shader_decisions {
95
110
  uint32_t wg_size = 0;
111
+ bool inplace = false;
112
+ };
113
+
114
+ struct ggml_webgpu_binary_shader_decisions {
115
+ uint32_t wg_size = 0;
116
+ bool inplace = false;
117
+ bool overlap = false;
118
+ bool src_overlap = false;
119
+ };
120
+
121
+ struct ggml_webgpu_processed_shader {
122
+ std::string wgsl;
123
+ std::string variant;
124
+ std::shared_ptr<void> decisions;
125
+ };
126
+
127
+ struct ggml_webgpu_ssm_conv_shader_decisions {
128
+ uint32_t block_size;
129
+ uint32_t tokens_per_wg;
130
+ };
131
+
132
+ struct ggml_webgpu_ssm_scan_pipeline_key {
133
+ int type;
134
+ int d_state;
135
+ bool xbc_overlap;
136
+
137
+ bool operator==(const ggml_webgpu_ssm_scan_pipeline_key & other) const {
138
+ return type == other.type && d_state == other.d_state && xbc_overlap == other.xbc_overlap;
139
+ }
140
+ };
141
+
142
+ struct ggml_webgpu_ssm_scan_pipeline_key_hash {
143
+ size_t operator()(const ggml_webgpu_ssm_scan_pipeline_key & key) const {
144
+ size_t seed = 0;
145
+ ggml_webgpu_hash_combine(seed, key.type);
146
+ ggml_webgpu_hash_combine(seed, key.d_state);
147
+ ggml_webgpu_hash_combine(seed, key.xbc_overlap);
148
+ return seed;
149
+ }
150
+ };
151
+
152
+ struct ggml_webgpu_ssm_scan_shader_decisions {
153
+ uint32_t wg_size;
154
+ uint32_t tokens_per_tile;
155
+ bool xbc_overlap = false;
96
156
  };
97
157
 
98
158
  /** Argsort **/
@@ -109,9 +169,11 @@ struct ggml_webgpu_set_rows_pipeline_key {
109
169
  int dst_type;
110
170
  int vec4;
111
171
  int i64_idx;
172
+ int pair_blocks;
112
173
 
113
174
  bool operator==(const ggml_webgpu_set_rows_pipeline_key & other) const {
114
- return dst_type == other.dst_type && vec4 == other.vec4 && i64_idx == other.i64_idx;
175
+ return dst_type == other.dst_type && vec4 == other.vec4 && i64_idx == other.i64_idx &&
176
+ pair_blocks == other.pair_blocks;
115
177
  }
116
178
  };
117
179
 
@@ -121,6 +183,7 @@ struct ggml_webgpu_set_rows_pipeline_key_hash {
121
183
  ggml_webgpu_hash_combine(seed, key.dst_type);
122
184
  ggml_webgpu_hash_combine(seed, key.vec4);
123
185
  ggml_webgpu_hash_combine(seed, key.i64_idx);
186
+ ggml_webgpu_hash_combine(seed, key.pair_blocks);
124
187
  return seed;
125
188
  }
126
189
  };
@@ -128,9 +191,30 @@ struct ggml_webgpu_set_rows_pipeline_key_hash {
128
191
  struct ggml_webgpu_set_rows_shader_decisions {
129
192
  bool vec4;
130
193
  bool i64_idx;
194
+ bool pair_blocks;
131
195
  uint32_t wg_size;
132
196
  };
133
197
 
198
+ /** Set **/
199
+
200
+ struct ggml_webgpu_set_pipeline_key {
201
+ ggml_type type;
202
+ bool inplace;
203
+
204
+ bool operator==(const ggml_webgpu_set_pipeline_key & other) const {
205
+ return type == other.type && inplace == other.inplace;
206
+ }
207
+ };
208
+
209
+ struct ggml_webgpu_set_pipeline_key_hash {
210
+ size_t operator()(const ggml_webgpu_set_pipeline_key & key) const {
211
+ size_t seed = 0;
212
+ ggml_webgpu_hash_combine(seed, key.type);
213
+ ggml_webgpu_hash_combine(seed, key.inplace);
214
+ return seed;
215
+ }
216
+ };
217
+
134
218
  /** Get Rows **/
135
219
 
136
220
  struct ggml_webgpu_get_rows_pipeline_key {
@@ -151,6 +235,59 @@ struct ggml_webgpu_get_rows_pipeline_key_hash {
151
235
  }
152
236
  };
153
237
 
238
+ /** Row Norm **/
239
+
240
+ struct ggml_webgpu_row_norm_pipeline_key {
241
+ ggml_op op;
242
+ ggml_type src_type;
243
+ ggml_type dst_type;
244
+ bool inplace;
245
+
246
+ bool operator==(const ggml_webgpu_row_norm_pipeline_key & other) const {
247
+ return op == other.op && src_type == other.src_type && dst_type == other.dst_type && inplace == other.inplace;
248
+ }
249
+ };
250
+
251
+ struct ggml_webgpu_row_norm_pipeline_key_hash {
252
+ size_t operator()(const ggml_webgpu_row_norm_pipeline_key & key) const {
253
+ size_t seed = 0;
254
+ ggml_webgpu_hash_combine(seed, key.op);
255
+ ggml_webgpu_hash_combine(seed, key.src_type);
256
+ ggml_webgpu_hash_combine(seed, key.dst_type);
257
+ ggml_webgpu_hash_combine(seed, key.inplace);
258
+ return seed;
259
+ }
260
+ };
261
+
262
+ /** RMS_NORM + MUL **/
263
+
264
+ struct ggml_webgpu_rms_norm_mul_pipeline_key {
265
+ bool inplace; // rn_src == dst
266
+ bool overlap; // mul_src == dst
267
+ bool src_overlap; // rn_src == mul_src
268
+
269
+ bool operator==(const ggml_webgpu_rms_norm_mul_pipeline_key & other) const {
270
+ return inplace == other.inplace && overlap == other.overlap && src_overlap == other.src_overlap;
271
+ }
272
+ };
273
+
274
+ struct ggml_webgpu_rms_norm_mul_pipeline_key_hash {
275
+ size_t operator()(const ggml_webgpu_rms_norm_mul_pipeline_key & key) const {
276
+ size_t seed = 0;
277
+ ggml_webgpu_hash_combine(seed, key.inplace);
278
+ ggml_webgpu_hash_combine(seed, key.overlap);
279
+ ggml_webgpu_hash_combine(seed, key.src_overlap);
280
+ return seed;
281
+ }
282
+ };
283
+
284
+ struct ggml_webgpu_rms_norm_mul_shader_decisions {
285
+ uint32_t wg_size = 0;
286
+ bool inplace = false;
287
+ bool overlap = false;
288
+ bool src_overlap = false;
289
+ };
290
+
154
291
  /** Pad **/
155
292
  struct ggml_webgpu_pad_pipeline_key {
156
293
  bool circular;
@@ -166,6 +303,107 @@ struct ggml_webgpu_pad_pipeline_key_hash {
166
303
  }
167
304
  };
168
305
 
306
+ /** Solve Tri **/
307
+ struct ggml_webgpu_solve_tri_pipeline_key {
308
+ int type;
309
+ int n;
310
+ int k;
311
+
312
+ bool operator==(const ggml_webgpu_solve_tri_pipeline_key & other) const {
313
+ return type == other.type && n == other.n && k == other.k;
314
+ }
315
+ };
316
+
317
+ struct ggml_webgpu_solve_tri_pipeline_key_hash {
318
+ size_t operator()(const ggml_webgpu_solve_tri_pipeline_key & key) const {
319
+ size_t seed = 0;
320
+ ggml_webgpu_hash_combine(seed, key.type);
321
+ ggml_webgpu_hash_combine(seed, key.n);
322
+ ggml_webgpu_hash_combine(seed, key.k);
323
+ return seed;
324
+ }
325
+ };
326
+
327
+ /** SSM Conv **/
328
+ struct ggml_webgpu_ssm_conv_pipeline_key {
329
+ int type;
330
+ int vectorized;
331
+
332
+ bool operator==(const ggml_webgpu_ssm_conv_pipeline_key & other) const {
333
+ return type == other.type && vectorized == other.vectorized;
334
+ }
335
+ };
336
+
337
+ /** CONV 2D */
338
+ struct ggml_webgpu_conv2d_pipeline_key {
339
+ ggml_type weight_type;
340
+ ggml_type input_type;
341
+ ggml_type output_type;
342
+
343
+ bool operator==(const ggml_webgpu_conv2d_pipeline_key & other) const {
344
+ return weight_type == other.weight_type && input_type == other.input_type && output_type == other.output_type;
345
+ }
346
+ };
347
+
348
+ struct ggml_webgpu_conv2d_pipeline_key_hash {
349
+ size_t operator()(const ggml_webgpu_conv2d_pipeline_key & key) const {
350
+ size_t seed = 0;
351
+ ggml_webgpu_hash_combine(seed, key.weight_type);
352
+ ggml_webgpu_hash_combine(seed, key.input_type);
353
+ ggml_webgpu_hash_combine(seed, key.output_type);
354
+ return seed;
355
+ }
356
+ };
357
+
358
+ /** Im2Col **/
359
+ struct ggml_webgpu_im2col_pipeline_key {
360
+ ggml_type input_type;
361
+ ggml_type output_type;
362
+
363
+ bool operator==(const ggml_webgpu_im2col_pipeline_key & other) const {
364
+ return input_type == other.input_type && output_type == other.output_type;
365
+ }
366
+ };
367
+
368
+ struct ggml_webgpu_im2col_pipeline_key_hash {
369
+ size_t operator()(const ggml_webgpu_im2col_pipeline_key & key) const {
370
+ size_t seed = 0;
371
+ ggml_webgpu_hash_combine(seed, key.input_type);
372
+ ggml_webgpu_hash_combine(seed, key.output_type);
373
+ return seed;
374
+ }
375
+ };
376
+
377
+ /** Gated Delta Net **/
378
+ struct ggml_webgpu_gated_delta_net_pipeline_key {
379
+ int type;
380
+ int s_v;
381
+ int kda;
382
+
383
+ bool operator==(const ggml_webgpu_gated_delta_net_pipeline_key & other) const {
384
+ return type == other.type && s_v == other.s_v && kda == other.kda;
385
+ }
386
+ };
387
+
388
+ struct ggml_webgpu_gated_delta_net_pipeline_key_hash {
389
+ size_t operator()(const ggml_webgpu_gated_delta_net_pipeline_key & key) const {
390
+ size_t seed = 0;
391
+ ggml_webgpu_hash_combine(seed, key.type);
392
+ ggml_webgpu_hash_combine(seed, key.s_v);
393
+ ggml_webgpu_hash_combine(seed, key.kda);
394
+ return seed;
395
+ }
396
+ };
397
+
398
+ struct ggml_webgpu_ssm_conv_pipeline_key_hash {
399
+ size_t operator()(const ggml_webgpu_ssm_conv_pipeline_key & key) const {
400
+ size_t seed = 0;
401
+ ggml_webgpu_hash_combine(seed, key.type);
402
+ ggml_webgpu_hash_combine(seed, key.vectorized);
403
+ return seed;
404
+ }
405
+ };
406
+
169
407
  /** Scale **/
170
408
 
171
409
  struct ggml_webgpu_scale_pipeline_key {
@@ -182,18 +420,47 @@ struct ggml_webgpu_scale_pipeline_key_hash {
182
420
  }
183
421
  };
184
422
 
423
+ /** Upscale **/
424
+
425
+ struct ggml_webgpu_upscale_pipeline_key {
426
+ ggml_type input_type;
427
+ ggml_type output_type;
428
+ uint32_t base_mode;
429
+ bool antialias;
430
+
431
+ bool operator==(const ggml_webgpu_upscale_pipeline_key & other) const {
432
+ return input_type == other.input_type && output_type == other.output_type && base_mode == other.base_mode &&
433
+ antialias == other.antialias;
434
+ }
435
+ };
436
+
437
+ struct ggml_webgpu_upscale_pipeline_key_hash {
438
+ size_t operator()(const ggml_webgpu_upscale_pipeline_key & key) const {
439
+ size_t seed = 0;
440
+ ggml_webgpu_hash_combine(seed, key.input_type);
441
+ ggml_webgpu_hash_combine(seed, key.output_type);
442
+ ggml_webgpu_hash_combine(seed, key.base_mode);
443
+ ggml_webgpu_hash_combine(seed, key.antialias);
444
+ return seed;
445
+ }
446
+ };
447
+
185
448
  /** Concat **/
186
449
 
187
450
  struct ggml_webgpu_concat_pipeline_key {
188
- int type;
451
+ int type;
452
+ bool src_overlap;
189
453
 
190
- bool operator==(const ggml_webgpu_concat_pipeline_key & other) const { return type == other.type; }
454
+ bool operator==(const ggml_webgpu_concat_pipeline_key & other) const {
455
+ return type == other.type && src_overlap == other.src_overlap;
456
+ }
191
457
  };
192
458
 
193
459
  struct ggml_webgpu_concat_pipeline_key_hash {
194
460
  size_t operator()(const ggml_webgpu_concat_pipeline_key & key) const {
195
461
  size_t seed = 0;
196
462
  ggml_webgpu_hash_combine(seed, key.type);
463
+ ggml_webgpu_hash_combine(seed, key.src_overlap);
197
464
  return seed;
198
465
  }
199
466
  };
@@ -241,16 +508,34 @@ struct ggml_webgpu_binary_pipeline_key_hash {
241
508
  }
242
509
  };
243
510
 
511
+ /* Add_Id */
512
+
513
+ struct ggml_webgpu_add_id_pipeline_key {
514
+ bool inplace;
515
+
516
+ bool operator==(const ggml_webgpu_add_id_pipeline_key & other) const { return inplace == other.inplace; }
517
+ };
518
+
519
+ struct ggml_webgpu_add_id_pipeline_key_hash {
520
+ size_t operator()(const ggml_webgpu_add_id_pipeline_key & key) const {
521
+ size_t seed = 0;
522
+ ggml_webgpu_hash_combine(seed, key.inplace);
523
+ return seed;
524
+ }
525
+ };
526
+
244
527
  /** Unary **/
245
528
 
246
529
  struct ggml_webgpu_unary_pipeline_key {
247
- int type;
248
- int op;
249
- bool is_unary; // many unary operators fall under the GGML_OP_UNARY umbrella
250
- bool inplace;
530
+ int type;
531
+ int op;
532
+ bool is_unary; // many unary operators fall under the GGML_OP_UNARY umbrella
533
+ bool inplace;
534
+ ggml_tri_type ttype; // only used for GGML_OP_TRI
251
535
 
252
536
  bool operator==(const ggml_webgpu_unary_pipeline_key & other) const {
253
- return type == other.type && op == other.op && is_unary == other.is_unary && inplace == other.inplace;
537
+ return type == other.type && op == other.op && is_unary == other.is_unary && inplace == other.inplace &&
538
+ ttype == other.ttype;
254
539
  }
255
540
  };
256
541
 
@@ -261,58 +546,285 @@ struct ggml_webgpu_unary_pipeline_key_hash {
261
546
  ggml_webgpu_hash_combine(seed, key.op);
262
547
  ggml_webgpu_hash_combine(seed, key.is_unary);
263
548
  ggml_webgpu_hash_combine(seed, key.inplace);
549
+ ggml_webgpu_hash_combine(seed, key.ttype);
264
550
  return seed;
265
551
  }
266
552
  };
267
553
 
268
554
  /** FlashAttention */
269
555
 
270
- struct ggml_webgpu_flash_attn_pipeline_key {
271
- ggml_type kv_type;
556
+ struct ggml_webgpu_flash_attn_common_pipeline_key {
557
+ ggml_type q_type;
558
+ ggml_type k_type;
559
+ ggml_type v_type;
560
+ ggml_type dst_type;
272
561
  uint32_t head_dim_qk;
273
562
  uint32_t head_dim_v;
274
563
  bool kv_direct;
564
+ bool kv_overlap;
275
565
  bool has_mask;
276
566
  bool has_sinks;
277
567
  bool uses_logit_softcap;
278
568
 
569
+ bool operator==(const ggml_webgpu_flash_attn_common_pipeline_key & other) const {
570
+ return q_type == other.q_type && k_type == other.k_type && v_type == other.v_type &&
571
+ dst_type == other.dst_type && head_dim_qk == other.head_dim_qk && head_dim_v == other.head_dim_v &&
572
+ kv_direct == other.kv_direct && kv_overlap == other.kv_overlap && has_mask == other.has_mask &&
573
+ has_sinks == other.has_sinks && uses_logit_softcap == other.uses_logit_softcap;
574
+ }
575
+ };
576
+
577
+ inline void ggml_webgpu_flash_attn_hash_common_pipeline_key(size_t & seed,
578
+ const ggml_webgpu_flash_attn_common_pipeline_key & key) {
579
+ ggml_webgpu_hash_combine(seed, key.q_type);
580
+ ggml_webgpu_hash_combine(seed, key.k_type);
581
+ ggml_webgpu_hash_combine(seed, key.v_type);
582
+ ggml_webgpu_hash_combine(seed, key.dst_type);
583
+ ggml_webgpu_hash_combine(seed, key.head_dim_qk);
584
+ ggml_webgpu_hash_combine(seed, key.head_dim_v);
585
+ ggml_webgpu_hash_combine(seed, key.kv_direct);
586
+ ggml_webgpu_hash_combine(seed, key.kv_overlap);
587
+ ggml_webgpu_hash_combine(seed, key.has_mask);
588
+ ggml_webgpu_hash_combine(seed, key.has_sinks);
589
+ ggml_webgpu_hash_combine(seed, key.uses_logit_softcap);
590
+ }
591
+
592
+ struct ggml_webgpu_flash_attn_vec_pipeline_key {
593
+ ggml_webgpu_flash_attn_common_pipeline_key common;
594
+
595
+ bool operator==(const ggml_webgpu_flash_attn_vec_pipeline_key & other) const { return common == other.common; }
596
+ };
597
+
598
+ struct ggml_webgpu_flash_attn_vec_pipeline_key_hash {
599
+ size_t operator()(const ggml_webgpu_flash_attn_vec_pipeline_key & key) const {
600
+ size_t seed = 0;
601
+ ggml_webgpu_flash_attn_hash_common_pipeline_key(seed, key.common);
602
+ return seed;
603
+ }
604
+ };
605
+
606
+ struct ggml_webgpu_flash_attn_pipeline_key {
607
+ ggml_webgpu_flash_attn_common_pipeline_key common;
608
+ bool use_sg_matrix;
609
+
279
610
  bool operator==(const ggml_webgpu_flash_attn_pipeline_key & other) const {
280
- return kv_type == other.kv_type && head_dim_qk == other.head_dim_qk && head_dim_v == other.head_dim_v &&
281
- kv_direct == other.kv_direct && has_mask == other.has_mask && has_sinks == other.has_sinks &&
282
- uses_logit_softcap == other.uses_logit_softcap;
611
+ return common == other.common && use_sg_matrix == other.use_sg_matrix;
283
612
  }
284
613
  };
285
614
 
286
615
  struct ggml_webgpu_flash_attn_pipeline_key_hash {
287
616
  size_t operator()(const ggml_webgpu_flash_attn_pipeline_key & key) const {
288
617
  size_t seed = 0;
289
- ggml_webgpu_hash_combine(seed, key.kv_type);
290
- ggml_webgpu_hash_combine(seed, key.head_dim_qk);
618
+ ggml_webgpu_flash_attn_hash_common_pipeline_key(seed, key.common);
619
+ ggml_webgpu_hash_combine(seed, key.use_sg_matrix);
620
+ return seed;
621
+ }
622
+ };
623
+
624
+ struct ggml_webgpu_flash_attn_vec_decisions {
625
+ uint32_t kv_tile = 0;
626
+ uint32_t wg_size = 0;
627
+ };
628
+
629
+ struct ggml_webgpu_flash_attn_decisions {
630
+ bool use_sg_matrix = false;
631
+ uint32_t q_tile = 0;
632
+ uint32_t kv_tile = 0;
633
+ uint32_t wg_size = 0;
634
+ };
635
+
636
+ inline constexpr uint32_t GGML_WEBGPU_FLASH_ATTN_TILE_KV_VEC_WIDTH = 4u;
637
+ inline constexpr uint32_t GGML_WEBGPU_FLASH_ATTN_TILE_Q_TILE = 4u;
638
+
639
+ inline size_t ggml_webgpu_flash_attn_tensor_offset(const ggml_tensor * tensor) {
640
+ constexpr uintptr_t ptr_base_addr = 0x1000u;
641
+ const ggml_tensor * base = tensor->view_src != nullptr ? tensor->view_src : tensor;
642
+ return reinterpret_cast<uintptr_t>(base->data) - ptr_base_addr + tensor->view_offs;
643
+ }
644
+
645
+ inline bool ggml_webgpu_flash_attn_float_vec4_aligned(const ggml_tensor * K, size_t storage_offset_alignment) {
646
+ const uint32_t offset_elems =
647
+ (uint32_t) ((ggml_webgpu_flash_attn_tensor_offset(K) & (storage_offset_alignment - 1)) /
648
+ ggml_type_size(K->type));
649
+ return offset_elems % GGML_WEBGPU_FLASH_ATTN_TILE_KV_VEC_WIDTH == 0u;
650
+ }
651
+
652
+ inline bool ggml_webgpu_flash_attn_float_vec4_aligned(const ggml_tensor * K,
653
+ const ggml_tensor * V,
654
+ size_t storage_offset_alignment) {
655
+ return ggml_webgpu_flash_attn_float_vec4_aligned(K, storage_offset_alignment) &&
656
+ ggml_webgpu_flash_attn_float_vec4_aligned(V, storage_offset_alignment);
657
+ }
658
+
659
+ inline bool ggml_webgpu_flash_attn_kv_direct(const ggml_tensor * Q,
660
+ const ggml_tensor * K,
661
+ const ggml_tensor * V,
662
+ uint32_t kv_direct_align) {
663
+ return K->type == GGML_TYPE_F16 && V->type == GGML_TYPE_F16 && (Q->ne[0] % kv_direct_align == 0) &&
664
+ (K->ne[1] % GGML_WEBGPU_KV_SEQ_PAD == 0);
665
+ }
666
+
667
+ inline ggml_webgpu_flash_attn_common_pipeline_key ggml_webgpu_flash_attn_make_common_pipeline_key(
668
+ const ggml_webgpu_shader_lib_context & context,
669
+ uint32_t kv_direct_align) {
670
+ ggml_webgpu_flash_attn_common_pipeline_key key = {};
671
+ key.q_type = context.src0->type;
672
+ key.k_type = context.src1->type;
673
+ key.v_type = context.src2->type;
674
+ key.dst_type = context.dst->type;
675
+ key.head_dim_qk = (uint32_t) context.src0->ne[0];
676
+ key.head_dim_v = (uint32_t) context.src2->ne[0];
677
+ key.kv_direct = ggml_webgpu_flash_attn_kv_direct(context.src0, context.src1, context.src2, kv_direct_align);
678
+ key.kv_overlap = ggml_webgpu_tensor_overlap(context.src1, context.src2);
679
+ key.has_mask = context.src3 != nullptr;
680
+ key.has_sinks = context.src4 != nullptr;
681
+ key.uses_logit_softcap = ggml_get_op_params_f32(context.dst, 2) != 0.0f;
682
+ return key;
683
+ }
684
+
685
+ inline std::vector<std::string> ggml_webgpu_flash_attn_common_defines(
686
+ const ggml_webgpu_flash_attn_common_pipeline_key & key,
687
+ std::string & variant,
688
+ uint32_t q_tile,
689
+ uint32_t kv_tile,
690
+ uint32_t wg_size) {
691
+ std::vector<std::string> defines;
692
+
693
+ switch (key.k_type) {
694
+ case GGML_TYPE_F32:
695
+ defines.push_back("K_F32");
696
+ break;
697
+ case GGML_TYPE_F16:
698
+ defines.push_back("K_F16");
699
+ break;
700
+ case GGML_TYPE_Q4_0:
701
+ defines.push_back("K_Q4_0");
702
+ break;
703
+ case GGML_TYPE_Q8_0:
704
+ defines.push_back("K_Q8_0");
705
+ break;
706
+ default:
707
+ GGML_ABORT("Unsupported K type for flash attention shader");
708
+ }
709
+ variant += std::string("_k") + ggml_type_name(key.k_type);
710
+
711
+ switch (key.v_type) {
712
+ case GGML_TYPE_F32:
713
+ defines.push_back("V_F32");
714
+ break;
715
+ case GGML_TYPE_F16:
716
+ defines.push_back("V_F16");
717
+ break;
718
+ case GGML_TYPE_Q4_0:
719
+ defines.push_back("V_Q4_0");
720
+ break;
721
+ case GGML_TYPE_Q8_0:
722
+ defines.push_back("V_Q8_0");
723
+ break;
724
+ default:
725
+ GGML_ABORT("Unsupported V type for flash attention shader");
726
+ }
727
+ variant += std::string("_v") + ggml_type_name(key.v_type);
728
+
729
+ switch (key.q_type) {
730
+ case GGML_TYPE_F32:
731
+ defines.push_back("Q_F32");
732
+ break;
733
+ case GGML_TYPE_F16:
734
+ defines.push_back("Q_F16");
735
+ break;
736
+ default:
737
+ GGML_ABORT("Unsupported Q type for flash attention shader");
738
+ }
739
+ variant += std::string("_q") + ggml_type_name(key.q_type);
740
+
741
+ switch (key.dst_type) {
742
+ case GGML_TYPE_F32:
743
+ defines.push_back("DST_F32");
744
+ break;
745
+ case GGML_TYPE_F16:
746
+ defines.push_back("DST_F16");
747
+ break;
748
+ default:
749
+ GGML_ABORT("Unsupported dst type for flash attention shader");
750
+ }
751
+ variant += std::string("_dst") + ggml_type_name(key.dst_type);
752
+
753
+ if (key.has_mask) {
754
+ defines.push_back("MASK");
755
+ variant += "_mask";
756
+ }
757
+ if (key.has_sinks) {
758
+ defines.push_back("SINKS");
759
+ variant += "_sinks";
760
+ }
761
+ if (key.uses_logit_softcap) {
762
+ defines.push_back("LOGIT_SOFTCAP");
763
+ variant += "_lgsc";
764
+ }
765
+ if (key.kv_direct) {
766
+ defines.push_back("KV_DIRECT");
767
+ variant += "_kvdirect";
768
+ }
769
+ if (key.kv_overlap) {
770
+ defines.push_back("KV_OVERLAP");
771
+ variant += "_kv_overlap";
772
+ }
773
+
774
+ defines.push_back(std::string("HEAD_DIM_QK=") + std::to_string(key.head_dim_qk));
775
+ variant += std::string("_hsqk") + std::to_string(key.head_dim_qk);
776
+
777
+ defines.push_back(std::string("HEAD_DIM_V=") + std::to_string(key.head_dim_v));
778
+ variant += std::string("_hsv") + std::to_string(key.head_dim_v);
779
+
780
+ defines.push_back(std::string("Q_TILE=") + std::to_string(q_tile));
781
+ defines.push_back(std::string("KV_TILE=") + std::to_string(kv_tile));
782
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
783
+
784
+ if (ggml_is_quantized(key.k_type) || ggml_is_quantized(key.v_type)) {
785
+ defines.push_back("U32_DEQUANT_HELPERS");
786
+ }
787
+
788
+ return defines;
789
+ }
790
+
791
+ struct ggml_webgpu_flash_attn_vec_reduce_pipeline_key {
792
+ uint32_t head_dim_v;
793
+ uint32_t wg_size;
794
+ ggml_type dst_type;
795
+ };
796
+
797
+ struct ggml_webgpu_flash_attn_vec_reduce_pipeline_key_hash {
798
+ size_t operator()(const ggml_webgpu_flash_attn_vec_reduce_pipeline_key & key) const {
799
+ size_t seed = 0;
291
800
  ggml_webgpu_hash_combine(seed, key.head_dim_v);
292
- ggml_webgpu_hash_combine(seed, key.kv_direct);
293
- ggml_webgpu_hash_combine(seed, key.has_mask);
294
- ggml_webgpu_hash_combine(seed, key.has_sinks);
295
- ggml_webgpu_hash_combine(seed, key.uses_logit_softcap);
801
+ ggml_webgpu_hash_combine(seed, key.wg_size);
802
+ ggml_webgpu_hash_combine(seed, key.dst_type);
296
803
  return seed;
297
804
  }
298
805
  };
299
806
 
300
- struct ggml_webgpu_flash_attn_shader_lib_context {
301
- ggml_webgpu_flash_attn_pipeline_key key;
302
- uint32_t sg_mat_m;
303
- uint32_t sg_mat_n;
304
- uint32_t sg_mat_k;
305
- size_t wg_mem_limit_bytes;
306
- uint32_t max_subgroup_size;
807
+ inline bool operator==(const ggml_webgpu_flash_attn_vec_reduce_pipeline_key & lhs,
808
+ const ggml_webgpu_flash_attn_vec_reduce_pipeline_key & rhs) {
809
+ return lhs.head_dim_v == rhs.head_dim_v && lhs.wg_size == rhs.wg_size && lhs.dst_type == rhs.dst_type;
810
+ }
811
+
812
+ struct ggml_webgpu_flash_attn_blk_pipeline_key {
813
+ uint32_t kv_tile;
814
+
815
+ bool operator==(const ggml_webgpu_flash_attn_blk_pipeline_key & other) const { return kv_tile == other.kv_tile; }
307
816
  };
308
817
 
309
- struct ggml_webgpu_flash_attn_shader_decisions {
310
- uint32_t q_tile = 0;
311
- uint32_t kv_tile = 0;
312
- uint32_t wg_size = 0;
818
+ struct ggml_webgpu_flash_attn_blk_pipeline_key_hash {
819
+ size_t operator()(const ggml_webgpu_flash_attn_blk_pipeline_key & key) const {
820
+ size_t seed = 0;
821
+ ggml_webgpu_hash_combine(seed, key.kv_tile);
822
+ return seed;
823
+ }
313
824
  };
314
825
 
315
- // This is exposed because it's necessary in supports_op
826
+ // Note: this will slightly overestimate memory usage for vec path
827
+ // since row_max and exp_sum shmem are not needed.
316
828
  inline size_t ggml_webgpu_flash_attn_wg_mem_bytes(uint32_t q_tile,
317
829
  uint32_t kv_tile,
318
830
  uint32_t head_dim_qk,
@@ -322,47 +834,83 @@ inline size_t ggml_webgpu_flash_attn_wg_mem_bytes(uint32_t q_tile,
322
834
  const uint32_t max_head_dim = std::max(head_dim_qk, head_dim_v);
323
835
  size_t f16_elems = 0;
324
836
  size_t f32_elems = 0;
325
- f16_elems += q_tile * head_dim_qk; // q_shmem
837
+
838
+ f32_elems += q_tile * head_dim_qk; // q_shmem
326
839
  if (!kv_direct) {
327
- f16_elems += kv_tile * max_head_dim; // kv_shmem
840
+ f32_elems += kv_tile * max_head_dim; // kv_shmem
328
841
  }
329
- f16_elems += q_tile * head_dim_v; // o_shmem
842
+ f32_elems += q_tile * head_dim_v; // o_shmem
330
843
  if (has_mask) {
331
- f16_elems += q_tile * kv_tile; // mask_shmem
844
+ f32_elems += q_tile * kv_tile; // mask_shmem
332
845
  }
333
- f16_elems += q_tile * kv_tile; // inter_shmem
846
+ f32_elems += q_tile * kv_tile; // inter_shmem
334
847
  f32_elems += q_tile; // row_max_shmem
335
848
  f32_elems += q_tile; // exp_sum_shmem
336
849
  return f16_elems * GGML_WEBGPU_F16_SIZE_BYTES + f32_elems * GGML_WEBGPU_F32_SIZE_BYTES;
337
850
  }
338
851
 
339
- /** Matrix Multiplication **/
340
-
341
- struct ggml_webgpu_legacy_mul_mat_pipeline_key {
342
- ggml_type src0_type;
343
- ggml_type src1_type;
344
-
345
- bool operator==(const ggml_webgpu_legacy_mul_mat_pipeline_key & other) const {
346
- return src0_type == other.src0_type && src1_type == other.src1_type;
852
+ inline uint32_t ggml_webgpu_flash_attn_max_kv_tile(size_t limit_bytes,
853
+ uint32_t q_tile,
854
+ uint32_t kv_granularity,
855
+ uint32_t head_dim_qk,
856
+ uint32_t head_dim_v,
857
+ bool has_mask,
858
+ bool kv_direct) {
859
+ const size_t base_q_bytes =
860
+ ggml_webgpu_flash_attn_wg_mem_bytes(q_tile, 0, head_dim_qk, head_dim_v, has_mask, kv_direct);
861
+ if (limit_bytes <= base_q_bytes) {
862
+ return 0;
347
863
  }
348
- };
864
+ const size_t one_kv_bytes =
865
+ ggml_webgpu_flash_attn_wg_mem_bytes(q_tile, 1, head_dim_qk, head_dim_v, has_mask, kv_direct);
866
+ const size_t bytes_per_kv = one_kv_bytes - base_q_bytes;
867
+ if (bytes_per_kv == 0) {
868
+ return 0;
869
+ }
870
+ const size_t max_kv_tile = (limit_bytes - base_q_bytes) / bytes_per_kv;
871
+ return (uint32_t) ((max_kv_tile / kv_granularity) * kv_granularity);
872
+ }
349
873
 
350
- struct ggml_webgpu_legacy_mul_mat_pipeline_key_hash {
351
- size_t operator()(const ggml_webgpu_legacy_mul_mat_pipeline_key & key) const {
352
- size_t seed = 0;
353
- ggml_webgpu_hash_combine(seed, key.src0_type);
354
- ggml_webgpu_hash_combine(seed, key.src1_type);
355
- return seed;
874
+ inline uint32_t ggml_webgpu_flash_attn_get_vec_kv_tile(size_t wg_mem_limit_bytes,
875
+ uint32_t head_dim_qk,
876
+ uint32_t head_dim_v,
877
+ bool has_mask,
878
+ bool kv_direct) {
879
+ const uint32_t max_kv_tile =
880
+ ggml_webgpu_flash_attn_max_kv_tile(wg_mem_limit_bytes, 1u, 1u, head_dim_qk, head_dim_v, has_mask, kv_direct);
881
+ GGML_ASSERT(max_kv_tile > 0);
882
+
883
+ uint32_t kv_tile = std::min(GGML_WEBGPU_FLASH_ATTN_VEC_MAX_KV_TILE, max_kv_tile);
884
+ if (kv_direct) {
885
+ kv_tile = std::min(kv_tile, GGML_WEBGPU_KV_SEQ_PAD);
886
+ while (GGML_WEBGPU_KV_SEQ_PAD % kv_tile != 0) {
887
+ kv_tile -= 1u;
888
+ }
356
889
  }
357
- };
890
+
891
+ return kv_tile;
892
+ }
893
+
894
+ inline bool ggml_webgpu_flash_attn_can_use_subgroup_matrix_path(bool supports_subgroup_matrix,
895
+ uint32_t sg_mat_k,
896
+ uint32_t sg_mat_n,
897
+ const ggml_tensor * Q,
898
+ const ggml_tensor * V) {
899
+ return supports_subgroup_matrix && Q->ne[0] % sg_mat_k == 0 && V->ne[0] % sg_mat_n == 0;
900
+ }
901
+
902
+ /** Matrix Multiplication **/
358
903
 
359
904
  struct ggml_webgpu_mul_mat_vec_pipeline_key {
360
905
  ggml_type src0_type;
361
906
  ggml_type src1_type;
362
907
  int vectorized;
908
+ uint32_t num_cols;
909
+ bool use_mmvq;
363
910
 
364
911
  bool operator==(const ggml_webgpu_mul_mat_vec_pipeline_key & other) const {
365
- return src0_type == other.src0_type && src1_type == other.src1_type && vectorized == other.vectorized;
912
+ return src0_type == other.src0_type && src1_type == other.src1_type && vectorized == other.vectorized &&
913
+ num_cols == other.num_cols && use_mmvq == other.use_mmvq;
366
914
  }
367
915
  };
368
916
 
@@ -372,17 +920,32 @@ struct ggml_webgpu_mul_mat_vec_pipeline_key_hash {
372
920
  ggml_webgpu_hash_combine(seed, key.src0_type);
373
921
  ggml_webgpu_hash_combine(seed, key.src1_type);
374
922
  ggml_webgpu_hash_combine(seed, key.vectorized);
923
+ ggml_webgpu_hash_combine(seed, key.num_cols);
924
+ ggml_webgpu_hash_combine(seed, key.use_mmvq);
375
925
  return seed;
376
926
  }
377
927
  };
378
928
 
379
929
  struct ggml_webgpu_mul_mat_vec_shader_decisions {
380
930
  uint32_t wg_size;
381
- uint32_t tile_k;
382
931
  uint32_t outputs_per_wg;
383
932
  uint32_t vec_size;
384
933
  };
385
934
 
935
+ struct ggml_webgpu_quantize_q8_pipeline_key {
936
+ ggml_type src0_type;
937
+
938
+ bool operator==(const ggml_webgpu_quantize_q8_pipeline_key & other) const { return src0_type == other.src0_type; }
939
+ };
940
+
941
+ struct ggml_webgpu_quantize_q8_pipeline_key_hash {
942
+ size_t operator()(const ggml_webgpu_quantize_q8_pipeline_key & key) const {
943
+ size_t seed = 0;
944
+ ggml_webgpu_hash_combine(seed, key.src0_type);
945
+ return seed;
946
+ }
947
+ };
948
+
386
949
  struct ggml_webgpu_mul_mat_pipeline_key {
387
950
  ggml_type src0_type;
388
951
  ggml_type src1_type;
@@ -426,8 +989,154 @@ struct ggml_webgpu_mul_mat_shader_decisions {
426
989
  uint32_t mul_mat_wg_size;
427
990
  };
428
991
 
429
- class ggml_webgpu_shader_lib {
430
- wgpu::Device device;
992
+ /** MUL_MAT_ID **/
993
+
994
+ struct ggml_webgpu_mul_mat_id_pipeline_key {
995
+ ggml_type src0_type;
996
+ ggml_type src1_type;
997
+ uint32_t n_experts;
998
+ uint32_t num_cols;
999
+ int vectorized;
1000
+
1001
+ bool operator==(const ggml_webgpu_mul_mat_id_pipeline_key & other) const {
1002
+ return src0_type == other.src0_type && src1_type == other.src1_type && n_experts == other.n_experts &&
1003
+ num_cols == other.num_cols && vectorized == other.vectorized;
1004
+ }
1005
+ };
1006
+
1007
+ struct ggml_webgpu_mul_mat_id_pipeline_key_hash {
1008
+ size_t operator()(const ggml_webgpu_mul_mat_id_pipeline_key & key) const {
1009
+ size_t seed = 0;
1010
+ ggml_webgpu_hash_combine(seed, key.src0_type);
1011
+ ggml_webgpu_hash_combine(seed, key.src1_type);
1012
+ ggml_webgpu_hash_combine(seed, key.n_experts);
1013
+ ggml_webgpu_hash_combine(seed, key.num_cols);
1014
+ ggml_webgpu_hash_combine(seed, key.vectorized);
1015
+ return seed;
1016
+ }
1017
+ };
1018
+
1019
+ /** Cpy **/
1020
+
1021
+ struct ggml_webgpu_cpy_pipeline_key {
1022
+ ggml_type src_type;
1023
+ ggml_type dst_type;
1024
+
1025
+ bool operator==(const ggml_webgpu_cpy_pipeline_key & other) const {
1026
+ return src_type == other.src_type && dst_type == other.dst_type;
1027
+ }
1028
+ };
1029
+
1030
+ struct ggml_webgpu_cpy_pipeline_key_hash {
1031
+ size_t operator()(const ggml_webgpu_cpy_pipeline_key & key) const {
1032
+ size_t seed = 0;
1033
+ ggml_webgpu_hash_combine(seed, key.src_type);
1034
+ ggml_webgpu_hash_combine(seed, key.dst_type);
1035
+ return seed;
1036
+ }
1037
+ };
1038
+
1039
+ /** Glu **/
1040
+
1041
+ struct ggml_webgpu_glu_pipeline_key {
1042
+ ggml_glu_op glu_op;
1043
+ ggml_type type;
1044
+ bool split;
1045
+
1046
+ bool operator==(const ggml_webgpu_glu_pipeline_key & other) const {
1047
+ return glu_op == other.glu_op && type == other.type && split == other.split;
1048
+ }
1049
+ };
1050
+
1051
+ struct ggml_webgpu_glu_pipeline_key_hash {
1052
+ size_t operator()(const ggml_webgpu_glu_pipeline_key & key) const {
1053
+ size_t seed = 0;
1054
+ ggml_webgpu_hash_combine(seed, key.glu_op);
1055
+ ggml_webgpu_hash_combine(seed, key.type);
1056
+ ggml_webgpu_hash_combine(seed, key.split);
1057
+ return seed;
1058
+ }
1059
+ };
1060
+
1061
+ /** Rope **/
1062
+
1063
+ struct ggml_webgpu_rope_pipeline_key {
1064
+ ggml_type type;
1065
+ bool inplace;
1066
+ bool has_ff;
1067
+
1068
+ bool operator==(const ggml_webgpu_rope_pipeline_key & other) const {
1069
+ return type == other.type && inplace == other.inplace && has_ff == other.has_ff;
1070
+ }
1071
+ };
1072
+
1073
+ struct ggml_webgpu_rope_pipeline_key_hash {
1074
+ size_t operator()(const ggml_webgpu_rope_pipeline_key & key) const {
1075
+ size_t seed = 0;
1076
+ ggml_webgpu_hash_combine(seed, key.type);
1077
+ ggml_webgpu_hash_combine(seed, key.inplace);
1078
+ ggml_webgpu_hash_combine(seed, key.has_ff);
1079
+ return seed;
1080
+ }
1081
+ };
1082
+
1083
+ /** SoftMax **/
1084
+
1085
+ struct ggml_webgpu_soft_max_pipeline_key {
1086
+ ggml_type mask_type;
1087
+ bool has_mask;
1088
+ bool has_sink;
1089
+ bool inplace;
1090
+
1091
+ bool operator==(const ggml_webgpu_soft_max_pipeline_key & other) const {
1092
+ return mask_type == other.mask_type && has_mask == other.has_mask && has_sink == other.has_sink &&
1093
+ inplace == other.inplace;
1094
+ }
1095
+ };
1096
+
1097
+ struct ggml_webgpu_soft_max_pipeline_key_hash {
1098
+ size_t operator()(const ggml_webgpu_soft_max_pipeline_key & key) const {
1099
+ size_t seed = 0;
1100
+ ggml_webgpu_hash_combine(seed, key.mask_type);
1101
+ ggml_webgpu_hash_combine(seed, key.has_mask);
1102
+ ggml_webgpu_hash_combine(seed, key.has_sink);
1103
+ ggml_webgpu_hash_combine(seed, key.inplace);
1104
+ return seed;
1105
+ }
1106
+ };
1107
+
1108
+ /** MMVQ **/
1109
+
1110
+ inline bool ggml_webgpu_can_use_mmvq(const ggml_tensor * src0,
1111
+ const ggml_tensor * src1,
1112
+ bool supports_dot_product,
1113
+ const std::string & vendor) {
1114
+ if (src1->ne[1] <= 4) {
1115
+ bool supports_dp4a = vendor == "amd" || vendor == "intel" || vendor == "nvidia";
1116
+ if (supports_dp4a && supports_dot_product) {
1117
+ switch (src1->type) {
1118
+ case GGML_TYPE_F32:
1119
+ switch (src0->type) {
1120
+ case GGML_TYPE_Q4_0:
1121
+ case GGML_TYPE_Q4_1:
1122
+ case GGML_TYPE_Q8_0:
1123
+ case GGML_TYPE_Q2_K:
1124
+ case GGML_TYPE_Q4_K:
1125
+ return src0->ne[0] % 4 == 0;
1126
+ default:
1127
+ break;
1128
+ }
1129
+ break;
1130
+ default:
1131
+ break;
1132
+ }
1133
+ }
1134
+ }
1135
+ return false;
1136
+ }
1137
+
1138
+ class ggml_webgpu_shader_lib {
1139
+ wgpu::Device device;
431
1140
  pre_wgsl::Preprocessor preprocessor;
432
1141
 
433
1142
  std::unordered_map<int, webgpu_pipeline> sum_rows_pipelines; // key is fixed, no variants yet
@@ -435,33 +1144,81 @@ class ggml_webgpu_shader_lib {
435
1144
  std::unordered_map<int, webgpu_pipeline> argsort_pipelines; // key is order
436
1145
  std::unordered_map<int, webgpu_pipeline> argsort_merge_pipelines; // key is order
437
1146
  std::unordered_map<int, webgpu_pipeline> cumsum_pipelines; // key is fixed, no variants yet
1147
+ std::unordered_map<ggml_webgpu_row_norm_pipeline_key, webgpu_pipeline, ggml_webgpu_row_norm_pipeline_key_hash>
1148
+ row_norm_pipelines; // op/inplace
1149
+
438
1150
  std::unordered_map<ggml_webgpu_get_rows_pipeline_key, webgpu_pipeline, ggml_webgpu_get_rows_pipeline_key_hash>
439
- get_rows_pipelines; // src_type, vectorized
1151
+ get_rows_pipelines; // src_type, vectorized
440
1152
  std::unordered_map<ggml_webgpu_unary_pipeline_key, webgpu_pipeline, ggml_webgpu_unary_pipeline_key_hash>
441
- unary_pipelines; // type/op/inplace
1153
+ unary_pipelines; // type/op/inplace
442
1154
  std::unordered_map<ggml_webgpu_scale_pipeline_key, webgpu_pipeline, ggml_webgpu_scale_pipeline_key_hash>
443
- scale_pipelines; // inplace
1155
+ scale_pipelines; // inplace
1156
+ std::unordered_map<ggml_webgpu_solve_tri_pipeline_key, webgpu_pipeline, ggml_webgpu_solve_tri_pipeline_key_hash>
1157
+ solve_tri_pipelines; // type
1158
+ std::unordered_map<ggml_webgpu_ssm_conv_pipeline_key, webgpu_pipeline, ggml_webgpu_ssm_conv_pipeline_key_hash>
1159
+ ssm_conv_pipelines; // type/vectorized
1160
+ std::unordered_map<ggml_webgpu_ssm_scan_pipeline_key, webgpu_pipeline, ggml_webgpu_ssm_scan_pipeline_key_hash>
1161
+ ssm_scan_pipelines; // type/d_state
1162
+ std::unordered_map<ggml_webgpu_gated_delta_net_pipeline_key,
1163
+ webgpu_pipeline,
1164
+ ggml_webgpu_gated_delta_net_pipeline_key_hash>
1165
+ gated_delta_net_pipelines; // type/S_v/kda
444
1166
  std::unordered_map<ggml_webgpu_pad_pipeline_key, webgpu_pipeline, ggml_webgpu_pad_pipeline_key_hash>
445
- pad_pipelines; // circular/non-circular
1167
+ pad_pipelines; // circular/non-circular
446
1168
  std::unordered_map<ggml_webgpu_binary_pipeline_key, webgpu_pipeline, ggml_webgpu_binary_pipeline_key_hash>
447
- binary_pipelines; // type/op/inplace/overlap
1169
+ binary_pipelines; // type/op/inplace/overlap/src_overlap
1170
+ std::unordered_map<ggml_webgpu_add_id_pipeline_key, webgpu_pipeline, ggml_webgpu_add_id_pipeline_key_hash>
1171
+ add_id_pipelines; // inplace
448
1172
  std::unordered_map<ggml_webgpu_concat_pipeline_key, webgpu_pipeline, ggml_webgpu_concat_pipeline_key_hash>
449
- concat_pipelines; // type
1173
+ concat_pipelines; // type
450
1174
  std::unordered_map<ggml_webgpu_repeat_pipeline_key, webgpu_pipeline, ggml_webgpu_repeat_pipeline_key_hash>
451
- repeat_pipelines; // type
1175
+ repeat_pipelines; // type
1176
+ std::unordered_map<ggml_webgpu_flash_attn_vec_pipeline_key,
1177
+ webgpu_pipeline,
1178
+ ggml_webgpu_flash_attn_vec_pipeline_key_hash>
1179
+ flash_attn_vec_pipelines;
452
1180
  std::unordered_map<ggml_webgpu_flash_attn_pipeline_key, webgpu_pipeline, ggml_webgpu_flash_attn_pipeline_key_hash>
453
1181
  flash_attn_pipelines;
454
- std::unordered_map<ggml_webgpu_legacy_mul_mat_pipeline_key,
1182
+ std::unordered_map<ggml_webgpu_flash_attn_vec_reduce_pipeline_key,
455
1183
  webgpu_pipeline,
456
- ggml_webgpu_legacy_mul_mat_pipeline_key_hash>
457
- mul_mat_legacy_pipelines; // legacy mul_mat (non-subgroup/non-regtile/non-vec)
1184
+ ggml_webgpu_flash_attn_vec_reduce_pipeline_key_hash>
1185
+ flash_attn_vec_reduce_pipelines;
1186
+ std::unordered_map<ggml_webgpu_flash_attn_blk_pipeline_key,
1187
+ webgpu_pipeline,
1188
+ ggml_webgpu_flash_attn_blk_pipeline_key_hash>
1189
+ flash_attn_blk_pipelines;
458
1190
  std::unordered_map<ggml_webgpu_mul_mat_vec_pipeline_key, webgpu_pipeline, ggml_webgpu_mul_mat_vec_pipeline_key_hash>
459
- mul_mat_vec_pipelines; // fast mat-vec (n==1)
1191
+ mul_mat_vec_pipelines; // fast mat-vec (n==1)
460
1192
  std::unordered_map<ggml_webgpu_mul_mat_pipeline_key, webgpu_pipeline, ggml_webgpu_mul_mat_pipeline_key_hash>
461
- mul_mat_fast_pipelines; // fast mat-mat (reg-tile or subgroup)
1193
+ mul_mat_fast_pipelines; // fast mat-mat (reg-tile or subgroup)
1194
+ std::unordered_map<ggml_webgpu_quantize_q8_pipeline_key, webgpu_pipeline, ggml_webgpu_quantize_q8_pipeline_key_hash>
1195
+ quantize_q8_pipelines;
1196
+ std::unordered_map<int, webgpu_pipeline> mul_mat_id_gather_pipelines; // key is fixed
1197
+ std::unordered_map<ggml_webgpu_mul_mat_id_pipeline_key, webgpu_pipeline, ggml_webgpu_mul_mat_id_pipeline_key_hash>
1198
+ mul_mat_id_pipelines; // src0_type/src1_type
1199
+ std::unordered_map<ggml_webgpu_mul_mat_id_pipeline_key, webgpu_pipeline, ggml_webgpu_mul_mat_id_pipeline_key_hash>
1200
+ mul_mat_id_vec_pipelines; // src0_type/src1_type
462
1201
 
463
1202
  std::unordered_map<ggml_webgpu_set_rows_pipeline_key, webgpu_pipeline, ggml_webgpu_set_rows_pipeline_key_hash>
464
1203
  set_rows_pipelines;
1204
+ std::unordered_map<ggml_webgpu_set_pipeline_key, webgpu_pipeline, ggml_webgpu_set_pipeline_key_hash> set_pipelines;
1205
+ std::unordered_map<ggml_webgpu_cpy_pipeline_key, webgpu_pipeline, ggml_webgpu_cpy_pipeline_key_hash> cpy_pipelines;
1206
+ std::unordered_map<ggml_webgpu_glu_pipeline_key, webgpu_pipeline, ggml_webgpu_glu_pipeline_key_hash> glu_pipelines;
1207
+ std::unordered_map<ggml_webgpu_rope_pipeline_key, webgpu_pipeline, ggml_webgpu_rope_pipeline_key_hash>
1208
+ rope_pipelines;
1209
+ std::unordered_map<ggml_webgpu_soft_max_pipeline_key, webgpu_pipeline, ggml_webgpu_soft_max_pipeline_key_hash>
1210
+ soft_max_pipelines;
1211
+ std::unordered_map<ggml_webgpu_conv2d_pipeline_key, webgpu_pipeline, ggml_webgpu_conv2d_pipeline_key_hash>
1212
+ conv2d_pipelines;
1213
+ std::unordered_map<ggml_webgpu_im2col_pipeline_key, webgpu_pipeline, ggml_webgpu_im2col_pipeline_key_hash>
1214
+ im2col_pipelines;
1215
+
1216
+ std::unordered_map<ggml_webgpu_rms_norm_mul_pipeline_key,
1217
+ webgpu_pipeline,
1218
+ ggml_webgpu_rms_norm_mul_pipeline_key_hash>
1219
+ rms_norm_mul_pipelines;
1220
+ std::unordered_map<ggml_webgpu_upscale_pipeline_key, webgpu_pipeline, ggml_webgpu_upscale_pipeline_key_hash>
1221
+ upscale_pipelines;
465
1222
 
466
1223
  public:
467
1224
  ggml_webgpu_shader_lib(wgpu::Device device) { this->device = device; }
@@ -479,6 +1236,70 @@ class ggml_webgpu_shader_lib {
479
1236
  return sum_rows_pipelines[1];
480
1237
  }
481
1238
 
1239
+ webgpu_pipeline get_row_norm_pipeline(const ggml_webgpu_shader_lib_context & context) {
1240
+ ggml_webgpu_row_norm_pipeline_key key = {};
1241
+ key.op = context.dst->op;
1242
+ key.src_type = context.src0->type;
1243
+ key.dst_type = context.dst->type;
1244
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
1245
+
1246
+ auto it = row_norm_pipelines.find(key);
1247
+ if (it != row_norm_pipelines.end()) {
1248
+ return it->second;
1249
+ }
1250
+ std::vector<std::string> defines;
1251
+ std::string variant;
1252
+
1253
+ switch (key.op) {
1254
+ case GGML_OP_RMS_NORM:
1255
+ defines.push_back("RMS_NORM");
1256
+ variant = "rms_norm";
1257
+ break;
1258
+ case GGML_OP_NORM:
1259
+ defines.push_back("NORM");
1260
+ variant = "norm";
1261
+ break;
1262
+ case GGML_OP_L2_NORM:
1263
+ defines.push_back("L2_NORM");
1264
+ variant = "l2_norm";
1265
+ break;
1266
+ default:
1267
+ GGML_ABORT("Unsupported op for row_norm shader");
1268
+ }
1269
+
1270
+ if (key.inplace) {
1271
+ defines.push_back("INPLACE");
1272
+ variant += "_inplace";
1273
+ }
1274
+
1275
+ if (key.src_type == GGML_TYPE_F32) {
1276
+ defines.push_back("SRC_F32");
1277
+ variant += "_src_f32";
1278
+ } else if (key.src_type == GGML_TYPE_F16) {
1279
+ defines.push_back("SRC_F16");
1280
+ variant += "_src_f16";
1281
+ }
1282
+
1283
+ if (key.dst_type == GGML_TYPE_F32) {
1284
+ defines.push_back("DST_F32");
1285
+ variant += "_dst_f32";
1286
+ } else if (key.dst_type == GGML_TYPE_F16) {
1287
+ defines.push_back("DST_F16");
1288
+ variant += "_dst_f16";
1289
+ }
1290
+
1291
+ const uint32_t row_norm_wg_size = 128u;
1292
+ uint32_t wg_size = std::min(context.max_wg_size, row_norm_wg_size);
1293
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
1294
+ auto processed = preprocessor.preprocess(wgsl_row_norm, defines);
1295
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
1296
+ decisions->wg_size = wg_size;
1297
+ decisions->inplace = key.inplace;
1298
+ row_norm_pipelines[key] = ggml_webgpu_create_pipeline(device, processed, variant);
1299
+ row_norm_pipelines[key].context = decisions;
1300
+ return row_norm_pipelines[key];
1301
+ }
1302
+
482
1303
  webgpu_pipeline get_argmax_pipeline(const ggml_webgpu_shader_lib_context & context) {
483
1304
  bool vec4 = context.src0->ne[0] % 4 == 0;
484
1305
 
@@ -500,9 +1321,13 @@ class ggml_webgpu_shader_lib {
500
1321
  }
501
1322
 
502
1323
  webgpu_pipeline get_set_rows_pipeline(const ggml_webgpu_shader_lib_context & context) {
503
- ggml_webgpu_set_rows_pipeline_key key = { .dst_type = context.dst->type,
504
- .vec4 = context.src0->ne[0] % 4 == 0,
505
- .i64_idx = context.src1->type == GGML_TYPE_I64 };
1324
+ const bool quantized = ggml_is_quantized(context.dst->type);
1325
+ ggml_webgpu_set_rows_pipeline_key key = {};
1326
+ key.dst_type = context.dst->type;
1327
+ key.vec4 =
1328
+ (context.dst->type == GGML_TYPE_F32 || context.dst->type == GGML_TYPE_F16) && context.src0->ne[0] % 4 == 0;
1329
+ key.i64_idx = context.src1->type == GGML_TYPE_I64;
1330
+ key.pair_blocks = quantized && ((context.src0->ne[0] / ggml_blck_size(context.dst->type)) % 2 == 0);
506
1331
 
507
1332
  auto it = set_rows_pipelines.find(key);
508
1333
  if (it != set_rows_pipelines.end()) {
@@ -521,6 +1346,14 @@ class ggml_webgpu_shader_lib {
521
1346
  defines.push_back("DST_F16");
522
1347
  variant += "_dstf16";
523
1348
  break;
1349
+ case GGML_TYPE_Q8_0:
1350
+ defines.push_back("DST_Q8_0");
1351
+ variant += "_dstq8_0";
1352
+ break;
1353
+ case GGML_TYPE_Q4_0:
1354
+ defines.push_back("DST_Q4_0");
1355
+ variant += "_dstq4_0";
1356
+ break;
524
1357
  default:
525
1358
  GGML_ABORT("Unsupported dst type for set_rows shader");
526
1359
  }
@@ -533,19 +1366,68 @@ class ggml_webgpu_shader_lib {
533
1366
  defines.push_back("I64_IDX");
534
1367
  variant += "_i64idx";
535
1368
  }
1369
+ if (key.pair_blocks) {
1370
+ defines.push_back("PAIR_BLOCKS");
1371
+ variant += "_pair_blocks";
1372
+ }
536
1373
 
537
1374
  defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
538
1375
 
539
- auto processed = preprocessor.preprocess(wgsl_set_rows, defines);
540
- auto decisions = std::make_shared<ggml_webgpu_set_rows_shader_decisions>();
1376
+ const auto & shader_source = quantized ? wgsl_set_rows_quant : wgsl_set_rows;
1377
+ auto processed = preprocessor.preprocess(shader_source, defines);
1378
+ auto decisions = std::make_shared<ggml_webgpu_set_rows_shader_decisions>();
541
1379
  decisions->vec4 = key.vec4;
542
1380
  decisions->i64_idx = key.i64_idx;
1381
+ decisions->pair_blocks = key.pair_blocks;
543
1382
  decisions->wg_size = context.max_wg_size;
544
1383
  set_rows_pipelines[key] = ggml_webgpu_create_pipeline(device, processed, variant);
545
1384
  set_rows_pipelines[key].context = decisions;
546
1385
  return set_rows_pipelines[key];
547
1386
  }
548
1387
 
1388
+ webgpu_pipeline get_set_pipeline(const ggml_webgpu_shader_lib_context & context) {
1389
+ ggml_webgpu_set_pipeline_key key = {};
1390
+ key.type = context.dst->type;
1391
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
1392
+
1393
+ auto it = set_pipelines.find(key);
1394
+ if (it != set_pipelines.end()) {
1395
+ return it->second;
1396
+ }
1397
+
1398
+ std::vector<std::string> defines;
1399
+ std::string variant = "set";
1400
+
1401
+ switch (key.type) {
1402
+ case GGML_TYPE_F32:
1403
+ defines.push_back("TYPE_F32");
1404
+ variant += "_f32";
1405
+ break;
1406
+ case GGML_TYPE_I32:
1407
+ defines.push_back("TYPE_I32");
1408
+ variant += "_i32";
1409
+ break;
1410
+ default:
1411
+ GGML_ABORT("Unsupported type for set shader");
1412
+ }
1413
+
1414
+ if (key.inplace) {
1415
+ defines.push_back("INPLACE");
1416
+ variant += "_inplace";
1417
+ }
1418
+
1419
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
1420
+
1421
+ auto processed = preprocessor.preprocess(wgsl_set, defines);
1422
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
1423
+ decisions->wg_size = context.max_wg_size;
1424
+ decisions->inplace = key.inplace;
1425
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1426
+ pipeline.context = decisions;
1427
+ set_pipelines[key] = pipeline;
1428
+ return set_pipelines[key];
1429
+ }
1430
+
549
1431
  webgpu_pipeline get_cumsum_pipeline(const ggml_webgpu_shader_lib_context & context) {
550
1432
  auto it = cumsum_pipelines.find(1);
551
1433
  if (it != cumsum_pipelines.end()) {
@@ -614,10 +1496,9 @@ class ggml_webgpu_shader_lib {
614
1496
 
615
1497
  webgpu_pipeline get_get_rows_pipeline(const ggml_webgpu_shader_lib_context & context) {
616
1498
  const bool vectorized = context.src0->type == GGML_TYPE_F32 && context.dst->ne[0] % 4 == 0;
617
- ggml_webgpu_get_rows_pipeline_key key = {
618
- .src_type = context.src0->type,
619
- .vectorized = (int) vectorized,
620
- };
1499
+ ggml_webgpu_get_rows_pipeline_key key = {};
1500
+ key.src_type = context.src0->type;
1501
+ key.vectorized = (int) vectorized;
621
1502
 
622
1503
  auto it = get_rows_pipelines.find(key);
623
1504
  if (it != get_rows_pipelines.end()) {
@@ -632,6 +1513,7 @@ class ggml_webgpu_shader_lib {
632
1513
 
633
1514
  switch (key.src_type) {
634
1515
  case GGML_TYPE_F32:
1516
+ defines.push_back("FLOAT_PARALLEL");
635
1517
  if (key.vectorized) {
636
1518
  defines.push_back("F32_VEC");
637
1519
  defines.push_back("SRC_TYPE=vec4<f32>");
@@ -646,6 +1528,7 @@ class ggml_webgpu_shader_lib {
646
1528
  variant += "_f32";
647
1529
  break;
648
1530
  case GGML_TYPE_F16:
1531
+ defines.push_back("FLOAT_PARALLEL");
649
1532
  defines.push_back("F16");
650
1533
  defines.push_back("SRC_TYPE=f16");
651
1534
  defines.push_back("DST_TYPE=f32");
@@ -653,6 +1536,7 @@ class ggml_webgpu_shader_lib {
653
1536
  variant += "_f16";
654
1537
  break;
655
1538
  case GGML_TYPE_I32:
1539
+ defines.push_back("FLOAT_PARALLEL");
656
1540
  defines.push_back("I32");
657
1541
  defines.push_back("SRC_TYPE=i32");
658
1542
  defines.push_back("DST_TYPE=i32");
@@ -664,22 +1548,54 @@ class ggml_webgpu_shader_lib {
664
1548
  std::string type_upper = type_str;
665
1549
  std::transform(type_upper.begin(), type_upper.end(), type_upper.begin(), ::toupper);
666
1550
 
1551
+ switch (key.src_type) {
1552
+ case GGML_TYPE_Q1_0:
1553
+ case GGML_TYPE_Q4_0:
1554
+ case GGML_TYPE_Q5_0:
1555
+ case GGML_TYPE_Q8_0:
1556
+ case GGML_TYPE_Q3_K:
1557
+ case GGML_TYPE_Q6_K:
1558
+ case GGML_TYPE_IQ2_XXS:
1559
+ case GGML_TYPE_IQ2_XS:
1560
+ case GGML_TYPE_IQ2_S:
1561
+ case GGML_TYPE_IQ3_XXS:
1562
+ case GGML_TYPE_IQ3_S:
1563
+ case GGML_TYPE_IQ1_S:
1564
+ case GGML_TYPE_IQ4_NL:
1565
+ case GGML_TYPE_MXFP4:
1566
+ case GGML_TYPE_NVFP4:
1567
+ {
1568
+ // Quantized types using u32 buffers for portability.
1569
+ defines.push_back("SRC_TYPE=u32");
1570
+ defines.push_back("U32_DEQUANT_HELPERS");
1571
+ break;
1572
+ }
1573
+ default:
1574
+ {
1575
+ defines.push_back(std::string("SRC_TYPE=") + type_str);
1576
+ }
1577
+ }
1578
+
667
1579
  defines.push_back("BYTE_HELPERS");
668
1580
  defines.push_back(type_upper + "_T");
669
1581
  defines.push_back(type_upper);
670
1582
  defines.push_back(type_upper + "_SCALE_MIN");
671
1583
  defines.push_back(type_upper + "_TABLES");
672
1584
  defines.push_back(type_upper + "_GRID");
1585
+ defines.push_back(type_upper + "_LUT");
673
1586
 
674
1587
  variant += "_";
675
1588
  variant += type_str;
676
1589
 
677
- defines.push_back(std::string("SRC_TYPE=") + type_str);
678
1590
  defines.push_back("DST_TYPE=f32");
679
1591
 
680
- if ((key.src_type >= GGML_TYPE_Q4_0 && key.src_type <= GGML_TYPE_Q8_1) ||
681
- key.src_type == GGML_TYPE_IQ4_NL) {
1592
+ if (key.src_type == GGML_TYPE_Q1_0) {
1593
+ defines.push_back("BLOCK_SIZE=128u");
1594
+ } else if ((key.src_type >= GGML_TYPE_Q4_0 && key.src_type <= GGML_TYPE_Q8_1) ||
1595
+ key.src_type == GGML_TYPE_IQ4_NL || key.src_type == GGML_TYPE_MXFP4) {
682
1596
  defines.push_back("BLOCK_SIZE=32u");
1597
+ } else if (key.src_type == GGML_TYPE_NVFP4) {
1598
+ defines.push_back("BLOCK_SIZE=64u");
683
1599
  } else if (key.src_type >= GGML_TYPE_Q2_K) {
684
1600
  defines.push_back("BLOCK_SIZE=256u");
685
1601
  } else {
@@ -705,7 +1621,8 @@ class ggml_webgpu_shader_lib {
705
1621
  }
706
1622
 
707
1623
  webgpu_pipeline get_scale_pipeline(const ggml_webgpu_shader_lib_context & context) {
708
- ggml_webgpu_scale_pipeline_key key = { .inplace = context.inplace };
1624
+ ggml_webgpu_scale_pipeline_key key = {};
1625
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
709
1626
 
710
1627
  auto it = scale_pipelines.find(key);
711
1628
  if (it != scale_pipelines.end()) {
@@ -725,14 +1642,189 @@ class ggml_webgpu_shader_lib {
725
1642
  auto processed = preprocessor.preprocess(wgsl_scale, defines);
726
1643
  auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
727
1644
  decisions->wg_size = context.max_wg_size;
1645
+ decisions->inplace = key.inplace;
728
1646
  webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
729
1647
  pipeline.context = decisions;
730
1648
  scale_pipelines[key] = pipeline;
731
1649
  return scale_pipelines[key];
732
1650
  }
733
1651
 
1652
+ webgpu_pipeline get_solve_tri_pipeline(const ggml_webgpu_shader_lib_context & context) {
1653
+ ggml_webgpu_solve_tri_pipeline_key key = {};
1654
+ key.type = context.dst->type;
1655
+ key.n = (int) context.src0->ne[0];
1656
+ key.k = (int) context.src1->ne[0];
1657
+
1658
+ auto it = solve_tri_pipelines.find(key);
1659
+ if (it != solve_tri_pipelines.end()) {
1660
+ return it->second;
1661
+ }
1662
+
1663
+ std::vector<std::string> defines;
1664
+ std::string variant = "solve_tri";
1665
+
1666
+ switch (key.type) {
1667
+ case GGML_TYPE_F32:
1668
+ variant += "_f32";
1669
+ break;
1670
+ default:
1671
+ GGML_ABORT("Unsupported type for solve_tri shader");
1672
+ }
1673
+
1674
+ const uint32_t wg_size = std::min((uint32_t) key.n, context.max_wg_size);
1675
+ const uint32_t k_tile = wg_size;
1676
+ const uint32_t bytes_per_row = ((uint32_t) key.n + wg_size) * GGML_WEBGPU_F32_SIZE_BYTES;
1677
+ const uint32_t batch_n = (uint32_t) (context.wg_mem_limit_bytes / bytes_per_row);
1678
+
1679
+ defines.push_back(std::string("N=") + std::to_string(key.n));
1680
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
1681
+ defines.push_back(std::string("K_TILE=") + std::to_string(k_tile));
1682
+ defines.push_back(std::string("BATCH_N=") + std::to_string(batch_n));
1683
+
1684
+ auto processed = preprocessor.preprocess(wgsl_solve_tri, defines);
1685
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
1686
+ decisions->wg_size = wg_size;
1687
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1688
+ pipeline.context = decisions;
1689
+ solve_tri_pipelines[key] = pipeline;
1690
+ return solve_tri_pipelines[key];
1691
+ }
1692
+
1693
+ webgpu_pipeline get_ssm_conv_pipeline(const ggml_webgpu_shader_lib_context & context) {
1694
+ ggml_webgpu_ssm_conv_pipeline_key key = {};
1695
+ key.type = context.dst->type;
1696
+ key.vectorized = context.src1->ne[0] == 4;
1697
+
1698
+ auto it = ssm_conv_pipelines.find(key);
1699
+ if (it != ssm_conv_pipelines.end()) {
1700
+ return it->second;
1701
+ }
1702
+
1703
+ std::vector<std::string> defines;
1704
+ std::string variant = "ssm_conv";
1705
+
1706
+ switch (key.type) {
1707
+ case GGML_TYPE_F32:
1708
+ variant += "_f32";
1709
+ break;
1710
+ default:
1711
+ GGML_ABORT("Unsupported type for ssm_conv shader");
1712
+ }
1713
+
1714
+ if (key.vectorized) {
1715
+ defines.push_back("VECTORIZED");
1716
+ variant += "_vec4";
1717
+ }
1718
+
1719
+ constexpr uint32_t block_size = 32u;
1720
+ constexpr uint32_t tokens_per_wg = 8u;
1721
+
1722
+ defines.push_back("BLOCK_SIZE=" + std::to_string(block_size) + "u");
1723
+ defines.push_back("TOKENS_PER_WG=" + std::to_string(tokens_per_wg) + "u");
1724
+
1725
+ auto processed = preprocessor.preprocess(wgsl_ssm_conv, defines);
1726
+ auto decisions = std::make_shared<ggml_webgpu_ssm_conv_shader_decisions>();
1727
+ decisions->block_size = block_size;
1728
+ decisions->tokens_per_wg = tokens_per_wg;
1729
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1730
+ pipeline.context = decisions;
1731
+ ssm_conv_pipelines[key] = pipeline;
1732
+ return ssm_conv_pipelines[key];
1733
+ }
1734
+
1735
+ webgpu_pipeline get_ssm_scan_pipeline(const ggml_webgpu_shader_lib_context & context) {
1736
+ ggml_webgpu_ssm_scan_pipeline_key key = {};
1737
+ key.type = context.dst->type;
1738
+ key.d_state = (int) context.src0->ne[0];
1739
+ key.xbc_overlap = ggml_webgpu_tensor_overlap(context.src1, context.src4) &&
1740
+ ggml_webgpu_tensor_overlap(context.src1, context.src5);
1741
+
1742
+ auto it = ssm_scan_pipelines.find(key);
1743
+ if (it != ssm_scan_pipelines.end()) {
1744
+ return it->second;
1745
+ }
1746
+
1747
+ std::vector<std::string> defines;
1748
+ std::string variant = "ssm_scan";
1749
+
1750
+ switch (key.type) {
1751
+ case GGML_TYPE_F32:
1752
+ variant += "_f32";
1753
+ break;
1754
+ default:
1755
+ GGML_ABORT("Unsupported type for ssm_scan shader");
1756
+ }
1757
+
1758
+ const uint32_t wg_size = (uint32_t) key.d_state;
1759
+
1760
+ constexpr uint32_t tokens_per_tile = 4u;
1761
+
1762
+ defines.push_back("WG_SIZE=" + std::to_string(wg_size) + "u");
1763
+ defines.push_back("TOKENS_PER_TILE=" + std::to_string(tokens_per_tile) + "u");
1764
+
1765
+ if (context.supports_subgroups) {
1766
+ defines.push_back("USE_SUBGROUP_REDUCTION");
1767
+ variant += "_sg_reduce";
1768
+ } else {
1769
+ variant += "_wg_reduce";
1770
+ }
1771
+
1772
+ if (key.xbc_overlap) {
1773
+ defines.push_back("XBC_OVERLAP");
1774
+ }
1775
+
1776
+ variant += "_d" + std::to_string(key.d_state);
1777
+
1778
+ auto processed = preprocessor.preprocess(wgsl_ssm_scan, defines);
1779
+ auto decisions = std::make_shared<ggml_webgpu_ssm_scan_shader_decisions>();
1780
+ decisions->wg_size = wg_size;
1781
+ decisions->tokens_per_tile = tokens_per_tile;
1782
+ decisions->xbc_overlap = key.xbc_overlap;
1783
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1784
+ pipeline.context = decisions;
1785
+ ssm_scan_pipelines[key] = pipeline;
1786
+ return ssm_scan_pipelines[key];
1787
+ }
1788
+
1789
+ webgpu_pipeline get_gated_delta_net_pipeline(const ggml_webgpu_shader_lib_context & context) {
1790
+ ggml_webgpu_gated_delta_net_pipeline_key key = {};
1791
+ key.type = context.dst->type;
1792
+ key.s_v = (int) context.src2->ne[0];
1793
+ key.kda = context.src3->ne[0] == context.src2->ne[0];
1794
+
1795
+ auto it = gated_delta_net_pipelines.find(key);
1796
+ if (it != gated_delta_net_pipelines.end()) {
1797
+ return it->second;
1798
+ }
1799
+
1800
+ std::vector<std::string> defines;
1801
+ std::string variant = "gated_delta_net";
1802
+
1803
+ switch (key.type) {
1804
+ case GGML_TYPE_F32:
1805
+ variant += "_f32";
1806
+ break;
1807
+ default:
1808
+ GGML_ABORT("Unsupported type for gated_delta_net shader");
1809
+ }
1810
+
1811
+ if (key.kda) {
1812
+ defines.push_back("KDA");
1813
+ variant += "_kda";
1814
+ }
1815
+
1816
+ defines.push_back("S_V=" + std::to_string(key.s_v) + "u");
1817
+ defines.push_back("WG_SIZE=" + std::to_string(key.s_v) + "u");
1818
+
1819
+ auto processed = preprocessor.preprocess(wgsl_gated_delta_net, defines);
1820
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1821
+ gated_delta_net_pipelines[key] = pipeline;
1822
+ return gated_delta_net_pipelines[key];
1823
+ }
1824
+
734
1825
  webgpu_pipeline get_pad_pipeline(const ggml_webgpu_shader_lib_context & context) {
735
- ggml_webgpu_pad_pipeline_key key = { .circular = ggml_get_op_params_i32(context.dst, 8) != 0 };
1826
+ ggml_webgpu_pad_pipeline_key key = {};
1827
+ key.circular = ggml_get_op_params_i32(context.dst, 8) != 0;
736
1828
 
737
1829
  auto it = pad_pipelines.find(key);
738
1830
  if (it != pad_pipelines.end()) {
@@ -758,16 +1850,55 @@ class ggml_webgpu_shader_lib {
758
1850
  return pad_pipelines[key];
759
1851
  }
760
1852
 
1853
+ webgpu_pipeline get_quantize_q8_pipeline(const ggml_webgpu_shader_lib_context & context) {
1854
+ ggml_webgpu_quantize_q8_pipeline_key key = {};
1855
+ key.src0_type = context.src0->type;
1856
+
1857
+ auto it = quantize_q8_pipelines.find(key);
1858
+ if (it != quantize_q8_pipelines.end()) {
1859
+ return it->second;
1860
+ }
1861
+ const char * shader_src = wgsl_quantize_q8;
1862
+ std::vector<std::string> defines;
1863
+ std::string variant = "quantize_q8";
1864
+
1865
+ uint32_t wg_size = WEBGPU_MUL_MAT_VEC_WG_SIZE;
1866
+
1867
+ defines.push_back("SRC1_INNER_TYPE=f32");
1868
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
1869
+
1870
+ const struct ggml_type_traits * src0_traits = ggml_get_type_traits(context.src0->type);
1871
+ std::string src0_name = src0_traits->type_name;
1872
+ std::string type_upper = src0_name;
1873
+ variant += "_" + src0_name;
1874
+ std::transform(type_upper.begin(), type_upper.end(), type_upper.begin(), ::toupper);
1875
+
1876
+ defines.push_back("MUL_ACC_" + type_upper);
1877
+ defines.push_back("Q8_1_T");
1878
+
1879
+ defines.push_back(context.supports_subgroups ? "USE_SUBGROUP_REDUCTION" : "USE_WORKGROUP_REDUCTION");
1880
+ variant += context.supports_subgroups ? "_sg_reduce" : "_wg_reduce";
1881
+
1882
+ auto processed = preprocessor.preprocess(shader_src, defines);
1883
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
1884
+ decisions->wg_size = wg_size;
1885
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1886
+ pipeline.context = decisions;
1887
+ quantize_q8_pipelines[key] = pipeline;
1888
+ return quantize_q8_pipelines[key];
1889
+ }
1890
+
761
1891
  webgpu_pipeline get_mul_mat_vec_pipeline(const ggml_webgpu_shader_lib_context & context) {
762
- ggml_webgpu_mul_mat_vec_pipeline_key key = {
763
- .src0_type = context.src0->type,
764
- .src1_type = context.src1->type,
765
- // Quantized mat-vec path currently runs scalar; only allow vectorization when both inputs are float
766
- .vectorized = (context.src0->ne[0] % 4 == 0 && context.dst->ne[0] % 4 == 0 &&
767
- (context.src0->type == GGML_TYPE_F32 || context.src0->type == GGML_TYPE_F16)) ?
768
- 1 :
769
- 0,
770
- };
1892
+ ggml_webgpu_mul_mat_vec_pipeline_key key = {};
1893
+ key.src0_type = context.src0->type;
1894
+ key.src1_type = context.src1->type;
1895
+ key.vectorized = (context.src0->ne[0] % 4 == 0 &&
1896
+ (context.src0->type == GGML_TYPE_F32 || context.src0->type == GGML_TYPE_F16)) ?
1897
+ 1 :
1898
+ 0;
1899
+ key.num_cols = context.dst->ne[1];
1900
+ key.use_mmvq =
1901
+ ggml_webgpu_can_use_mmvq(context.src0, context.src1, context.supports_dot_product, context.vendor);
771
1902
 
772
1903
  auto it = mul_mat_vec_pipelines.find(key);
773
1904
  if (it != mul_mat_vec_pipelines.end()) {
@@ -775,7 +1906,8 @@ class ggml_webgpu_shader_lib {
775
1906
  }
776
1907
 
777
1908
  std::vector<std::string> defines;
778
- std::string variant = "mul_mat_vec";
1909
+ std::string variant = "mul_mat_vec";
1910
+ const char * shader_src = wgsl_mul_mat_vec;
779
1911
 
780
1912
  // src0 type (matrix row)
781
1913
  switch (context.src0->type) {
@@ -800,9 +1932,43 @@ class ggml_webgpu_shader_lib {
800
1932
 
801
1933
  defines.push_back("BYTE_HELPERS");
802
1934
  defines.push_back("MUL_ACC_" + type_upper);
803
-
804
- // For fast path we always dequantize from f16 inside the shader
805
- defines.push_back("SRC0_INNER_TYPE=f16");
1935
+ defines.push_back("U32_DEQUANT_HELPERS");
1936
+ defines.push_back("SRC0_INNER_TYPE=u32");
1937
+ switch (context.src0->type) {
1938
+ case GGML_TYPE_Q8_0:
1939
+ case GGML_TYPE_Q4_0:
1940
+ case GGML_TYPE_Q4_1:
1941
+ if (key.use_mmvq) {
1942
+ defines.push_back("LEGACY_QUANTS");
1943
+ }
1944
+ break;
1945
+ case GGML_TYPE_Q2_K:
1946
+ case GGML_TYPE_Q4_K:
1947
+ if (key.use_mmvq) {
1948
+ defines.push_back("K_QUANTS");
1949
+ }
1950
+ break;
1951
+ case GGML_TYPE_IQ1_S:
1952
+ case GGML_TYPE_IQ1_M:
1953
+ case GGML_TYPE_IQ2_S:
1954
+ case GGML_TYPE_IQ3_S:
1955
+ case GGML_TYPE_IQ4_NL:
1956
+ case GGML_TYPE_IQ4_XS:
1957
+ defines.push_back(type_upper + "_GRID");
1958
+ break;
1959
+ case GGML_TYPE_IQ2_XXS:
1960
+ case GGML_TYPE_IQ2_XS:
1961
+ case GGML_TYPE_IQ3_XXS:
1962
+ defines.push_back(type_upper + "_GRID");
1963
+ defines.push_back(type_upper + "_TABLES");
1964
+ break;
1965
+ case GGML_TYPE_MXFP4:
1966
+ case GGML_TYPE_NVFP4:
1967
+ defines.push_back(type_upper + "_LUT");
1968
+ break;
1969
+ default:
1970
+ break;
1971
+ }
806
1972
  break;
807
1973
  }
808
1974
  }
@@ -825,25 +1991,33 @@ class ggml_webgpu_shader_lib {
825
1991
  defines.push_back(key.vectorized ? "VEC" : "SCALAR");
826
1992
 
827
1993
  uint32_t wg_size = WEBGPU_MUL_MAT_VEC_WG_SIZE;
828
- uint32_t tile_k = WEBGPU_MUL_MAT_VEC_FLOAT_TILE_K;
829
1994
  uint32_t outputs_per_wg = WEBGPU_MUL_MAT_VEC_FLOAT_OUTPUTS_PER_WG;
830
1995
 
831
- if (key.src0_type >= GGML_TYPE_Q2_K) {
832
- tile_k = WEBGPU_MUL_MAT_VEC_K_Q_TILE_K;
1996
+ if (key.src0_type == GGML_TYPE_Q1_0) {
1997
+ outputs_per_wg = WEBGPU_MUL_MAT_VEC_LEGACY_Q_OUTPUTS_PER_WG;
1998
+ } else if (key.src0_type >= GGML_TYPE_Q2_K) {
833
1999
  outputs_per_wg = WEBGPU_MUL_MAT_VEC_K_Q_OUTPUTS_PER_WG;
834
2000
  } else if (key.src0_type >= GGML_TYPE_Q4_0) {
835
- tile_k = WEBGPU_MUL_MAT_VEC_LEGACY_Q_TILE_K;
836
2001
  outputs_per_wg = WEBGPU_MUL_MAT_VEC_LEGACY_Q_OUTPUTS_PER_WG;
837
2002
  }
838
2003
 
2004
+ if (key.use_mmvq) {
2005
+ defines.push_back("MMVQ");
2006
+ defines.push_back("Q8_1_T");
2007
+ }
2008
+
839
2009
  defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
840
- defines.push_back(std::string("TILE_K=") + std::to_string(tile_k));
841
2010
  defines.push_back(std::string("OUTPUTS_PER_WG=") + std::to_string(outputs_per_wg));
2011
+ defines.push_back(context.supports_subgroups ? "USE_SUBGROUP_REDUCTION" : "USE_WORKGROUP_REDUCTION");
2012
+ variant += context.supports_subgroups ? "_sg_reduce" : "_wg_reduce";
2013
+ if (key.vectorized) {
2014
+ variant += "_vectorized";
2015
+ }
2016
+ defines.push_back(std::string("NUM_COLS=") + std::to_string(key.num_cols));
842
2017
 
843
- auto processed = preprocessor.preprocess(wgsl_mul_mat_vec, defines);
2018
+ auto processed = preprocessor.preprocess(shader_src, defines);
844
2019
  auto decisions = std::make_shared<ggml_webgpu_mul_mat_vec_shader_decisions>();
845
2020
  decisions->wg_size = wg_size;
846
- decisions->tile_k = tile_k;
847
2021
  decisions->outputs_per_wg = outputs_per_wg;
848
2022
  decisions->vec_size = key.vectorized ? 4 : 1;
849
2023
 
@@ -854,15 +2028,14 @@ class ggml_webgpu_shader_lib {
854
2028
  }
855
2029
 
856
2030
  webgpu_pipeline get_mul_mat_fast_pipeline(const ggml_webgpu_shader_lib_context & context) {
857
- ggml_webgpu_mul_mat_pipeline_key key = {
858
- .src0_type = context.src0->type,
859
- .src1_type = context.src1->type,
860
- .vectorized = (context.src0->ne[0] % 4 == 0 && context.dst->ne[0] % 4 == 0 && context.dst->ne[1] % 4 == 0 &&
861
- (context.src0->type == GGML_TYPE_F32 || context.src0->type == GGML_TYPE_F16)) ?
862
- 1 :
863
- 0,
864
- .use_subgroup_matrix = context.supports_subgroup_matrix
865
- };
2031
+ ggml_webgpu_mul_mat_pipeline_key key = {};
2032
+ key.src0_type = context.src0->type;
2033
+ key.src1_type = context.src1->type;
2034
+ key.vectorized = (context.src0->ne[0] % 4 == 0 && context.dst->ne[0] % 4 == 0 &&
2035
+ (context.src0->type == GGML_TYPE_F32 || context.src0->type == GGML_TYPE_F16)) ?
2036
+ 1 :
2037
+ 0;
2038
+ key.use_subgroup_matrix = context.supports_subgroup_matrix;
866
2039
 
867
2040
  auto it = mul_mat_fast_pipelines.find(key);
868
2041
  if (it != mul_mat_fast_pipelines.end()) {
@@ -915,9 +2088,31 @@ class ggml_webgpu_shader_lib {
915
2088
  defines.push_back("MUL_ACC_" + type_upper);
916
2089
  defines.push_back("INIT_SRC0_SHMEM_" + type_upper);
917
2090
  defines.push_back("INIT_SRC1_SHMEM_FLOAT");
918
-
919
- // Use f16 inside the shader for quantized types
920
- defines.push_back("SRC0_INNER_TYPE=f16");
2091
+ defines.push_back("U32_DEQUANT_HELPERS");
2092
+ defines.push_back("SRC0_INNER_TYPE=u32");
2093
+
2094
+ switch (context.src0->type) {
2095
+ case GGML_TYPE_IQ1_S:
2096
+ case GGML_TYPE_IQ1_M:
2097
+ case GGML_TYPE_IQ4_NL:
2098
+ case GGML_TYPE_IQ4_XS:
2099
+ defines.push_back(type_upper + "_GRID");
2100
+ break;
2101
+ case GGML_TYPE_IQ2_XXS:
2102
+ case GGML_TYPE_IQ2_XS:
2103
+ case GGML_TYPE_IQ2_S:
2104
+ case GGML_TYPE_IQ3_XXS:
2105
+ case GGML_TYPE_IQ3_S:
2106
+ defines.push_back(type_upper + "_GRID");
2107
+ defines.push_back(type_upper + "_TABLES");
2108
+ break;
2109
+ case GGML_TYPE_MXFP4:
2110
+ case GGML_TYPE_NVFP4:
2111
+ defines.push_back(type_upper + "_LUT");
2112
+ break;
2113
+ default:
2114
+ break;
2115
+ }
921
2116
 
922
2117
  variant += std::string("_") + src0_name;
923
2118
  break;
@@ -927,13 +2122,22 @@ class ggml_webgpu_shader_lib {
927
2122
  // VEC/SCALAR controls
928
2123
  defines.push_back(key.vectorized ? "VEC" : "SCALAR");
929
2124
 
2125
+ const bool is_quant = ggml_is_quantized(context.src0->type);
2126
+
2127
+ uint32_t tile_k;
2128
+ if (key.use_subgroup_matrix) {
2129
+ tile_k = is_quant ? WEBGPU_MUL_MAT_SUBGROUP_TILE_K_QUANT : WEBGPU_MUL_MAT_SUBGROUP_TILE_K_FLOAT;
2130
+ } else {
2131
+ tile_k = is_quant ? WEBGPU_MUL_MAT_REG_TILE_K_QUANT : WEBGPU_MUL_MAT_REG_TILE_K_FLOAT;
2132
+ }
2133
+
930
2134
  // Tiles
931
2135
  defines.push_back("TILE_M=" + std::to_string(WEBGPU_MUL_MAT_TILE_M) + "u");
932
2136
  defines.push_back("TILE_N=" + std::to_string(WEBGPU_MUL_MAT_TILE_N) + "u");
933
- defines.push_back("TILE_K=" + std::to_string(WEBGPU_MUL_MAT_TILE_K) + "u");
934
2137
 
935
2138
  // Subgroup matrix specifics
936
2139
  if (key.use_subgroup_matrix) {
2140
+ defines.push_back("TILE_K=" + std::to_string(tile_k) + "u");
937
2141
  defines.push_back("MAX_SUBGROUP_SIZE=" + std::to_string(context.max_subgroup_size) + "u");
938
2142
  defines.push_back("SUBGROUP_M=" + std::to_string(WEBGPU_MUL_MAT_SUBGROUP_M) + "u");
939
2143
  defines.push_back("SUBGROUP_N=" + std::to_string(WEBGPU_MUL_MAT_SUBGROUP_N) + "u");
@@ -953,12 +2157,13 @@ class ggml_webgpu_shader_lib {
953
2157
  if (!key.use_subgroup_matrix) {
954
2158
  defines.push_back("WORKGROUP_SIZE_M=" + std::to_string(WEBGPU_MUL_MAT_WG_SIZE_M) + "u");
955
2159
  defines.push_back("WORKGROUP_SIZE_N=" + std::to_string(WEBGPU_MUL_MAT_WG_SIZE_N) + "u");
2160
+ defines.push_back("TILE_K=" + std::to_string(tile_k) + "u");
956
2161
  }
957
2162
 
958
2163
  auto processed = preprocessor.preprocess(shader_src, defines);
959
2164
 
960
2165
  auto decisions = std::make_shared<ggml_webgpu_mul_mat_shader_decisions>();
961
- decisions->tile_k = WEBGPU_MUL_MAT_TILE_K;
2166
+ decisions->tile_k = tile_k;
962
2167
  decisions->tile_m = WEBGPU_MUL_MAT_TILE_M;
963
2168
  decisions->tile_n = WEBGPU_MUL_MAT_TILE_N;
964
2169
  decisions->use_subgroup_matrix = key.use_subgroup_matrix;
@@ -981,84 +2186,279 @@ class ggml_webgpu_shader_lib {
981
2186
  return mul_mat_fast_pipelines[key];
982
2187
  }
983
2188
 
984
- webgpu_pipeline get_mul_mat_legacy_pipeline(const ggml_webgpu_shader_lib_context & context) {
985
- ggml_webgpu_legacy_mul_mat_pipeline_key key = { .src0_type = context.src0->type,
986
- .src1_type = context.src1->type };
2189
+ webgpu_pipeline get_mul_mat_id_gather_pipeline(const ggml_webgpu_shader_lib_context & context) {
2190
+ auto it = mul_mat_id_gather_pipelines.find(1);
2191
+ if (it != mul_mat_id_gather_pipelines.end()) {
2192
+ return it->second;
2193
+ }
2194
+ std::vector<std::string> defines;
2195
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
987
2196
 
988
- auto it = mul_mat_legacy_pipelines.find(key);
989
- if (it != mul_mat_legacy_pipelines.end()) {
2197
+ auto processed = preprocessor.preprocess(wgsl_mul_mat_id_gather, defines);
2198
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
2199
+ decisions->wg_size = context.max_wg_size;
2200
+
2201
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, "mul_mat_id_gather");
2202
+ pipeline.context = decisions;
2203
+ mul_mat_id_gather_pipelines[1] = pipeline;
2204
+ return pipeline;
2205
+ }
2206
+
2207
+ webgpu_pipeline get_mul_mat_id_pipeline(const ggml_webgpu_shader_lib_context & context) {
2208
+ ggml_webgpu_mul_mat_id_pipeline_key key = {};
2209
+ key.src0_type = context.src0->type;
2210
+ key.src1_type = context.src1->type;
2211
+ key.n_experts = context.src0->ne[2];
2212
+ key.vectorized = (context.src0->ne[0] % 4 == 0 && context.src0->ne[1] % 4 == 0 &&
2213
+ (context.src0->type == GGML_TYPE_F32 || context.src0->type == GGML_TYPE_F16)) ?
2214
+ 1 :
2215
+ 0;
2216
+
2217
+ auto it = mul_mat_id_pipelines.find(key);
2218
+ if (it != mul_mat_id_pipelines.end()) {
990
2219
  return it->second;
991
2220
  }
992
2221
 
993
2222
  std::vector<std::string> defines;
994
- std::string variant = "mul_mat";
2223
+ std::string variant = "mul_mat_id";
2224
+ defines.push_back("MUL_MAT_ID");
995
2225
 
2226
+ // src1 type
996
2227
  switch (context.src1->type) {
997
2228
  case GGML_TYPE_F32:
998
- defines.push_back("SRC1_TYPE=f32");
999
- variant += "_f32";
2229
+ defines.push_back("SRC1_INNER_TYPE=f32");
1000
2230
  break;
1001
2231
  case GGML_TYPE_F16:
1002
- defines.push_back("SRC1_TYPE=f16");
1003
- variant += "_f16";
2232
+ defines.push_back("SRC1_INNER_TYPE=f16");
1004
2233
  break;
1005
2234
  default:
1006
- GGML_ABORT("Unsupported src1 type for mul_mat legacy shader");
2235
+ GGML_ABORT("Unsupported src1 type for mul_mat fast shader");
1007
2236
  }
1008
2237
 
2238
+ // src0 type
1009
2239
  const struct ggml_type_traits * src0_traits = ggml_get_type_traits(context.src0->type);
1010
2240
  const char * src0_name = src0_traits->type_name;
1011
2241
 
1012
2242
  switch (context.src0->type) {
1013
2243
  case GGML_TYPE_F32:
1014
- defines.push_back("SRC0_TYPE=f32");
1015
- defines.push_back("FLOAT");
2244
+ defines.push_back("SRC0_INNER_TYPE=f32");
2245
+ defines.push_back("INIT_SRC0_SHMEM_FLOAT");
2246
+ defines.push_back("INIT_SRC1_SHMEM_FLOAT");
1016
2247
  variant += "_f32";
1017
2248
  break;
1018
2249
  case GGML_TYPE_F16:
1019
- defines.push_back("SRC0_TYPE=f16");
1020
- defines.push_back("FLOAT");
2250
+ defines.push_back("SRC0_INNER_TYPE=f16");
2251
+ defines.push_back("INIT_SRC0_SHMEM_FLOAT");
2252
+ defines.push_back("INIT_SRC1_SHMEM_FLOAT");
1021
2253
  variant += "_f16";
1022
2254
  break;
1023
2255
  default:
1024
2256
  {
1025
- // quantized types
1026
2257
  std::string type_upper = src0_name;
1027
2258
  std::transform(type_upper.begin(), type_upper.end(), type_upper.begin(), ::toupper);
1028
2259
 
1029
- defines.push_back(std::string("SRC0_TYPE=") + src0_name);
1030
2260
  defines.push_back("BYTE_HELPERS");
1031
- defines.push_back(type_upper + "_T");
1032
- defines.push_back(type_upper);
1033
- defines.push_back(type_upper + "_SCALE_MIN");
1034
- defines.push_back(type_upper + "_TABLES");
1035
- defines.push_back(type_upper + "_GRID");
2261
+ defines.push_back("INIT_SRC0_SHMEM_" + type_upper);
2262
+ defines.push_back("INIT_SRC1_SHMEM_FLOAT");
2263
+ defines.push_back("U32_DEQUANT_HELPERS");
2264
+ defines.push_back("SRC0_INNER_TYPE=u32");
2265
+
2266
+ switch (context.src0->type) {
2267
+ case GGML_TYPE_IQ1_S:
2268
+ case GGML_TYPE_IQ1_M:
2269
+ case GGML_TYPE_IQ4_NL:
2270
+ case GGML_TYPE_IQ4_XS:
2271
+ defines.push_back(type_upper + "_GRID");
2272
+ break;
2273
+ case GGML_TYPE_IQ2_XXS:
2274
+ case GGML_TYPE_IQ2_XS:
2275
+ case GGML_TYPE_IQ2_S:
2276
+ case GGML_TYPE_IQ3_XXS:
2277
+ case GGML_TYPE_IQ3_S:
2278
+ defines.push_back(type_upper + "_GRID");
2279
+ defines.push_back(type_upper + "_TABLES");
2280
+ break;
2281
+ case GGML_TYPE_MXFP4:
2282
+ case GGML_TYPE_NVFP4:
2283
+ defines.push_back(type_upper + "_LUT");
2284
+ break;
2285
+ default:
2286
+ break;
2287
+ }
1036
2288
 
1037
2289
  variant += std::string("_") + src0_name;
1038
2290
  break;
1039
2291
  }
1040
2292
  }
1041
2293
 
1042
- auto processed = preprocessor.preprocess(wgsl_mul_mat, defines);
2294
+ // VEC/SCALAR controls
2295
+ defines.push_back(key.vectorized ? "VEC" : "SCALAR");
1043
2296
 
1044
- auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
1045
- decisions->wg_size = WEBGPU_MUL_MAT_WG_SIZE;
2297
+ // mul_mat_id is register-tile only.
2298
+ const uint32_t tile_k =
2299
+ ggml_is_quantized(context.src0->type) ? WEBGPU_MUL_MAT_REG_TILE_K_QUANT : WEBGPU_MUL_MAT_REG_TILE_K_FLOAT;
2300
+
2301
+ // Tiles
2302
+ defines.push_back("TILE_M=" + std::to_string(WEBGPU_MUL_MAT_TILE_M) + "u");
2303
+ defines.push_back("TILE_N=" + std::to_string(WEBGPU_MUL_MAT_TILE_N) + "u");
2304
+ defines.push_back("TILE_K=" + std::to_string(tile_k) + "u");
2305
+
2306
+ defines.push_back("WORKGROUP_SIZE_M=" + std::to_string(WEBGPU_MUL_MAT_WG_SIZE_M) + "u");
2307
+ defines.push_back("WORKGROUP_SIZE_N=" + std::to_string(WEBGPU_MUL_MAT_WG_SIZE_N) + "u");
2308
+
2309
+ // variant suffix for src1 type
2310
+ variant += std::string("_") + (context.src1->type == GGML_TYPE_F32 ? "f32" : "f16");
2311
+ if (key.vectorized) {
2312
+ variant += "_vectorized";
2313
+ }
2314
+
2315
+ auto processed = preprocessor.preprocess(wgsl_mul_mat_id, defines);
2316
+
2317
+ auto decisions = std::make_shared<ggml_webgpu_mul_mat_shader_decisions>();
2318
+ decisions->tile_k = tile_k;
2319
+ decisions->tile_m = WEBGPU_MUL_MAT_TILE_M;
2320
+ decisions->tile_n = WEBGPU_MUL_MAT_TILE_N;
2321
+ decisions->wg_size_m = WEBGPU_MUL_MAT_WG_SIZE_M;
2322
+ decisions->wg_size_n = WEBGPU_MUL_MAT_WG_SIZE_N;
2323
+ decisions->wg_size = WEBGPU_MUL_MAT_WG_SIZE_M * WEBGPU_MUL_MAT_WG_SIZE_N;
2324
+
2325
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
2326
+ pipeline.context = decisions;
2327
+ mul_mat_id_pipelines[key] = pipeline;
2328
+ return mul_mat_id_pipelines[key];
2329
+ }
2330
+
2331
+ webgpu_pipeline get_mul_mat_id_vec_pipeline(const ggml_webgpu_shader_lib_context & context) {
2332
+ ggml_webgpu_mul_mat_id_pipeline_key key = {};
2333
+ key.src0_type = context.src0->type;
2334
+ key.src1_type = context.src1->type;
2335
+ key.n_experts = context.src0->ne[2];
2336
+ key.vectorized = (context.src0->ne[0] % 4 == 0 &&
2337
+ (context.src0->type == GGML_TYPE_F32 || context.src0->type == GGML_TYPE_F16)) ?
2338
+ 1 :
2339
+ 0;
2340
+
2341
+ auto it = mul_mat_id_vec_pipelines.find(key);
2342
+ if (it != mul_mat_id_vec_pipelines.end()) {
2343
+ return it->second;
2344
+ }
2345
+
2346
+ std::vector<std::string> defines;
2347
+ std::string variant = "mul_mat_id_vec";
2348
+ const char * shader_src = wgsl_mul_mat_id_vec;
2349
+
2350
+ // src1 type
2351
+ switch (context.src1->type) {
2352
+ case GGML_TYPE_F32:
2353
+ defines.push_back("SRC1_INNER_TYPE=f32");
2354
+ break;
2355
+ case GGML_TYPE_F16:
2356
+ defines.push_back("SRC1_INNER_TYPE=f16");
2357
+ break;
2358
+ default:
2359
+ GGML_ABORT("Unsupported src1 type for mul_mat fast shader");
2360
+ }
2361
+
2362
+ // src0 type
2363
+ switch (context.src0->type) {
2364
+ case GGML_TYPE_F32:
2365
+ defines.push_back("SRC0_INNER_TYPE=f32");
2366
+ defines.push_back("MUL_ACC_FLOAT");
2367
+ variant += "_f32";
2368
+ break;
2369
+ case GGML_TYPE_F16:
2370
+ defines.push_back("SRC0_INNER_TYPE=f16");
2371
+ defines.push_back("MUL_ACC_FLOAT");
2372
+ variant += "_f16";
2373
+ break;
2374
+ default:
2375
+ {
2376
+ // Quantized types: use helpers but accumulate in f16
2377
+ const struct ggml_type_traits * src0_traits = ggml_get_type_traits(context.src0->type);
2378
+ std::string src0_name = src0_traits->type_name;
2379
+ std::string type_upper = src0_name;
2380
+ variant += "_" + src0_name;
2381
+ std::transform(type_upper.begin(), type_upper.end(), type_upper.begin(), ::toupper);
2382
+
2383
+ defines.push_back("BYTE_HELPERS");
2384
+ defines.push_back("MUL_ACC_" + type_upper);
2385
+ defines.push_back("U32_DEQUANT_HELPERS");
2386
+ defines.push_back("SRC0_INNER_TYPE=u32");
2387
+ switch (context.src0->type) {
2388
+ case GGML_TYPE_IQ1_S:
2389
+ case GGML_TYPE_IQ1_M:
2390
+ case GGML_TYPE_IQ2_S:
2391
+ case GGML_TYPE_IQ3_S:
2392
+ case GGML_TYPE_IQ4_NL:
2393
+ case GGML_TYPE_IQ4_XS:
2394
+ defines.push_back(type_upper + "_GRID");
2395
+ break;
2396
+ case GGML_TYPE_IQ2_XXS:
2397
+ case GGML_TYPE_IQ2_XS:
2398
+ case GGML_TYPE_IQ3_XXS:
2399
+ defines.push_back(type_upper + "_GRID");
2400
+ defines.push_back(type_upper + "_TABLES");
2401
+ break;
2402
+ case GGML_TYPE_MXFP4:
2403
+ case GGML_TYPE_NVFP4:
2404
+ defines.push_back(type_upper + "_LUT");
2405
+ break;
2406
+ default:
2407
+ break;
2408
+ }
2409
+ break;
2410
+ }
2411
+ }
2412
+
2413
+ // VEC/SCALAR controls
2414
+ defines.push_back(key.vectorized ? "VEC" : "SCALAR");
2415
+
2416
+ uint32_t wg_size = WEBGPU_MUL_MAT_VEC_WG_SIZE;
2417
+ uint32_t outputs_per_wg = WEBGPU_MUL_MAT_VEC_FLOAT_OUTPUTS_PER_WG;
2418
+
2419
+ if (key.src0_type == GGML_TYPE_Q1_0) {
2420
+ outputs_per_wg = WEBGPU_MUL_MAT_VEC_LEGACY_Q_OUTPUTS_PER_WG;
2421
+ } else if (key.src0_type >= GGML_TYPE_Q2_K) {
2422
+ outputs_per_wg = WEBGPU_MUL_MAT_VEC_K_Q_OUTPUTS_PER_WG;
2423
+ } else if (key.src0_type >= GGML_TYPE_Q4_0) {
2424
+ outputs_per_wg = WEBGPU_MUL_MAT_VEC_LEGACY_Q_OUTPUTS_PER_WG;
2425
+ }
2426
+
2427
+ // variant suffix for src1 type
2428
+ variant += std::string("_") + (context.src1->type == GGML_TYPE_F32 ? "f32" : "f16");
2429
+
2430
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
2431
+ defines.push_back(std::string("OUTPUTS_PER_WG=") + std::to_string(outputs_per_wg));
2432
+ defines.push_back(context.supports_subgroups ? "USE_SUBGROUP_REDUCTION" : "USE_WORKGROUP_REDUCTION");
2433
+ variant += context.supports_subgroups ? "_sg_reduce" : "_wg_reduce";
2434
+ if (key.vectorized) {
2435
+ variant += "_vectorized";
2436
+ }
2437
+ defines.push_back(std::string("NUM_COLS=1"));
2438
+
2439
+ defines.push_back(std::string("N_EXPERTS=") + std::to_string(key.n_experts));
2440
+
2441
+ auto processed = preprocessor.preprocess(shader_src, defines);
2442
+
2443
+ auto decisions = std::make_shared<ggml_webgpu_mul_mat_vec_shader_decisions>();
2444
+ decisions->wg_size = wg_size;
2445
+ decisions->outputs_per_wg = outputs_per_wg;
1046
2446
 
1047
2447
  webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1048
2448
  pipeline.context = decisions;
1049
- mul_mat_legacy_pipelines[key] = pipeline;
1050
- return mul_mat_legacy_pipelines[key];
2449
+ mul_mat_id_vec_pipelines[key] = pipeline;
2450
+ return mul_mat_id_vec_pipelines[key];
1051
2451
  }
1052
2452
 
1053
2453
  webgpu_pipeline get_unary_pipeline(const ggml_webgpu_shader_lib_context & context) {
1054
2454
  const bool is_unary = context.dst->op == GGML_OP_UNARY;
1055
2455
  const int op = is_unary ? (int) ggml_get_unary_op(context.dst) : context.dst->op;
1056
- ggml_webgpu_unary_pipeline_key key = {
1057
- .type = context.dst->type,
1058
- .op = op,
1059
- .is_unary = is_unary,
1060
- .inplace = context.inplace,
1061
- };
2456
+ ggml_webgpu_unary_pipeline_key key = {};
2457
+ key.type = context.dst->type;
2458
+ key.op = op;
2459
+ key.is_unary = is_unary;
2460
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst) || context.dst->op == GGML_OP_FILL;
2461
+ key.ttype = (ggml_tri_type) ggml_get_op_params_i32(context.dst, 0);
1062
2462
 
1063
2463
  auto it = unary_pipelines.find(key);
1064
2464
  if (it != unary_pipelines.end()) {
@@ -1088,25 +2488,88 @@ class ggml_webgpu_shader_lib {
1088
2488
  variant += "_inplace";
1089
2489
  }
1090
2490
 
2491
+ if (op == GGML_OP_TRI) {
2492
+ switch (key.ttype) {
2493
+ case GGML_TRI_TYPE_LOWER:
2494
+ defines.push_back("TRI_TYPE_LOWER");
2495
+ variant += "_tri_type_lower";
2496
+ break;
2497
+ case GGML_TRI_TYPE_LOWER_DIAG:
2498
+ defines.push_back("TRI_TYPE_LOWER_DIAG");
2499
+ variant += "_tri_type_lower_diag";
2500
+ break;
2501
+ case GGML_TRI_TYPE_UPPER:
2502
+ defines.push_back("TRI_TYPE_UPPER");
2503
+ variant += "_tri_type_upper";
2504
+ break;
2505
+ case GGML_TRI_TYPE_UPPER_DIAG:
2506
+ defines.push_back("TRI_TYPE_UPPER_DIAG");
2507
+ variant += "_tri_upper_diag";
2508
+ break;
2509
+ default:
2510
+ GGML_ABORT("Unsupported ggml_tri_type for unary shader");
2511
+ }
2512
+ }
2513
+
1091
2514
  defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
1092
2515
 
1093
2516
  auto processed = preprocessor.preprocess(wgsl_unary, defines);
1094
2517
  auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
1095
2518
  decisions->wg_size = context.max_wg_size;
2519
+ decisions->inplace = key.inplace;
1096
2520
  webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1097
2521
  pipeline.context = decisions;
1098
2522
  unary_pipelines[key] = pipeline;
1099
2523
  return unary_pipelines[key];
1100
2524
  }
1101
2525
 
2526
+ webgpu_pipeline get_rms_norm_mul_pipeline(const ggml_webgpu_shader_lib_context & context) {
2527
+ ggml_webgpu_rms_norm_mul_pipeline_key key = {};
2528
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
2529
+ key.overlap = ggml_webgpu_tensor_equal(context.src1, context.dst);
2530
+ key.src_overlap = ggml_webgpu_tensor_overlap(context.src0, context.src1);
2531
+
2532
+ auto it = rms_norm_mul_pipelines.find(key);
2533
+ if (it != rms_norm_mul_pipelines.end()) {
2534
+ return it->second;
2535
+ }
2536
+
2537
+ std::vector<std::string> defines;
2538
+ std::string op_name = "RMS_NORM_MUL";
2539
+ std::string variant = op_name;
2540
+
2541
+ if (key.inplace) {
2542
+ defines.push_back("INPLACE");
2543
+ variant += "_inplace";
2544
+ } else if (key.overlap) {
2545
+ defines.push_back("OVERLAP");
2546
+ variant += "_overlap";
2547
+ } else if (key.src_overlap) {
2548
+ defines.push_back("SRC_OVERLAP");
2549
+ variant += "_src_overlap";
2550
+ }
2551
+
2552
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
2553
+
2554
+ auto processed = preprocessor.preprocess(wgsl_rms_norm_mul, defines);
2555
+ auto pipeline_decisions = std::make_shared<ggml_webgpu_rms_norm_mul_shader_decisions>();
2556
+ pipeline_decisions->wg_size = context.max_wg_size;
2557
+ pipeline_decisions->inplace = key.inplace;
2558
+ pipeline_decisions->overlap = key.overlap;
2559
+ pipeline_decisions->src_overlap = key.src_overlap;
2560
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
2561
+ pipeline.context = pipeline_decisions;
2562
+ rms_norm_mul_pipelines[key] = pipeline;
2563
+ return rms_norm_mul_pipelines[key];
2564
+ }
2565
+
1102
2566
  webgpu_pipeline get_binary_pipeline(const ggml_webgpu_shader_lib_context & context) {
1103
- ggml_webgpu_binary_pipeline_key key = {
1104
- .type = context.dst->type,
1105
- .op = context.dst->op,
1106
- .inplace = context.inplace,
1107
- .overlap = context.overlap,
1108
- .src_overlap = context.src_overlap,
1109
- };
2567
+ ggml_webgpu_binary_pipeline_key key = {};
2568
+ key.type = context.dst->type;
2569
+ key.op = context.dst->op;
2570
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
2571
+ key.overlap = ggml_webgpu_tensor_equal(context.src1, context.dst);
2572
+ key.src_overlap = ggml_webgpu_tensor_overlap(context.src0, context.src1);
1110
2573
 
1111
2574
  auto it = binary_pipelines.find(key);
1112
2575
  if (it != binary_pipelines.end()) {
@@ -1145,19 +2608,54 @@ class ggml_webgpu_shader_lib {
1145
2608
 
1146
2609
  defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
1147
2610
 
1148
- auto processed = preprocessor.preprocess(wgsl_binary, defines);
1149
- auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
1150
- decisions->wg_size = context.max_wg_size;
2611
+ auto processed = preprocessor.preprocess(wgsl_binary, defines);
2612
+ auto pipeline_decisions = std::make_shared<ggml_webgpu_binary_shader_decisions>();
2613
+ pipeline_decisions->wg_size = context.max_wg_size;
2614
+ pipeline_decisions->inplace = key.inplace;
2615
+ pipeline_decisions->overlap = key.overlap;
2616
+ pipeline_decisions->src_overlap = key.src_overlap;
2617
+
1151
2618
  webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1152
- pipeline.context = decisions;
2619
+ pipeline.context = pipeline_decisions;
1153
2620
  binary_pipelines[key] = pipeline;
1154
2621
  return binary_pipelines[key];
1155
2622
  }
1156
2623
 
2624
+ webgpu_pipeline get_add_id_pipeline(const ggml_webgpu_shader_lib_context & context) {
2625
+ ggml_webgpu_add_id_pipeline_key key = {};
2626
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
2627
+
2628
+ auto it = add_id_pipelines.find(key);
2629
+ if (it != add_id_pipelines.end()) {
2630
+ return it->second;
2631
+ }
2632
+
2633
+ std::vector<std::string> defines;
2634
+ std::string variant = "add_id";
2635
+ const char * shader_src = wgsl_add_id;
2636
+
2637
+ if (key.inplace) {
2638
+ defines.push_back("INPLACE");
2639
+ variant += "_inplace";
2640
+ }
2641
+
2642
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
2643
+
2644
+ auto processed = preprocessor.preprocess(shader_src, defines);
2645
+ auto pipeline_decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
2646
+ pipeline_decisions->wg_size = context.max_wg_size;
2647
+ pipeline_decisions->inplace = key.inplace;
2648
+
2649
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
2650
+ pipeline.context = pipeline_decisions;
2651
+ add_id_pipelines[key] = pipeline;
2652
+ return pipeline;
2653
+ }
2654
+
1157
2655
  webgpu_pipeline get_concat_pipeline(const ggml_webgpu_shader_lib_context & context) {
1158
- ggml_webgpu_concat_pipeline_key key = {
1159
- .type = context.dst->type,
1160
- };
2656
+ ggml_webgpu_concat_pipeline_key key = {};
2657
+ key.type = context.dst->type;
2658
+ key.src_overlap = ggml_webgpu_tensor_overlap(context.src0, context.src1);
1161
2659
 
1162
2660
  auto it = concat_pipelines.find(key);
1163
2661
  if (it != concat_pipelines.end()) {
@@ -1180,11 +2678,17 @@ class ggml_webgpu_shader_lib {
1180
2678
  GGML_ABORT("Unsupported type for concat shader");
1181
2679
  }
1182
2680
 
2681
+ if (key.src_overlap) {
2682
+ defines.push_back("SRC_OVERLAP");
2683
+ variant += "_src_overlap";
2684
+ }
2685
+
1183
2686
  defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
1184
2687
 
1185
2688
  auto processed = preprocessor.preprocess(wgsl_concat, defines);
1186
- auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
2689
+ auto decisions = std::make_shared<ggml_webgpu_binary_shader_decisions>();
1187
2690
  decisions->wg_size = context.max_wg_size;
2691
+ decisions->src_overlap = key.src_overlap;
1188
2692
  webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1189
2693
  pipeline.context = decisions;
1190
2694
  concat_pipelines[key] = pipeline;
@@ -1192,9 +2696,8 @@ class ggml_webgpu_shader_lib {
1192
2696
  }
1193
2697
 
1194
2698
  webgpu_pipeline get_repeat_pipeline(const ggml_webgpu_shader_lib_context & context) {
1195
- ggml_webgpu_repeat_pipeline_key key = {
1196
- .type = context.dst->type,
1197
- };
2699
+ ggml_webgpu_repeat_pipeline_key key = {};
2700
+ key.type = context.dst->type;
1198
2701
 
1199
2702
  auto it = repeat_pipelines.find(key);
1200
2703
  if (it != repeat_pipelines.end()) {
@@ -1233,102 +2736,544 @@ class ggml_webgpu_shader_lib {
1233
2736
  }
1234
2737
 
1235
2738
  webgpu_pipeline get_flash_attn_pipeline(const ggml_webgpu_shader_lib_context & context) {
1236
- const bool has_mask = context.src3 != nullptr;
1237
- const bool has_sinks = context.src4 != nullptr;
1238
-
1239
- bool kv_direct = (context.src1->type == GGML_TYPE_F16) && (context.src0->ne[0] % context.sg_mat_k == 0) &&
1240
- (context.src1->ne[1] % context.sg_mat_n == 0);
1241
-
1242
- ggml_webgpu_flash_attn_pipeline_key key = {
1243
- .kv_type = context.src1->type,
1244
- .head_dim_qk = (uint32_t) context.src0->ne[0],
1245
- .head_dim_v = (uint32_t) context.src2->ne[0],
1246
- .kv_direct = kv_direct,
1247
- .has_mask = has_mask,
1248
- .has_sinks = has_sinks,
1249
- .uses_logit_softcap = (*(float *) &context.dst->op_params[2]) != 0.0f,
1250
- };
2739
+ const bool can_use_subgroup_matrix = ggml_webgpu_flash_attn_can_use_subgroup_matrix_path(
2740
+ context.supports_subgroup_matrix, context.sg_mat_k, context.sg_mat_n, context.src0, context.src2);
2741
+ ggml_webgpu_flash_attn_decisions decisions = {};
2742
+ decisions.use_sg_matrix = can_use_subgroup_matrix;
2743
+ decisions.q_tile = decisions.use_sg_matrix ? context.sg_mat_m : GGML_WEBGPU_FLASH_ATTN_TILE_Q_TILE;
2744
+
2745
+ ggml_webgpu_flash_attn_pipeline_key key = {};
2746
+ key.common =
2747
+ ggml_webgpu_flash_attn_make_common_pipeline_key(context, decisions.use_sg_matrix ? context.sg_mat_k : 1u);
2748
+ key.common.kv_direct = decisions.use_sg_matrix && key.common.kv_direct;
2749
+ key.use_sg_matrix = decisions.use_sg_matrix;
2750
+
2751
+ const uint32_t max_kv_tile = ggml_webgpu_flash_attn_max_kv_tile(
2752
+ context.wg_mem_limit_bytes, decisions.q_tile, decisions.use_sg_matrix ? context.sg_mat_n : 1u,
2753
+ key.common.head_dim_qk, key.common.head_dim_v, key.common.has_mask, key.common.kv_direct);
2754
+ GGML_ASSERT(max_kv_tile > 0);
2755
+
2756
+ decisions.kv_tile = decisions.use_sg_matrix ?
2757
+ std::min(max_kv_tile, context.sg_mat_n * GGML_WEBGPU_FLASH_ATTN_PREFERRED_KV_SG_TILES) :
2758
+ std::min(GGML_WEBGPU_FLASH_ATTN_TILE_MAX_KV_TILE, max_kv_tile);
2759
+ decisions.wg_size =
2760
+ decisions.use_sg_matrix ?
2761
+ std::max(context.max_subgroup_size, GGML_WEBGPU_FLASH_ATTN_PREFERRED_WG_SIZE) :
2762
+ std::min(context.max_wg_size, std::max(GGML_WEBGPU_FLASH_ATTN_PREFERRED_WG_SIZE,
2763
+ GGML_WEBGPU_FLASH_ATTN_TILE_Q_TILE * context.max_subgroup_size));
2764
+
2765
+ if (key.common.kv_direct) {
2766
+ decisions.kv_tile = std::min(decisions.kv_tile, GGML_WEBGPU_KV_SEQ_PAD);
2767
+ while (GGML_WEBGPU_KV_SEQ_PAD % decisions.kv_tile != 0) {
2768
+ decisions.kv_tile -= decisions.use_sg_matrix ? context.sg_mat_n : context.min_subgroup_size;
2769
+ }
2770
+ }
1251
2771
 
1252
2772
  auto it = flash_attn_pipelines.find(key);
1253
2773
  if (it != flash_attn_pipelines.end()) {
1254
2774
  return it->second;
1255
2775
  }
1256
2776
 
2777
+ std::string variant = decisions.use_sg_matrix ? "flash_attn" : "flash_attn_tile";
2778
+ std::vector<std::string> defines = ggml_webgpu_flash_attn_common_defines(key.common, variant, decisions.q_tile,
2779
+ decisions.kv_tile, decisions.wg_size);
2780
+ const char * shader_src = nullptr;
2781
+ if (!key.use_sg_matrix) {
2782
+ shader_src = wgsl_flash_attn_tile;
2783
+ defines.push_back("MIN_SUBGROUP_SIZE=" + std::to_string(context.min_subgroup_size) + "u");
2784
+ defines.push_back("MAX_SUBGROUP_SIZE=" + std::to_string(context.max_subgroup_size) + "u");
2785
+ variant += "_tile_sg" + std::to_string(context.min_subgroup_size) + "_" +
2786
+ std::to_string(context.max_subgroup_size);
2787
+ } else {
2788
+ shader_src = wgsl_flash_attn;
2789
+ defines.push_back(std::string("SG_MAT_M=") + std::to_string(context.sg_mat_m));
2790
+ defines.push_back(std::string("SG_MAT_N=") + std::to_string(context.sg_mat_n));
2791
+ defines.push_back(std::string("SG_MAT_K=") + std::to_string(context.sg_mat_k));
2792
+ }
2793
+ auto pipeline_decisions = std::make_shared<ggml_webgpu_flash_attn_decisions>(decisions);
2794
+ webgpu_pipeline pipeline =
2795
+ ggml_webgpu_create_pipeline(device, preprocessor.preprocess(shader_src, defines), variant);
2796
+ pipeline.context = pipeline_decisions;
2797
+ flash_attn_pipelines[key] = pipeline;
2798
+ return flash_attn_pipelines[key];
2799
+ }
2800
+
2801
+ webgpu_pipeline get_flash_attn_vec_pipeline(const ggml_webgpu_shader_lib_context & context) {
2802
+ ggml_webgpu_flash_attn_vec_pipeline_key key = {};
2803
+ key.common = ggml_webgpu_flash_attn_make_common_pipeline_key(context, GGML_WEBGPU_FLASH_ATTN_TILE_KV_VEC_WIDTH);
2804
+
2805
+ auto it = flash_attn_vec_pipelines.find(key);
2806
+ if (it != flash_attn_vec_pipelines.end()) {
2807
+ return it->second;
2808
+ }
2809
+
2810
+ ggml_webgpu_flash_attn_vec_decisions decisions = {};
2811
+ decisions.kv_tile =
2812
+ ggml_webgpu_flash_attn_get_vec_kv_tile(context.wg_mem_limit_bytes, key.common.head_dim_qk,
2813
+ key.common.head_dim_v, key.common.has_mask, key.common.kv_direct);
2814
+ decisions.wg_size = context.max_subgroup_size;
2815
+
2816
+ std::string variant = "flash_attn_vec";
2817
+ std::vector<std::string> defines =
2818
+ ggml_webgpu_flash_attn_common_defines(key.common, variant, 1u, decisions.kv_tile, decisions.wg_size);
2819
+ if (key.common.has_mask) {
2820
+ defines.push_back("BLK");
2821
+ variant.resize(variant.size() - (sizeof("_mask") - 1));
2822
+ variant += "_mask_blk";
2823
+ }
2824
+
2825
+ uint32_t d_split = context.min_subgroup_size;
2826
+ if (key.common.k_type == GGML_TYPE_F16 && key.common.v_type == GGML_TYPE_F16) {
2827
+ const uint32_t D = key.common.head_dim_qk | key.common.head_dim_v;
2828
+ const uint32_t D_lsb = D & (~(D - 1u));
2829
+ d_split = std::min(std::min(context.min_subgroup_size, 4u), std::max(D_lsb / 4u, 1u));
2830
+ }
2831
+
2832
+ defines.push_back(std::string("D_SPLIT=") + std::to_string(d_split));
2833
+ variant += "_dsplit" + std::to_string(d_split);
2834
+
2835
+ auto pipeline_decisions = std::make_shared<ggml_webgpu_flash_attn_vec_decisions>(decisions);
2836
+ webgpu_pipeline pipeline =
2837
+ ggml_webgpu_create_pipeline(device, preprocessor.preprocess(wgsl_flash_attn_vec_split, defines), variant);
2838
+ pipeline.context = pipeline_decisions;
2839
+ flash_attn_vec_pipelines[key] = pipeline;
2840
+ return flash_attn_vec_pipelines[key];
2841
+ }
2842
+
2843
+ webgpu_pipeline get_flash_attn_blk_pipeline(const ggml_webgpu_shader_lib_context & context, uint32_t kv_tile) {
2844
+ ggml_webgpu_flash_attn_blk_pipeline_key key = {};
2845
+ key.kv_tile = kv_tile;
2846
+ auto it = flash_attn_blk_pipelines.find(key);
2847
+ if (it != flash_attn_blk_pipelines.end()) {
2848
+ return it->second;
2849
+ }
2850
+
1257
2851
  std::vector<std::string> defines;
1258
- std::string variant = "flash_attn";
2852
+ std::string variant = "flash_attn_vec_blk";
1259
2853
 
1260
- switch (key.kv_type) {
2854
+ defines.push_back(std::string("KV_TILE=") + std::to_string(key.kv_tile));
2855
+ variant += std::string("_kvt") + std::to_string(key.kv_tile);
2856
+
2857
+ uint32_t wg_size = 1;
2858
+ while ((wg_size << 1) <= context.max_wg_size) {
2859
+ wg_size <<= 1;
2860
+ }
2861
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
2862
+ variant += std::string("_wg") + std::to_string(wg_size);
2863
+
2864
+ webgpu_pipeline pipeline =
2865
+ ggml_webgpu_create_pipeline(device, preprocessor.preprocess(wgsl_flash_attn_vec_blk, defines), variant);
2866
+ flash_attn_blk_pipelines[key] = pipeline;
2867
+ return flash_attn_blk_pipelines[key];
2868
+ }
2869
+
2870
+ webgpu_pipeline get_flash_attn_vec_reduce_pipeline(const ggml_webgpu_shader_lib_context & context) {
2871
+ ggml_webgpu_flash_attn_vec_reduce_pipeline_key key = {};
2872
+ key.head_dim_v = (uint32_t) context.src2->ne[0];
2873
+ key.dst_type = context.dst->type;
2874
+ key.wg_size = context.max_wg_size;
2875
+ auto it = flash_attn_vec_reduce_pipelines.find(key);
2876
+ if (it != flash_attn_vec_reduce_pipelines.end()) {
2877
+ return it->second;
2878
+ }
2879
+
2880
+ std::vector<std::string> defines;
2881
+ std::string variant = "flash_attn_vec_reduce";
2882
+
2883
+ switch (key.dst_type) {
1261
2884
  case GGML_TYPE_F32:
1262
- defines.push_back("KV_F32");
2885
+ defines.push_back("DST_F32");
1263
2886
  break;
1264
2887
  case GGML_TYPE_F16:
1265
- defines.push_back("KV_F16");
2888
+ defines.push_back("DST_F16");
1266
2889
  break;
1267
- case GGML_TYPE_Q4_0:
1268
- defines.push_back("KV_Q4_0");
2890
+ default:
2891
+ GGML_ABORT("Unsupported dst type for flash attention vec reduce shader");
2892
+ }
2893
+ variant += std::string("_dst") + ggml_type_name(key.dst_type);
2894
+
2895
+ defines.push_back(std::string("HEAD_DIM_V=") + std::to_string(key.head_dim_v));
2896
+ variant += std::string("_hsv") + std::to_string(key.head_dim_v);
2897
+
2898
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
2899
+ variant += std::string("_wg") + std::to_string(context.max_wg_size);
2900
+
2901
+ webgpu_pipeline pipeline =
2902
+ ggml_webgpu_create_pipeline(device, preprocessor.preprocess(wgsl_flash_attn_vec_reduce, defines), variant);
2903
+ flash_attn_vec_reduce_pipelines[key] = pipeline;
2904
+ return flash_attn_vec_reduce_pipelines[key];
2905
+ }
2906
+
2907
+ webgpu_pipeline get_cpy_pipeline(const ggml_webgpu_shader_lib_context & context) {
2908
+ ggml_webgpu_cpy_pipeline_key key = {};
2909
+ key.src_type = context.src0->type;
2910
+ key.dst_type = context.dst->type;
2911
+
2912
+ auto it = cpy_pipelines.find(key);
2913
+ if (it != cpy_pipelines.end()) {
2914
+ return it->second;
2915
+ }
2916
+
2917
+ std::vector<std::string> defines;
2918
+ std::string variant = "cpy";
2919
+
2920
+ switch (key.src_type) {
2921
+ case GGML_TYPE_F32:
2922
+ defines.push_back("SRC_F32");
2923
+ variant += "_f32";
1269
2924
  break;
1270
- case GGML_TYPE_Q8_0:
1271
- defines.push_back("KV_Q8_0");
2925
+ case GGML_TYPE_F16:
2926
+ defines.push_back("SRC_F16");
2927
+ variant += "_f16";
2928
+ break;
2929
+ default:
2930
+ GGML_ABORT("Unsupported src type for cpy shader");
2931
+ }
2932
+
2933
+ switch (key.dst_type) {
2934
+ case GGML_TYPE_F32:
2935
+ defines.push_back("DST_F32");
2936
+ variant += "_f32";
2937
+ break;
2938
+ case GGML_TYPE_F16:
2939
+ defines.push_back("DST_F16");
2940
+ variant += "_f16";
2941
+ break;
2942
+ case GGML_TYPE_I32:
2943
+ defines.push_back("DST_I32");
2944
+ variant += "_i32";
2945
+ break;
2946
+ default:
2947
+ GGML_ABORT("Unsupported dst type for cpy shader");
2948
+ }
2949
+
2950
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
2951
+
2952
+ auto processed = preprocessor.preprocess(wgsl_cpy, defines);
2953
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
2954
+ decisions->wg_size = context.max_wg_size;
2955
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
2956
+ pipeline.context = decisions;
2957
+ cpy_pipelines[key] = pipeline;
2958
+ return cpy_pipelines[key];
2959
+ }
2960
+
2961
+ webgpu_pipeline get_glu_pipeline(const ggml_webgpu_shader_lib_context & context) {
2962
+ ggml_webgpu_glu_pipeline_key key = {};
2963
+ key.glu_op = ggml_get_glu_op(context.dst);
2964
+ key.type = context.dst->type;
2965
+ key.split = (context.src1 != nullptr);
2966
+
2967
+ auto it = glu_pipelines.find(key);
2968
+ if (it != glu_pipelines.end()) {
2969
+ return it->second;
2970
+ }
2971
+
2972
+ std::vector<std::string> defines;
2973
+ std::string variant = "glu";
2974
+
2975
+ switch (key.glu_op) {
2976
+ case GGML_GLU_OP_REGLU:
2977
+ defines.push_back("OP_REGLU");
2978
+ variant += "_reglu";
2979
+ break;
2980
+ case GGML_GLU_OP_GEGLU:
2981
+ defines.push_back("OP_GEGLU");
2982
+ variant += "_geglu";
2983
+ break;
2984
+ case GGML_GLU_OP_SWIGLU:
2985
+ defines.push_back("OP_SWIGLU");
2986
+ variant += "_swiglu";
2987
+ break;
2988
+ case GGML_GLU_OP_SWIGLU_OAI:
2989
+ defines.push_back("OP_SWIGLU_OAI");
2990
+ variant += "_swiglu_oai";
2991
+ break;
2992
+ case GGML_GLU_OP_GEGLU_ERF:
2993
+ defines.push_back("OP_GEGLU_ERF");
2994
+ variant += "_geglu_erf";
2995
+ break;
2996
+ case GGML_GLU_OP_GEGLU_QUICK:
2997
+ defines.push_back("OP_GEGLU_QUICK");
2998
+ variant += "_geglu_quick";
2999
+ break;
3000
+ default:
3001
+ GGML_ABORT("Unsupported GLU op");
3002
+ }
3003
+ switch (key.type) {
3004
+ case GGML_TYPE_F32:
3005
+ defines.push_back("TYPE_F32");
3006
+ variant += "_f32";
3007
+ break;
3008
+ case GGML_TYPE_F16:
3009
+ defines.push_back("TYPE_F16");
3010
+ variant += "_f16";
3011
+ break;
3012
+ default:
3013
+ GGML_ABORT("Unsupported type for GLU shader");
3014
+ }
3015
+
3016
+ if (key.split) {
3017
+ variant += "_split";
3018
+ } else {
3019
+ defines.push_back("NO_SPLIT");
3020
+ }
3021
+
3022
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
3023
+
3024
+ auto processed = preprocessor.preprocess(wgsl_glu, defines);
3025
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
3026
+ decisions->wg_size = context.max_wg_size;
3027
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
3028
+ pipeline.context = decisions;
3029
+ glu_pipelines[key] = pipeline;
3030
+ return glu_pipelines[key];
3031
+ }
3032
+
3033
+ webgpu_pipeline get_rope_pipeline(const ggml_webgpu_shader_lib_context & context) {
3034
+ ggml_webgpu_rope_pipeline_key key = {};
3035
+ key.type = context.dst->type;
3036
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
3037
+ key.has_ff = (context.src2 != nullptr);
3038
+
3039
+ auto it = rope_pipelines.find(key);
3040
+ if (it != rope_pipelines.end()) {
3041
+ return it->second;
3042
+ }
3043
+
3044
+ std::vector<std::string> defines;
3045
+ std::string variant = "rope";
3046
+
3047
+ switch (key.type) {
3048
+ case GGML_TYPE_F32:
3049
+ defines.push_back("TYPE_F32");
3050
+ variant += "_f32";
3051
+ break;
3052
+ case GGML_TYPE_F16:
3053
+ defines.push_back("TYPE_F16");
3054
+ variant += "_f16";
1272
3055
  break;
1273
3056
  default:
1274
- GGML_ABORT("Unsupported KV type for flash attention shader");
3057
+ GGML_ABORT("Unsupported type for ROPE shader");
3058
+ }
3059
+
3060
+ if (key.inplace) {
3061
+ defines.push_back("INPLACE");
3062
+ variant += "_inplace";
3063
+ }
3064
+
3065
+ if (key.has_ff) {
3066
+ defines.push_back("FF_FUNC");
3067
+ variant += "_ff";
1275
3068
  }
1276
- variant += std::string("_") + ggml_type_name(key.kv_type);
3069
+
3070
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
3071
+
3072
+ auto processed = preprocessor.preprocess(wgsl_rope, defines);
3073
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
3074
+ decisions->wg_size = context.max_wg_size;
3075
+ decisions->inplace = key.inplace;
3076
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
3077
+ pipeline.context = decisions;
3078
+ rope_pipelines[key] = pipeline;
3079
+ return rope_pipelines[key];
3080
+ }
3081
+
3082
+ webgpu_pipeline get_soft_max_pipeline(const ggml_webgpu_shader_lib_context & context) {
3083
+ ggml_webgpu_soft_max_pipeline_key key = {};
3084
+ key.mask_type = context.src1 ? context.src1->type : GGML_TYPE_F32;
3085
+ key.has_mask = (context.src1 != nullptr);
3086
+ key.has_sink = (context.src2 != nullptr);
3087
+ key.inplace = ggml_webgpu_tensor_equal(context.src0, context.dst);
3088
+
3089
+ auto it = soft_max_pipelines.find(key);
3090
+ if (it != soft_max_pipelines.end()) {
3091
+ return it->second;
3092
+ }
3093
+
3094
+ std::vector<std::string> defines;
3095
+ std::string variant = "soft_max";
1277
3096
 
1278
3097
  if (key.has_mask) {
1279
- defines.push_back("MASK");
1280
- variant += "_mask";
3098
+ defines.push_back("HAS_MASK");
3099
+ switch (key.mask_type) {
3100
+ case GGML_TYPE_F32:
3101
+ defines.push_back("MASK_F32");
3102
+ variant += "_mask_f32";
3103
+ break;
3104
+ case GGML_TYPE_F16:
3105
+ defines.push_back("MASK_F16");
3106
+ variant += "_mask_f16";
3107
+ break;
3108
+ default:
3109
+ GGML_ABORT("Unsupported type for SOFT_MAX shader");
3110
+ }
1281
3111
  }
1282
- if (key.has_sinks) {
1283
- defines.push_back("SINKS");
1284
- variant += "_sinks";
3112
+
3113
+ if (key.has_sink) {
3114
+ defines.push_back("HAS_SINK");
3115
+ variant += "_sink";
1285
3116
  }
1286
- if (key.uses_logit_softcap) {
1287
- defines.push_back("LOGIT_SOFTCAP");
1288
- variant += "_lgsc";
3117
+
3118
+ if (key.inplace) {
3119
+ defines.push_back("INPLACE");
3120
+ variant += "_inplace";
1289
3121
  }
1290
- if (key.kv_direct) {
1291
- defines.push_back("KV_DIRECT");
1292
- variant += "_kvdirect";
3122
+
3123
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
3124
+
3125
+ auto processed = preprocessor.preprocess(wgsl_soft_max, defines);
3126
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
3127
+ decisions->wg_size = context.max_wg_size;
3128
+ decisions->inplace = key.inplace;
3129
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
3130
+ pipeline.context = decisions;
3131
+ soft_max_pipelines[key] = pipeline;
3132
+ return soft_max_pipelines[key];
3133
+ }
3134
+
3135
+ webgpu_pipeline get_conv2d_pipeline(const ggml_webgpu_shader_lib_context & context) {
3136
+ ggml_webgpu_conv2d_pipeline_key key = {};
3137
+ key.weight_type = context.src0->type;
3138
+ key.input_type = context.src1->type;
3139
+ key.output_type = context.dst->type;
3140
+
3141
+ auto it = conv2d_pipelines.find(key);
3142
+ if (it != conv2d_pipelines.end()) {
3143
+ return it->second;
1293
3144
  }
1294
3145
 
1295
- defines.push_back(std::string("HEAD_DIM_QK=") + std::to_string(key.head_dim_qk));
1296
- variant += std::string("_hsqk") + std::to_string(key.head_dim_qk);
3146
+ std::vector<std::string> defines;
3147
+ std::string variant = "conv_2d";
3148
+
3149
+ auto push_type_defines = [&](const char * prefix, ggml_type type) {
3150
+ std::string s_prefix = prefix;
3151
+ if (type == GGML_TYPE_F32) {
3152
+ defines.push_back(s_prefix + "_F32");
3153
+ } else if (type == GGML_TYPE_F16) {
3154
+ defines.push_back(s_prefix + "_F16");
3155
+ } else {
3156
+ GGML_ABORT("Unsupported type for CONV_2D shader");
3157
+ }
3158
+ };
1297
3159
 
1298
- defines.push_back(std::string("HEAD_DIM_V=") + std::to_string(key.head_dim_v));
1299
- variant += std::string("_hsv") + std::to_string(key.head_dim_v);
3160
+ push_type_defines("WEIGHT", key.weight_type);
3161
+ push_type_defines("INPUT", key.input_type);
3162
+ push_type_defines("OUTPUT", key.output_type);
3163
+
3164
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
1300
3165
 
1301
- defines.push_back(std::string("SG_MAT_M=") + std::to_string(context.sg_mat_m));
1302
- defines.push_back(std::string("SG_MAT_N=") + std::to_string(context.sg_mat_n));
1303
- defines.push_back(std::string("SG_MAT_K=") + std::to_string(context.sg_mat_k));
1304
-
1305
- uint32_t q_tile = context.sg_mat_m;
1306
- uint32_t kv_tile =
1307
- std::min(ggml_webgpu_flash_attn_max_kv_tile({ key, context.sg_mat_m, context.sg_mat_n, context.sg_mat_k,
1308
- context.wg_mem_limit_bytes, context.max_subgroup_size }),
1309
- context.sg_mat_n * GGML_WEBGPU_FLASH_ATTN_PREFERRED_KV_SG_TILES);
1310
- if (key.kv_direct) {
1311
- while (GGML_WEBGPU_KV_SEQ_PAD % kv_tile != 0) {
1312
- kv_tile -= context.sg_mat_n;
3166
+ auto processed = preprocessor.preprocess(wgsl_conv2d, defines);
3167
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
3168
+ decisions->wg_size = context.max_wg_size;
3169
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
3170
+ pipeline.context = decisions;
3171
+ conv2d_pipelines[key] = pipeline;
3172
+ return conv2d_pipelines[key];
3173
+ }
3174
+
3175
+ webgpu_pipeline get_im2col_pipeline(const ggml_webgpu_shader_lib_context & context) {
3176
+ ggml_webgpu_im2col_pipeline_key key = {};
3177
+ key.input_type = context.src1->type;
3178
+ key.output_type = context.dst->type;
3179
+
3180
+ auto it = im2col_pipelines.find(key);
3181
+ if (it != im2col_pipelines.end()) {
3182
+ return it->second;
3183
+ }
3184
+
3185
+ std::vector<std::string> defines;
3186
+ std::string variant = "im2col";
3187
+
3188
+ auto push_type_defines = [&](const char * prefix, ggml_type type) {
3189
+ std::string s_prefix = prefix;
3190
+ if (type == GGML_TYPE_F32) {
3191
+ defines.push_back(s_prefix + "_F32");
3192
+ } else if (type == GGML_TYPE_F16) {
3193
+ defines.push_back(s_prefix + "_F16");
3194
+ } else {
3195
+ GGML_ABORT("Unsupported type for IM2COL shader");
1313
3196
  }
3197
+ };
3198
+
3199
+ push_type_defines("INPUT", key.input_type);
3200
+ push_type_defines("OUTPUT", key.output_type);
3201
+
3202
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
3203
+
3204
+ auto processed = preprocessor.preprocess(wgsl_im2col, defines);
3205
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
3206
+ decisions->wg_size = context.max_wg_size;
3207
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
3208
+ pipeline.context = decisions;
3209
+ im2col_pipelines[key] = pipeline;
3210
+ return im2col_pipelines[key];
3211
+ }
3212
+
3213
+ webgpu_pipeline get_upscale_pipeline(const ggml_webgpu_shader_lib_context & context) {
3214
+ const uint32_t mode_flags = (uint32_t) ggml_get_op_params_i32(context.dst, 0);
3215
+ const uint32_t base_mode = mode_flags & 0xFFu;
3216
+ const bool antialias = (mode_flags & GGML_SCALE_FLAG_ANTIALIAS) != 0u;
3217
+
3218
+ ggml_webgpu_upscale_pipeline_key key = {};
3219
+ key.input_type = context.src0->type;
3220
+ key.output_type = context.dst->type;
3221
+ key.base_mode = base_mode;
3222
+ key.antialias = antialias;
3223
+
3224
+ auto it = upscale_pipelines.find(key);
3225
+ if (it != upscale_pipelines.end()) {
3226
+ return it->second;
1314
3227
  }
1315
3228
 
1316
- defines.push_back(std::string("Q_TILE=") + std::to_string(q_tile));
1317
- defines.push_back(std::string("KV_TILE=") + std::to_string(kv_tile));
3229
+ std::vector<std::string> defines;
3230
+ std::string variant = "upscale";
1318
3231
 
1319
- uint32_t wg_size = std::max(context.max_subgroup_size, GGML_WEBGPU_FLASH_ATTN_PREFERRED_WG_SIZE);
1320
- defines.push_back(std::string("WG_SIZE=") + std::to_string(wg_size));
3232
+ if (key.input_type == GGML_TYPE_F16) {
3233
+ defines.push_back("SRC_F16");
3234
+ variant += "_src_f16";
3235
+ } else {
3236
+ variant += "_src_f32";
3237
+ }
1321
3238
 
1322
- auto processed = preprocessor.preprocess(wgsl_flash_attn, defines);
1323
- auto decisions = std::make_shared<ggml_webgpu_flash_attn_shader_decisions>();
1324
- decisions->q_tile = q_tile;
1325
- decisions->kv_tile = kv_tile;
1326
- decisions->wg_size = wg_size;
3239
+ if (key.output_type == GGML_TYPE_F16) {
3240
+ defines.push_back("DST_F16");
3241
+ variant += "_dst_f16";
3242
+ } else {
3243
+ variant += "_dst_f32";
3244
+ }
1327
3245
 
1328
- webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
1329
- pipeline.context = decisions;
1330
- flash_attn_pipelines[key] = pipeline;
1331
- return flash_attn_pipelines[key];
3246
+ switch (base_mode) {
3247
+ case GGML_SCALE_MODE_NEAREST:
3248
+ defines.push_back("NEAREST");
3249
+ variant += "_nearest";
3250
+ break;
3251
+ case GGML_SCALE_MODE_BILINEAR:
3252
+ defines.push_back("BILINEAR");
3253
+ variant += "_bilinear";
3254
+ break;
3255
+ case GGML_SCALE_MODE_BICUBIC:
3256
+ defines.push_back("BICUBIC");
3257
+ variant += "_bicubic";
3258
+ break;
3259
+ default:
3260
+ GGML_ABORT("Unsupported upscale mode");
3261
+ }
3262
+
3263
+ if (antialias) {
3264
+ defines.push_back("ANTIALIAS");
3265
+ variant += "_aa";
3266
+ }
3267
+
3268
+ defines.push_back(std::string("WG_SIZE=") + std::to_string(context.max_wg_size));
3269
+
3270
+ auto processed = preprocessor.preprocess(wgsl_upscale, defines);
3271
+ auto decisions = std::make_shared<ggml_webgpu_generic_shader_decisions>();
3272
+ decisions->wg_size = context.max_wg_size;
3273
+ webgpu_pipeline pipeline = ggml_webgpu_create_pipeline(device, processed, variant);
3274
+ pipeline.context = decisions;
3275
+ upscale_pipelines[key] = pipeline;
3276
+ return upscale_pipelines[key];
1332
3277
  }
1333
3278
 
1334
3279
  private:
@@ -1350,25 +3295,6 @@ class ggml_webgpu_shader_lib {
1350
3295
  pipeline_desc.layout = nullptr; // nullptr means auto layout
1351
3296
  return { device.CreateComputePipeline(&pipeline_desc), label };
1352
3297
  }
1353
-
1354
- static uint32_t ggml_webgpu_flash_attn_max_kv_tile(const ggml_webgpu_flash_attn_shader_lib_context & context) {
1355
- const size_t limit_bytes = context.wg_mem_limit_bytes;
1356
- const size_t q_tile = context.sg_mat_m;
1357
- const size_t base_q_bytes =
1358
- (context.key.head_dim_qk + context.key.head_dim_v) * q_tile * GGML_WEBGPU_F16_SIZE_BYTES +
1359
- 2 * q_tile * GGML_WEBGPU_F32_SIZE_BYTES;
1360
- size_t bytes_per_kv = 0;
1361
- if (!context.key.kv_direct) {
1362
- bytes_per_kv += std::max(context.key.head_dim_qk, context.key.head_dim_v);
1363
- }
1364
- if (context.key.has_mask) {
1365
- bytes_per_kv += q_tile;
1366
- }
1367
- bytes_per_kv += q_tile;
1368
- bytes_per_kv *= GGML_WEBGPU_F16_SIZE_BYTES;
1369
- const uint32_t max_kv_tile = (limit_bytes - base_q_bytes) / bytes_per_kv;
1370
- return (max_kv_tile / context.sg_mat_n) * context.sg_mat_n;
1371
- }
1372
3298
  };
1373
3299
 
1374
3300
  #endif // GGML_WEBGPU_SHADER_LIB_HPP