whispercpp 1.3.7 → 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 (308) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -4
  3. data/ext/options.rb +1 -1
  4. data/ext/ruby_whisper.c +0 -1
  5. data/ext/ruby_whisper.h +7 -1
  6. data/ext/ruby_whisper_context.c +50 -1
  7. data/ext/ruby_whisper_log_settable.h +1 -2
  8. data/ext/ruby_whisper_params.c +9 -8
  9. data/ext/ruby_whisper_transcribe.cpp +0 -19
  10. data/ext/ruby_whisper_vad_context.c +30 -10
  11. data/ext/ruby_whisper_vad_context_detect.cpp +8 -9
  12. data/ext/ruby_whisper_vad_params.c +4 -4
  13. data/ext/ruby_whisper_vad_segment.c +2 -2
  14. data/ext/sources/CMakeLists.txt +2 -1
  15. data/ext/sources/cmake/parakeet.pc.in +2 -2
  16. data/ext/sources/cmake/whisper.pc.in +2 -2
  17. data/ext/sources/examples/cli/cli.cpp +9 -1
  18. data/ext/sources/examples/common-ggml.cpp +2 -0
  19. data/ext/sources/examples/vad-speech-segments/speech.cpp +3 -2
  20. data/ext/sources/ggml/CMakeLists.txt +3 -4
  21. data/ext/sources/ggml/include/ggml-cuda.h +0 -3
  22. data/ext/sources/ggml/include/ggml-sycl.h +8 -0
  23. data/ext/sources/ggml/include/ggml.h +3 -1
  24. data/ext/sources/ggml/src/CMakeLists.txt +8 -1
  25. data/ext/sources/ggml/src/ggml-backend-meta.cpp +7 -4
  26. data/ext/sources/ggml/src/ggml-common.h +13 -2
  27. data/ext/sources/ggml/src/ggml-cpu/CMakeLists.txt +1 -1
  28. data/ext/sources/ggml/src/ggml-cpu/amx/mmq.cpp +5 -6
  29. data/ext/sources/ggml/src/ggml-cpu/arch/arm/quants.c +78 -4
  30. data/ext/sources/ggml/src/ggml-cpu/arch/x86/quants.c +142 -4
  31. data/ext/sources/ggml/src/ggml-cpu/arch-fallback.h +7 -2
  32. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu.c +14 -0
  33. data/ext/sources/ggml/src/ggml-cpu/llamafile/sgemm.cpp +26 -19
  34. data/ext/sources/ggml/src/ggml-cpu/ops.cpp +129 -46
  35. data/ext/sources/ggml/src/ggml-cpu/quants.c +51 -0
  36. data/ext/sources/ggml/src/ggml-cpu/quants.h +3 -0
  37. data/ext/sources/ggml/src/ggml-cpu/simd-gemm.h +1 -1
  38. data/ext/sources/ggml/src/ggml-cpu/simd-mappings.h +11 -0
  39. data/ext/sources/ggml/src/ggml-cpu/vec.cpp +2 -2
  40. data/ext/sources/ggml/src/ggml-cuda/binbcast.cu +90 -46
  41. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cu +81 -0
  42. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cuh +3 -0
  43. data/ext/sources/ggml/src/ggml-cuda/common.cuh +4 -0
  44. data/ext/sources/ggml/src/ggml-cuda/concat.cu +33 -21
  45. data/ext/sources/ggml/src/ggml-cuda/conv-transpose-1d.cu +14 -12
  46. data/ext/sources/ggml/src/ggml-cuda/convert.cu +86 -34
  47. data/ext/sources/ggml/src/ggml-cuda/cpy.cu +80 -29
  48. data/ext/sources/ggml/src/ggml-cuda/fattn-common.cuh +9 -5
  49. data/ext/sources/ggml/src/ggml-cuda/fattn-mma-f16.cuh +4 -0
  50. data/ext/sources/ggml/src/ggml-cuda/fattn-tile.cuh +9 -5
  51. data/ext/sources/ggml/src/ggml-cuda/fattn.cu +27 -21
  52. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cu +40 -25
  53. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cuh +10 -0
  54. data/ext/sources/ggml/src/ggml-cuda/getrows.cu +15 -12
  55. data/ext/sources/ggml/src/ggml-cuda/ggml-cuda.cu +718 -1248
  56. data/ext/sources/ggml/src/ggml-cuda/mmq.cu +7 -0
  57. data/ext/sources/ggml/src/ggml-cuda/mmvq.cu +77 -40
  58. data/ext/sources/ggml/src/ggml-cuda/out-prod.cu +55 -12
  59. data/ext/sources/ggml/src/ggml-cuda/set-rows.cu +64 -4
  60. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu +1 -0
  61. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu +1 -0
  62. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu +1 -0
  63. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu +1 -0
  64. data/ext/sources/ggml/src/ggml-cuda/topk-moe.cu +7 -1
  65. data/ext/sources/ggml/src/ggml-cuda/vendors/hip.h +1 -0
  66. data/ext/sources/ggml/src/ggml-cuda/vendors/musa.h +1 -0
  67. data/ext/sources/ggml/src/ggml-hexagon/CMakeLists.txt +0 -5
  68. data/ext/sources/ggml/src/ggml-hexagon/ggml-hexagon.cpp +1634 -1293
  69. data/ext/sources/ggml/src/ggml-hexagon/htp/CMakeLists.txt +11 -40
  70. data/ext/sources/ggml/src/ggml-hexagon/htp/cmake-toolchain.cmake +13 -15
  71. data/ext/sources/ggml/src/ggml-hexagon/htp/concat-ops.c +1 -1
  72. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.c +1749 -399
  73. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.h +303 -0
  74. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-common.h +80 -0
  75. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dma.h +26 -23
  76. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-profile.h +64 -0
  77. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-utils.h +1 -83
  78. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-fa-kernels.h +555 -0
  79. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-mm-kernels-tiled.h +1303 -0
  80. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.c +9 -0
  81. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.h +27 -4
  82. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-utils.h +59 -37
  83. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ctx.h +11 -3
  84. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ops.h +52 -12
  85. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-vtcm.h +19 -0
  86. data/ext/sources/ggml/src/ggml-hexagon/htp/htp_iface.idl +2 -1
  87. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-base.h +14 -30
  88. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-exp.h +39 -0
  89. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-fa-kernels.h +232 -0
  90. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-flat.h +1511 -0
  91. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-tiled.h +1200 -0
  92. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-sigmoid.h +39 -0
  93. data/ext/sources/ggml/src/ggml-hexagon/htp/main.c +127 -32
  94. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.c +3023 -4425
  95. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.h +650 -0
  96. data/ext/sources/ggml/src/ggml-hexagon/htp/rope-ops.c +48 -13
  97. data/ext/sources/ggml/src/ggml-hexagon/htp/ssm-conv.c +10 -9
  98. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.c +15 -3
  99. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.h +8 -0
  100. data/ext/sources/ggml/src/ggml-hexagon/htp-opnode.h +168 -50
  101. data/ext/sources/ggml/src/ggml-hexagon/libggml-htp.inf +0 -4
  102. data/ext/sources/ggml/src/ggml-hip/CMakeLists.txt +5 -0
  103. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.cpp +69 -5
  104. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.h +4 -1
  105. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.m +27 -6
  106. data/ext/sources/ggml/src/ggml-metal/ggml-metal-impl.h +38 -0
  107. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.cpp +132 -2
  108. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.h +2 -0
  109. data/ext/sources/ggml/src/ggml-metal/ggml-metal.metal +345 -87
  110. data/ext/sources/ggml/src/ggml-opencl/CMakeLists.txt +13 -0
  111. data/ext/sources/ggml/src/ggml-opencl/fa_tune.h +92 -0
  112. data/ext/sources/ggml/src/ggml-opencl/ggml-opencl.cpp +4060 -357
  113. data/ext/sources/ggml/src/ggml-opencl/kernels/cvt.cl +198 -0
  114. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f16.cl +81 -41
  115. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32.cl +88 -39
  116. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_f16.cl +1995 -96
  117. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q4_0.cl +1615 -0
  118. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q8_0.cl +1486 -0
  119. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_pre_f16.cl +156 -0
  120. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32_ns.cl +74 -6
  121. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_0_f32_ns.cl +74 -6
  122. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_1_f32_ns.cl +74 -6
  123. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_k_f32_ns.cl +71 -6
  124. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_0_f32_ns.cl +74 -6
  125. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_1_f32_ns.cl +74 -6
  126. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_k_f32_ns.cl +74 -6
  127. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q6_k_f32_ns.cl +74 -6
  128. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q1_0_f32.cl +94 -0
  129. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q1_0_f32.cl +121 -0
  130. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q8_0_f32.cl +1 -1
  131. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q1_0_f32_l4_lm.cl +156 -0
  132. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +1149 -0
  133. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32.cl +141 -0
  134. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32_flat.cl +190 -0
  135. data/ext/sources/ggml/src/ggml-opencl/kernels/norm.cl +5 -2
  136. data/ext/sources/ggml/src/ggml-opencl/kernels/set_rows.cl +500 -0
  137. data/ext/sources/ggml/src/ggml-opencl/libdl.h +79 -0
  138. data/ext/sources/ggml/src/ggml-openvino/.clang-format +0 -5
  139. data/ext/sources/ggml/src/ggml-openvino/CMakeLists.txt +2 -4
  140. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.cpp +733 -130
  141. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.h +76 -23
  142. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.cpp +57 -3
  143. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.h +29 -8
  144. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino.cpp +307 -59
  145. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.cpp +66 -0
  146. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.h +10 -4
  147. data/ext/sources/ggml/src/ggml-openvino/openvino/decoder.h +56 -16
  148. data/ext/sources/ggml/src/ggml-openvino/openvino/frontend.h +1 -1
  149. data/ext/sources/ggml/src/ggml-openvino/openvino/input_model.h +4 -4
  150. data/ext/sources/ggml/src/ggml-openvino/openvino/node_context.h +94 -37
  151. data/ext/sources/ggml/src/ggml-openvino/openvino/op/add_id.cpp +76 -0
  152. data/ext/sources/ggml/src/ggml-openvino/openvino/op/argsort.cpp +47 -0
  153. data/ext/sources/ggml/src/ggml-openvino/openvino/op/clamp.cpp +33 -0
  154. data/ext/sources/ggml/src/ggml-openvino/openvino/op/concat.cpp +48 -0
  155. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cont.cpp +8 -16
  156. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cpy.cpp +14 -1
  157. data/ext/sources/ggml/src/ggml-openvino/openvino/op/div.cpp +146 -0
  158. data/ext/sources/ggml/src/ggml-openvino/openvino/op/flash_attn_ext.cpp +108 -21
  159. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.cpp +282 -0
  160. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.hpp +65 -0
  161. data/ext/sources/ggml/src/ggml-openvino/openvino/op/get_rows.cpp +2 -9
  162. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_geglu.cpp +21 -7
  163. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_swiglu.cpp +41 -8
  164. data/ext/sources/ggml/src/ggml-openvino/openvino/op/im2col.cpp +120 -0
  165. data/ext/sources/ggml/src/ggml-openvino/openvino/op/l2_norm.cpp +44 -0
  166. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mul_mat_id.cpp +226 -0
  167. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mulmat.cpp +19 -9
  168. data/ext/sources/ggml/src/ggml-openvino/openvino/op/norm.cpp +58 -0
  169. data/ext/sources/ggml/src/ggml-openvino/openvino/op/pad.cpp +95 -0
  170. data/ext/sources/ggml/src/ggml-openvino/openvino/op/permute.cpp +58 -13
  171. data/ext/sources/ggml/src/ggml-openvino/openvino/op/repeat.cpp +74 -0
  172. data/ext/sources/ggml/src/ggml-openvino/openvino/op/reshape.cpp +13 -6
  173. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rms_norm.cpp +1 -1
  174. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rope.cpp +134 -38
  175. data/ext/sources/ggml/src/ggml-openvino/openvino/op/set_rows.cpp +3 -3
  176. data/ext/sources/ggml/src/ggml-openvino/openvino/op/softmax.cpp +126 -49
  177. data/ext/sources/ggml/src/ggml-openvino/openvino/op/ssm_conv.cpp +59 -0
  178. data/ext/sources/ggml/src/ggml-openvino/openvino/op/sum_rows.cpp +27 -0
  179. data/ext/sources/ggml/src/ggml-openvino/openvino/op/transpose.cpp +32 -1
  180. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_silu.cpp +1 -1
  181. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_softplus.cpp +38 -0
  182. data/ext/sources/ggml/src/ggml-openvino/openvino/op/view.cpp +90 -25
  183. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.cpp +41 -23
  184. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.h +18 -5
  185. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/mark_decompression_convert_constant_folding.h +1 -1
  186. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.cpp +43 -40
  187. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.h +5 -4
  188. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.cpp +548 -3
  189. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.h +28 -26
  190. data/ext/sources/ggml/src/ggml-openvino/utils.cpp +383 -94
  191. data/ext/sources/ggml/src/ggml-openvino/utils.h +11 -8
  192. data/ext/sources/ggml/src/ggml-quants.c +76 -0
  193. data/ext/sources/ggml/src/ggml-quants.h +3 -0
  194. data/ext/sources/ggml/src/ggml-sycl/CMakeLists.txt +5 -5
  195. data/ext/sources/ggml/src/ggml-sycl/backend.hpp +2 -0
  196. data/ext/sources/ggml/src/ggml-sycl/binbcast.cpp +12 -0
  197. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.cpp +102 -0
  198. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.hpp +8 -0
  199. data/ext/sources/ggml/src/ggml-sycl/common.cpp +6 -8
  200. data/ext/sources/ggml/src/ggml-sycl/common.hpp +19 -2
  201. data/ext/sources/ggml/src/ggml-sycl/concat.cpp +21 -1
  202. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.cpp +158 -0
  203. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.hpp +10 -0
  204. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.cpp +125 -0
  205. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.hpp +10 -0
  206. data/ext/sources/ggml/src/ggml-sycl/conv2d.cpp +150 -0
  207. data/ext/sources/ggml/src/ggml-sycl/conv2d.hpp +10 -0
  208. data/ext/sources/ggml/src/ggml-sycl/conv3d.cpp +224 -0
  209. data/ext/sources/ggml/src/ggml-sycl/conv3d.hpp +8 -0
  210. data/ext/sources/ggml/src/ggml-sycl/convert.cpp +6 -0
  211. data/ext/sources/ggml/src/ggml-sycl/cpy.cpp +706 -0
  212. data/ext/sources/ggml/src/ggml-sycl/cpy.hpp +281 -0
  213. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.cpp +255 -0
  214. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.hpp +7 -0
  215. data/ext/sources/ggml/src/ggml-sycl/dequantize.hpp +15 -0
  216. data/ext/sources/ggml/src/ggml-sycl/dmmv.cpp +492 -319
  217. data/ext/sources/ggml/src/ggml-sycl/dpct/helper.hpp +15 -7
  218. data/ext/sources/ggml/src/ggml-sycl/element_wise.cpp +215 -115
  219. data/ext/sources/ggml/src/ggml-sycl/element_wise.hpp +2 -0
  220. data/ext/sources/ggml/src/ggml-sycl/ggml-sycl.cpp +1006 -336
  221. data/ext/sources/ggml/src/ggml-sycl/mmvq.cpp +252 -67
  222. data/ext/sources/ggml/src/ggml-sycl/mmvq.hpp +17 -0
  223. data/ext/sources/ggml/src/ggml-sycl/norm.cpp +103 -49
  224. data/ext/sources/ggml/src/ggml-sycl/outprod.cpp +45 -9
  225. data/ext/sources/ggml/src/ggml-sycl/pool.cpp +185 -0
  226. data/ext/sources/ggml/src/ggml-sycl/pool.hpp +22 -0
  227. data/ext/sources/ggml/src/ggml-sycl/presets.hpp +3 -1
  228. data/ext/sources/ggml/src/ggml-sycl/set_rows.cpp +10 -2
  229. data/ext/sources/ggml/src/ggml-sycl/softmax.cpp +9 -10
  230. data/ext/sources/ggml/src/ggml-sycl/vecdotq.hpp +35 -0
  231. data/ext/sources/ggml/src/ggml-vulkan/CMakeLists.txt +5 -0
  232. data/ext/sources/ggml/src/ggml-vulkan/ggml-vulkan.cpp +833 -215
  233. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp +61 -0
  234. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +1 -1
  235. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp +431 -0
  236. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/diag.comp +3 -3
  237. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn.comp +1 -0
  238. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm1.comp +1 -0
  239. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.glsl +21 -19
  240. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/get_rows_back.comp +25 -0
  241. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_head.glsl +23 -4
  242. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_main.glsl +14 -18
  243. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/l2_norm.comp +4 -7
  244. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq.comp +21 -24
  245. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp +31 -23
  246. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_cm2.comp +6 -5
  247. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_funcs.glsl +84 -67
  248. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/norm.comp +10 -10
  249. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/repeat_back.comp +3 -3
  250. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/roll.comp +3 -3
  251. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tri.comp +3 -3
  252. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/unary.comp +168 -0
  253. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +121 -74
  254. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp +26 -19
  255. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu.cpp +31 -36
  256. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl +16 -2
  257. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_split.wgsl +7 -7
  258. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/get_rows.wgsl +21 -0
  259. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_decls.tmpl +439 -320
  260. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_vec.wgsl +2 -2
  261. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl +45 -39
  262. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_acc.tmpl +586 -465
  263. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_q_acc.tmpl +63 -69
  264. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/quantize_q8.wgsl +14 -9
  265. data/ext/sources/ggml/src/ggml.c +36 -14
  266. data/ext/sources/include/whisper.h +21 -0
  267. data/ext/sources/src/whisper.cpp +164 -14
  268. data/lib/whisper/log_settable.rb +5 -8
  269. data/lib/whisper/model/uri.rb +0 -7
  270. data/sig/whisper.rbs +6 -0
  271. data/test/test_vad.rb +9 -0
  272. data/test/test_vad_context.rb +2 -2
  273. data/whispercpp.gemspec +1 -1
  274. metadata +62 -37
  275. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-flash-attn-ops.c +0 -1878
  276. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-matmul-ops.c +0 -2066
  277. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-ops.c +0 -6
  278. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-ops.h +0 -88
  279. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-profile.h +0 -34
  280. data/ext/sources/ggml/src/ggml-hexagon/htp/vtcm-utils.h +0 -16
  281. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_gelu.cpp +0 -25
  282. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/abs.comp +0 -21
  283. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/ceil.comp +0 -22
  284. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/clamp.comp +0 -17
  285. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/cos.comp +0 -17
  286. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/elu.comp +0 -27
  287. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/exp.comp +0 -20
  288. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/floor.comp +0 -22
  289. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu.comp +0 -25
  290. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_erf.comp +0 -39
  291. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_quick.comp +0 -23
  292. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardsigmoid.comp +0 -22
  293. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardswish.comp +0 -22
  294. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/leaky_relu.comp +0 -22
  295. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/neg.comp +0 -20
  296. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/relu.comp +0 -21
  297. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/round.comp +0 -29
  298. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sgn.comp +0 -21
  299. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sigmoid.comp +0 -20
  300. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/silu.comp +0 -22
  301. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sin.comp +0 -17
  302. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/softplus.comp +0 -23
  303. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sqrt.comp +0 -17
  304. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/square.comp +0 -17
  305. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/step.comp +0 -22
  306. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tanh.comp +0 -20
  307. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/trunc.comp +0 -22
  308. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/xielu.comp +0 -35
@@ -129,7 +129,7 @@ typedef struct VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE {
129
129
  #endif
130
130
 
131
131
  #define ROUNDUP_POW2(M, N) (((M) + (N) - 1) & ~((N) - 1))
132
- #define CEIL_DIV(M, N) (((M) + (N)-1) / (N))
132
+ #define CEIL_DIV(M, N) (((M) / (N)) + (((M) % (N)) != 0))
133
133
  static bool is_pow2(uint32_t x) { return x > 1 && (x & (x-1)) == 0; }
134
134
 
135
135
  #define VK_VENDOR_ID_AMD 0x1002
@@ -308,6 +308,7 @@ enum vk_device_architecture {
308
308
  AMD_RDNA1,
309
309
  AMD_RDNA2,
310
310
  AMD_RDNA3,
311
+ INTEL_XE1,
311
312
  INTEL_XE2,
312
313
  NVIDIA_PRE_TURING,
313
314
  NVIDIA_TURING,
@@ -365,21 +366,26 @@ static vk_device_architecture get_device_architecture(const vk::PhysicalDevice&
365
366
  const std::vector<vk::ExtensionProperties> ext_props = device.enumerateDeviceExtensionProperties();
366
367
 
367
368
  bool subgroup_size_control = false;
369
+ bool integer_dot_product = false;
368
370
 
369
371
  for (const auto& properties : ext_props) {
370
372
  if (strcmp("VK_EXT_subgroup_size_control", properties.extensionName) == 0) {
371
373
  subgroup_size_control = true;
374
+ } else if (strcmp("VK_KHR_shader_integer_dot_product", properties.extensionName) == 0) {
375
+ integer_dot_product = true;
372
376
  }
373
377
  }
374
378
 
375
- if (!subgroup_size_control) {
379
+ if (!subgroup_size_control || !integer_dot_product) {
376
380
  return vk_device_architecture::OTHER;
377
381
  }
378
382
 
379
383
  vk::PhysicalDeviceProperties2 props2;
380
384
  vk::PhysicalDeviceSubgroupSizeControlPropertiesEXT subgroup_size_control_props;
385
+ vk::PhysicalDeviceShaderIntegerDotProductPropertiesKHR integer_dot_props;
381
386
 
382
387
  props2.pNext = &subgroup_size_control_props;
388
+ subgroup_size_control_props.pNext = &integer_dot_props;
383
389
  device.getProperties2(&props2);
384
390
 
385
391
  if (subgroup_size_control_props.minSubgroupSize == 16) {
@@ -388,6 +394,9 @@ static vk_device_architecture get_device_architecture(const vk::PhysicalDevice&
388
394
  // https://www.intel.com/content/www/us/en/content-details/824434/2024-intel-tech-tour-xe2-and-lunar-lake-s-gpu.html
389
395
  // https://www.intel.com/content/www/us/en/docs/oneapi/optimization-guide-gpu/2025-0/intel-xe-gpu-architecture.html
390
396
  return vk_device_architecture::INTEL_XE2;
397
+ } else if (subgroup_size_control_props.minSubgroupSize == 8 &&
398
+ integer_dot_product && integer_dot_props.integerDotProduct4x8BitPackedSignedAccelerated) {
399
+ return vk_device_architecture::INTEL_XE1;
391
400
  }
392
401
  } else if (props.vendorID == VK_VENDOR_ID_NVIDIA) {
393
402
  const std::vector<vk::ExtensionProperties> ext_props = device.enumerateDeviceExtensionProperties();
@@ -493,6 +502,20 @@ struct vk_conv2d_pipeline_state {
493
502
  }
494
503
  };
495
504
 
505
+ struct vk_conv3d_pipeline_state {
506
+ vk_conv3d_pipeline_state(uint32_t s0, uint32_t s1, uint32_t s2, uint32_t p0, uint32_t p1, uint32_t p2,
507
+ uint32_t d0, uint32_t d1, uint32_t d2, uint32_t KW, uint32_t KH, uint32_t KD, uint32_t aligned)
508
+ : s0(s0), s1(s1), s2(s2), p0(p0), p1(p1), p2(p2), d0(d0), d1(d1), d2(d2), KW(KW), KH(KH), KD(KD), aligned(aligned) {}
509
+
510
+ uint32_t s0, s1, s2, p0, p1, p2, d0, d1, d2, KW, KH, KD;
511
+ uint32_t aligned;
512
+
513
+ bool operator<(const vk_conv3d_pipeline_state &b) const {
514
+ return std::tie(s0, s1, s2, p0, p1, p2, d0, d1, d2, KW, KH, KD, aligned) <
515
+ std::tie(b.s0, b.s1, b.s2, b.p0, b.p1, b.p2, b.d0, b.d1, b.d2, b.KW, b.KH, b.KD, b.aligned);
516
+ }
517
+ };
518
+
496
519
  struct vk_solve_tri_pipeline_state {
497
520
  vk_solve_tri_pipeline_state(uint32_t N, uint32_t K)
498
521
  : N(N), K(K) {}
@@ -685,6 +708,7 @@ struct vk_device_struct {
685
708
 
686
709
  bool add_rms_fusion;
687
710
  uint32_t partials_binding_alignment;
711
+ uint32_t max_nodes_per_submit;
688
712
 
689
713
  bool shader_64b_indexing;
690
714
 
@@ -777,6 +801,7 @@ struct vk_device_struct {
777
801
  vk_pipeline pipeline_mul_mat_vec_nc_f16_f32;
778
802
  vk_pipeline pipeline_get_rows[GGML_TYPE_COUNT];
779
803
  vk_pipeline pipeline_get_rows_f32[GGML_TYPE_COUNT];
804
+ vk_pipeline pipeline_get_rows_back_f32;
780
805
  vk_pipeline pipeline_acc_f32;
781
806
  vk_pipeline pipeline_set_f32;
782
807
 
@@ -798,17 +823,13 @@ struct vk_device_struct {
798
823
 
799
824
  vk_pipeline pipeline_add_id_f32;
800
825
 
801
- vk_pipeline pipeline_concat_f32, pipeline_concat_f16, pipeline_concat_i32;
826
+ vk_pipeline pipeline_concat_i8, pipeline_concat_i16, pipeline_concat_i32, pipeline_concat_i64;
802
827
  vk_pipeline pipeline_upscale_nearest_f32, pipeline_upscale_bilinear_f32, pipeline_upscale_bicubic_f32, pipeline_upscale_bilinear_antialias_f32;
803
828
  vk_pipeline pipeline_scale_f32;
804
- vk_pipeline pipeline_sqr_f32;
805
- vk_pipeline pipeline_sqrt_f32;
806
- vk_pipeline pipeline_sin_f32;
807
- vk_pipeline pipeline_cos_f32;
808
829
  vk_pipeline pipeline_log[2];
809
830
  vk_pipeline pipeline_tri[2];
810
831
  vk_pipeline pipeline_diag[2];
811
- vk_pipeline pipeline_clamp_f32;
832
+ vk_pipeline pipeline_clamp[2];
812
833
  vk_pipeline pipeline_pad_f32;
813
834
  vk_pipeline pipeline_roll_f32;
814
835
  vk_pipeline pipeline_repeat_i32, pipeline_repeat_back_f32;
@@ -833,12 +854,17 @@ struct vk_device_struct {
833
854
 
834
855
  // [src/dst 0=fp32,1=fp16]
835
856
  vk_pipeline pipeline_exp[2];
857
+ vk_pipeline pipeline_expm1[2];
836
858
  vk_pipeline pipeline_elu[2];
837
859
  vk_pipeline pipeline_gelu[2];
838
860
  vk_pipeline pipeline_gelu_erf[2];
839
861
  vk_pipeline pipeline_gelu_quick[2];
840
862
  vk_pipeline pipeline_silu[2];
841
863
  vk_pipeline pipeline_relu[2];
864
+ vk_pipeline pipeline_sqr[2];
865
+ vk_pipeline pipeline_sqrt[2];
866
+ vk_pipeline pipeline_sin[2];
867
+ vk_pipeline pipeline_cos[2];
842
868
  vk_pipeline pipeline_xielu[2];
843
869
  vk_pipeline pipeline_neg[2];
844
870
  vk_pipeline pipeline_tanh[2];
@@ -870,7 +896,7 @@ struct vk_device_struct {
870
896
  vk_pipeline pipeline_geglu_erf[2];
871
897
  vk_pipeline pipeline_geglu_quick[2];
872
898
 
873
- vk_pipeline pipeline_leaky_relu_f32;
899
+ vk_pipeline pipeline_leaky_relu[2];
874
900
  vk_pipeline pipeline_silu_back_f32;
875
901
  vk_pipeline pipeline_diag_mask_inf_f32;
876
902
  vk_pipeline pipeline_soft_max_f32, pipeline_soft_max_f32_f16;
@@ -901,14 +927,17 @@ struct vk_device_struct {
901
927
  vk_pipeline pipeline_im2col_3d_f32, pipeline_im2col_3d_f32_f16;
902
928
  vk_pipeline pipeline_timestep_embedding_f32;
903
929
  vk_pipeline pipeline_conv_transpose_1d_f32;
930
+ vk_pipeline pipeline_col2im_1d_f32;
931
+ vk_pipeline pipeline_col2im_1d_f16;
932
+ vk_pipeline pipeline_col2im_1d_bf16;
904
933
  vk_pipeline pipeline_snake_f32;
905
934
  vk_pipeline pipeline_snake_f16;
906
935
  vk_pipeline pipeline_snake_bf16;
907
936
  vk_pipeline pipeline_pool2d_f32;
908
937
  vk_pipeline pipeline_rwkv_wkv6_f32;
909
938
  vk_pipeline pipeline_rwkv_wkv7_f32;
910
- // [size_idx][kda] where size_idx: 0=d32, 1=d64, 2=d128
911
- vk_pipeline pipeline_gated_delta_net[3][2];
939
+ // [size_idx][kda] where size_idx: 0=d16, 1=d32, 2=d64, 3=d128
940
+ vk_pipeline pipeline_gated_delta_net[4][2];
912
941
  vk_pipeline pipeline_ssm_scan_f32_d128;
913
942
  vk_pipeline pipeline_ssm_scan_f32_d256;
914
943
  vk_pipeline pipeline_ssm_conv_f32;
@@ -920,6 +949,8 @@ struct vk_device_struct {
920
949
  std::map<vk_conv2d_pipeline_state, vk_pipeline> pipeline_conv2d_f16_f32[CONV_SHAPE_COUNT];
921
950
  std::map<vk_conv2d_pipeline_state, vk_pipeline> pipeline_conv_transpose_2d_f32[CONV_SHAPE_COUNT];
922
951
  std::map<vk_conv2d_pipeline_state, vk_pipeline> pipeline_conv_transpose_2d_f16_f32[CONV_SHAPE_COUNT];
952
+ std::map<vk_conv3d_pipeline_state, vk_pipeline> pipeline_conv3d_f32[CONV_SHAPE_COUNT];
953
+ std::map<vk_conv3d_pipeline_state, vk_pipeline> pipeline_conv3d_f16_f32[CONV_SHAPE_COUNT];
923
954
  vk_pipeline pipeline_conv2d_dw_whcn_f32, pipeline_conv2d_dw_whcn_f16_f32;
924
955
  vk_pipeline pipeline_conv2d_dw_cwhn_f32, pipeline_conv2d_dw_cwhn_f16_f32;
925
956
 
@@ -1202,30 +1233,35 @@ struct vk_op_glu_push_constants {
1202
1233
  uint32_t mode; // 0: default, 1: swapped, 2: split
1203
1234
  float alpha; // for swiglu_oai
1204
1235
  float limit;
1236
+ uint32_t nb00;
1205
1237
  uint32_t nb01;
1206
1238
  uint32_t nb02;
1207
1239
  uint32_t nb03;
1208
- uint32_t ne01;
1209
- uint32_t ne02;
1240
+ uint32_t nb10;
1210
1241
  uint32_t nb11;
1211
1242
  uint32_t nb12;
1212
1243
  uint32_t nb13;
1213
- uint32_t ne11;
1214
- uint32_t ne12;
1244
+ uint32_t nb20;
1245
+ uint32_t nb21;
1246
+ uint32_t nb22;
1247
+ uint32_t nb23;
1248
+ uint32_t ne21;
1249
+ uint32_t ne22;
1250
+ uint32_t misalign_offsets;
1251
+ uint32_t ne2_012mp; uint32_t ne2_012L;
1252
+ uint32_t ne2_01mp; uint32_t ne2_01L;
1253
+ uint32_t ne2_0mp; uint32_t ne2_0L;
1215
1254
  };
1255
+ static_assert(sizeof(vk_op_glu_push_constants) <= 128, "sizeof(vk_op_glu_push_constants) must be <= 128");
1216
1256
 
1217
1257
  struct vk_op_unary_push_constants {
1218
1258
  uint32_t ne;
1219
1259
  uint32_t ne00; uint32_t ne01; uint32_t ne02; uint32_t ne03; uint32_t nb00; uint32_t nb01; uint32_t nb02; uint32_t nb03;
1220
1260
  uint32_t ne10; uint32_t ne11; uint32_t ne12; uint32_t ne13; uint32_t nb10; uint32_t nb11; uint32_t nb12; uint32_t nb13;
1221
1261
  uint32_t misalign_offsets;
1222
- float param1; float param2;
1223
- uint32_t ne0_012mp; uint32_t ne0_012L;
1224
- uint32_t ne0_01mp; uint32_t ne0_01L;
1225
- uint32_t ne0_0mp; uint32_t ne0_0L;
1226
- uint32_t ne1_012mp; uint32_t ne1_012L;
1227
- uint32_t ne1_01mp; uint32_t ne1_01L;
1228
- uint32_t ne1_0mp; uint32_t ne1_0L;
1262
+ float param1; float param2; float param3; float param4;
1263
+ uint32_t ne0_012mp; uint32_t ne0_01mp; uint32_t ne0_0mp; uint32_t ne0_Ls;
1264
+ uint32_t ne1_012mp; uint32_t ne1_01mp; uint32_t ne1_0mp; uint32_t ne1_Ls;
1229
1265
  };
1230
1266
  static_assert(sizeof(vk_op_unary_push_constants) <= 128, "sizeof(vk_op_unary_push_constants) must be <= 128");
1231
1267
 
@@ -1330,6 +1366,10 @@ static void init_fastdiv_values(uint32_t d, uint32_t &mp, uint32_t &L)
1330
1366
  mp = (uint32_t)((uint64_t{1} << 32) * ((uint64_t{1} << L) - d) / d + 1);
1331
1367
  }
1332
1368
 
1369
+ static uint32_t pack_fastdiv_L(uint32_t L0, uint32_t L1, uint32_t L2) {
1370
+ return L0 | (L1 << 8) | (L2 << 16);
1371
+ }
1372
+
1333
1373
  template <typename T> void init_pushconst_fastdiv(T &p) {
1334
1374
  GGML_UNUSED(p);
1335
1375
  static_assert(!std::is_const<T>::value, "unexpected type");
@@ -1337,12 +1377,29 @@ template <typename T> void init_pushconst_fastdiv(T &p) {
1337
1377
 
1338
1378
  template <> void init_pushconst_fastdiv(vk_op_unary_push_constants &p) {
1339
1379
  // Compute magic values to divide by these six numbers.
1340
- init_fastdiv_values(p.ne02*p.ne01*p.ne00, p.ne0_012mp, p.ne0_012L);
1341
- init_fastdiv_values(p.ne01*p.ne00, p.ne0_01mp, p.ne0_01L);
1342
- init_fastdiv_values(p.ne00, p.ne0_0mp, p.ne0_0L);
1343
- init_fastdiv_values(p.ne12*p.ne11*p.ne10, p.ne1_012mp, p.ne1_012L);
1344
- init_fastdiv_values(p.ne11*p.ne10, p.ne1_01mp, p.ne1_01L);
1345
- init_fastdiv_values(p.ne10, p.ne1_0mp, p.ne1_0L);
1380
+ uint32_t ne0_012L;
1381
+ uint32_t ne0_01L;
1382
+ uint32_t ne0_0L;
1383
+ uint32_t ne1_012L;
1384
+ uint32_t ne1_01L;
1385
+ uint32_t ne1_0L;
1386
+
1387
+ init_fastdiv_values(p.ne02*p.ne01*p.ne00, p.ne0_012mp, ne0_012L);
1388
+ init_fastdiv_values(p.ne01*p.ne00, p.ne0_01mp, ne0_01L);
1389
+ init_fastdiv_values(p.ne00, p.ne0_0mp, ne0_0L);
1390
+ init_fastdiv_values(p.ne12*p.ne11*p.ne10, p.ne1_012mp, ne1_012L);
1391
+ init_fastdiv_values(p.ne11*p.ne10, p.ne1_01mp, ne1_01L);
1392
+ init_fastdiv_values(p.ne10, p.ne1_0mp, ne1_0L);
1393
+
1394
+ p.ne0_Ls = pack_fastdiv_L(ne0_012L, ne0_01L, ne0_0L);
1395
+ p.ne1_Ls = pack_fastdiv_L(ne1_012L, ne1_01L, ne1_0L);
1396
+ }
1397
+
1398
+ template <> void init_pushconst_fastdiv(vk_op_glu_push_constants &p) {
1399
+ // GLU linearizes over dst, then uses dst coordinates for src0/src1.
1400
+ init_fastdiv_values(p.ne22*p.ne21*p.ne20, p.ne2_012mp, p.ne2_012L);
1401
+ init_fastdiv_values(p.ne21*p.ne20, p.ne2_01mp, p.ne2_01L);
1402
+ init_fastdiv_values(p.ne20, p.ne2_0mp, p.ne2_0L);
1346
1403
  }
1347
1404
 
1348
1405
  struct vk_op_binary_push_constants {
@@ -1525,6 +1582,16 @@ struct vk_op_timestep_embedding_push_constants {
1525
1582
  uint32_t max_period;
1526
1583
  };
1527
1584
 
1585
+ struct vk_op_col2im_1d_push_constants {
1586
+ uint32_t T_out;
1587
+ uint32_t OC;
1588
+ uint32_t K_OC;
1589
+ uint32_t T_in;
1590
+ uint32_t K;
1591
+ int32_t stride;
1592
+ int32_t p0;
1593
+ };
1594
+
1528
1595
  struct vk_op_conv_transpose_1d_push_constants {
1529
1596
  uint32_t Cout;
1530
1597
  uint32_t Cin;
@@ -1629,6 +1696,41 @@ template <> void init_pushconst_fastdiv(vk_op_conv2d_push_constants &p) {
1629
1696
  init_fastdiv_values(p.OW*p.OH, p.OWOHmp, p.OWOHL);
1630
1697
  }
1631
1698
 
1699
+ struct vk_op_conv3d_push_constants {
1700
+ uint32_t OC;
1701
+ uint32_t IC;
1702
+ uint32_t N;
1703
+
1704
+ uint32_t IW;
1705
+ uint32_t IH;
1706
+ uint32_t ID;
1707
+ uint32_t OW;
1708
+ uint32_t OH;
1709
+ uint32_t OD;
1710
+
1711
+ uint32_t nb01;
1712
+ uint32_t nb02;
1713
+ uint32_t nb03;
1714
+
1715
+ uint32_t nb11;
1716
+ uint32_t nb12;
1717
+ uint32_t nb13;
1718
+
1719
+ uint32_t nb1;
1720
+ uint32_t nb2;
1721
+ uint32_t nb3;
1722
+
1723
+ uint32_t OWmp; uint32_t OWL;
1724
+ uint32_t OWOHmp; uint32_t OWOHL;
1725
+ uint32_t OWOHODmp; uint32_t OWOHODL;
1726
+ };
1727
+
1728
+ template <> void init_pushconst_fastdiv(vk_op_conv3d_push_constants &p) {
1729
+ init_fastdiv_values(p.OW, p.OWmp, p.OWL);
1730
+ init_fastdiv_values(p.OW*p.OH, p.OWOHmp, p.OWOHL);
1731
+ init_fastdiv_values(p.OW*p.OH*p.OD, p.OWOHODmp, p.OWOHODL);
1732
+ }
1733
+
1632
1734
  struct vk_op_conv2d_dw_push_constants {
1633
1735
  uint32_t ne;
1634
1736
  uint32_t batches;
@@ -1805,6 +1907,38 @@ static bool vk_enable_sync_logger = false;
1805
1907
  static uint32_t vk_perf_logger_frequency = 1;
1806
1908
  static std::string vk_pipeline_stats_filter;
1807
1909
 
1910
+ static uint64_t ggml_vk_get_node_flops(const ggml_tensor * node) {
1911
+ if (node->op == GGML_OP_MUL_MAT || node->op == GGML_OP_MUL_MAT_ID) {
1912
+ const uint64_t m = node->ne[0];
1913
+ const uint64_t n = node->ne[1];
1914
+ const uint64_t k = node->src[1]->ne[0];
1915
+ const uint64_t batch = node->ne[2] * node->ne[3];
1916
+ return m * n * (k + (k - 1)) * batch;
1917
+ }
1918
+ if (node->op == GGML_OP_CONV_2D || node->op == GGML_OP_CONV_TRANSPOSE_2D) {
1919
+ const ggml_tensor * knl = node->src[0];
1920
+ const uint64_t Cout = node->ne[2];
1921
+ const uint64_t size_K = node->src[1]->ne[2] * knl->ne[0] * knl->ne[1];
1922
+ const uint64_t size_N = node->ne[3] * node->ne[0] * node->ne[1];
1923
+ return Cout * size_N * (size_K + (size_K - 1));
1924
+ }
1925
+ if (node->op == GGML_OP_CONV_3D) {
1926
+ const ggml_tensor * knl = node->src[0];
1927
+ const uint64_t OC = ggml_get_op_params_i32(node, 11);
1928
+ const uint64_t IC = ggml_get_op_params_i32(node, 9);
1929
+ const uint64_t size_K = IC * knl->ne[0] * knl->ne[1] * knl->ne[2];
1930
+ const uint64_t size_N = node->ne[3] / OC * node->ne[0] * node->ne[1] * node->ne[2];
1931
+ return OC * size_N * (size_K + (size_K - 1));
1932
+ }
1933
+ if (node->op == GGML_OP_FLASH_ATTN_EXT) {
1934
+ const ggml_tensor * q = node->src[0];
1935
+ const ggml_tensor * k = node->src[1];
1936
+ const ggml_tensor * v = node->src[2];
1937
+ return 2ull * q->ne[1] * q->ne[2] * (k->ne[0] + v->ne[0]) * k->ne[1] * q->ne[3];
1938
+ }
1939
+ return 0;
1940
+ }
1941
+
1808
1942
  class vk_perf_logger {
1809
1943
  public:
1810
1944
  void print_timings(bool force = false) {
@@ -1853,7 +1987,7 @@ class vk_perf_logger {
1853
1987
  }
1854
1988
 
1855
1989
  std::string get_node_fusion_name(const ggml_tensor * node, const char *fusion_name, uint64_t *n_flops) {
1856
- *n_flops = 0;
1990
+ *n_flops = ggml_vk_get_node_flops(node);
1857
1991
  std::string fusion_str;
1858
1992
  if (fusion_name) {
1859
1993
  fusion_str = fusion_name + std::string(" ");
@@ -1880,35 +2014,22 @@ class vk_perf_logger {
1880
2014
  if (batch > 1) {
1881
2015
  name += " batch=" + std::to_string(batch);
1882
2016
  }
1883
- name = fusion_str + name;
1884
- *n_flops = m * n * (k + (k - 1)) * batch;
1885
- return name;
2017
+ return fusion_str + name;
1886
2018
  }
1887
2019
  if (node->op == GGML_OP_CONV_2D || node->op == GGML_OP_CONV_TRANSPOSE_2D) {
1888
2020
  std::string name = ggml_op_name(node->op);
1889
- ggml_tensor * knl = node->src[0];
1890
- uint64_t OW = node->ne[0];
1891
- uint64_t OH = node->ne[1];
1892
- uint64_t N = node->ne[3];
2021
+ const ggml_tensor * knl = node->src[0];
1893
2022
  uint64_t Cout = node->ne[2];
1894
- uint64_t KW = knl->ne[0];
1895
- uint64_t KH = knl->ne[1];
1896
- uint64_t Cin = node->src[1]->ne[2];
1897
- // KxCRS @ CRSxNPQ = KxNPQ -> M=K, K=CRS, N=NPQ
1898
- uint64_t size_M = Cout;
1899
- uint64_t size_K = Cin * KW * KH;
1900
- uint64_t size_N = N * OW * OH;
1901
- *n_flops = size_M * size_N * (size_K + (size_K - 1));
1902
- name += " M=Cout=" + std::to_string(size_M) + ", K=Cin*KW*KH=" + std::to_string(size_K) +
2023
+ uint64_t size_K = node->src[1]->ne[2] * knl->ne[0] * knl->ne[1];
2024
+ uint64_t size_N = node->ne[3] * node->ne[0] * node->ne[1];
2025
+ name += " M=Cout=" + std::to_string(Cout) + ", K=Cin*KW*KH=" + std::to_string(size_K) +
1903
2026
  ", N=N*OW*OH=" + std::to_string(size_N);
1904
- name = fusion_str + name;
1905
- return name;
2027
+ return fusion_str + name;
1906
2028
  }
1907
2029
  if (node->op == GGML_OP_RMS_NORM) {
1908
2030
  std::string name = ggml_op_name(node->op);
1909
2031
  name += "(" + std::to_string(node->ne[0]) + "," + std::to_string(node->ne[1]) + "," + std::to_string(node->ne[2]) + "," + std::to_string(node->ne[3]) + ")";
1910
- name = fusion_str + name;
1911
- return name;
2032
+ return fusion_str + name;
1912
2033
  }
1913
2034
  if (node->op == GGML_OP_FLASH_ATTN_EXT) {
1914
2035
  const ggml_tensor * dst = node;
@@ -1924,7 +2045,6 @@ class vk_perf_logger {
1924
2045
  " k(" << k->ne[0] << "," << k->ne[1] << "," << k->ne[2] << "," << k->ne[3] << "), " <<
1925
2046
  " v(" << v->ne[0] << "," << v->ne[1] << "," << v->ne[2] << "," << v->ne[3] << "), " <<
1926
2047
  " m(" << (m?m->ne[0]:0) << "," << (m?m->ne[1]:0) << "," << (m?m->ne[2]:0) << "," << (m?m->ne[3]:0) << ")";
1927
- *n_flops = 2ull * q->ne[1] * q->ne[2] * (k->ne[0] + v->ne[0]) * k->ne[1] * q->ne[3];
1928
2048
  return name.str();
1929
2049
  }
1930
2050
  if (node->op == GGML_OP_TOP_K) {
@@ -1988,7 +2108,7 @@ struct ggml_backend_vk_context {
1988
2108
  bool do_add_rms_partials_offset_calculation;
1989
2109
  bool do_add_rms_partials;
1990
2110
 
1991
- uint64_t last_total_mul_mat_bytes {};
2111
+ uint64_t last_total_flops {UINT64_MAX};
1992
2112
 
1993
2113
  // Cache most recent tensor that was converted into prealloc_y, and what pipeline it used to convert.
1994
2114
  vk_pipeline_struct * prealloc_y_last_pipeline_used {};
@@ -2355,6 +2475,85 @@ static bool ggml_vk_strip_decode_vector(const uint32_t * code, size_t word_count
2355
2475
  return true;
2356
2476
  }
2357
2477
 
2478
+ // Remove the loop unrolling hint of the matmul shader's BK loop
2479
+ // and replace it with the dont_unroll hint for better performance on
2480
+ // hardware like Apple M1/M2.
2481
+ // Assumes 1. code comes from mul_mm.comp 2. the K-tile loop has no loop
2482
+ // control hint and 3. the BK loop is the last loop nested directly inside
2483
+ // the K-tile loop.
2484
+ // Returns true when the input was modified; returns false otherwise
2485
+ // without touching `out`.
2486
+ static bool ggml_vk_roll_bk_loop(const uint32_t * code, size_t word_count, std::vector<uint32_t> & out) {
2487
+ if (word_count < 5) {
2488
+ return false;
2489
+ }
2490
+
2491
+ struct vk_spv_loop {
2492
+ size_t header;
2493
+ size_t end;
2494
+ uint32_t control;
2495
+ };
2496
+
2497
+ std::vector<vk_spv_loop> loops;
2498
+
2499
+ // Collect a list of all loops in the module.
2500
+ for (size_t pos = 5; pos < word_count; ) {
2501
+ const uint32_t wc = code[pos] >> spv::WordCountShift;
2502
+ const uint32_t op = code[pos] & spv::OpCodeMask;
2503
+ if (wc == 0 || pos + wc > word_count) {
2504
+ return false;
2505
+ }
2506
+
2507
+ if (op == spv::OpLoopMerge && wc >= 4) { loops.push_back({ pos, 0, code[pos + 3] }); }
2508
+
2509
+ if (op == spv::OpLabel && wc >= 2) {
2510
+ for (auto & l : loops) {
2511
+ if (l.end == 0 && code[l.header + 1] == code[pos + 1]) { l.end = pos; }
2512
+ }
2513
+ }
2514
+
2515
+ pos += wc;
2516
+ }
2517
+
2518
+ auto encloses = [](const vk_spv_loop & a, const vk_spv_loop & b) {
2519
+ return a.header < b.header && b.header < a.end;
2520
+ };
2521
+
2522
+ // Find the BK loop.
2523
+ const vk_spv_loop * bk = nullptr;
2524
+ for (const auto & h : loops) {
2525
+ if (h.control != spv::LoopControlUnrollMask) {
2526
+ continue;
2527
+ }
2528
+ const vk_spv_loop * parent = nullptr;
2529
+ bool has_child = false;
2530
+ for (const auto & g : loops) {
2531
+ if (encloses(g, h) && (!parent || g.header > parent->header)) {
2532
+ parent = &g;
2533
+ }
2534
+ if (encloses(h, g)) {
2535
+ has_child = true;
2536
+ }
2537
+ }
2538
+ // BK loop should be the last loop nested inside the loop with no hint
2539
+ // and have at least one child loop.
2540
+ if (parent &&
2541
+ parent->control == spv::LoopControlMaskNone &&
2542
+ has_child &&
2543
+ (!bk || h.header > bk->header)) {
2544
+ bk = &h;
2545
+ }
2546
+ }
2547
+ if (!bk) {
2548
+ return false;
2549
+ }
2550
+
2551
+ // set DontUnroll instead of Unroll
2552
+ out.assign(code, code + word_count);
2553
+ out[bk->header + 3] = spv::LoopControlDontUnrollMask;
2554
+ return true;
2555
+ }
2556
+
2358
2557
  static void ggml_vk_create_pipeline_func(vk_device& device, vk_pipeline& pipeline, size_t spv_size, const void* spv_data, const std::string entrypoint,
2359
2558
  uint32_t parameter_count, std::array<uint32_t, 3> wg_denoms, std::vector<uint32_t> specialization_constants,
2360
2559
  bool disable_robustness, bool require_full_subgroups, uint32_t required_subgroup_size) {
@@ -2438,6 +2637,22 @@ static void ggml_vk_create_pipeline_func(vk_device& device, vk_pipeline& pipelin
2438
2637
  }
2439
2638
  #endif
2440
2639
 
2640
+ #if VK_HEADER_VERSION >= 287
2641
+ // Roll the mul_mm BK loop on Asahi Linux. Skip bf16 and the mul_mmq pipelines.
2642
+ if (device->driver_id == vk::DriverId::eMesaHoneykrisp &&
2643
+ pipeline->name.rfind("matmul", 0) == 0 &&
2644
+ pipeline->name.find("bf16") == std::string::npos &&
2645
+ pipeline->name.find("q8_1") == std::string::npos) {
2646
+ const uint32_t * src = spirv.empty() ? reinterpret_cast<const uint32_t *>(spv_data) : spirv.data();
2647
+ size_t src_n = spirv.empty() ? spv_size / sizeof(uint32_t) : spirv.size();
2648
+ std::vector<uint32_t> rolled;
2649
+ if (ggml_vk_roll_bk_loop(src, src_n, rolled)) {
2650
+ spirv = std::move(rolled);
2651
+ shader_module_create_info = vk::ShaderModuleCreateInfo({}, spirv.size() * sizeof(uint32_t), spirv.data());
2652
+ }
2653
+ }
2654
+ #endif
2655
+
2441
2656
  pipeline->shader_module = device->device.createShaderModule(shader_module_create_info);
2442
2657
 
2443
2658
  vk::PushConstantRange pcr(
@@ -2968,13 +3183,13 @@ static vk_buffer ggml_vk_create_buffer(vk_device& device, size_t size, const std
2968
3183
  if (memory_type_indices.empty()) {
2969
3184
  continue;
2970
3185
  }
2971
- buf->memory_property_flags = req_flags;
2972
3186
 
2973
3187
  bool done = false;
2974
3188
 
2975
3189
  for (auto mtype_it = memory_type_indices.begin(); mtype_it != memory_type_indices.end(); mtype_it++) {
2976
3190
  try {
2977
3191
  buf->device_memory = device->device.allocateMemory({ mem_req.size, *mtype_it, &mem_flags_info });
3192
+ buf->memory_property_flags = mem_props.memoryTypes[*mtype_it].propertyFlags;
2978
3193
  done = true;
2979
3194
  break;
2980
3195
  } catch (const vk::SystemError& e) {
@@ -3040,8 +3255,10 @@ static vk_buffer ggml_vk_create_buffer_device(vk_device& device, size_t size) {
3040
3255
  buf = ggml_vk_create_buffer(device, size, {vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent,
3041
3256
  vk::MemoryPropertyFlagBits::eDeviceLocal});
3042
3257
  } else if (device->uma) {
3043
- // Fall back to host memory type
3044
- buf = ggml_vk_create_buffer(device, size, {vk::MemoryPropertyFlagBits::eDeviceLocal,
3258
+ // On UMA, prefer host-visible memory so direct tensor borrowing works.
3259
+ // If unavailable, fall back to device-local memory.
3260
+ buf = ggml_vk_create_buffer(device, size, {vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent,
3261
+ vk::MemoryPropertyFlagBits::eDeviceLocal,
3045
3262
  vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent});
3046
3263
  } else if (device->disable_host_visible_vidmem) {
3047
3264
  if (device->allow_sysmem_fallback) {
@@ -3742,7 +3959,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
3742
3959
  l_warptile = { 256, 128, 128, 16, subgroup_size_8, 64, 2, tm_m, tn_m, tk_m, subgroup_size_8 };
3743
3960
  l_warptile_mmq = l_warptile_mmq_int = { 256, 128, 128, 32, subgroup_size_8, 64, 2, tm_m, tn_m, tk_m, subgroup_size_8 };
3744
3961
  l_warptile_mmq_int_k = { 256, 128, 128, 32, subgroup_size_16, 64, 1, 4, 2, 1, subgroup_size_16 };
3745
- } else if (device->vendor_id == VK_VENDOR_ID_INTEL && device->coopmat_support && device->architecture == INTEL_XE2) {
3962
+ } else if (device->vendor_id == VK_VENDOR_ID_INTEL && device->coopmat_support) {
3746
3963
  // Xe2/Xe3 with coopmat enabled - warptile performance tuning
3747
3964
  l_warptile = { 512, 128, 128, 16, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 };
3748
3965
  l_warptile_mmq = { 512, 128, 128, 32, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 };
@@ -4032,19 +4249,35 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4032
4249
  }
4033
4250
  #endif
4034
4251
 
4252
+ auto const &ggml_vk_mul_mm_spec = [](std::vector<uint32_t> spec, bool aligned) {
4253
+ spec.push_back(aligned ? 1u : 0u);
4254
+ return spec;
4255
+ };
4256
+
4035
4257
  const int mul_mat_id_param_count = 5;
4036
4258
 
4037
4259
  #if defined(VK_NV_cooperative_matrix2) && defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT)
4038
4260
  if (device->coopmat2) {
4261
+ auto const &ggml_vk_mul_mm_cm2_spec = [](std::vector<uint32_t> spec, bool aligned, bool mul_mat_id) {
4262
+ if (mul_mat_id && spec.size() > 5) {
4263
+ spec.insert(spec.begin() + 5, aligned ? 1u : 0u);
4264
+ } else {
4265
+ spec.push_back(aligned ? 1u : 0u);
4266
+ }
4267
+ if (mul_mat_id && spec.size() == 6) {
4268
+ spec.push_back(32);
4269
+ }
4270
+ return spec;
4271
+ };
4039
4272
 
4040
4273
  // Create 6 variants, {s,m,l}x{unaligned,aligned}
4041
4274
  #define CREATE_MM(PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT) \
4042
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1, true); \
4043
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1, true); \
4044
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1, true); \
4045
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _cm2_len, NAMELC ## _aligned ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align, true); \
4046
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _cm2_len, NAMELC ## _aligned ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align, true); \
4047
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _cm2_len, NAMELC ## _aligned ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align, true); \
4275
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_cm2_spec(l_ ## WARPTILE, false, PARAMCOUNT == mul_mat_id_param_count), 1, true); \
4276
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_cm2_spec(m_ ## WARPTILE, false, PARAMCOUNT == mul_mat_id_param_count), 1, true); \
4277
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_cm2_spec(s_ ## WARPTILE, false, PARAMCOUNT == mul_mat_id_param_count), 1, true); \
4278
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_cm2_spec(l_ ## WARPTILE, true, PARAMCOUNT == mul_mat_id_param_count), l_align, true); \
4279
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_cm2_spec(m_ ## WARPTILE, true, PARAMCOUNT == mul_mat_id_param_count), m_align, true); \
4280
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## F16ACC ## _cm2_len, NAMELC ## F16ACC ## _cm2_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_cm2_spec(s_ ## WARPTILE, true, PARAMCOUNT == mul_mat_id_param_count), s_align, true); \
4048
4281
 
4049
4282
  // Create 2 variants, {f16,f32} accumulator
4050
4283
  #define CREATE_MM2(PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT) \
@@ -4119,17 +4352,17 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4119
4352
  // Create 6 variants, {s,m,l}x{unaligned,aligned}
4120
4353
  #define CREATE_MM(TYPE, PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \
4121
4354
  if (device->mul_mat ## ID ## _l[TYPE]) \
4122
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1, false, true); \
4355
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, false), 1, false, true); \
4123
4356
  if (device->mul_mat ## ID ## _m[TYPE]) \
4124
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1, false, true); \
4357
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, false), 1, false, true); \
4125
4358
  if (device->mul_mat ## ID ## _s[TYPE]) \
4126
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1, false, true); \
4359
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, false), 1, false, true); \
4127
4360
  if (device->mul_mat ## ID ## _l[TYPE]) \
4128
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _cm1_len, NAMELC ## _aligned ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align, false, true); \
4361
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, true), l_align, false, true); \
4129
4362
  if (device->mul_mat ## ID ## _m[TYPE]) \
4130
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _cm1_len, NAMELC ## _aligned ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align, false, true); \
4363
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, true), m_align, false, true); \
4131
4364
  if (device->mul_mat ## ID ## _s[TYPE]) \
4132
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _cm1_len, NAMELC ## _aligned ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align, false, true); \
4365
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## F16ACC ## _cm1_len, NAMELC ## F16ACC ## _cm1_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, true), s_align, false, true); \
4133
4366
 
4134
4367
  // Create 2 variants, {f16,f32} accumulator
4135
4368
  #define CREATE_MM2(TYPE, PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \
@@ -4242,32 +4475,32 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4242
4475
  // Selects dot2 SPIR-V variant at runtime when device->dot2_f16 is true
4243
4476
  #define CREATE_MM(TYPE, PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID, REQSUBGROUPSIZE) \
4244
4477
  if (device->mul_mat ## ID ## _l[TYPE]) \
4245
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4478
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4246
4479
  if (device->mul_mat ## ID ## _m[TYPE]) \
4247
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4480
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4248
4481
  if (device->mul_mat ## ID ## _s[TYPE]) \
4249
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4482
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4250
4483
  if (device->mul_mat ## ID ## _l[TYPE]) \
4251
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", (device->dot2_f16 ? NAMELC ## _dot2_aligned ## F16ACC ## _len : NAMELC ## _aligned ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2_aligned ## F16ACC ## _data : NAMELC ## _aligned ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4484
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, true), l_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4252
4485
  if (device->mul_mat ## ID ## _m[TYPE]) \
4253
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", (device->dot2_f16 ? NAMELC ## _dot2_aligned ## F16ACC ## _len : NAMELC ## _aligned ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2_aligned ## F16ACC ## _data : NAMELC ## _aligned ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4486
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, true), m_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4254
4487
  if (device->mul_mat ## ID ## _s[TYPE]) \
4255
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", (device->dot2_f16 ? NAMELC ## _dot2_aligned ## F16ACC ## _len : NAMELC ## _aligned ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2_aligned ## F16ACC ## _data : NAMELC ## _aligned ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4488
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _len : NAMELC ## F16ACC ## _len), (device->dot2_f16 ? NAMELC ## _dot2 ## F16ACC ## _data : NAMELC ## F16ACC ## _data), "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, true), s_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4256
4489
 
4257
4490
  // bf16 scalar path promotes to f32, no dot2 variant
4258
4491
  #define CREATE_MM_NODOT2(TYPE, PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID, REQSUBGROUPSIZE) \
4259
4492
  if (device->mul_mat ## ID ## _l[TYPE]) \
4260
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4493
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4261
4494
  if (device->mul_mat ## ID ## _m[TYPE]) \
4262
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4495
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4263
4496
  if (device->mul_mat ## ID ## _s[TYPE]) \
4264
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4497
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4265
4498
  if (device->mul_mat ## ID ## _l[TYPE]) \
4266
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _len, NAMELC ## _aligned ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4499
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, true), l_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4267
4500
  if (device->mul_mat ## ID ## _m[TYPE]) \
4268
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _len, NAMELC ## _aligned ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4501
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, true), m_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4269
4502
  if (device->mul_mat ## ID ## _s[TYPE]) \
4270
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _len, NAMELC ## _aligned ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4503
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## F16ACC ## _len, NAMELC ## F16ACC ## _data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, true), s_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4271
4504
 
4272
4505
  #define CREATE_MMQ(TYPE, PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID, REQSUBGROUPSIZE) \
4273
4506
  if (device->mul_mat ## ID ## _l_int[TYPE]) { \
@@ -4432,17 +4665,17 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4432
4665
  // Create 6 variants, {s,m,l}x{unaligned,aligned}
4433
4666
  #define CREATE_MM(TYPE, PIPELINE_NAME, NAMELC, F16ACC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID, REQSUBGROUPSIZE) \
4434
4667
  if (device->mul_mat ## ID ## _l[TYPE]) \
4435
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4668
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->l, #NAMELC #F16ACC "_l", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4436
4669
  if (device->mul_mat ## ID ## _m[TYPE]) \
4437
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4670
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->m, #NAMELC #F16ACC "_m", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4438
4671
  if (device->mul_mat ## ID ## _s[TYPE]) \
4439
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4672
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->s, #NAMELC #F16ACC "_s", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, false), 1, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4440
4673
  if (device->mul_mat ## ID ## _l[TYPE]) \
4441
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## _aligned ## F16ACC ## _fp32_len, NAMELC ## _aligned ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, l_ ## WARPTILE, l_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4674
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_l, #NAMELC #F16ACC "_aligned_l", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), l_ ## WG_DENOMS, ggml_vk_mul_mm_spec(l_ ## WARPTILE, true), l_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4442
4675
  if (device->mul_mat ## ID ## _m[TYPE]) \
4443
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## _aligned ## F16ACC ## _fp32_len, NAMELC ## _aligned ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, m_ ## WARPTILE, m_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4676
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_m, #NAMELC #F16ACC "_aligned_m", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), m_ ## WG_DENOMS, ggml_vk_mul_mm_spec(m_ ## WARPTILE, true), m_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4444
4677
  if (device->mul_mat ## ID ## _s[TYPE]) \
4445
- ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## _aligned ## F16ACC ## _fp32_len, NAMELC ## _aligned ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, s_ ## WARPTILE, s_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4678
+ ggml_vk_create_pipeline(device, device-> PIPELINE_NAME ->a_s, #NAMELC #F16ACC "_aligned_s", NAMELC ## F16ACC ## _fp32_len, NAMELC ## F16ACC ## _fp32_data, "main", PARAMCOUNT, sizeof(PUSHCONST), s_ ## WG_DENOMS, ggml_vk_mul_mm_spec(s_ ## WARPTILE, true), s_align, false, REQSUBGROUPSIZE > 0, REQSUBGROUPSIZE); \
4446
4679
 
4447
4680
  #define CREATE_MMQ(TYPE, PIPELINE_NAME, NAMELC, WG_DENOMS, WARPTILE, PUSHCONST, PARAMCOUNT, ID) \
4448
4681
  if (device->mul_mat ## ID ## _l_int[TYPE]) \
@@ -4599,7 +4832,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4599
4832
  }
4600
4833
  uint32_t rm_iq = 2 * rm_kq;
4601
4834
 
4602
- const bool use_subgroups = device->subgroup_arithmetic && device->architecture != vk_device_architecture::AMD_GCN;
4835
+ const bool use_subgroups = device->subgroup_arithmetic;
4603
4836
  // Ensure a subgroup size >= 16 is available
4604
4837
  const bool use_subgroups16 = use_subgroups && subgroup_min_size_16;
4605
4838
 
@@ -4837,6 +5070,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4837
5070
  ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_IQ4_NL], "get_rows_iq4_nl_f32", get_rows_iq4_nl_f32_len, get_rows_iq4_nl_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1);
4838
5071
  ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_MXFP4], "get_rows_mxfp4_f32", get_rows_mxfp4_f32_len, get_rows_mxfp4_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1);
4839
5072
  ggml_vk_create_pipeline(device, device->pipeline_get_rows_f32[GGML_TYPE_NVFP4], "get_rows_nvfp4_f32", get_rows_nvfp4_f32_len, get_rows_nvfp4_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {1024, 1, 1}, {}, 1);
5073
+ ggml_vk_create_pipeline(device, device->pipeline_get_rows_back_f32, "get_rows_back_f32", get_rows_back_f32_len, get_rows_back_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {256, 1, 1}, {}, 1, true);
4840
5074
 
4841
5075
  ggml_vk_create_pipeline(device, device->pipeline_matmul_split_k_reduce, "split_k_reduce", split_k_reduce_len, split_k_reduce_data, "main", 2, 2 * sizeof(uint32_t), {256 * 4, 1, 1}, {}, 1);
4842
5076
  ggml_vk_create_pipeline(device, device->pipeline_flash_attn_split_k_reduce, "fa_split_k_reduce", fa_split_k_reduce_len, fa_split_k_reduce_data, "main", 3, sizeof(vk_op_flash_attn_split_k_reduce_push_constants), {1, device->subgroup_size, 1}, {device->subgroup_size}, 1, true);
@@ -4861,7 +5095,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4861
5095
  }
4862
5096
  ggml_vk_create_pipeline(device, device->pipeline_mul_mat_vec_nc_f16_f32, "mul_mat_vec_nc_f16_f32", mul_mat_vec_nc_f16_f32_len, mul_mat_vec_nc_f16_f32_data, "main", mul_mat_vec_num_bindings, sizeof(vk_mat_vec_nc_push_constants), {1, 1, 1}, {}, 1);
4863
5097
 
4864
- ggml_vk_create_pipeline(device, device->pipeline_norm_f32, "norm_f32", norm_f32_len, norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1);
5098
+ ggml_vk_create_pipeline(device, device->pipeline_norm_f32, "norm_f32", norm_f32_len, norm_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {1, 1, 1}, {}, 1);
4865
5099
  ggml_vk_create_pipeline(device, device->pipeline_group_norm_f32, "group_norm_f32", group_norm_f32_len, group_norm_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, {}, 1);
4866
5100
 
4867
5101
  ggml_vk_create_pipeline(device, device->pipeline_rms_norm_f32, "rms_norm_f32", rms_norm_f32_len, rms_norm_f32_data, "main", 4, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {0, 0}, 1, true);
@@ -4969,9 +5203,10 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4969
5203
  ggml_vk_create_pipeline(device, device->pipeline_acc_f32, "acc_f32", acc_f32_len, acc_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {0, 1}, 1);
4970
5204
  ggml_vk_create_pipeline(device, device->pipeline_set_f32, "set_f32", acc_f32_len, acc_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {0, 0}, 1);
4971
5205
 
4972
- ggml_vk_create_pipeline(device, device->pipeline_concat_f32, "concat_f32", concat_f32_len, concat_f32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1);
4973
- ggml_vk_create_pipeline(device, device->pipeline_concat_f16, "concat_f16", concat_f16_len, concat_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1);
5206
+ ggml_vk_create_pipeline(device, device->pipeline_concat_i8, "concat_i8", concat_i8_len, concat_i8_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1);
5207
+ ggml_vk_create_pipeline(device, device->pipeline_concat_i16, "concat_i16", concat_i16_len, concat_i16_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1);
4974
5208
  ggml_vk_create_pipeline(device, device->pipeline_concat_i32, "concat_i32", concat_i32_len, concat_i32_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1);
5209
+ ggml_vk_create_pipeline(device, device->pipeline_concat_i64, "concat_i64", concat_i64_len, concat_i64_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1);
4975
5210
 
4976
5211
  ggml_vk_create_pipeline(device, device->pipeline_upscale_nearest_f32, "upscale_f32", upscale_f32_len, upscale_f32_data, "main", 2, sizeof(vk_op_upscale_push_constants), {512, 1, 1}, {GGML_SCALE_MODE_NEAREST}, 1);
4977
5212
  ggml_vk_create_pipeline(device, device->pipeline_upscale_bilinear_f32, "upscale_f32", upscale_f32_len, upscale_f32_data, "main", 2, sizeof(vk_op_upscale_push_constants), {512, 1, 1}, {GGML_SCALE_MODE_BILINEAR}, 1);
@@ -4980,11 +5215,6 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4980
5215
 
4981
5216
  ggml_vk_create_pipeline(device, device->pipeline_scale_f32, "scale_f32", scale_f32_len, scale_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4982
5217
 
4983
- ggml_vk_create_pipeline(device, device->pipeline_sqr_f32, "sqr_f32", sqr_f32_len, sqr_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4984
- ggml_vk_create_pipeline(device, device->pipeline_sqrt_f32, "sqrt_f32", sqrt_f32_len, sqrt_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4985
- ggml_vk_create_pipeline(device, device->pipeline_sin_f32, "sin_f32", sin_f32_len, sin_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4986
- ggml_vk_create_pipeline(device, device->pipeline_cos_f32, "cos_f32", cos_f32_len, cos_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4987
-
4988
5218
  ggml_vk_create_pipeline(device, device->pipeline_log[0], "log_f32", log_f32_len, log_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4989
5219
  ggml_vk_create_pipeline(device, device->pipeline_log[1], "log_f16", log_f16_len, log_f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4990
5220
 
@@ -4994,8 +5224,6 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
4994
5224
  ggml_vk_create_pipeline(device, device->pipeline_diag[0], "diag_f32", diag_f32_len, diag_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4995
5225
  ggml_vk_create_pipeline(device, device->pipeline_diag[1], "diag_f16", diag_f16_len, diag_f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4996
5226
 
4997
- ggml_vk_create_pipeline(device, device->pipeline_clamp_f32, "clamp_f32", clamp_f32_len, clamp_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
4998
-
4999
5227
  ggml_vk_create_pipeline(device, device->pipeline_pad_f32, "pad_f32", pad_f32_len, pad_f32_data, "main", 2, sizeof(vk_op_pad_push_constants), {512, 1, 1}, {}, 1);
5000
5228
 
5001
5229
  ggml_vk_create_pipeline(device, device->pipeline_roll_f32, "roll_f32", roll_f32_len, roll_f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
@@ -5006,8 +5234,8 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5006
5234
  ggml_vk_create_pipeline(device, device->pipeline_repeat_i16, "repeat_i16", repeat_i16_len, repeat_i16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
5007
5235
 
5008
5236
  #define CREATE_UNARY(name) \
5009
- ggml_vk_create_pipeline(device, device->pipeline_ ## name [0], #name "_f32", name ## _f32_len, name ## _f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1); \
5010
- ggml_vk_create_pipeline(device, device->pipeline_ ## name [1], #name "_f16", name ## _f16_len, name ## _f16_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1);
5237
+ ggml_vk_create_pipeline(device, device->pipeline_ ## name [0], #name "_f32", name ## _f32_len, name ## _f32_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1); \
5238
+ ggml_vk_create_pipeline(device, device->pipeline_ ## name [1], #name "_f16", name ## _f16_len, name ## _f16_data, "main", 2, sizeof(vk_op_unary_push_constants), {512, 1, 1}, {}, 1);
5011
5239
 
5012
5240
  CREATE_UNARY(elu)
5013
5241
  CREATE_UNARY(gelu)
@@ -5015,6 +5243,12 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5015
5243
  CREATE_UNARY(gelu_quick)
5016
5244
  CREATE_UNARY(silu)
5017
5245
  CREATE_UNARY(relu)
5246
+ CREATE_UNARY(sqr)
5247
+ CREATE_UNARY(sqrt)
5248
+ CREATE_UNARY(sin)
5249
+ CREATE_UNARY(cos)
5250
+ CREATE_UNARY(clamp)
5251
+ CREATE_UNARY(leaky_relu)
5018
5252
  CREATE_UNARY(xielu)
5019
5253
  CREATE_UNARY(neg)
5020
5254
  CREATE_UNARY(tanh)
@@ -5030,6 +5264,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5030
5264
  CREATE_UNARY(trunc)
5031
5265
  CREATE_UNARY(sgn)
5032
5266
  CREATE_UNARY(exp)
5267
+ CREATE_UNARY(expm1)
5033
5268
  #undef CREATE_UNARY
5034
5269
 
5035
5270
  ggml_vk_create_pipeline(device, device->pipeline_add1_f16_f16, "add1_f16_f16", add1_f16_f16_len, add1_f16_f16_data, "main", 3, sizeof(vk_op_binary_push_constants), {512, 1, 1}, {}, 1);
@@ -5053,7 +5288,6 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5053
5288
  CREATE_GLU(geglu_quick)
5054
5289
  #undef CREATE_GLU
5055
5290
 
5056
- ggml_vk_create_pipeline(device, device->pipeline_leaky_relu_f32, "leaky_relu_f32", leaky_relu_f32_len, leaky_relu_f32_data, "main", 2, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1);
5057
5291
  ggml_vk_create_pipeline(device, device->pipeline_silu_back_f32, "silu_back_f32", silu_back_f32_len, silu_back_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1);
5058
5292
 
5059
5293
  ggml_vk_create_pipeline(device, device->pipeline_diag_mask_inf_f32, "diag_mask_inf_f32", diag_mask_inf_f32_len, diag_mask_inf_f32_data, "main", 2, sizeof(vk_op_diag_mask_push_constants), {1, 512, 1}, {}, 1, true);
@@ -5174,6 +5408,9 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5174
5408
  ggml_vk_create_pipeline(device, device->pipeline_timestep_embedding_f32, "timestep_embedding_f32", timestep_embedding_f32_len, timestep_embedding_f32_data, "main", 2, sizeof(vk_op_timestep_embedding_push_constants), {256, 1, 1}, {}, 1);
5175
5409
 
5176
5410
  ggml_vk_create_pipeline(device, device->pipeline_conv_transpose_1d_f32, "conv_transpose_1d_f32", conv_transpose_1d_f32_len, conv_transpose_1d_f32_data, "main", 3, sizeof(vk_op_conv_transpose_1d_push_constants), {1, 1, 1}, {}, 1);
5411
+ ggml_vk_create_pipeline(device, device->pipeline_col2im_1d_f32, "col2im_1d_f32", col2im_1d_f32_len, col2im_1d_f32_data, "main", 2, sizeof(vk_op_col2im_1d_push_constants), {256, 1, 1}, {}, 1, true);
5412
+ ggml_vk_create_pipeline(device, device->pipeline_col2im_1d_f16, "col2im_1d_f16", col2im_1d_f16_len, col2im_1d_f16_data, "main", 2, sizeof(vk_op_col2im_1d_push_constants), {256, 1, 1}, {}, 1, true);
5413
+ ggml_vk_create_pipeline(device, device->pipeline_col2im_1d_bf16, "col2im_1d_bf16", col2im_1d_bf16_len, col2im_1d_bf16_data, "main", 2, sizeof(vk_op_col2im_1d_push_constants), {256, 1, 1}, {}, 1, true);
5177
5414
 
5178
5415
  ggml_vk_create_pipeline(device, device->pipeline_snake_f32, "snake_f32", snake_f32_len, snake_f32_data, "main", 4, sizeof(vk_op_snake_push_constants), {256, 1, 1}, {}, 1);
5179
5416
  ggml_vk_create_pipeline(device, device->pipeline_snake_f16, "snake_f16", snake_f16_len, snake_f16_data, "main", 4, sizeof(vk_op_snake_push_constants), {256, 1, 1}, {}, 1);
@@ -5186,14 +5423,14 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5186
5423
  ggml_vk_create_pipeline(device, device->pipeline_rwkv_wkv7_f32, "rwkv_wkv7_f32", rwkv_wkv7_f32_len, rwkv_wkv7_f32_data, "main", 8, sizeof(vk_op_rwkv_wkv7_push_constants), {1, 1, 1}, {device->subgroup_size}, 1);
5187
5424
 
5188
5425
  {
5189
- const uint32_t gdn_sizes[] = {32, 64, 128};
5426
+ const uint32_t gdn_sizes[] = {16, 32, 64, 128};
5190
5427
  const char * gdn_names[][2] = {
5428
+ {"gated_delta_net_f32_d16", "gated_delta_net_f32_d16_kda"},
5191
5429
  {"gated_delta_net_f32_d32", "gated_delta_net_f32_d32_kda"},
5192
5430
  {"gated_delta_net_f32_d64", "gated_delta_net_f32_d64_kda"},
5193
5431
  {"gated_delta_net_f32_d128", "gated_delta_net_f32_d128_kda"},
5194
5432
  };
5195
- const bool use_subgroup_reduce = device->subgroup_arithmetic;
5196
- for (uint32_t si = 0; si < 3; si++) {
5433
+ for (uint32_t si = 0; si < 4; si++) {
5197
5434
  const uint32_t S_V = gdn_sizes[si];
5198
5435
  GGML_ASSERT(is_pow2(S_V));
5199
5436
 
@@ -5207,10 +5444,29 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5207
5444
  lanes_per_column = std::min(S_V, device->subgroup_size);
5208
5445
  }
5209
5446
 
5210
- const bool need_clustered_shader = lanes_per_column != 1 && (lanes_per_column < device->subgroup_size);
5447
+ // gated_delta_net.comp relies on S_V % COLS_PER_WG == 0 and
5448
+ // S_V % LANES_PER_COLUMN == 0 to avoid bounds checks.
5449
+ while (lanes_per_column > 1u) {
5450
+ const bool valid_lanes = (device->subgroup_size % lanes_per_column) == 0 &&
5451
+ (S_V % lanes_per_column) == 0;
5452
+ const uint32_t cols_per_wg = valid_lanes ? device->subgroup_size / lanes_per_column : 0;
5453
+ if (valid_lanes && cols_per_wg > 0 && (S_V % cols_per_wg) == 0) {
5454
+ break;
5455
+ }
5456
+ lanes_per_column >>= 1u;
5457
+ }
5458
+
5459
+ GGML_ASSERT((device->subgroup_size % lanes_per_column) == 0);
5460
+ GGML_ASSERT((S_V % lanes_per_column) == 0);
5461
+ GGML_ASSERT((S_V % (device->subgroup_size / lanes_per_column)) == 0);
5462
+
5463
+ const bool need_partial_subgroup_reduce = lanes_per_column != 1u && lanes_per_column < device->subgroup_size;
5464
+ const bool use_clustered_reduce = device->subgroup_arithmetic && device->subgroup_clustered && need_partial_subgroup_reduce;
5465
+ const bool use_subgroup_reduce = device->subgroup_arithmetic && !need_partial_subgroup_reduce;
5466
+ const bool use_subgroup_ops = use_clustered_reduce || use_subgroup_reduce;
5211
5467
  size_t gdn_len;
5212
5468
  const void * gdn_data;
5213
- if (use_subgroup_reduce && need_clustered_shader) {
5469
+ if (use_clustered_reduce) {
5214
5470
  gdn_len = gated_delta_net_f32_len;
5215
5471
  gdn_data = (const void *)gated_delta_net_f32_data;
5216
5472
  } else if (use_subgroup_reduce) {
@@ -5227,7 +5483,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5227
5483
  for (uint32_t kda = 0; kda < 2; kda++) {
5228
5484
  ggml_vk_create_pipeline(device, device->pipeline_gated_delta_net[si][kda],
5229
5485
  gdn_names[si][kda], gdn_len, gdn_data, "main", 7, sizeof(vk_op_gated_delta_net_push_constants),
5230
- wg_denoms, {S_V, kda, device->subgroup_size, lanes_per_column}, 1, true, use_subgroup_reduce, device->subgroup_size);
5486
+ wg_denoms, {S_V, kda, device->subgroup_size, lanes_per_column}, 1, true, use_subgroup_ops, device->subgroup_size);
5231
5487
  }
5232
5488
  }
5233
5489
  }
@@ -5248,7 +5504,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5248
5504
 
5249
5505
  ggml_vk_create_pipeline(device, device->pipeline_opt_step_sgd_f32, "opt_step_sgd_f32", opt_step_sgd_f32_len, opt_step_sgd_f32_data, "main", 3, sizeof(vk_op_push_constants), {512, 1, 1}, {}, 1);
5250
5506
 
5251
- // conv2d, conv_transpose_2d
5507
+ // conv2d, conv_transpose_2d, conv3d
5252
5508
  for (uint32_t s = 0; s < CONV_SHAPE_COUNT; ++s) {
5253
5509
  // smaller WG for the small-tile fallback gives more concurrent WGs per SM
5254
5510
  uint32_t conv2d_WG_SIZE = (s == CONV_SHAPE_64x32) ? 128 : 256;
@@ -5311,8 +5567,8 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5311
5567
  return (conv2d_BS.K * (conv2d_BS.CRS + pad) + conv2d_BS.CRS * (conv2d_BS.NPQ + pad) + csh_elems) * elem_size;
5312
5568
  };
5313
5569
 
5314
- // coopmat1 needs to store the output through shared memory, so check up front
5315
- // whether it'll fit and disable it before applying coopmat1 parameters.
5570
+ // 2D, transpose-2D, and 3D conv use the same KxCRS @ CRSxNPQ shmem
5571
+ // layout. cm1 needs Csh for output, so check before applying cm1 params.
5316
5572
  if (conv2d_use_cm1 && device->properties.limits.maxComputeSharedMemorySize < shmem_req(conv2d_cm1_shmem_pad, true, true)) {
5317
5573
  conv2d_use_cm1 = false;
5318
5574
  }
@@ -5404,6 +5660,53 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
5404
5660
  }
5405
5661
  #undef CREATE_CONV
5406
5662
  #undef CREATE_CONVS
5663
+
5664
+ std::vector<uint32_t> conv3d_spec_constants = { conv2d_WG_SIZE, conv2d_BS.K, conv2d_BS.CRS, conv2d_BS.NPQ, conv2d_TS_K, conv2d_SHMEM_PAD };
5665
+ #define CREATE_CONV3D(type_suffix, spv_suffix) \
5666
+ for (auto &c : device->pipeline_conv3d##type_suffix[s]) { \
5667
+ const vk_conv3d_pipeline_state &state = c.first; \
5668
+ std::vector<uint32_t> spec_constants_cpy = conv3d_spec_constants; \
5669
+ spec_constants_cpy.push_back(state.s0); \
5670
+ spec_constants_cpy.push_back(state.s1); \
5671
+ spec_constants_cpy.push_back(state.s2); \
5672
+ spec_constants_cpy.push_back(state.p0); \
5673
+ spec_constants_cpy.push_back(state.p1); \
5674
+ spec_constants_cpy.push_back(state.p2); \
5675
+ spec_constants_cpy.push_back(state.d0); \
5676
+ spec_constants_cpy.push_back(state.d1); \
5677
+ spec_constants_cpy.push_back(state.d2); \
5678
+ spec_constants_cpy.push_back(state.KW); \
5679
+ spec_constants_cpy.push_back(state.KH); \
5680
+ spec_constants_cpy.push_back(state.KD); \
5681
+ spec_constants_cpy.push_back(state.aligned); \
5682
+ spec_constants_cpy.push_back(conv2d_csh_store); \
5683
+ spec_constants_cpy.push_back(conv2d_WM); \
5684
+ spec_constants_cpy.push_back(conv2d_WN); \
5685
+ ggml_vk_create_pipeline( \
5686
+ device, c.second, "conv3d" #type_suffix, \
5687
+ conv3d##type_suffix##spv_suffix##_len, conv3d##type_suffix##spv_suffix##_data, "main", 3, \
5688
+ sizeof(vk_op_conv3d_push_constants), wg_denoms, spec_constants_cpy, 1, true, conv2d_required_subgroup_size != 0, conv2d_required_subgroup_size); \
5689
+ }
5690
+ #if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT)
5691
+ if (device->coopmat2) {
5692
+ CREATE_CONV3D(_f32, _cm2)
5693
+ CREATE_CONV3D(_f16_f32, _cm2)
5694
+ } else
5695
+ #endif
5696
+ #if defined(VK_KHR_cooperative_matrix) && defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT)
5697
+ if (conv2d_use_cm1) {
5698
+ CREATE_CONV3D(_f32, _cm1)
5699
+ CREATE_CONV3D(_f16_f32, _cm1)
5700
+ } else
5701
+ #endif
5702
+ if (conv2d_UNROLL) {
5703
+ CREATE_CONV3D(_f32, _unroll)
5704
+ CREATE_CONV3D(_f16_f32, _unroll)
5705
+ } else {
5706
+ CREATE_CONV3D(_f32, )
5707
+ CREATE_CONV3D(_f16_f32, )
5708
+ }
5709
+ #undef CREATE_CONV3D
5407
5710
  }
5408
5711
 
5409
5712
  ggml_vk_create_pipeline(device, device->pipeline_conv2d_dw_whcn_f32, "conv2d_dw_whcn_f32", conv2d_dw_whcn_f32_len, conv2d_dw_whcn_f32_data, "main", 3, sizeof(vk_op_conv2d_dw_push_constants), {512, 1, 1}, {}, 1);
@@ -5698,6 +6001,14 @@ static vk_device ggml_vk_get_device(size_t idx) {
5698
6001
  device->subgroup_vote = (vk11_props.subgroupSupportedStages & vk::ShaderStageFlagBits::eCompute) &&
5699
6002
  (vk11_props.subgroupSupportedOperations & vk::SubgroupFeatureFlagBits::eVote);
5700
6003
 
6004
+ // Submit at least every 100 nodes, in case there are workloads without as much matmul.
6005
+ device->max_nodes_per_submit = 100;
6006
+ const char* GGML_VK_MAX_NODES_PER_SUBMIT = getenv("GGML_VK_MAX_NODES_PER_SUBMIT");
6007
+ if (GGML_VK_MAX_NODES_PER_SUBMIT != nullptr) {
6008
+ uint32_t max_nodes_per_submit = std::stoul(GGML_VK_MAX_NODES_PER_SUBMIT);
6009
+ device->max_nodes_per_submit = std::max(max_nodes_per_submit, 1u);
6010
+ }
6011
+
5701
6012
  const bool force_disable_f16 = getenv("GGML_VK_DISABLE_F16") != nullptr;
5702
6013
 
5703
6014
  device->fp16 = !force_disable_f16 && fp16_storage && fp16_compute;
@@ -6172,9 +6483,8 @@ static vk_device ggml_vk_get_device(size_t idx) {
6172
6483
  break;
6173
6484
  case VK_VENDOR_ID_INTEL: {
6174
6485
  // Current Windows driver does not expose BF16 support.
6175
- // We only want to use l_warptile if coopmat is available and is Xe2+
6176
- const bool xe2_with_coopmat = device->coopmat_support && device->architecture == INTEL_XE2;
6177
- const bool use_l_warptile = (i == GGML_TYPE_BF16) ? (device->coopmat_bf16_support && xe2_with_coopmat) : xe2_with_coopmat;
6486
+ // We only want to use l_warptile if coopmat is available
6487
+ const bool use_l_warptile = (i == GGML_TYPE_BF16) ? (device->coopmat_bf16_support && device->coopmat_support) : device->coopmat_support;
6178
6488
  device->mul_mat_l[i] = use_l_warptile;
6179
6489
  device->mul_mat_id_l[i] = use_l_warptile;
6180
6490
  device->mul_mat_m[i] = true;
@@ -7741,6 +8051,23 @@ static void ggml_vk_buffer_read_2d(vk_buffer& src, size_t offset, void * dst, si
7741
8051
  if(src->memory_property_flags & vk::MemoryPropertyFlagBits::eHostVisible && src->device->uma) {
7742
8052
  GGML_ASSERT(src->memory_property_flags & vk::MemoryPropertyFlagBits::eHostCoherent);
7743
8053
 
8054
+ std::lock_guard<std::recursive_mutex> guard(src->device->mutex);
8055
+ vk_context subctx = ggml_vk_create_temporary_context(src->device->compute_queue.cmd_pool);
8056
+ ggml_vk_ctx_begin(src->device, subctx);
8057
+ subctx->s->buffer->buf.pipelineBarrier(
8058
+ vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eTransfer,
8059
+ vk::PipelineStageFlagBits::eHost,
8060
+ {},
8061
+ { { vk::AccessFlagBits::eShaderWrite | vk::AccessFlagBits::eTransferWrite,
8062
+ vk::AccessFlagBits::eHostRead } },
8063
+ {}, {});
8064
+ ggml_vk_ctx_end(subctx);
8065
+ ggml_vk_submit(subctx, src->device->fence);
8066
+ VK_CHECK(src->device->device.waitForFences({ src->device->fence }, true, UINT64_MAX),
8067
+ "vk_buffer_read_2d uma waitForFences");
8068
+ src->device->device.resetFences({ src->device->fence });
8069
+ ggml_vk_queue_command_pools_cleanup(src->device);
8070
+
7744
8071
  if (width == spitch && width == dpitch) {
7745
8072
  memcpy(dst, (const uint8_t *) src->ptr + offset, width * height);
7746
8073
  } else {
@@ -8175,7 +8502,6 @@ static vk_pipeline ggml_vk_get_cpy_pipeline(ggml_backend_vk_context * ctx, const
8175
8502
  static void ggml_vk_cpy_to_contiguous(ggml_backend_vk_context * ctx, vk_context& subctx, vk_pipeline pipeline, const ggml_tensor * tensor, const vk_subbuffer & in, const vk_subbuffer & out) {
8176
8503
  VK_LOG_DEBUG("ggml_vk_cpy_to_contiguous((" << tensor << ", type=" << tensor->type << ", ne0=" << tensor->ne[0] << ", ne1=" << tensor->ne[1] << ", ne2=" << tensor->ne[2] << ", ne3=" << tensor->ne[3] << ", nb0=" << tensor->nb[0] << ", nb1=" << tensor->nb[1] << ", nb2=" << tensor->nb[2] << ", nb3=" << tensor->nb[3] << "), ";
8177
8504
  std::cerr << "buffer in size=" << in.buffer->size << ", buffer out size=" << out.buffer->size << ")");
8178
- const int tensor_type_size = ggml_type_size(tensor->type);
8179
8505
 
8180
8506
  const uint32_t ne = ggml_nelements(tensor);
8181
8507
  std::array<uint32_t, 3> elements;
@@ -8188,14 +8514,11 @@ static void ggml_vk_cpy_to_contiguous(ggml_backend_vk_context * ctx, vk_context&
8188
8514
  elements = { ne, 1, 1 };
8189
8515
  }
8190
8516
 
8191
- vk_op_unary_push_constants pc = {
8192
- (uint32_t)ne,
8193
- (uint32_t)tensor->ne[0], (uint32_t)tensor->ne[1], (uint32_t)tensor->ne[2], (uint32_t)tensor->ne[3], (uint32_t)tensor->nb[0] / tensor_type_size, (uint32_t)tensor->nb[1] / tensor_type_size, (uint32_t)tensor->nb[2] / tensor_type_size, (uint32_t)tensor->nb[3] / tensor_type_size,
8194
- (uint32_t)tensor->ne[0], (uint32_t)tensor->ne[1], (uint32_t)tensor->ne[2], (uint32_t)tensor->ne[3], 1 , (uint32_t)tensor->ne[0] , (uint32_t)(tensor->ne[0] * tensor->ne[1]) , (uint32_t)(tensor->ne[0] * tensor->ne[1] * tensor->ne[2]),
8195
- 0,
8196
- 0.0f, 0.0f,
8197
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8198
- };
8517
+ vk_op_unary_push_constants pc = vk_op_unary_push_constants_init(tensor, tensor, ne);
8518
+ pc.nb10 = 1;
8519
+ pc.nb11 = (uint32_t)tensor->ne[0];
8520
+ pc.nb12 = (uint32_t)(tensor->ne[0] * tensor->ne[1]);
8521
+ pc.nb13 = (uint32_t)(tensor->ne[0] * tensor->ne[1] * tensor->ne[2]);
8199
8522
  init_pushconst_fastdiv(pc);
8200
8523
  ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, pc, elements);
8201
8524
  ggml_vk_sync_buffers(ctx, subctx);
@@ -8209,7 +8532,6 @@ static void ggml_vk_cpy_to_strided(
8209
8532
  uint32_t nb10, uint32_t nb11, uint32_t nb12, uint32_t nb13) {
8210
8533
  VK_LOG_DEBUG("ggml_vk_cpy_to_strided((" << tensor << ", type=" << tensor->type << ", ne0=" << tensor->ne[0] << ", ne1=" << tensor->ne[1] << ", ne2=" << tensor->ne[2] << ", ne3=" << tensor->ne[3] << ", nb0=" << tensor->nb[0] << ", nb1=" << tensor->nb[1] << ", nb2=" << tensor->nb[2] << ", nb3=" << tensor->nb[3] << "), ";
8211
8534
  std::cerr << "dst_nb=(" << nb10 << ", " << nb11 << ", " << nb12 << ", " << nb13 << "), buffer in size=" << in.buffer->size << ", buffer out size=" << out.buffer->size << ")");
8212
- const int tensor_type_size = ggml_type_size(tensor->type);
8213
8535
 
8214
8536
  const uint32_t ne = ggml_nelements(tensor);
8215
8537
  std::array<uint32_t, 3> elements;
@@ -8222,14 +8544,11 @@ static void ggml_vk_cpy_to_strided(
8222
8544
  elements = { ne, 1, 1 };
8223
8545
  }
8224
8546
 
8225
- vk_op_unary_push_constants pc = {
8226
- (uint32_t)ne,
8227
- (uint32_t)tensor->ne[0], (uint32_t)tensor->ne[1], (uint32_t)tensor->ne[2], (uint32_t)tensor->ne[3], (uint32_t)tensor->nb[0] / tensor_type_size, (uint32_t)tensor->nb[1] / tensor_type_size, (uint32_t)tensor->nb[2] / tensor_type_size, (uint32_t)tensor->nb[3] / tensor_type_size,
8228
- (uint32_t)tensor->ne[0], (uint32_t)tensor->ne[1], (uint32_t)tensor->ne[2], (uint32_t)tensor->ne[3], nb10, nb11, nb12, nb13,
8229
- 0,
8230
- 0.0f, 0.0f,
8231
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8232
- };
8547
+ vk_op_unary_push_constants pc = vk_op_unary_push_constants_init(tensor, tensor, ne);
8548
+ pc.nb10 = nb10;
8549
+ pc.nb11 = nb11;
8550
+ pc.nb12 = nb12;
8551
+ pc.nb13 = nb13;
8233
8552
  init_pushconst_fastdiv(pc);
8234
8553
  ggml_vk_dispatch_pipeline(ctx, subctx, pipeline, { in, out }, pc, elements);
8235
8554
  ggml_vk_sync_buffers(ctx, subctx);
@@ -9991,7 +10310,8 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx
9991
10310
  }
9992
10311
 
9993
10312
  // Only use mask opt when the mask is fairly large. This hasn't been tuned extensively.
9994
- bool use_mask_opt = mask && nem1 >= 32 && nem0 * nem1 > 32768 && nem0 >= tuning_params.block_cols * 16;
10313
+ bool use_mask_opt = mask && nem1 >= 32 && nem0 * nem1 > 32768 && nem0 >= tuning_params.block_cols * 16
10314
+ && (ctx->device->architecture != vk_device_architecture::AMD_GCN || HSK > 256 || HSV > 256);
9995
10315
  vk_fa_pipeline_state fa_pipeline_state = get_fa_pipeline_state(ctx->device, tuning_params, HSK, HSV, aligned, f32acc,
9996
10316
  mask != nullptr, use_mask_opt, logit_softcap != 0, k->type, v->type);
9997
10317
 
@@ -10219,6 +10539,11 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10219
10539
  return ctx->device->pipeline_get_rows_f32[src0->type];
10220
10540
  }
10221
10541
  return nullptr;
10542
+ case GGML_OP_GET_ROWS_BACK:
10543
+ if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_I32 && dst->type == GGML_TYPE_F32) {
10544
+ return ctx->device->pipeline_get_rows_back_f32;
10545
+ }
10546
+ return nullptr;
10222
10547
  case GGML_OP_ACC:
10223
10548
  if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10224
10549
  return ctx->device->pipeline_acc_f32;
@@ -10281,17 +10606,27 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10281
10606
  return ctx->device->pipeline_add_id_f32;
10282
10607
  }
10283
10608
  return nullptr;
10284
- case GGML_OP_CONCAT:
10285
- if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10286
- return ctx->device->pipeline_concat_f32;
10609
+ case GGML_OP_CONCAT: {
10610
+ if (src0->type != src1->type || src0->type != dst->type) {
10611
+ return nullptr;
10287
10612
  }
10288
- if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) {
10289
- return ctx->device->pipeline_concat_f16;
10613
+ if (ggml_blck_size(src0->type) != 1) {
10614
+ return nullptr;
10290
10615
  }
10291
- if (src0->type == GGML_TYPE_I32 && src1->type == GGML_TYPE_I32 && dst->type == GGML_TYPE_I32) {
10616
+ const size_t type_size = ggml_type_size(src0->type);
10617
+ switch (type_size) {
10618
+ case 1:
10619
+ return ctx->device->pipeline_concat_i8;
10620
+ case 2:
10621
+ return ctx->device->pipeline_concat_i16;
10622
+ case 4:
10292
10623
  return ctx->device->pipeline_concat_i32;
10624
+ case 8:
10625
+ return ctx->device->pipeline_concat_i64;
10626
+ default:
10627
+ return nullptr;
10293
10628
  }
10294
- return nullptr;
10629
+ }
10295
10630
  case GGML_OP_UPSCALE:
10296
10631
  if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10297
10632
  uint32_t mode = (ggml_get_op_params_i32(dst, 0) & (0xFF | GGML_SCALE_FLAG_ANTIALIAS));
@@ -10315,23 +10650,27 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10315
10650
  }
10316
10651
  return nullptr;
10317
10652
  case GGML_OP_SQR:
10318
- if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10319
- return ctx->device->pipeline_sqr_f32;
10653
+ if (src0->type == dst->type &&
10654
+ (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16)) {
10655
+ return ctx->device->pipeline_sqr[dst->type == GGML_TYPE_F16];
10320
10656
  }
10321
10657
  return nullptr;
10322
10658
  case GGML_OP_SQRT:
10323
- if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10324
- return ctx->device->pipeline_sqrt_f32;
10659
+ if (src0->type == dst->type &&
10660
+ (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16)) {
10661
+ return ctx->device->pipeline_sqrt[dst->type == GGML_TYPE_F16];
10325
10662
  }
10326
10663
  return nullptr;
10327
10664
  case GGML_OP_SIN:
10328
- if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10329
- return ctx->device->pipeline_sin_f32;
10665
+ if (src0->type == dst->type &&
10666
+ (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16)) {
10667
+ return ctx->device->pipeline_sin[dst->type == GGML_TYPE_F16];
10330
10668
  }
10331
10669
  return nullptr;
10332
10670
  case GGML_OP_COS:
10333
- if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10334
- return ctx->device->pipeline_cos_f32;
10671
+ if (src0->type == dst->type &&
10672
+ (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16)) {
10673
+ return ctx->device->pipeline_cos[dst->type == GGML_TYPE_F16];
10335
10674
  }
10336
10675
  return nullptr;
10337
10676
  case GGML_OP_LOG:
@@ -10353,8 +10692,9 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10353
10692
  }
10354
10693
  return nullptr;
10355
10694
  case GGML_OP_CLAMP:
10356
- if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10357
- return ctx->device->pipeline_clamp_f32;
10695
+ if (src0->type == dst->type &&
10696
+ (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16)) {
10697
+ return ctx->device->pipeline_clamp[dst->type == GGML_TYPE_F16];
10358
10698
  }
10359
10699
  return nullptr;
10360
10700
  case GGML_OP_PAD:
@@ -10434,6 +10774,8 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10434
10774
  switch (ggml_get_unary_op(dst)) {
10435
10775
  case GGML_UNARY_OP_EXP:
10436
10776
  return ctx->device->pipeline_exp[dst->type == GGML_TYPE_F16];
10777
+ case GGML_UNARY_OP_EXPM1:
10778
+ return ctx->device->pipeline_expm1[dst->type == GGML_TYPE_F16];
10437
10779
  case GGML_UNARY_OP_ELU:
10438
10780
  return ctx->device->pipeline_elu[dst->type == GGML_TYPE_F16];
10439
10781
  case GGML_UNARY_OP_SILU:
@@ -10652,6 +10994,13 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10652
10994
  return ctx->device->pipeline_conv_transpose_1d_f32;
10653
10995
  }
10654
10996
  return nullptr;
10997
+ case GGML_OP_COL2IM_1D:
10998
+ switch (src0->type) {
10999
+ case GGML_TYPE_F32: return ctx->device->pipeline_col2im_1d_f32;
11000
+ case GGML_TYPE_F16: return ctx->device->pipeline_col2im_1d_f16;
11001
+ case GGML_TYPE_BF16: return ctx->device->pipeline_col2im_1d_bf16;
11002
+ default: return nullptr;
11003
+ }
10655
11004
  case GGML_OP_POOL_2D:
10656
11005
  if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10657
11006
  return ctx->device->pipeline_pool2d_f32;
@@ -10673,9 +11022,10 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10673
11022
  const uint32_t kda = (dst->src[3]->ne[0] == (int64_t)S_v) ? 1 : 0;
10674
11023
  uint32_t si;
10675
11024
  switch (S_v) {
10676
- case 32: si = 0; break;
10677
- case 64: si = 1; break;
10678
- case 128: si = 2; break;
11025
+ case 16: si = 0; break;
11026
+ case 32: si = 1; break;
11027
+ case 64: si = 2; break;
11028
+ case 128: si = 3; break;
10679
11029
  default: return nullptr;
10680
11030
  }
10681
11031
  return ctx->device->pipeline_gated_delta_net[si][kda];
@@ -10712,8 +11062,9 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10712
11062
  }
10713
11063
  return nullptr;
10714
11064
  case GGML_OP_LEAKY_RELU:
10715
- if (src0->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
10716
- return ctx->device->pipeline_leaky_relu_f32;
11065
+ if (src0->type == dst->type &&
11066
+ (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16)) {
11067
+ return ctx->device->pipeline_leaky_relu[dst->type == GGML_TYPE_F16];
10717
11068
  }
10718
11069
  return nullptr;
10719
11070
  case GGML_OP_CONV_2D:
@@ -10790,6 +11141,61 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
10790
11141
  }
10791
11142
  }
10792
11143
  return nullptr;
11144
+ case GGML_OP_CONV_3D:
11145
+ if (src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
11146
+ const uint32_t OC = (uint32_t)ggml_get_op_params_i32(dst, 11);
11147
+ const uint32_t IC = (uint32_t)ggml_get_op_params_i32(dst, 9);
11148
+ const uint32_t N = (uint32_t)ggml_get_op_params_i32(dst, 10);
11149
+ const uint32_t NPQ = N * dst->ne[2] * dst->ne[1] * dst->ne[0];
11150
+ const vk_conv_shapes shape = ggml_vk_conv_select_shape(ctx, OC, NPQ);
11151
+
11152
+ const uint32_t KW = (uint32_t)src0->ne[0];
11153
+ const uint32_t KH = (uint32_t)src0->ne[1];
11154
+ const uint32_t KD = (uint32_t)src0->ne[2];
11155
+ const uint32_t s0 = (uint32_t)ggml_get_op_params_i32(dst, 0);
11156
+ const uint32_t s1 = (uint32_t)ggml_get_op_params_i32(dst, 1);
11157
+ const uint32_t s2 = (uint32_t)ggml_get_op_params_i32(dst, 2);
11158
+ const uint32_t p0 = (uint32_t)ggml_get_op_params_i32(dst, 3);
11159
+ const uint32_t p1 = (uint32_t)ggml_get_op_params_i32(dst, 4);
11160
+ const uint32_t p2 = (uint32_t)ggml_get_op_params_i32(dst, 5);
11161
+ const uint32_t d0 = (uint32_t)ggml_get_op_params_i32(dst, 6);
11162
+ const uint32_t d1 = (uint32_t)ggml_get_op_params_i32(dst, 7);
11163
+ const uint32_t d2 = (uint32_t)ggml_get_op_params_i32(dst, 8);
11164
+
11165
+ const uint32_t CRS = IC * KW * KH * KD;
11166
+ const uint32_t BS_K = vk_conv_block_sizes[shape].K;
11167
+ const uint32_t BS_CRS = vk_conv_block_sizes[shape].CRS;
11168
+ const uint32_t BS_NPQ = vk_conv_block_sizes[shape].NPQ;
11169
+ const uint32_t aligned = ((OC % BS_K == 0) &&
11170
+ (CRS % BS_CRS == 0) &&
11171
+ (NPQ % BS_NPQ == 0)) ? 1u : 0u;
11172
+
11173
+ vk_conv3d_pipeline_state conv3d_pipeline_state(s0, s1, s2, p0, p1, p2, d0, d1, d2, KW, KH, KD, aligned);
11174
+
11175
+ std::map<vk_conv3d_pipeline_state, vk_pipeline> *pipelines = nullptr;
11176
+ if (src0->type == GGML_TYPE_F32) {
11177
+ pipelines = &ctx->device->pipeline_conv3d_f32[shape];
11178
+ } else if (src0->type == GGML_TYPE_F16) {
11179
+ pipelines = &ctx->device->pipeline_conv3d_f16_f32[shape];
11180
+ } else {
11181
+ return nullptr;
11182
+ }
11183
+
11184
+ vk_pipeline pipeline = nullptr;
11185
+
11186
+ {
11187
+ std::lock_guard<std::mutex> guard(ctx->device->compile_mutex);
11188
+ auto it = pipelines->find(conv3d_pipeline_state);
11189
+ if (it != pipelines->end()) {
11190
+ pipeline = it->second;
11191
+ } else {
11192
+ (*pipelines)[conv3d_pipeline_state] = pipeline = std::make_shared<vk_pipeline_struct>();
11193
+ }
11194
+ }
11195
+
11196
+ return pipeline;
11197
+ }
11198
+ return nullptr;
10793
11199
  case GGML_OP_ADD1:
10794
11200
  if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F16 && dst->type == GGML_TYPE_F16) {
10795
11201
  return ctx->device->pipeline_add1_f16_f16;
@@ -10832,6 +11238,21 @@ template <> void init_pushconst_tensor_offsets(ggml_backend_vk_context * ctx, vk
10832
11238
  GGML_UNUSED(src3);
10833
11239
  }
10834
11240
 
11241
+ template <> void init_pushconst_tensor_offsets(ggml_backend_vk_context * ctx, vk_op_glu_push_constants &p, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, const ggml_tensor * src3, ggml_tensor * dst) {
11242
+ const uint32_t a_offset = get_misalign_bytes(ctx, src0) / ggml_type_size(src0->type);
11243
+ const uint32_t b_offset = src1 ? get_misalign_bytes(ctx, src1) / ggml_type_size(src1->type) : a_offset;
11244
+ const uint32_t d_offset = get_misalign_bytes(ctx, dst) / ggml_type_size(dst->type);
11245
+
11246
+ GGML_ASSERT(a_offset < (1u << 8));
11247
+ GGML_ASSERT(b_offset < (1u << 8));
11248
+ GGML_ASSERT(d_offset < (1u << 8));
11249
+
11250
+ p.misalign_offsets = (a_offset << 16) | (b_offset << 8) | d_offset;
11251
+
11252
+ GGML_UNUSED(src2);
11253
+ GGML_UNUSED(src3);
11254
+ }
11255
+
10835
11256
  template <> void init_pushconst_tensor_offsets(ggml_backend_vk_context * ctx, vk_op_sum_rows_push_constants &p, const ggml_tensor * src0, const ggml_tensor * src1, const ggml_tensor * src2, const ggml_tensor * src3, ggml_tensor * dst) {
10836
11257
  const uint32_t a_offset = get_misalign_bytes(ctx, src0) / ggml_type_size(src0->type);
10837
11258
  const uint32_t d_offset = get_misalign_bytes(ctx, dst) / ggml_type_size(dst->type);
@@ -11025,6 +11446,10 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co
11025
11446
  elements[1] = std::min(elements[1], ctx->device->properties.limits.maxComputeWorkGroupCount[1]);
11026
11447
  elements[2] = std::min(elements[2], ctx->device->properties.limits.maxComputeWorkGroupCount[2]);
11027
11448
  break;
11449
+ case GGML_OP_GET_ROWS_BACK:
11450
+ elements = { (uint32_t)dst->ne[0], (uint32_t)dst->ne[1], 1 };
11451
+ elements[1] = std::min(elements[1], ctx->device->properties.limits.maxComputeWorkGroupCount[1]);
11452
+ break;
11028
11453
  case GGML_OP_ARGSORT:
11029
11454
  GGML_ASSERT(0);
11030
11455
  break;
@@ -11082,6 +11507,10 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co
11082
11507
  {
11083
11508
  elements = {uint32_t(src0->ne[1]), 1, 1}; // parallelize in {Cout, 1, 1}
11084
11509
  } break;
11510
+ case GGML_OP_COL2IM_1D:
11511
+ {
11512
+ elements = { uint32_t(dst->ne[0]), uint32_t(dst->ne[1]), 1 };
11513
+ } break;
11085
11514
  case GGML_OP_POOL_2D:
11086
11515
  {
11087
11516
  const uint32_t N = dst->ne[3];
@@ -11106,6 +11535,21 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co
11106
11535
  GGML_ABORT("invalid push constant type for CONV_2D");
11107
11536
  }
11108
11537
  break;
11538
+ case GGML_OP_CONV_3D:
11539
+ if constexpr (std::is_same_v<PC, vk_op_conv3d_push_constants>) {
11540
+ const uint32_t NPQ = pc.N * pc.OD * pc.OH * pc.OW;
11541
+ const vk_conv_shapes shape = ggml_vk_conv_select_shape(ctx, pc.OC, NPQ);
11542
+ const uint32_t NPQ_blocks = CEIL_DIV(NPQ, vk_conv_block_sizes[shape].NPQ);
11543
+
11544
+ elements = { pc.OC, NPQ_blocks, 1 };
11545
+ if (elements[1] > 512) {
11546
+ elements[2] = CEIL_DIV(elements[1], 512);
11547
+ elements[1] = 512;
11548
+ }
11549
+ } else {
11550
+ GGML_ABORT("invalid push constant type for CONV_3D");
11551
+ }
11552
+ break;
11109
11553
  case GGML_OP_ADD:
11110
11554
  case GGML_OP_SUB:
11111
11555
  case GGML_OP_DIV:
@@ -11122,6 +11566,7 @@ static void ggml_vk_op_f32(ggml_backend_vk_context * ctx, vk_context& subctx, co
11122
11566
  case GGML_OP_TRI:
11123
11567
  case GGML_OP_DIAG:
11124
11568
  case GGML_OP_CLAMP:
11569
+ case GGML_OP_LEAKY_RELU:
11125
11570
  case GGML_OP_PAD:
11126
11571
  case GGML_OP_ROLL:
11127
11572
  case GGML_OP_REPEAT:
@@ -11266,6 +11711,21 @@ static void ggml_vk_get_rows(ggml_backend_vk_context * ctx, vk_context& subctx,
11266
11711
  });
11267
11712
  }
11268
11713
 
11714
+ static void ggml_vk_get_rows_back(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
11715
+ const uint32_t src0_type_size = ggml_type_size(src0->type);
11716
+ const uint32_t src1_type_size = ggml_type_size(src1->type);
11717
+ const uint32_t dst_type_size = ggml_type_size(dst->type);
11718
+
11719
+ ggml_vk_op_f32<vk_op_binary_push_constants>(ctx, subctx, src0, src1, nullptr, nullptr, dst, GGML_OP_GET_ROWS_BACK, {
11720
+ (uint32_t)ggml_nelements(src0),
11721
+ (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], (uint32_t)src0->ne[2], (uint32_t)src0->ne[3], (uint32_t)src0->nb[0] / src0_type_size, (uint32_t)src0->nb[1] / src0_type_size, (uint32_t)src0->nb[2] / src0_type_size, (uint32_t)src0->nb[3] / src0_type_size,
11722
+ (uint32_t)src1->ne[0], (uint32_t)src1->ne[1], (uint32_t)src1->ne[2], (uint32_t)src1->ne[3], (uint32_t)src1->nb[0] / src1_type_size, (uint32_t)src1->nb[1] / src1_type_size, (uint32_t)src1->nb[2] / src1_type_size, (uint32_t)src1->nb[3] / src1_type_size,
11723
+ (uint32_t) dst->ne[0], (uint32_t) dst->ne[1], (uint32_t) dst->ne[2], (uint32_t) dst->ne[3], (uint32_t) dst->nb[0] / dst_type_size, (uint32_t) dst->nb[1] / dst_type_size, (uint32_t) dst->nb[2] / dst_type_size, (uint32_t) dst->nb[3] / dst_type_size,
11724
+ 0,
11725
+ 0.0f, 0.0f, 0,
11726
+ });
11727
+ }
11728
+
11269
11729
  static void ggml_vk_acc(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
11270
11730
  const uint32_t src0_type_size = ggml_type_size(src0->type);
11271
11731
  const uint32_t src1_type_size = ggml_type_size(src1->type);
@@ -11973,8 +12433,10 @@ static void ggml_vk_silu_back(ggml_backend_vk_context * ctx, vk_context& subctx,
11973
12433
 
11974
12434
  static void ggml_vk_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) {
11975
12435
  float * op_params = (float *)dst->op_params;
12436
+ vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst);
12437
+ p.param1 = op_params[0];
11976
12438
 
11977
- ggml_vk_op_f32<vk_op_push_constants>(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_NORM, { (uint32_t)src0->ne[0], (uint32_t)src0->ne[1], op_params[0], 0.0f, 0.0f, 0.0f });
12439
+ ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_NORM, std::move(p));
11978
12440
  }
11979
12441
 
11980
12442
  static void ggml_vk_group_norm(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) {
@@ -12181,17 +12643,17 @@ static void ggml_vk_l2_norm(ggml_backend_vk_context * ctx, vk_context& subctx, c
12181
12643
  }
12182
12644
 
12183
12645
  static void ggml_vk_unary(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) {
12184
- ggml_vk_op_f32<vk_op_push_constants>(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_UNARY, { (uint32_t)ggml_nelements(src0), 0, 0.0f, 0.0f, 0.0f, 0.0f });
12646
+ ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_UNARY, vk_op_unary_push_constants_init(src0, dst));
12185
12647
  }
12186
12648
 
12187
12649
  static void ggml_vk_xielu(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) {
12188
12650
  float * op_params = (float *)dst->op_params;
12189
- ggml_vk_op_f32<vk_op_push_constants>(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_UNARY,
12190
- {
12191
- (uint32_t)ggml_nelements(src0), 0,
12192
- op_params[1], op_params[2], op_params[3], op_params[4]
12193
- }
12194
- );
12651
+ vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst);
12652
+ p.param1 = op_params[1];
12653
+ p.param2 = op_params[2];
12654
+ p.param3 = op_params[3];
12655
+ p.param4 = op_params[4];
12656
+ ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_UNARY, std::move(p));
12195
12657
  }
12196
12658
 
12197
12659
  static void ggml_vk_glu(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
@@ -12211,6 +12673,9 @@ static void ggml_vk_glu(ggml_backend_vk_context * ctx, vk_context& subctx, const
12211
12673
  }
12212
12674
 
12213
12675
  const uint32_t mode = split ? 2 : (swapped ? 1 : 0);
12676
+ const uint32_t src0_type_size = ggml_type_size(src0->type);
12677
+ const uint32_t src1_type_size = split ? ggml_type_size(src1->type) : src0_type_size;
12678
+ const uint32_t dst_type_size = ggml_type_size(dst->type);
12214
12679
 
12215
12680
  ggml_vk_op_f32<vk_op_glu_push_constants>(ctx, subctx, src0, src1, nullptr, nullptr, dst, GGML_OP_GLU,
12216
12681
  {
@@ -12220,16 +12685,22 @@ static void ggml_vk_glu(ggml_backend_vk_context * ctx, vk_context& subctx, const
12220
12685
  mode,
12221
12686
  alpha,
12222
12687
  limit,
12223
- (uint32_t)(src0->nb[1] / src0->nb[0]),
12224
- (uint32_t)(src0->nb[2] / src0->nb[0]),
12225
- (uint32_t)(src0->nb[3] / src0->nb[0]),
12226
- (uint32_t)src0->ne[1],
12227
- (uint32_t)src0->ne[2],
12228
- (uint32_t)(dst->nb[1] / dst->nb[0]),
12229
- (uint32_t)(dst->nb[2] / dst->nb[0]),
12230
- (uint32_t)(dst->nb[3] / dst->nb[0]),
12688
+ (uint32_t)(src0->nb[0] / src0_type_size),
12689
+ (uint32_t)(src0->nb[1] / src0_type_size),
12690
+ (uint32_t)(src0->nb[2] / src0_type_size),
12691
+ (uint32_t)(src0->nb[3] / src0_type_size),
12692
+ (uint32_t)((split ? src1->nb[0] : src0->nb[0]) / src1_type_size),
12693
+ (uint32_t)((split ? src1->nb[1] : src0->nb[1]) / src1_type_size),
12694
+ (uint32_t)((split ? src1->nb[2] : src0->nb[2]) / src1_type_size),
12695
+ (uint32_t)((split ? src1->nb[3] : src0->nb[3]) / src1_type_size),
12696
+ (uint32_t)(dst->nb[0] / dst_type_size),
12697
+ (uint32_t)(dst->nb[1] / dst_type_size),
12698
+ (uint32_t)(dst->nb[2] / dst_type_size),
12699
+ (uint32_t)(dst->nb[3] / dst_type_size),
12231
12700
  (uint32_t)dst->ne[1],
12232
- (uint32_t)dst->ne[2]
12701
+ (uint32_t)dst->ne[2],
12702
+ 0,
12703
+ 0, 0, 0, 0, 0, 0,
12233
12704
  });
12234
12705
  }
12235
12706
 
@@ -12862,6 +13333,32 @@ static void ggml_vk_conv_transpose_1d(ggml_backend_vk_context * ctx, vk_context&
12862
13333
  ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, nullptr, dst, GGML_OP_CONV_TRANSPOSE_1D, std::move(p));
12863
13334
  }
12864
13335
 
13336
+ static void ggml_vk_col2im_1d(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) {
13337
+ // src0: [K_OC, T_in] columns from matmul
13338
+ // dst: [T_out, OC]
13339
+
13340
+ const int32_t stride = dst->op_params[0];
13341
+ const int32_t oc = dst->op_params[1];
13342
+ const int32_t p0 = dst->op_params[2];
13343
+
13344
+ const uint32_t K_OC = static_cast<uint32_t>(src0->ne[0]);
13345
+ const uint32_t T_in = static_cast<uint32_t>(src0->ne[1]);
13346
+ const uint32_t T_out = static_cast<uint32_t>(dst->ne[0]);
13347
+ const uint32_t OC = static_cast<uint32_t>(oc);
13348
+ const uint32_t K = K_OC / OC;
13349
+
13350
+ vk_op_col2im_1d_push_constants p{};
13351
+ p.T_out = T_out;
13352
+ p.OC = OC;
13353
+ p.K_OC = K_OC;
13354
+ p.T_in = T_in;
13355
+ p.K = K;
13356
+ p.stride = stride;
13357
+ p.p0 = p0;
13358
+
13359
+ ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_COL2IM_1D, std::move(p));
13360
+ }
13361
+
12865
13362
  // Dispatch the fused snake activation: y = x + sin^2(a * x) * inv_b.
12866
13363
  // Match the naive mul -> sin -> sqr -> mul -> add chain and run the
12867
13364
  // dedicated kernel directly. The pattern is validated by
@@ -12969,6 +13466,51 @@ static void ggml_vk_conv_2d(ggml_backend_vk_context * ctx, vk_context & subctx,
12969
13466
  ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, nullptr, dst, dst->op, std::move(p));
12970
13467
  }
12971
13468
 
13469
+ static void ggml_vk_conv_3d(ggml_backend_vk_context * ctx, vk_context & subctx, const ggml_tensor * src0,
13470
+ const ggml_tensor * src1, ggml_tensor * dst) {
13471
+ GGML_ASSERT(src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16);
13472
+ GGML_ASSERT(src1->type == GGML_TYPE_F32);
13473
+ GGML_ASSERT(dst->type == GGML_TYPE_F32);
13474
+
13475
+ GGML_TENSOR_BINARY_OP_LOCALS
13476
+ GGML_ASSERT(nb00 == sizeof(float) || nb00 == sizeof(ggml_fp16_t));
13477
+ GGML_ASSERT(nb10 == sizeof(float));
13478
+ GGML_ASSERT(nb0 == sizeof(float));
13479
+
13480
+ vk_op_conv3d_push_constants p{};
13481
+ p.IC = static_cast<uint32_t>(ggml_get_op_params_i32(dst, 9));
13482
+ p.N = static_cast<uint32_t>(ggml_get_op_params_i32(dst, 10));
13483
+ p.OC = static_cast<uint32_t>(ggml_get_op_params_i32(dst, 11));
13484
+ GGML_ASSERT(src0->ne[3] == (int64_t)p.IC * p.OC);
13485
+ GGML_ASSERT(src1->ne[3] == (int64_t)p.IC * p.N);
13486
+ GGML_ASSERT(dst->ne[3] == (int64_t)p.OC * p.N);
13487
+
13488
+ p.IW = static_cast<uint32_t>(ne10);
13489
+ p.IH = static_cast<uint32_t>(ne11);
13490
+ p.ID = static_cast<uint32_t>(ne12);
13491
+ p.OW = static_cast<uint32_t>(ne0);
13492
+ p.OH = static_cast<uint32_t>(ne1);
13493
+ p.OD = static_cast<uint32_t>(ne2);
13494
+
13495
+ // the shader clamps src addresses to p.IC * p.N * p.IW * p.IH * p.ID - 1 in uint32, so the
13496
+ // total input element count must fit in a uint32.
13497
+ GGML_ASSERT((uint64_t)p.IC * p.N * p.IW * p.IH * p.ID <= 0xFFFFFFFFull);
13498
+
13499
+ p.nb01 = static_cast<uint32_t>(nb01 / nb00);
13500
+ p.nb02 = static_cast<uint32_t>(nb02 / nb00);
13501
+ p.nb03 = static_cast<uint32_t>(nb03 / nb00);
13502
+
13503
+ p.nb11 = static_cast<uint32_t>(nb11 / nb10);
13504
+ p.nb12 = static_cast<uint32_t>(nb12 / nb10);
13505
+ p.nb13 = static_cast<uint32_t>(nb13 / nb10);
13506
+
13507
+ p.nb1 = static_cast<uint32_t>(nb1 / nb0);
13508
+ p.nb2 = static_cast<uint32_t>(nb2 / nb0);
13509
+ p.nb3 = static_cast<uint32_t>(nb3 / nb0);
13510
+
13511
+ ggml_vk_op_f32(ctx, subctx, src0, src1, nullptr, nullptr, dst, GGML_OP_CONV_3D, std::move(p));
13512
+ }
13513
+
12972
13514
  static void ggml_vk_conv_2d_dw(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
12973
13515
  vk_op_conv2d_dw_push_constants p{};
12974
13516
  p.ne = ggml_nelements(dst);
@@ -12995,7 +13537,10 @@ static void ggml_vk_conv_2d_dw(ggml_backend_vk_context * ctx, vk_context& subctx
12995
13537
 
12996
13538
  static void ggml_vk_leaky_relu(ggml_backend_vk_context * ctx, vk_context& subctx, const ggml_tensor * src0, ggml_tensor * dst) {
12997
13539
  const float * op_params = (const float *)dst->op_params;
12998
- ggml_vk_op_f32<vk_op_push_constants>(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_LEAKY_RELU, { (uint32_t)ggml_nelements(src0), 0, op_params[0], 0.0f, 0.0f, 0.0f });
13540
+ vk_op_unary_push_constants p = vk_op_unary_push_constants_init(src0, dst);
13541
+ p.param1 = op_params[0];
13542
+
13543
+ ggml_vk_op_f32(ctx, subctx, src0, nullptr, nullptr, nullptr, dst, GGML_OP_LEAKY_RELU, std::move(p));
12999
13544
  }
13000
13545
 
13001
13546
  #ifdef GGML_VULKAN_RUN_TESTS
@@ -14098,6 +14643,10 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_cgraph * cgr
14098
14643
  case GGML_OP_GET_ROWS:
14099
14644
  ggml_vk_get_rows(ctx, compute_ctx, src0, src1, node);
14100
14645
 
14646
+ break;
14647
+ case GGML_OP_GET_ROWS_BACK:
14648
+ ggml_vk_get_rows_back(ctx, compute_ctx, src0, src1, node);
14649
+
14101
14650
  break;
14102
14651
  case GGML_OP_ADD:
14103
14652
  if (ctx->num_additional_fused_ops) {
@@ -14232,6 +14781,7 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_cgraph * cgr
14232
14781
  switch (ggml_get_unary_op(node)) {
14233
14782
  case GGML_UNARY_OP_ELU:
14234
14783
  case GGML_UNARY_OP_EXP:
14784
+ case GGML_UNARY_OP_EXPM1:
14235
14785
  case GGML_UNARY_OP_SILU:
14236
14786
  case GGML_UNARY_OP_GELU:
14237
14787
  case GGML_UNARY_OP_GELU_ERF:
@@ -14348,6 +14898,10 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_cgraph * cgr
14348
14898
  case GGML_OP_TIMESTEP_EMBEDDING:
14349
14899
  ggml_vk_timestep_embedding(ctx, compute_ctx, src0, node);
14350
14900
 
14901
+ break;
14902
+ case GGML_OP_COL2IM_1D:
14903
+ ggml_vk_col2im_1d(ctx, compute_ctx, src0, node);
14904
+
14351
14905
  break;
14352
14906
  case GGML_OP_CONV_TRANSPOSE_1D:
14353
14907
  ggml_vk_conv_transpose_1d(ctx, compute_ctx, src0, src1, node);
@@ -14361,6 +14915,10 @@ static bool ggml_vk_build_graph(ggml_backend_vk_context * ctx, ggml_cgraph * cgr
14361
14915
  case GGML_OP_CONV_TRANSPOSE_2D:
14362
14916
  ggml_vk_conv_2d(ctx, compute_ctx, src0, src1, node);
14363
14917
 
14918
+ break;
14919
+ case GGML_OP_CONV_3D:
14920
+ ggml_vk_conv_3d(ctx, compute_ctx, src0, src1, node);
14921
+
14364
14922
  break;
14365
14923
  case GGML_OP_CONV_2D_DW:
14366
14924
  ggml_vk_conv_2d_dw(ctx, compute_ctx, src0, src1, node);
@@ -15744,24 +16302,34 @@ static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backend, ggml_cg
15744
16302
  }
15745
16303
 
15746
16304
  // Submit after enough work has accumulated, to overlap CPU cmdbuffer generation with GPU execution.
15747
- // Estimate the amount of matmul work by looking at the weight matrix size, and submit every 100MB
15748
- // (and scaled down based on model size, so smaller models submit earlier).
15749
- // Also submit at least every 100 nodes, in case there are workloads without as much matmul.
15750
- int nodes_per_submit = 100;
15751
- int submitted_nodes = 0;
15752
- int submit_count = 0;
15753
- uint64_t mul_mat_bytes = 0;
15754
- uint64_t total_mul_mat_bytes = 0;
15755
- uint64_t mul_mat_bytes_per_submit = std::min(uint64_t(100*1000*1000), ctx->last_total_mul_mat_bytes / 40u);
16305
+ // Estimate the amount of compute work using flops, and submit every 200 GFLOP
16306
+ // (and scaled down based on total graph flops, so smaller models submit earlier).
16307
+ // Also submit at least every 100 nodes, in case there are workloads without heavy compute.
16308
+ uint32_t submitted_nodes = 0;
16309
+ uint32_t submit_count = 0;
16310
+ uint64_t batch_flops = 0;
16311
+ uint64_t total_flops = 0;
16312
+ uint64_t flops_cap = 200'000'000'000ULL;
16313
+
16314
+ // On weaker AMD GPUs larger submissions can hit a driver timeout, submit more often to avoid this
16315
+ if (ctx->device->vendor_id == VK_VENDOR_ID_AMD && ctx->device->shader_core_count > 0) {
16316
+ if (ctx->device->architecture == AMD_GCN && ctx->device->shader_core_count < 32) {
16317
+ flops_cap = 500'000'000ULL * ctx->device->shader_core_count;
16318
+ } else if (ctx->device->architecture != AMD_GCN && ctx->device->shader_core_count < 24) {
16319
+ flops_cap = 2'000'000'000ULL * ctx->device->shader_core_count;
16320
+ }
16321
+ }
16322
+ uint64_t flops_per_submit = std::min(flops_cap, ctx->last_total_flops / 40u);
16323
+
15756
16324
  for (int i = 0; i < cgraph->n_nodes; i++) {
15757
16325
  if (first_node_in_batch) {
15758
16326
  submit_node_idx = i;
15759
16327
  }
15760
16328
 
15761
- if (cgraph->nodes[i]->op == GGML_OP_MUL_MAT || cgraph->nodes[i]->op == GGML_OP_MUL_MAT_ID) {
15762
- auto bytes = ggml_nbytes(cgraph->nodes[i]->src[0]);
15763
- mul_mat_bytes += bytes;
15764
- total_mul_mat_bytes += bytes;
16329
+ {
16330
+ auto node_flops = ggml_vk_get_node_flops(cgraph->nodes[i]);
16331
+ batch_flops += node_flops;
16332
+ total_flops += node_flops;
15765
16333
  }
15766
16334
 
15767
16335
  // op_srcs_fused_elementwise indicates whether an op's srcs all contribute to
@@ -15973,8 +16541,8 @@ static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backend, ggml_cg
15973
16541
 
15974
16542
  // Signal the almost_ready fence when the graph is mostly complete (< 20% remaining)
15975
16543
  bool almost_ready = (cgraph->n_nodes - i) < cgraph->n_nodes / 5;
15976
- bool submit = (submitted_nodes >= nodes_per_submit) ||
15977
- (mul_mat_bytes_per_submit != 0 && mul_mat_bytes >= mul_mat_bytes_per_submit) ||
16544
+ bool submit = (submitted_nodes >= ctx->device->max_nodes_per_submit) ||
16545
+ (flops_per_submit != 0 && batch_flops >= flops_per_submit) ||
15978
16546
  (i + ctx->num_additional_fused_ops >= last_node) ||
15979
16547
  (almost_ready && !ctx->almost_ready_fence_pending);
15980
16548
 
@@ -16008,9 +16576,9 @@ static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backend, ggml_cg
16008
16576
  if (submit && enqueued) {
16009
16577
  first_node_in_batch = true;
16010
16578
  submitted_nodes = 0;
16011
- mul_mat_bytes = 0;
16579
+ batch_flops = 0;
16012
16580
  if (submit_count < 3) {
16013
- mul_mat_bytes_per_submit *= 2;
16581
+ flops_per_submit *= 2;
16014
16582
  }
16015
16583
  submit_count++;
16016
16584
  }
@@ -16019,7 +16587,7 @@ static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backend, ggml_cg
16019
16587
  ctx->fused_ops_write_mask = 0;
16020
16588
  }
16021
16589
 
16022
- ctx->last_total_mul_mat_bytes = total_mul_mat_bytes;
16590
+ ctx->last_total_flops = total_flops;
16023
16591
 
16024
16592
  if (vk_perf_logger_enabled) {
16025
16593
  // End the command buffer and submit/wait
@@ -16621,6 +17189,7 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
16621
17189
  case GGML_OP_UNARY:
16622
17190
  switch (ggml_get_unary_op(op)) {
16623
17191
  case GGML_UNARY_OP_EXP:
17192
+ case GGML_UNARY_OP_EXPM1:
16624
17193
  case GGML_UNARY_OP_ELU:
16625
17194
  case GGML_UNARY_OP_GELU:
16626
17195
  case GGML_UNARY_OP_GELU_ERF:
@@ -16641,8 +17210,7 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
16641
17210
  case GGML_UNARY_OP_FLOOR:
16642
17211
  case GGML_UNARY_OP_TRUNC:
16643
17212
  case GGML_UNARY_OP_SGN:
16644
- return ggml_is_contiguous(op->src[0]) &&
16645
- (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) &&
17213
+ return (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) &&
16646
17214
  (op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16) &&
16647
17215
  (op->src[0]->type == op->type);
16648
17216
  default:
@@ -16658,7 +17226,8 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
16658
17226
  case GGML_GLU_OP_GEGLU_QUICK:
16659
17227
  return (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) &&
16660
17228
  (op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16) &&
16661
- (op->src[0]->type == op->type);
17229
+ (op->src[0]->type == op->type) &&
17230
+ (!op->src[1] || op->src[1]->type == op->src[0]->type);
16662
17231
  default:
16663
17232
  return false;
16664
17233
  }
@@ -16809,23 +17378,28 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
16809
17378
  return false;
16810
17379
  }
16811
17380
  }
17381
+ case GGML_OP_GET_ROWS_BACK:
17382
+ return op->type == GGML_TYPE_F32 && op->src[0]->type == GGML_TYPE_F32;
16812
17383
  case GGML_OP_SET_ROWS:
16813
17384
  {
16814
- switch (op->type) {
16815
- case GGML_TYPE_F32:
16816
- case GGML_TYPE_F16:
16817
- case GGML_TYPE_BF16:
16818
- case GGML_TYPE_Q1_0:
16819
- case GGML_TYPE_Q4_0:
16820
- case GGML_TYPE_Q4_1:
16821
- case GGML_TYPE_Q5_0:
16822
- case GGML_TYPE_Q5_1:
16823
- case GGML_TYPE_Q8_0:
16824
- case GGML_TYPE_IQ4_NL:
16825
- return true;
16826
- default:
16827
- return false;
17385
+ if (op->src[0]->type == GGML_TYPE_F32) {
17386
+ switch (op->type) {
17387
+ case GGML_TYPE_F32:
17388
+ case GGML_TYPE_F16:
17389
+ case GGML_TYPE_BF16:
17390
+ case GGML_TYPE_Q1_0:
17391
+ case GGML_TYPE_Q4_0:
17392
+ case GGML_TYPE_Q4_1:
17393
+ case GGML_TYPE_Q5_0:
17394
+ case GGML_TYPE_Q5_1:
17395
+ case GGML_TYPE_Q8_0:
17396
+ case GGML_TYPE_IQ4_NL:
17397
+ return true;
17398
+ default:
17399
+ return false;
17400
+ }
16828
17401
  }
17402
+ return false;
16829
17403
  }
16830
17404
  case GGML_OP_CONT:
16831
17405
  case GGML_OP_CPY:
@@ -16905,12 +17479,11 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
16905
17479
  case GGML_OP_TRANSPOSE:
16906
17480
  case GGML_OP_RMS_NORM:
16907
17481
  return true;
16908
- case GGML_OP_NORM:
16909
17482
  case GGML_OP_GROUP_NORM:
16910
17483
  return ggml_is_contiguous(op->src[0]);
17484
+ case GGML_OP_NORM:
16911
17485
  case GGML_OP_L2_NORM:
16912
- return ggml_is_contiguous_rows(op->src[0]) &&
16913
- op->src[0]->type == GGML_TYPE_F32 && op->type == GGML_TYPE_F32;
17486
+ return op->src[0]->type == GGML_TYPE_F32 && op->type == GGML_TYPE_F32;
16914
17487
  case GGML_OP_ADD:
16915
17488
  case GGML_OP_SUB:
16916
17489
  case GGML_OP_MUL:
@@ -16929,8 +17502,9 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
16929
17502
  case GGML_OP_SIN:
16930
17503
  case GGML_OP_COS:
16931
17504
  case GGML_OP_CLAMP:
16932
- return op->src[0]->type == GGML_TYPE_F32;
16933
17505
  case GGML_OP_LEAKY_RELU:
17506
+ return (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) &&
17507
+ op->type == op->src[0]->type;
16934
17508
  case GGML_OP_OPT_STEP_ADAMW:
16935
17509
  case GGML_OP_OPT_STEP_SGD:
16936
17510
  return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32;
@@ -16977,8 +17551,14 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
16977
17551
  case GGML_OP_SET:
16978
17552
  return op->src[0]->type == op->src[1]->type && op->src[0]->type == op->type &&
16979
17553
  (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_I32);
16980
- case GGML_OP_CONCAT:
16981
- return ggml_type_size(op->src[0]->type) == ggml_type_size(GGML_TYPE_F32);
17554
+ case GGML_OP_CONCAT: {
17555
+ if (op->src[0]->type != op->src[1]->type || op->src[0]->type != op->type) {
17556
+ return false;
17557
+ }
17558
+ const size_t type_size = ggml_type_size(op->type);
17559
+ return ggml_blck_size(op->type) == 1 &&
17560
+ (type_size == 1 || type_size == 2 || type_size == 4 || type_size == 8);
17561
+ }
16982
17562
  case GGML_OP_ADD1:
16983
17563
  return (op->src[0]->type == GGML_TYPE_F32 && op->src[1]->type == GGML_TYPE_F32)
16984
17564
  || (op->src[0]->type == GGML_TYPE_F16 && op->src[1]->type == GGML_TYPE_F32)
@@ -17054,7 +17634,7 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
17054
17634
  case GGML_OP_GATED_DELTA_NET:
17055
17635
  {
17056
17636
  const uint32_t S_v = op->src[2]->ne[0];
17057
- if (S_v != 32 && S_v != 64 && S_v != 128) {
17637
+ if (S_v != 16 && S_v != 32 && S_v != 64 && S_v != 128) {
17058
17638
  return false;
17059
17639
  }
17060
17640
  for (int i = 0; i < 6; i++) {
@@ -17106,6 +17686,13 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
17106
17686
  return op->src[0]->type == GGML_TYPE_F32;
17107
17687
  case GGML_OP_CONV_TRANSPOSE_1D:
17108
17688
  return op->src[0]->type == GGML_TYPE_F32 && op->src[1]->type == GGML_TYPE_F32;
17689
+ case GGML_OP_COL2IM_1D:
17690
+ return (op->src[0]->type == GGML_TYPE_F32 ||
17691
+ op->src[0]->type == GGML_TYPE_F16 ||
17692
+ op->src[0]->type == GGML_TYPE_BF16) &&
17693
+ op->type == op->src[0]->type &&
17694
+ ggml_is_contiguous(op->src[0]) &&
17695
+ ggml_is_contiguous(op);
17109
17696
  case GGML_OP_CONV_2D:
17110
17697
  case GGML_OP_CONV_TRANSPOSE_2D:
17111
17698
  {
@@ -17117,6 +17704,13 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
17117
17704
  ggml_is_contiguous(op->src[1]) &&
17118
17705
  ggml_is_contiguous(op));
17119
17706
  }
17707
+ case GGML_OP_CONV_3D:
17708
+ return (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) &&
17709
+ op->src[1]->type == GGML_TYPE_F32 &&
17710
+ op->type == GGML_TYPE_F32 &&
17711
+ ggml_is_contiguous(op->src[0]) &&
17712
+ ggml_is_contiguous(op->src[1]) &&
17713
+ ggml_is_contiguous(op);
17120
17714
  default:
17121
17715
  return false;
17122
17716
  }
@@ -17433,9 +18027,9 @@ static bool ggml_vk_device_is_supported(const vk::PhysicalDevice & vkdev) {
17433
18027
  static bool ggml_vk_khr_cooperative_matrix_support(const vk::PhysicalDeviceProperties& props, const vk::PhysicalDeviceDriverProperties& driver_props, vk_device_architecture arch) {
17434
18028
  switch (props.vendorID) {
17435
18029
  case VK_VENDOR_ID_INTEL:
17436
- // Only allowing Xe2 GPU at the moment since Xe2 GPU can gain significant performance boost,
17437
- // while some older hardware (ex. Arc A770) has performance regressions
17438
- return arch == vk_device_architecture::INTEL_XE2;
18030
+ // Only allowing Xe2/Xe3 GPU and integrated Xe GPUs at the moment since older hardware (ex. Arc A770) has performance regressions.
18031
+ return (arch == vk_device_architecture::INTEL_XE2) ||
18032
+ (arch == vk_device_architecture::INTEL_XE1 && props.deviceType == vk::PhysicalDeviceType::eIntegratedGpu && driver_props.driverID == vk::DriverId::eIntelProprietaryWindows);
17439
18033
  case VK_VENDOR_ID_AMD:
17440
18034
  if (driver_props.driverID == vk::DriverId::eAmdProprietary || driver_props.driverID == vk::DriverId::eAmdOpenSource) {
17441
18035
  // Workaround for AMD proprietary driver reporting support on all GPUs
@@ -17483,6 +18077,8 @@ static uint32_t ggml_vk_intel_shader_core_count(const vk::PhysicalDevice& vkdev)
17483
18077
  case 0xE20B: // B580
17484
18078
  case 0xE211: // Pro B60
17485
18079
  return 20;
18080
+ case 0xB080: // PTL Xe3 LPG 2x6 (12 subslices)
18081
+ return 12;
17486
18082
  default:
17487
18083
  return 0;
17488
18084
  }
@@ -17788,6 +18384,9 @@ static void ggml_vk_check_results_0(ggml_backend_vk_context * ctx, ggml_cgraph *
17788
18384
  case GGML_UNARY_OP_EXP:
17789
18385
  tensor_clone = ggml_exp(ggml_ctx, src_clone[0]);
17790
18386
  break;
18387
+ case GGML_UNARY_OP_EXPM1:
18388
+ tensor_clone = ggml_expm1(ggml_ctx, src_clone[0]);
18389
+ break;
17791
18390
  case GGML_UNARY_OP_ELU:
17792
18391
  tensor_clone = ggml_elu(ggml_ctx, src_clone[0]);
17793
18392
  break;
@@ -17934,6 +18533,11 @@ static void ggml_vk_check_results_0(ggml_backend_vk_context * ctx, ggml_cgraph *
17934
18533
  const int32_t p0 = tensor->op_params[1];
17935
18534
  const int32_t d0 = tensor->op_params[2];
17936
18535
  tensor_clone = ggml_conv_transpose_1d(ggml_ctx, src_clone[0], src_clone[1], s0, p0, d0);
18536
+ } else if (tensor->op == GGML_OP_COL2IM_1D) {
18537
+ const int32_t stride = tensor->op_params[0];
18538
+ const int32_t oc = tensor->op_params[1];
18539
+ const int32_t p0 = tensor->op_params[2];
18540
+ tensor_clone = ggml_col2im_1d(ggml_ctx, src_clone[0], stride, oc, p0);
17937
18541
  } else if (tensor->op == GGML_OP_POOL_2D) {
17938
18542
  enum ggml_op_pool op = static_cast<ggml_op_pool>(tensor->op_params[0]);
17939
18543
  const int32_t k0 = tensor->op_params[1];
@@ -17952,6 +18556,20 @@ static void ggml_vk_check_results_0(ggml_backend_vk_context * ctx, ggml_cgraph *
17952
18556
  const int32_t d0 = tensor->op_params[4];
17953
18557
  const int32_t d1 = tensor->op_params[5];
17954
18558
  tensor_clone = ggml_conv_2d(ggml_ctx, src_clone[0], src_clone[1], s0, s1, p0, p1, d0, d1);
18559
+ } else if (tensor->op == GGML_OP_CONV_3D) {
18560
+ const int32_t s0 = tensor->op_params[0];
18561
+ const int32_t s1 = tensor->op_params[1];
18562
+ const int32_t s2 = tensor->op_params[2];
18563
+ const int32_t p0 = tensor->op_params[3];
18564
+ const int32_t p1 = tensor->op_params[4];
18565
+ const int32_t p2 = tensor->op_params[5];
18566
+ const int32_t d0 = tensor->op_params[6];
18567
+ const int32_t d1 = tensor->op_params[7];
18568
+ const int32_t d2 = tensor->op_params[8];
18569
+ const int32_t IC = tensor->op_params[9];
18570
+ const int32_t N = tensor->op_params[10];
18571
+ const int32_t OC = tensor->op_params[11];
18572
+ tensor_clone = ggml_conv_3d_direct(ggml_ctx, src_clone[0], src_clone[1], s0, s1, s2, p0, p1, p2, d0, d1, d2, IC, N, OC);
17955
18573
  } else if (tensor->op == GGML_OP_CONV_2D_DW) {
17956
18574
  const int32_t s0 = tensor->op_params[0];
17957
18575
  const int32_t s1 = tensor->op_params[1];