kazutab commited on
Commit
ecd6272
·
verified ·
1 Parent(s): a779940

Upload folder using huggingface_hub (part 6)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +25 -0
  2. backend/llama.cpp/LICENSE +21 -0
  3. backend/llama.cpp/Makefile +9 -0
  4. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-apir.h +15 -0
  5. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-backend.cpp +58 -0
  6. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer-type.cpp +110 -0
  7. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer.cpp +173 -0
  8. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-device.cpp +192 -0
  9. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-impl.h +36 -0
  10. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward.gen.h +53 -0
  11. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.cpp +99 -0
  12. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.h +23 -0
  13. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.cpp +179 -0
  14. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.h +86 -0
  15. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.cpp +545 -0
  16. backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.h +115 -0
  17. backend/llama.cpp/ggml/src/ggml-vulkan/CMakeLists.txt +236 -0
  18. backend/llama.cpp/ggml/src/ggml-vulkan/cmake/host-toolchain.cmake.in +15 -0
  19. backend/llama.cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp +0 -0
  20. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt +35 -0
  21. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/acc.comp +37 -0
  22. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add.comp +69 -0
  23. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add1.comp +28 -0
  24. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add_id.comp +42 -0
  25. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/arange.comp +20 -0
  26. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argmax.comp +60 -0
  27. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort.comp +86 -0
  28. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort_large.comp +114 -0
  29. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp +61 -0
  30. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/concat.comp +41 -0
  31. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp +53 -0
  32. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_dw.comp +105 -0
  33. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +480 -0
  34. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp +431 -0
  35. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv_transpose_1d.comp +98 -0
  36. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy.comp +25 -0
  37. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp +51 -0
  38. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp +320 -0
  39. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_transpose.comp +67 -0
  40. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_equal.comp +31 -0
  41. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_experts.comp +51 -0
  42. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum.comp +83 -0
  43. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass1.comp +60 -0
  44. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass2.comp +66 -0
  45. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_f32.comp +20 -0
  46. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl +692 -0
  47. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl +1376 -0
  48. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_head.glsl +13 -0
  49. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_m.comp +42 -0
  50. backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_s.comp +35 -0
.gitattributes CHANGED
@@ -36,3 +36,28 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
36
  backend/llama.cpp/conversion/__pycache__/base.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
37
  backend/llama.cpp/docs/android/imported-into-android-studio.jpg filter=lfs diff=lfs merge=lfs -text
38
  backend/llama.cpp/docs/development/llama-star/idea-arch.key filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  backend/llama.cpp/conversion/__pycache__/base.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
37
  backend/llama.cpp/docs/android/imported-into-android-studio.jpg filter=lfs diff=lfs merge=lfs -text
38
  backend/llama.cpp/docs/development/llama-star/idea-arch.key filter=lfs diff=lfs merge=lfs -text
39
+ backend/llama.cpp/gguf-py/gguf/__pycache__/constants.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
40
+ backend/llama.cpp/gguf-py/gguf/__pycache__/gguf_writer.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
41
+ backend/llama.cpp/gguf-py/gguf/__pycache__/quants.cpython-313.pyc filter=lfs diff=lfs merge=lfs -text
42
+ backend/llama.cpp/media/llama0-banner.png filter=lfs diff=lfs merge=lfs -text
43
+ backend/llama.cpp/media/llama0-logo.png filter=lfs diff=lfs merge=lfs -text
44
+ backend/llama.cpp/media/matmul.png filter=lfs diff=lfs merge=lfs -text
45
+ backend/llama.cpp/models/ggml-vocab-aquila.gguf filter=lfs diff=lfs merge=lfs -text
46
+ backend/llama.cpp/models/ggml-vocab-baichuan.gguf filter=lfs diff=lfs merge=lfs -text
47
+ backend/llama.cpp/models/ggml-vocab-bert-bge.gguf filter=lfs diff=lfs merge=lfs -text
48
+ backend/llama.cpp/models/ggml-vocab-command-r.gguf filter=lfs diff=lfs merge=lfs -text
49
+ backend/llama.cpp/models/ggml-vocab-deepseek-coder.gguf filter=lfs diff=lfs merge=lfs -text
50
+ backend/llama.cpp/models/ggml-vocab-deepseek-llm.gguf filter=lfs diff=lfs merge=lfs -text
51
+ backend/llama.cpp/models/ggml-vocab-falcon.gguf filter=lfs diff=lfs merge=lfs -text
52
+ backend/llama.cpp/models/ggml-vocab-gemma-4.gguf filter=lfs diff=lfs merge=lfs -text
53
+ backend/llama.cpp/models/ggml-vocab-gpt-2.gguf filter=lfs diff=lfs merge=lfs -text
54
+ backend/llama.cpp/models/ggml-vocab-gpt-neox.gguf filter=lfs diff=lfs merge=lfs -text
55
+ backend/llama.cpp/models/ggml-vocab-llama-bpe.gguf filter=lfs diff=lfs merge=lfs -text
56
+ backend/llama.cpp/models/ggml-vocab-llama-spm.gguf filter=lfs diff=lfs merge=lfs -text
57
+ backend/llama.cpp/models/ggml-vocab-mpt.gguf filter=lfs diff=lfs merge=lfs -text
58
+ backend/llama.cpp/models/ggml-vocab-nomic-bert-moe.gguf filter=lfs diff=lfs merge=lfs -text
59
+ backend/llama.cpp/models/ggml-vocab-phi-3.gguf filter=lfs diff=lfs merge=lfs -text
60
+ backend/llama.cpp/models/ggml-vocab-qwen2.gguf filter=lfs diff=lfs merge=lfs -text
61
+ backend/llama.cpp/models/ggml-vocab-qwen35.gguf filter=lfs diff=lfs merge=lfs -text
62
+ backend/llama.cpp/models/ggml-vocab-refact.gguf filter=lfs diff=lfs merge=lfs -text
63
+ backend/llama.cpp/models/ggml-vocab-starcoder.gguf filter=lfs diff=lfs merge=lfs -text
backend/llama.cpp/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023-2026 The ggml authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
backend/llama.cpp/Makefile ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ define newline
2
+
3
+
4
+ endef
5
+
6
+ $(error Build system changed:$(newline)\
7
+ The Makefile build has been replaced by CMake.$(newline)$(newline)\
8
+ For build instructions see:$(newline)\
9
+ https://github.com/ggml-org/llama.cpp/blob/master/docs/build.md$(newline)${newline})
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-apir.h ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "backend/shared/apir_backend.h"
2
+ #include "ggml-alloc.h"
3
+ #include "ggml-impl.h"
4
+ #include "ggml.h"
5
+ #include "virtgpu-shm.h"
6
+ #include "virtgpu-utils.h"
7
+
8
+ struct apir_buffer_context_t {
9
+ apir_buffer_host_handle_t host_handle;
10
+
11
+ struct virtgpu_shmem shmem;
12
+ apir_buffer_type_host_handle_t buft_host_handle;
13
+ };
14
+
15
+ #include "virtgpu-forward.gen.h"
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-backend.cpp ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "virtgpu-forward-impl.h"
2
+
3
+ static long long current_time_ms() {
4
+ timespec ts;
5
+ clock_gettime(CLOCK_REALTIME, &ts); // Use CLOCK_MONOTONIC for elapsed time
6
+ return (long long) ts.tv_sec * 1000000000LL + ts.tv_nsec;
7
+ }
8
+
9
+ ggml_status apir_backend_graph_compute(virtgpu * gpu, ggml_cgraph * cgraph) {
10
+ apir_encoder * encoder;
11
+ apir_decoder * decoder;
12
+ ApirForwardReturnCode ret;
13
+
14
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BACKEND_GRAPH_COMPUTE);
15
+
16
+ std::vector<uint8_t> cgraph_data;
17
+ size_t cgraph_size = apir_serialize_ggml_cgraph(cgraph, cgraph_data);
18
+
19
+ virtgpu_shmem temp_shmem; // Local storage for large buffers
20
+ virtgpu_shmem * shmem = &temp_shmem;
21
+ bool using_shared_shmem = false;
22
+
23
+ if (cgraph_size <= gpu->data_shmem.mmap_size) {
24
+ // Lock mutex before using shared data_shmem buffer
25
+ if (mtx_lock(&gpu->data_shmem_mutex) != thrd_success) {
26
+ GGML_ABORT(GGML_VIRTGPU "%s: Failed to lock data_shmem mutex", __func__);
27
+ }
28
+ using_shared_shmem = true;
29
+ shmem = &gpu->data_shmem;
30
+ } else if (virtgpu_shmem_create(gpu, cgraph_size, shmem)) {
31
+ GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate the guest-host shared buffer", __func__);
32
+ }
33
+
34
+ apir_encode_virtgpu_shmem_res_id(encoder, shmem->res_id);
35
+
36
+ apir_encode_size_t(encoder, &cgraph_size);
37
+
38
+ char * shmem_data = (char *) shmem->mmap_ptr;
39
+ apir_encoder secondary_enc = apir_new_encoder(shmem_data, cgraph_size);
40
+
41
+ apir_encode_cgraph_data(&secondary_enc, cgraph_data);
42
+
43
+ REMOTE_CALL(gpu, encoder, decoder, ret);
44
+
45
+ ggml_status status = GGML_STATUS_ABORTED;
46
+ apir_decode_ggml_status(decoder, &status);
47
+
48
+ remote_call_finish(gpu, encoder, decoder);
49
+
50
+ // Unlock mutex before cleanup
51
+ if (using_shared_shmem) {
52
+ mtx_unlock(&gpu->data_shmem_mutex);
53
+ } else {
54
+ virtgpu_shmem_destroy(gpu, shmem);
55
+ }
56
+
57
+ return status;
58
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer-type.cpp ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "virtgpu-forward-impl.h"
2
+
3
+ char * apir_buffer_type_get_name(virtgpu * gpu, apir_buffer_type_host_handle_t host_handle) {
4
+ apir_encoder * encoder;
5
+ apir_decoder * decoder;
6
+ ApirForwardReturnCode ret;
7
+
8
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_NAME);
9
+
10
+ apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
11
+
12
+ REMOTE_CALL(gpu, encoder, decoder, ret);
13
+
14
+ const size_t string_size = apir_decode_array_size_unchecked(decoder);
15
+ char * string = (char *) apir_decoder_alloc_array(sizeof(char), string_size);
16
+ if (!string) {
17
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: Could not allocate the device name buffer\n", __func__);
18
+ apir_decoder_set_fatal(decoder);
19
+ }
20
+ apir_decode_char_array(decoder, string, string_size);
21
+
22
+ remote_call_finish(gpu, encoder, decoder);
23
+
24
+ return string;
25
+ }
26
+
27
+ size_t apir_buffer_type_get_alignment(virtgpu * gpu, apir_buffer_type_host_handle_t host_handle) {
28
+ apir_encoder * encoder;
29
+ apir_decoder * decoder;
30
+ ApirForwardReturnCode ret;
31
+
32
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_ALIGNMENT);
33
+
34
+ apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
35
+
36
+ REMOTE_CALL(gpu, encoder, decoder, ret);
37
+
38
+ size_t alignment;
39
+ apir_decode_size_t(decoder, &alignment);
40
+
41
+ remote_call_finish(gpu, encoder, decoder);
42
+
43
+ return alignment;
44
+ }
45
+
46
+ size_t apir_buffer_type_get_max_size(virtgpu * gpu, apir_buffer_type_host_handle_t host_handle) {
47
+ apir_encoder * encoder;
48
+ apir_decoder * decoder;
49
+ ApirForwardReturnCode ret;
50
+
51
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_MAX_SIZE);
52
+
53
+ apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
54
+
55
+ REMOTE_CALL(gpu, encoder, decoder, ret);
56
+
57
+ size_t max_size;
58
+ apir_decode_size_t(decoder, &max_size);
59
+
60
+ remote_call_finish(gpu, encoder, decoder);
61
+
62
+ return max_size;
63
+ }
64
+
65
+ apir_buffer_context_t apir_buffer_type_alloc_buffer(virtgpu * gpu,
66
+ apir_buffer_type_host_handle_t host_handle,
67
+ size_t size) {
68
+ apir_encoder * encoder;
69
+ apir_decoder * decoder;
70
+ ApirForwardReturnCode ret;
71
+
72
+ apir_buffer_context_t buffer_context;
73
+
74
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_ALLOC_BUFFER);
75
+
76
+ apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
77
+
78
+ apir_encode_size_t(encoder, &size);
79
+
80
+ REMOTE_CALL(gpu, encoder, decoder, ret);
81
+
82
+ apir_decode_apir_buffer_host_handle_t(decoder, &buffer_context.host_handle);
83
+
84
+ remote_call_finish(gpu, encoder, decoder);
85
+
86
+ return buffer_context;
87
+ }
88
+
89
+ size_t apir_buffer_type_get_alloc_size(virtgpu * gpu,
90
+ apir_buffer_type_host_handle_t host_handle,
91
+ const ggml_tensor * op) {
92
+ apir_encoder * encoder;
93
+ apir_decoder * decoder;
94
+ ApirForwardReturnCode ret;
95
+
96
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_TYPE_GET_ALLOC_SIZE);
97
+
98
+ apir_encode_apir_buffer_type_host_handle(encoder, host_handle);
99
+
100
+ apir_encode_ggml_tensor_inline(encoder, op);
101
+
102
+ REMOTE_CALL(gpu, encoder, decoder, ret);
103
+
104
+ size_t alloc_size;
105
+ apir_decode_size_t(decoder, &alloc_size);
106
+
107
+ remote_call_finish(gpu, encoder, decoder);
108
+
109
+ return alloc_size;
110
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer.cpp ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "virtgpu-forward-impl.h"
2
+
3
+ void * apir_buffer_get_base(virtgpu * gpu, apir_buffer_context_t * buffer_context) {
4
+ apir_encoder * encoder;
5
+ apir_decoder * decoder;
6
+ ApirForwardReturnCode ret;
7
+
8
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_GET_BASE);
9
+
10
+ apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
11
+
12
+ REMOTE_CALL(gpu, encoder, decoder, ret);
13
+
14
+ uintptr_t base;
15
+ apir_decode_uintptr_t(decoder, &base);
16
+
17
+ remote_call_finish(gpu, encoder, decoder);
18
+
19
+ return (void *) base;
20
+ }
21
+
22
+ void apir_buffer_set_tensor(virtgpu * gpu,
23
+ apir_buffer_context_t * buffer_context,
24
+ ggml_tensor * tensor,
25
+ const void * data,
26
+ size_t offset,
27
+ size_t size) {
28
+ apir_encoder * encoder;
29
+ apir_decoder * decoder;
30
+ ApirForwardReturnCode ret;
31
+
32
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_SET_TENSOR);
33
+
34
+ apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
35
+ apir_encode_ggml_tensor(encoder, tensor);
36
+
37
+ virtgpu_shmem temp_shmem; // Local storage for large buffers
38
+ virtgpu_shmem * shmem = &temp_shmem;
39
+ bool using_shared_shmem = false;
40
+
41
+ if (size <= gpu->data_shmem.mmap_size) {
42
+ // Lock mutex before using shared data_shmem buffer
43
+ if (mtx_lock(&gpu->data_shmem_mutex) != thrd_success) {
44
+ GGML_ABORT(GGML_VIRTGPU "%s: Failed to lock data_shmem mutex", __func__);
45
+ }
46
+ using_shared_shmem = true;
47
+ shmem = &gpu->data_shmem;
48
+
49
+ } else if (virtgpu_shmem_create(gpu, size, shmem)) {
50
+ GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate the guest-host shared buffer", __func__);
51
+ }
52
+
53
+ memcpy(shmem->mmap_ptr, data, size);
54
+ apir_encode_virtgpu_shmem_res_id(encoder, shmem->res_id);
55
+
56
+ apir_encode_size_t(encoder, &offset);
57
+ apir_encode_size_t(encoder, &size);
58
+
59
+ REMOTE_CALL(gpu, encoder, decoder, ret);
60
+
61
+ remote_call_finish(gpu, encoder, decoder);
62
+
63
+ // Unlock mutex before cleanup
64
+ if (using_shared_shmem) {
65
+ mtx_unlock(&gpu->data_shmem_mutex);
66
+ } else {
67
+ virtgpu_shmem_destroy(gpu, shmem);
68
+ }
69
+
70
+ return;
71
+ }
72
+
73
+ void apir_buffer_get_tensor(virtgpu * gpu,
74
+ apir_buffer_context_t * buffer_context,
75
+ const ggml_tensor * tensor,
76
+ void * data,
77
+ size_t offset,
78
+ size_t size) {
79
+ apir_encoder * encoder;
80
+ apir_decoder * decoder;
81
+ ApirForwardReturnCode ret;
82
+
83
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_GET_TENSOR);
84
+
85
+ apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
86
+ apir_encode_ggml_tensor(encoder, tensor);
87
+
88
+ virtgpu_shmem temp_shmem; // Local storage for large buffers
89
+ virtgpu_shmem * shmem = &temp_shmem;
90
+ bool using_shared_shmem = false;
91
+
92
+ if (size <= gpu->data_shmem.mmap_size) {
93
+ // Lock mutex before using shared data_shmem buffer
94
+ if (mtx_lock(&gpu->data_shmem_mutex) != thrd_success) {
95
+ GGML_ABORT(GGML_VIRTGPU "%s: Failed to lock data_shmem mutex", __func__);
96
+ }
97
+ using_shared_shmem = true;
98
+ shmem = &gpu->data_shmem;
99
+
100
+ } else if (virtgpu_shmem_create(gpu, size, shmem)) {
101
+ GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate the guest-host shared buffer", __func__);
102
+ }
103
+
104
+ apir_encode_virtgpu_shmem_res_id(encoder, shmem->res_id);
105
+ apir_encode_size_t(encoder, &offset);
106
+ apir_encode_size_t(encoder, &size);
107
+
108
+ REMOTE_CALL(gpu, encoder, decoder, ret);
109
+
110
+ memcpy(data, shmem->mmap_ptr, size);
111
+
112
+ remote_call_finish(gpu, encoder, decoder);
113
+
114
+ // Unlock mutex before cleanup
115
+ if (using_shared_shmem) {
116
+ mtx_unlock(&gpu->data_shmem_mutex);
117
+ } else {
118
+ virtgpu_shmem_destroy(gpu, shmem);
119
+ }
120
+ }
121
+
122
+ bool apir_buffer_cpy_tensor(virtgpu * gpu,
123
+ apir_buffer_context_t * buffer_context,
124
+ const ggml_tensor * src,
125
+ const ggml_tensor * dst) {
126
+ apir_encoder * encoder;
127
+ apir_decoder * decoder;
128
+ ApirForwardReturnCode ret;
129
+
130
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_CPY_TENSOR);
131
+
132
+ apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
133
+ apir_encode_ggml_tensor(encoder, src);
134
+ apir_encode_ggml_tensor(encoder, dst);
135
+
136
+ REMOTE_CALL(gpu, encoder, decoder, ret);
137
+
138
+ bool ret_val;
139
+ apir_decode_bool_t(decoder, &ret_val);
140
+
141
+ remote_call_finish(gpu, encoder, decoder);
142
+
143
+ return ret_val;
144
+ }
145
+
146
+ void apir_buffer_clear(virtgpu * gpu, apir_buffer_context_t * buffer_context, uint8_t value) {
147
+ apir_encoder * encoder;
148
+ apir_decoder * decoder;
149
+ ApirForwardReturnCode ret;
150
+
151
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_CLEAR);
152
+
153
+ apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
154
+ apir_encode_uint8_t(encoder, &value);
155
+
156
+ REMOTE_CALL(gpu, encoder, decoder, ret);
157
+
158
+ remote_call_finish(gpu, encoder, decoder);
159
+ }
160
+
161
+ void apir_buffer_free_buffer(virtgpu * gpu, apir_buffer_context_t * buffer_context) {
162
+ apir_encoder * encoder;
163
+ apir_decoder * decoder;
164
+ ApirForwardReturnCode ret;
165
+
166
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_BUFFER_FREE_BUFFER);
167
+
168
+ apir_encode_apir_buffer_host_handle_t(encoder, &buffer_context->host_handle);
169
+
170
+ REMOTE_CALL(gpu, encoder, decoder, ret);
171
+
172
+ remote_call_finish(gpu, encoder, decoder);
173
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-device.cpp ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "virtgpu-forward-impl.h"
2
+ #include "virtgpu-shm.h"
3
+
4
+ int apir_device_get_count(virtgpu * gpu) {
5
+ apir_encoder * encoder;
6
+ apir_decoder * decoder;
7
+ ApirForwardReturnCode ret;
8
+
9
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_COUNT);
10
+ REMOTE_CALL(gpu, encoder, decoder, ret);
11
+
12
+ int32_t dev_count = -1;
13
+ apir_decode_int32_t(decoder, &dev_count);
14
+
15
+ remote_call_finish(gpu, encoder, decoder);
16
+
17
+ return dev_count;
18
+ }
19
+
20
+ char * apir_device_get_name(virtgpu * gpu) {
21
+ apir_encoder * encoder;
22
+ apir_decoder * decoder;
23
+ ApirForwardReturnCode ret;
24
+
25
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_NAME);
26
+ REMOTE_CALL(gpu, encoder, decoder, ret);
27
+
28
+ const size_t string_size = apir_decode_array_size_unchecked(decoder);
29
+ char * string = (char *) apir_decoder_alloc_array(sizeof(char), string_size);
30
+ if (!string) {
31
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: Could not allocate the device name buffer\n", __func__);
32
+ return NULL;
33
+ }
34
+ apir_decode_char_array(decoder, string, string_size);
35
+
36
+ remote_call_finish(gpu, encoder, decoder);
37
+
38
+ return string;
39
+ }
40
+
41
+ char * apir_device_get_description(virtgpu * gpu) {
42
+ apir_encoder * encoder;
43
+ apir_decoder * decoder;
44
+ ApirForwardReturnCode ret;
45
+
46
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_DESCRIPTION);
47
+
48
+ REMOTE_CALL(gpu, encoder, decoder, ret);
49
+
50
+ const size_t string_size = apir_decode_array_size_unchecked(decoder);
51
+ char * string = (char *) apir_decoder_alloc_array(sizeof(char), string_size);
52
+ if (!string) {
53
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: Could not allocate the device description buffer\n", __func__);
54
+
55
+ return NULL;
56
+ }
57
+ apir_decode_char_array(decoder, string, string_size);
58
+
59
+ remote_call_finish(gpu, encoder, decoder);
60
+
61
+ return string;
62
+ }
63
+
64
+ uint32_t apir_device_get_type(virtgpu * gpu) {
65
+ static uint32_t dev_type = 255;
66
+ if (dev_type != 255) {
67
+ return dev_type;
68
+ }
69
+
70
+ apir_encoder * encoder;
71
+ apir_decoder * decoder;
72
+ ApirForwardReturnCode ret;
73
+
74
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_TYPE);
75
+
76
+ REMOTE_CALL(gpu, encoder, decoder, ret);
77
+
78
+ apir_decode_uint32_t(decoder, &dev_type);
79
+
80
+ remote_call_finish(gpu, encoder, decoder);
81
+
82
+ return dev_type;
83
+ }
84
+
85
+ void apir_device_get_memory(virtgpu * gpu, size_t * free, size_t * total) {
86
+ static size_t dev_free = 0;
87
+ static size_t dev_total = 0;
88
+ apir_encoder * encoder;
89
+ apir_decoder * decoder;
90
+ ApirForwardReturnCode ret;
91
+
92
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_MEMORY);
93
+
94
+ REMOTE_CALL(gpu, encoder, decoder, ret);
95
+
96
+ apir_decode_size_t(decoder, &dev_free);
97
+ apir_decode_size_t(decoder, &dev_total);
98
+
99
+ *free = dev_free;
100
+ *total = dev_total;
101
+
102
+ remote_call_finish(gpu, encoder, decoder);
103
+
104
+ return;
105
+ }
106
+
107
+ bool apir_device_supports_op(virtgpu * gpu, const ggml_tensor * op) {
108
+ apir_encoder * encoder;
109
+ apir_decoder * decoder;
110
+ ApirForwardReturnCode ret;
111
+
112
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_SUPPORTS_OP);
113
+
114
+ apir_encode_ggml_tensor_inline(encoder, op);
115
+
116
+ REMOTE_CALL(gpu, encoder, decoder, ret);
117
+
118
+ bool supports_op;
119
+ apir_decode_bool_t(decoder, &supports_op);
120
+
121
+ remote_call_finish(gpu, encoder, decoder);
122
+
123
+ return supports_op;
124
+ }
125
+
126
+ apir_buffer_type_host_handle_t apir_device_get_buffer_type(virtgpu * gpu) {
127
+ apir_encoder * encoder;
128
+ apir_decoder * decoder;
129
+ ApirForwardReturnCode ret;
130
+
131
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_BUFFER_TYPE);
132
+
133
+ REMOTE_CALL(gpu, encoder, decoder, ret);
134
+
135
+ apir_buffer_type_host_handle_t buft_handle;
136
+ apir_decode_apir_buffer_type_host_handle_t(decoder, &buft_handle);
137
+
138
+ remote_call_finish(gpu, encoder, decoder);
139
+
140
+ return buft_handle;
141
+ }
142
+
143
+ void apir_device_get_props(virtgpu * gpu,
144
+ bool * async,
145
+ bool * host_buffer,
146
+ bool * buffer_from_host_ptr,
147
+ bool * events) {
148
+ apir_encoder * encoder;
149
+ apir_decoder * decoder;
150
+ ApirForwardReturnCode ret;
151
+
152
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_GET_PROPS);
153
+
154
+ REMOTE_CALL(gpu, encoder, decoder, ret);
155
+
156
+ apir_decode_bool_t(decoder, async);
157
+ apir_decode_bool_t(decoder, host_buffer);
158
+ apir_decode_bool_t(decoder, buffer_from_host_ptr);
159
+ apir_decode_bool_t(decoder, events);
160
+
161
+ remote_call_finish(gpu, encoder, decoder);
162
+
163
+ return;
164
+ }
165
+
166
+ apir_buffer_context_t apir_device_buffer_from_ptr(virtgpu * gpu, size_t size, size_t max_tensor_size) {
167
+ apir_encoder * encoder;
168
+ apir_decoder * decoder;
169
+ ApirForwardReturnCode ret;
170
+
171
+ apir_buffer_context_t buffer_context;
172
+
173
+ REMOTE_CALL_PREPARE(gpu, encoder, APIR_COMMAND_TYPE_DEVICE_BUFFER_FROM_PTR);
174
+
175
+ if (virtgpu_shmem_create(gpu, size, &buffer_context.shmem)) {
176
+ GGML_ABORT(GGML_VIRTGPU "%s: Couldn't allocate %ldb of guest-host shared buffer", __func__, size);
177
+ }
178
+
179
+ apir_encode_virtgpu_shmem_res_id(encoder, buffer_context.shmem.res_id);
180
+
181
+ apir_encode_size_t(encoder, &size);
182
+ apir_encode_size_t(encoder, &max_tensor_size);
183
+
184
+ REMOTE_CALL(gpu, encoder, decoder, ret);
185
+
186
+ apir_decode_apir_buffer_host_handle_t(decoder, &buffer_context.host_handle);
187
+ buffer_context.buft_host_handle = apir_decode_apir_buffer_type_host_handle(decoder);
188
+
189
+ remote_call_finish(gpu, encoder, decoder);
190
+
191
+ return buffer_context;
192
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward-impl.h ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ // clang-format off
4
+ #include "virtgpu.h"
5
+ #include "ggml-remoting.h"
6
+ #include "backend/shared/apir_backend.h"
7
+ #include "backend/shared/apir_cs_ggml.h"
8
+ #include "ggml-backend-impl.h"
9
+ // clang-format on
10
+
11
+ #define REMOTE_CALL_PREPARE(gpu_dev_name, encoder_name, apir_command_type__) \
12
+ int32_t REMOTE_CALL_PREPARE_forward_flag = (int32_t) apir_command_type__; \
13
+ const char * REMOTE_CALL_PREPARE_command_name = apir_dispatch_command_name(apir_command_type__); \
14
+ do { \
15
+ encoder_name = remote_call_prepare(gpu_dev_name, APIR_COMMAND_TYPE_FORWARD, REMOTE_CALL_PREPARE_forward_flag); \
16
+ if (!encoder_name) { \
17
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to prepare the remote call encoder", __func__); \
18
+ } \
19
+ } while (0)
20
+
21
+ #define REMOTE_CALL(gpu_dev_name, encoder_name, decoder_name, ret_name) \
22
+ do { \
23
+ ret_name = (ApirForwardReturnCode) remote_call(gpu_dev_name, encoder_name, &decoder_name, 0, NULL); \
24
+ if (!decoder_name) { \
25
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to kick the remote call", __func__); \
26
+ } \
27
+ if (ret_name < APIR_FORWARD_BASE_INDEX) { \
28
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to forward the API call: %s: code %d", __func__, \
29
+ apir_forward_error(ret_name), ret_name); \
30
+ } \
31
+ ret_name = (ApirForwardReturnCode) (ret_name - APIR_FORWARD_BASE_INDEX); \
32
+ if (ret_name != 0) { \
33
+ GGML_ABORT(GGML_VIRTGPU "backend function '%s' failed (return code: %d)", \
34
+ REMOTE_CALL_PREPARE_command_name, ret_name); \
35
+ } \
36
+ } while (0)
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-forward.gen.h ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ /* device */
4
+ void apir_device_get_device_count(struct virtgpu * gpu);
5
+ int apir_device_get_count(struct virtgpu * gpu);
6
+ char * apir_device_get_name(struct virtgpu * gpu);
7
+ char * apir_device_get_description(struct virtgpu * gpu);
8
+ uint32_t apir_device_get_type(struct virtgpu * gpu);
9
+ void apir_device_get_memory(struct virtgpu * gpu, size_t * free, size_t * total);
10
+ bool apir_device_supports_op(struct virtgpu * gpu, const ggml_tensor * op);
11
+ apir_buffer_type_host_handle_t apir_device_get_buffer_type(struct virtgpu * gpu);
12
+ void apir_device_get_props(struct virtgpu * gpu,
13
+ bool * async,
14
+ bool * host_buffer,
15
+ bool * buffer_from_host_ptr,
16
+ bool * events);
17
+ apir_buffer_context_t apir_device_buffer_from_ptr(struct virtgpu * gpu, size_t size, size_t max_tensor_size);
18
+
19
+ /* buffer-type */
20
+ char * apir_buffer_type_get_name(struct virtgpu * gpu, apir_buffer_type_host_handle_t host_handle);
21
+ size_t apir_buffer_type_get_alignment(struct virtgpu * gpu, apir_buffer_type_host_handle_t host_handle);
22
+ size_t apir_buffer_type_get_max_size(struct virtgpu * gpu, apir_buffer_type_host_handle_t host_handle);
23
+ /* apir_buffer_type_is_host is deprecated. */
24
+ apir_buffer_context_t apir_buffer_type_alloc_buffer(struct virtgpu * gpu,
25
+ apir_buffer_type_host_handle_t host_handle,
26
+ size_t size);
27
+ size_t apir_buffer_type_get_alloc_size(struct virtgpu * gpu,
28
+ apir_buffer_type_host_handle_t host_handle,
29
+ const ggml_tensor * op);
30
+
31
+ /* buffer */
32
+ void * apir_buffer_get_base(struct virtgpu * gpu, apir_buffer_context_t * buffer_context);
33
+ void apir_buffer_set_tensor(struct virtgpu * gpu,
34
+ apir_buffer_context_t * buffer_context,
35
+ ggml_tensor * tensor,
36
+ const void * data,
37
+ size_t offset,
38
+ size_t size);
39
+ void apir_buffer_get_tensor(struct virtgpu * gpu,
40
+ apir_buffer_context_t * buffer_context,
41
+ const ggml_tensor * tensor,
42
+ void * data,
43
+ size_t offset,
44
+ size_t size);
45
+ bool apir_buffer_cpy_tensor(struct virtgpu * gpu,
46
+ apir_buffer_context_t * buffer_context,
47
+ const ggml_tensor * src,
48
+ const ggml_tensor * dst);
49
+ void apir_buffer_clear(struct virtgpu * gpu, apir_buffer_context_t * buffer_context, uint8_t value);
50
+ void apir_buffer_free_buffer(struct virtgpu * gpu, apir_buffer_context_t * buffer_context);
51
+
52
+ /* backend */
53
+ ggml_status apir_backend_graph_compute(struct virtgpu * gpu, ggml_cgraph * cgraph);
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.cpp ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "virtgpu-shm.h"
2
+
3
+ #include "virtgpu.h"
4
+ #include "ggml-remoting.h"
5
+
6
+ #include <assert.h>
7
+
8
+ static uint32_t virtgpu_ioctl_resource_create_blob(virtgpu * gpu,
9
+ uint32_t blob_mem,
10
+ uint32_t blob_flags,
11
+ size_t blob_size,
12
+ uint64_t blob_id,
13
+ uint32_t * res_id) {
14
+ #ifdef SIMULATE_BO_SIZE_FIX
15
+ blob_size = align64(blob_size, 4096);
16
+ #endif
17
+
18
+ drm_virtgpu_resource_create_blob args = {
19
+ .blob_mem = blob_mem,
20
+ .blob_flags = blob_flags,
21
+ .bo_handle = 0,
22
+ .res_handle = 0,
23
+ .size = blob_size,
24
+ .pad = 0,
25
+ .cmd_size = 0,
26
+ .cmd = 0,
27
+ .blob_id = blob_id,
28
+ };
29
+
30
+ if (virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &args)) {
31
+ return 0;
32
+ }
33
+
34
+ *res_id = args.res_handle;
35
+ return args.bo_handle;
36
+ }
37
+
38
+ static void virtgpu_ioctl_gem_close(virtgpu * gpu, uint32_t gem_handle) {
39
+ drm_gem_close args = {
40
+ .handle = gem_handle,
41
+ .pad = 0,
42
+ };
43
+
44
+ const int ret = virtgpu_ioctl(gpu, DRM_IOCTL_GEM_CLOSE, &args);
45
+ assert(!ret);
46
+ #ifdef NDEBUG
47
+ UNUSED(ret);
48
+ #endif
49
+ }
50
+
51
+ static void * virtgpu_ioctl_map(virtgpu * gpu, uint32_t gem_handle, size_t size) {
52
+ drm_virtgpu_map args = {
53
+ .offset = 0,
54
+ .handle = gem_handle,
55
+ .pad = 0,
56
+ };
57
+
58
+ if (virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_MAP, &args)) {
59
+ return NULL;
60
+ }
61
+
62
+ void * ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, gpu->fd, args.offset);
63
+ if (ptr == MAP_FAILED) {
64
+ return NULL;
65
+ }
66
+
67
+ return ptr;
68
+ }
69
+
70
+ void virtgpu_shmem_destroy(virtgpu * gpu, virtgpu_shmem * shmem) {
71
+ munmap(shmem->mmap_ptr, shmem->mmap_size);
72
+ virtgpu_ioctl_gem_close(gpu, shmem->gem_handle);
73
+ }
74
+
75
+ int virtgpu_shmem_create(virtgpu * gpu, size_t size, virtgpu_shmem * shmem) {
76
+ size = align64(size, 16384);
77
+
78
+ uint32_t res_id;
79
+ uint32_t gem_handle = virtgpu_ioctl_resource_create_blob(gpu, VIRTGPU_BLOB_MEM_HOST3D,
80
+ VIRTGPU_BLOB_FLAG_USE_MAPPABLE, size, 0, &res_id);
81
+
82
+ if (!gem_handle) {
83
+ return 1;
84
+ }
85
+
86
+ void * ptr = virtgpu_ioctl_map(gpu, gem_handle, size);
87
+ if (!ptr) {
88
+ virtgpu_ioctl_gem_close(gpu, gem_handle);
89
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: virtgpu_ioctl_map failed\n", __func__);
90
+ return 1;
91
+ }
92
+
93
+ shmem->res_id = res_id;
94
+ shmem->mmap_size = size;
95
+ shmem->mmap_ptr = ptr;
96
+ shmem->gem_handle = gem_handle;
97
+
98
+ return 0;
99
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-shm.h ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include "virtgpu-utils.h"
4
+
5
+ #include <sys/mman.h>
6
+
7
+ #include <atomic>
8
+ #include <cassert>
9
+ #include <cstddef>
10
+ #include <cstdint>
11
+
12
+ struct virtgpu;
13
+
14
+ struct virtgpu_shmem {
15
+ uint32_t res_id;
16
+ size_t mmap_size;
17
+ void * mmap_ptr;
18
+
19
+ uint32_t gem_handle;
20
+ };
21
+
22
+ int virtgpu_shmem_create(virtgpu * gpu, size_t size, virtgpu_shmem * shmem);
23
+ void virtgpu_shmem_destroy(virtgpu * gpu, virtgpu_shmem * shmem);
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.cpp ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "virtgpu-utils.h"
2
+
3
+ #include <malloc.h>
4
+ #include <stdlib.h>
5
+
6
+ #include <cstring>
7
+
8
+ #define NODE_ALLOC_ALIGN 64
9
+ #define NODE_PTR_MASK (~((uintptr_t) NODE_ALLOC_ALIGN - 1))
10
+ #define NODE_LEVEL_MASK ((uintptr_t) NODE_ALLOC_ALIGN - 1)
11
+ #define NULL_NODE 0
12
+
13
+ #define os_malloc_aligned(_size, _align) _aligned_malloc(_size, _align)
14
+ #define os_free_aligned(_ptr) free(_ptr)
15
+ #define p_atomic_cmpxchg(v, old, _new) __sync_val_compare_and_swap((v), (old), (_new))
16
+
17
+ static inline uint64_t util_logbase2_64(uint64_t n) {
18
+ #if defined(HAVE___BUILTIN_CLZLL)
19
+ return ((sizeof(uint64_t) * 8 - 1) - __builtin_clzll(n | 1));
20
+ #else
21
+ uint64_t pos = 0ull;
22
+ if (n >= 1ull << 32) {
23
+ n >>= 32;
24
+ pos += 32;
25
+ }
26
+ if (n >= 1ull << 16) {
27
+ n >>= 16;
28
+ pos += 16;
29
+ }
30
+ if (n >= 1ull << 8) {
31
+ n >>= 8;
32
+ pos += 8;
33
+ }
34
+ if (n >= 1ull << 4) {
35
+ n >>= 4;
36
+ pos += 4;
37
+ }
38
+ if (n >= 1ull << 2) {
39
+ n >>= 2;
40
+ pos += 2;
41
+ }
42
+ if (n >= 1ull << 1) {
43
+ pos += 1;
44
+ }
45
+ return pos;
46
+ #endif
47
+ }
48
+
49
+ void util_sparse_array_init(util_sparse_array * arr, size_t elem_size, size_t node_size) {
50
+ memset(arr, 0, sizeof(*arr));
51
+ arr->elem_size = elem_size;
52
+ arr->node_size_log2 = util_logbase2_64(node_size);
53
+ assert(node_size >= 2 && node_size == (1ull << arr->node_size_log2));
54
+ }
55
+
56
+ static inline void * os_malloc_aligned(size_t size, size_t alignment) {
57
+ void * ptr;
58
+ alignment = (alignment + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
59
+ if (posix_memalign(&ptr, alignment, size) != 0) {
60
+ return NULL;
61
+ }
62
+ return ptr;
63
+ }
64
+
65
+ static inline void * _util_sparse_array_node_data(uintptr_t handle) {
66
+ return (void *) (handle & NODE_PTR_MASK);
67
+ }
68
+
69
+ static inline unsigned _util_sparse_array_node_level(uintptr_t handle) {
70
+ return handle & NODE_LEVEL_MASK;
71
+ }
72
+
73
+ static inline void _util_sparse_array_node_finish(util_sparse_array * arr, uintptr_t node) {
74
+ if (_util_sparse_array_node_level(node) > 0) {
75
+ uintptr_t * children = (uintptr_t *) _util_sparse_array_node_data(node);
76
+ size_t node_size = 1ull << arr->node_size_log2;
77
+ for (size_t i = 0; i < node_size; i++) {
78
+ if (children[i]) {
79
+ _util_sparse_array_node_finish(arr, children[i]);
80
+ }
81
+ }
82
+ }
83
+
84
+ os_free_aligned(_util_sparse_array_node_data(node));
85
+ }
86
+
87
+ static inline uintptr_t _util_sparse_array_node(void * data, unsigned level) {
88
+ assert(data != NULL);
89
+ assert(((uintptr_t) data & NODE_LEVEL_MASK) == 0);
90
+ assert((level & NODE_PTR_MASK) == 0);
91
+ return (uintptr_t) data | level;
92
+ }
93
+
94
+ inline uintptr_t _util_sparse_array_node_alloc(util_sparse_array * arr, unsigned level) {
95
+ size_t size;
96
+ if (level == 0) {
97
+ size = arr->elem_size << arr->node_size_log2;
98
+ } else {
99
+ size = sizeof(uintptr_t) << arr->node_size_log2;
100
+ }
101
+
102
+ void * data = os_malloc_aligned(size, NODE_ALLOC_ALIGN);
103
+ memset(data, 0, size);
104
+
105
+ return _util_sparse_array_node(data, level);
106
+ }
107
+
108
+ static inline uintptr_t _util_sparse_array_set_or_free_node(uintptr_t * node_ptr, uintptr_t cmp_node, uintptr_t node) {
109
+ uintptr_t prev_node = p_atomic_cmpxchg(node_ptr, cmp_node, node);
110
+
111
+ if (prev_node != cmp_node) {
112
+ /* We lost the race. Free this one and return the one that was already
113
+ * allocated.
114
+ */
115
+ os_free_aligned(_util_sparse_array_node_data(node));
116
+ return prev_node;
117
+ } else {
118
+ return node;
119
+ }
120
+ }
121
+
122
+ void * util_sparse_array_get(util_sparse_array * arr, uint64_t idx) {
123
+ const unsigned node_size_log2 = arr->node_size_log2;
124
+ uintptr_t root = p_atomic_read(&arr->root);
125
+ if (unlikely(!root)) {
126
+ unsigned root_level = 0;
127
+ uint64_t idx_iter = idx >> node_size_log2;
128
+ while (idx_iter) {
129
+ idx_iter >>= node_size_log2;
130
+ root_level++;
131
+ }
132
+ uintptr_t new_root = _util_sparse_array_node_alloc(arr, root_level);
133
+ root = _util_sparse_array_set_or_free_node(&arr->root, NULL_NODE, new_root);
134
+ }
135
+
136
+ while (1) {
137
+ unsigned root_level = _util_sparse_array_node_level(root);
138
+ uint64_t root_idx = idx >> (root_level * node_size_log2);
139
+ if (likely(root_idx < (1ull << node_size_log2))) {
140
+ break;
141
+ }
142
+
143
+ /* In this case, we have a root but its level is low enough that the
144
+ * requested index is out-of-bounds.
145
+ */
146
+ uintptr_t new_root = _util_sparse_array_node_alloc(arr, root_level + 1);
147
+
148
+ uintptr_t * new_root_children = (uintptr_t *) _util_sparse_array_node_data(new_root);
149
+ new_root_children[0] = root;
150
+
151
+ /* We only add one at a time instead of the whole tree because it's
152
+ * easier to ensure correctness of both the tree building and the
153
+ * clean-up path. Because we're only adding one node we never have to
154
+ * worry about trying to free multiple things without freeing the old
155
+ * things.
156
+ */
157
+ root = _util_sparse_array_set_or_free_node(&arr->root, root, new_root);
158
+ }
159
+
160
+ void * node_data = _util_sparse_array_node_data(root);
161
+ unsigned node_level = _util_sparse_array_node_level(root);
162
+ while (node_level > 0) {
163
+ uint64_t child_idx = (idx >> (node_level * node_size_log2)) & ((1ull << node_size_log2) - 1);
164
+
165
+ uintptr_t * children = (uintptr_t *) node_data;
166
+ uintptr_t child = p_atomic_read(&children[child_idx]);
167
+
168
+ if (unlikely(!child)) {
169
+ child = _util_sparse_array_node_alloc(arr, node_level - 1);
170
+ child = _util_sparse_array_set_or_free_node(&children[child_idx], NULL_NODE, child);
171
+ }
172
+
173
+ node_data = _util_sparse_array_node_data(child);
174
+ node_level = _util_sparse_array_node_level(child);
175
+ }
176
+
177
+ uint64_t elem_idx = idx & ((1ull << node_size_log2) - 1);
178
+ return (void *) ((char *) node_data + (elem_idx * arr->elem_size));
179
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu-utils.h ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <atomic>
4
+ #include <cassert>
5
+ #include <cerrno>
6
+ #include <cstdarg>
7
+ #include <cstddef>
8
+ #include <cstdint>
9
+ #include <cstdio>
10
+ #include <cstdlib>
11
+ #include <ctime>
12
+
13
+ #define unlikely(x) __builtin_expect(!!(x), 0)
14
+ #define likely(x) __builtin_expect(!!(x), 1)
15
+
16
+ #ifndef UNUSED
17
+ # define UNUSED(x) (void) (x)
18
+ #endif
19
+
20
+ /** Checks is a value is a power of two. Does not handle zero. */
21
+ #define IS_POT(v) (((v) & ((v) - 1)) == 0)
22
+
23
+ /** Checks is a value is a power of two. Zero handled. */
24
+ #define IS_POT_NONZERO(v) ((v) != 0 && IS_POT(v))
25
+
26
+ /** Align a value to a power of two */
27
+ #define ALIGN_POT(x, pot_align) (((x) + (pot_align) - 1) & ~((pot_align) - 1))
28
+
29
+ #define p_atomic_read(_v) __atomic_load_n((_v), __ATOMIC_ACQUIRE)
30
+
31
+ static inline bool util_is_power_of_two_nonzero64(uint64_t v) {
32
+ return IS_POT_NONZERO(v);
33
+ }
34
+
35
+ static inline uint64_t align64(uint64_t value, uint64_t alignment) {
36
+ assert(util_is_power_of_two_nonzero64(alignment));
37
+ return ALIGN_POT(value, alignment);
38
+ }
39
+
40
+ struct list_head {
41
+ list_head * prev;
42
+ list_head * next;
43
+ };
44
+
45
+ struct util_sparse_array {
46
+ size_t elem_size;
47
+ unsigned node_size_log2;
48
+
49
+ uintptr_t root;
50
+ };
51
+
52
+ void * util_sparse_array_get(util_sparse_array * arr, uint64_t idx);
53
+ void util_sparse_array_init(util_sparse_array * arr, size_t elem_size, size_t node_size);
54
+
55
+ inline void os_time_sleep(int64_t usecs) {
56
+ timespec time;
57
+ time.tv_sec = usecs / 1000000;
58
+ time.tv_nsec = (usecs % 1000000) * 1000;
59
+ while (clock_nanosleep(CLOCK_MONOTONIC, 0, &time, &time) == EINTR)
60
+ ;
61
+ }
62
+
63
+ struct timer_data {
64
+ long long start;
65
+ long long total;
66
+ long long count;
67
+ };
68
+
69
+ static inline void start_timer(timer_data * timer) {
70
+ timespec ts;
71
+ clock_gettime(CLOCK_MONOTONIC, &ts);
72
+ timer->start = (long long) ts.tv_sec * 1000000000LL + ts.tv_nsec;
73
+ }
74
+
75
+ // returns the duration in ns
76
+ static inline long long stop_timer(timer_data * timer) {
77
+ timespec ts;
78
+ clock_gettime(CLOCK_MONOTONIC, &ts);
79
+ long long timer_end = (long long) ts.tv_sec * 1000000000LL + ts.tv_nsec;
80
+
81
+ long long duration = (timer_end - timer->start);
82
+ timer->total += duration;
83
+ timer->count += 1;
84
+
85
+ return duration;
86
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.cpp ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "virtgpu.h"
2
+ #include "ggml-remoting.h"
3
+
4
+ #include <stdio.h>
5
+ #include <unistd.h>
6
+
7
+ #include <cassert>
8
+ #include <cerrno>
9
+ #include <cstdlib>
10
+
11
+ static virt_gpu_result_t virtgpu_open_device(virtgpu * gpu, const drmDevicePtr dev);
12
+ static virt_gpu_result_t virtgpu_open(virtgpu * gpu);
13
+
14
+ static virt_gpu_result_t virtgpu_init_capset(virtgpu * gpu);
15
+ static virt_gpu_result_t virtgpu_init_context(virtgpu * gpu);
16
+
17
+ static int virtgpu_ioctl_context_init(virtgpu * gpu, virgl_renderer_capset capset_id);
18
+ static int virtgpu_ioctl_get_caps(virtgpu * gpu,
19
+ virgl_renderer_capset id,
20
+ uint32_t version,
21
+ void * capset,
22
+ size_t capset_size);
23
+ static uint64_t virtgpu_ioctl_getparam(virtgpu * gpu, uint64_t param);
24
+ static void virtgpu_init_renderer_info(virtgpu * gpu);
25
+
26
+ static void log_call_duration(long long call_duration_ns, const char * name);
27
+
28
+ const uint64_t APIR_HANDSHAKE_MAX_WAIT_MS = 2 * 1000; // 2s
29
+ const uint64_t APIR_LOADLIBRARY_MAX_WAIT_MS = 60 * 1000; // 60s
30
+
31
+ static int virtgpu_handshake(virtgpu * gpu) {
32
+ apir_encoder * encoder;
33
+ apir_decoder * decoder;
34
+
35
+ encoder = remote_call_prepare(gpu, APIR_COMMAND_TYPE_HANDSHAKE, 0);
36
+ if (!encoder) {
37
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to prepare the remote call encoder", __func__);
38
+ return 1;
39
+ }
40
+
41
+ /* write handshake props */
42
+
43
+ uint32_t guest_major = APIR_PROTOCOL_MAJOR;
44
+ uint32_t guest_minor = APIR_PROTOCOL_MINOR;
45
+ apir_encode_uint32_t(encoder, &guest_major);
46
+ apir_encode_uint32_t(encoder, &guest_minor);
47
+
48
+ /* *** */
49
+
50
+ uint32_t ret_magic;
51
+ long long call_duration_ns;
52
+ ret_magic = remote_call(gpu, encoder, &decoder, APIR_HANDSHAKE_MAX_WAIT_MS, &call_duration_ns);
53
+ log_call_duration(call_duration_ns, "API Remoting handshake");
54
+
55
+ if (!decoder) {
56
+ GGML_ABORT(GGML_VIRTGPU
57
+ "%s: failed to initiate the communication with the virglrenderer library. "
58
+ "Most likely, the wrong virglrenderer library was loaded in the hypervisor.",
59
+ __func__);
60
+ return 1;
61
+ }
62
+
63
+ /* read handshake return values */
64
+
65
+ uint32_t host_major;
66
+ uint32_t host_minor;
67
+
68
+ if (ret_magic != APIR_HANDSHAKE_MAGIC) {
69
+ GGML_ABORT(GGML_VIRTGPU "%s: handshake with the virglrenderer failed (code=%d | %s)", __func__, ret_magic,
70
+ apir_backend_initialize_error(ret_magic));
71
+ } else {
72
+ apir_decode_uint32_t(decoder, &host_major);
73
+ apir_decode_uint32_t(decoder, &host_minor);
74
+ }
75
+
76
+ remote_call_finish(gpu, encoder, decoder);
77
+
78
+ if (ret_magic != APIR_HANDSHAKE_MAGIC) {
79
+ return 1;
80
+ }
81
+
82
+ GGML_LOG_INFO(GGML_VIRTGPU "%s: Guest is running with %u.%u\n", __func__, guest_major, guest_minor);
83
+ GGML_LOG_INFO(GGML_VIRTGPU "%s: Host is running with %u.%u\n", __func__, host_major, host_minor);
84
+
85
+ if (guest_major != host_major) {
86
+ GGML_LOG_ERROR(GGML_VIRTGPU "Host major (%d) and guest major (%d) version differ\n", host_major, guest_major);
87
+ } else if (guest_minor != host_minor) {
88
+ GGML_LOG_WARN(GGML_VIRTGPU "Host minor (%d) and guest minor (%d) version differ\n", host_minor, guest_minor);
89
+ }
90
+
91
+ return 0;
92
+ }
93
+
94
+ static ApirLoadLibraryReturnCode virtgpu_load_library(virtgpu * gpu) {
95
+ apir_encoder * encoder;
96
+ apir_decoder * decoder;
97
+ ApirLoadLibraryReturnCode ret;
98
+
99
+ encoder = remote_call_prepare(gpu, APIR_COMMAND_TYPE_LOADLIBRARY, 0);
100
+ if (!encoder) {
101
+ GGML_ABORT(GGML_VIRTGPU "%s: hypercall error: failed to prepare the API Remoting command encoder", __func__);
102
+ return APIR_LOAD_LIBRARY_HYPERCALL_INITIALIZATION_ERROR;
103
+ }
104
+
105
+ long long call_duration_ns;
106
+
107
+ ret = (ApirLoadLibraryReturnCode) remote_call(gpu, encoder, &decoder, APIR_LOADLIBRARY_MAX_WAIT_MS,
108
+ &call_duration_ns);
109
+ log_call_duration(call_duration_ns, "API Remoting LoadLibrary");
110
+
111
+ if (!decoder) {
112
+ GGML_ABORT(GGML_VIRTGPU "%s: hypercall error: failed to trigger the API Remoting hypercall.\n", __func__);
113
+ return APIR_LOAD_LIBRARY_HYPERCALL_INITIALIZATION_ERROR;
114
+ }
115
+
116
+ remote_call_finish(gpu, encoder, decoder);
117
+
118
+ if (ret == APIR_LOAD_LIBRARY_SUCCESS) {
119
+ GGML_LOG_INFO(GGML_VIRTGPU "The API Remoting backend was successfully loaded and initialized\n");
120
+
121
+ return ret;
122
+ }
123
+
124
+ // something wrong happened, find out what.
125
+ if (ret < APIR_LOAD_LIBRARY_INIT_BASE_INDEX) {
126
+ if (ret == APIR_LOAD_LIBRARY_ENV_VAR_MISSING) {
127
+ GGML_ABORT(GGML_VIRTGPU
128
+ "%s: virglrenderer could not open the API Remoting backend library, "
129
+ "some environment variables are missing. "
130
+ "Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
131
+ __func__, apir_load_library_error(ret));
132
+ } else if (ret == APIR_LOAD_LIBRARY_CANNOT_OPEN) {
133
+ GGML_ABORT(GGML_VIRTGPU
134
+ "%s: virglrenderer could not open the API Remoting backend library. "
135
+ "Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
136
+ __func__, apir_load_library_error(ret));
137
+ } else if (ret == APIR_LOAD_LIBRARY_ENV_VAR_MISSING) {
138
+ GGML_ABORT(GGML_VIRTGPU
139
+ "%s: could not load the backend library, some symbols are missing. "
140
+ "Make sure virglrenderer is correctly configured by the hypervisor. (%s) ",
141
+ __func__, apir_load_library_error(ret));
142
+ } else {
143
+ GGML_ABORT(GGML_VIRTGPU "%s: virglrenderer could not load the API Remoting backend library. (%s - code %d)",
144
+ __func__, apir_load_library_error(ret), ret);
145
+ }
146
+ return ret;
147
+ }
148
+
149
+ GGML_LOG_INFO(GGML_VIRTGPU "%s: virglrenderer successfully loaded the API Remoting backend library.\n", __func__);
150
+
151
+ ApirLoadLibraryReturnCode apir_ret = (ApirLoadLibraryReturnCode) (ret - APIR_LOAD_LIBRARY_INIT_BASE_INDEX);
152
+
153
+ if (apir_ret == APIR_LOAD_LIBRARY_CANNOT_OPEN) {
154
+ GGML_ABORT(GGML_VIRTGPU
155
+ "%s: the API Remoting backend library couldn't load the GGML backend library. "
156
+ "Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
157
+ __func__, apir_load_library_error(apir_ret));
158
+ } else if (apir_ret == APIR_LOAD_LIBRARY_SYMBOL_MISSING) {
159
+ GGML_ABORT(
160
+ GGML_VIRTGPU
161
+ "%s: the API Remoting backend library couldn't load the GGML backend library, some symbols are missing. "
162
+ "Make sure virglrenderer is correctly configured by the hypervisor. (%s)",
163
+ __func__, apir_load_library_error(apir_ret));
164
+ } else if (apir_ret < APIR_LOAD_LIBRARY_INIT_BASE_INDEX) {
165
+ GGML_ABORT(GGML_VIRTGPU
166
+ "%s: the API Remoting backend library couldn't load the GGML backend library: apir code=%d | %s)",
167
+ __func__, apir_ret, apir_load_library_error(apir_ret));
168
+ } else {
169
+ uint32_t lib_ret = apir_ret - APIR_LOAD_LIBRARY_INIT_BASE_INDEX;
170
+ GGML_ABORT(GGML_VIRTGPU
171
+ "%s: the API Remoting backend library failed to initialize its backend library: apir code=%d)",
172
+ __func__, lib_ret);
173
+ }
174
+ return ret;
175
+ }
176
+
177
+ virtgpu * create_virtgpu() {
178
+ virtgpu * gpu = new virtgpu();
179
+
180
+ gpu->use_apir_capset = getenv("GGML_REMOTING_USE_APIR_CAPSET") != nullptr;
181
+ util_sparse_array_init(&gpu->shmem_array, sizeof(virtgpu_shmem), 1024);
182
+
183
+ // Initialize mutex to protect shared data_shmem buffer
184
+ if (mtx_init(&gpu->data_shmem_mutex, mtx_plain) != thrd_success) {
185
+ delete gpu;
186
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to initialize data_shmem mutex", __func__);
187
+ return NULL;
188
+ }
189
+
190
+ if (virtgpu_open(gpu) != APIR_SUCCESS) {
191
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to open the virtgpu device\n", __func__);
192
+ return NULL;
193
+ }
194
+
195
+ if (virtgpu_init_capset(gpu) != APIR_SUCCESS) {
196
+ if (gpu->use_apir_capset) {
197
+ GGML_ABORT(GGML_VIRTGPU
198
+ "%s: failed to initialize the virtgpu APIR capset. Make sure that the virglrenderer library "
199
+ "supports it.",
200
+ __func__);
201
+ } else {
202
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to initialize the virtgpu Venus capset", __func__);
203
+ }
204
+ return NULL;
205
+ }
206
+
207
+ if (virtgpu_init_context(gpu) != APIR_SUCCESS) {
208
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to initialize the GPU context", __func__);
209
+ return NULL;
210
+ }
211
+
212
+ if (virtgpu_shmem_create(gpu, SHMEM_REPLY_SIZE, &gpu->reply_shmem)) {
213
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to create the shared reply memory pages", __func__);
214
+ return NULL;
215
+ }
216
+
217
+ if (virtgpu_shmem_create(gpu, SHMEM_DATA_SIZE, &gpu->data_shmem)) {
218
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to create the shared data memory pages", __func__);
219
+ return NULL;
220
+ }
221
+
222
+ if (virtgpu_handshake(gpu)) {
223
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to handshake with the virglrenderer library", __func__);
224
+ return NULL;
225
+ }
226
+
227
+ if (virtgpu_load_library(gpu) != APIR_LOAD_LIBRARY_SUCCESS) {
228
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to load the backend library", __func__);
229
+ return NULL;
230
+ }
231
+
232
+ return gpu;
233
+ }
234
+
235
+ static virt_gpu_result_t virtgpu_open(virtgpu * gpu) {
236
+ drmDevicePtr devs[8];
237
+ int count = drmGetDevices2(0, devs, ARRAY_SIZE(devs));
238
+ if (count < 0) {
239
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to enumerate DRM devices\n", __func__);
240
+ return APIR_ERROR_INITIALIZATION_FAILED;
241
+ }
242
+
243
+ virt_gpu_result_t result = APIR_ERROR_INITIALIZATION_FAILED;
244
+ for (int i = 0; i < count; i++) {
245
+ result = virtgpu_open_device(gpu, devs[i]);
246
+ if (result == APIR_SUCCESS) {
247
+ break;
248
+ }
249
+ }
250
+
251
+ drmFreeDevices(devs, count);
252
+
253
+ return result;
254
+ }
255
+
256
+ static virt_gpu_result_t virtgpu_open_device(virtgpu * gpu, const drmDevicePtr dev) {
257
+ const char * node_path = dev->nodes[DRM_NODE_RENDER];
258
+
259
+ int fd = open(node_path, O_RDWR | O_CLOEXEC);
260
+ if (fd < 0) {
261
+ GGML_ABORT(GGML_VIRTGPU "%s: failed to open %s", __func__, node_path);
262
+ return APIR_ERROR_INITIALIZATION_FAILED;
263
+ }
264
+
265
+ drmVersionPtr version = drmGetVersion(fd);
266
+ if (!version || strcmp(version->name, "virtio_gpu") || version->version_major != 0) {
267
+ if (version) {
268
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: unknown DRM driver %s version %d\n", __func__, version->name,
269
+ version->version_major);
270
+ } else {
271
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to get DRM driver version\n", __func__);
272
+ }
273
+
274
+ if (version) {
275
+ drmFreeVersion(version);
276
+ }
277
+ close(fd);
278
+ return APIR_ERROR_INITIALIZATION_FAILED;
279
+ }
280
+
281
+ gpu->fd = fd;
282
+
283
+ drmFreeVersion(version);
284
+
285
+ GGML_LOG_INFO(GGML_VIRTGPU "using DRM device %s\n", node_path);
286
+
287
+ return APIR_SUCCESS;
288
+ }
289
+
290
+ static virt_gpu_result_t virtgpu_init_context(virtgpu * gpu) {
291
+ assert(!gpu->capset.version);
292
+ const int ret = virtgpu_ioctl_context_init(gpu, gpu->capset.id);
293
+ if (ret) {
294
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to initialize context: %s\n", __func__, strerror(errno));
295
+ return APIR_ERROR_INITIALIZATION_FAILED;
296
+ }
297
+
298
+ return APIR_SUCCESS;
299
+ }
300
+
301
+ static virt_gpu_result_t virtgpu_init_capset(virtgpu * gpu) {
302
+ if (gpu->use_apir_capset) {
303
+ GGML_LOG_INFO(GGML_VIRTGPU "Using the APIR capset\n");
304
+ gpu->capset.id = VIRTGPU_DRM_CAPSET_APIR;
305
+ } else {
306
+ GGML_LOG_INFO(GGML_VIRTGPU "Using the Venus capset\n");
307
+ gpu->capset.id = VIRTGPU_DRM_CAPSET_VENUS;
308
+ }
309
+ gpu->capset.version = 0;
310
+
311
+ int ret =
312
+ virtgpu_ioctl_get_caps(gpu, gpu->capset.id, gpu->capset.version, &gpu->capset.data, sizeof(gpu->capset.data));
313
+
314
+ if (ret) {
315
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: failed to get APIR v%d capset: %s\n", __func__, gpu->capset.version,
316
+ strerror(errno));
317
+ return APIR_ERROR_INITIALIZATION_FAILED;
318
+ }
319
+
320
+ assert(gpu->capset.data.supports_blob_resources);
321
+
322
+ return APIR_SUCCESS;
323
+ }
324
+
325
+ static int virtgpu_ioctl_context_init(virtgpu * gpu, virgl_renderer_capset capset_id) {
326
+ drm_virtgpu_context_set_param ctx_set_params[3] = {
327
+ {
328
+ .param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID,
329
+ .value = capset_id,
330
+ },
331
+ {
332
+ .param = VIRTGPU_CONTEXT_PARAM_NUM_RINGS,
333
+ .value = 1,
334
+ },
335
+ {
336
+ .param = VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK,
337
+ .value = 0, /* don't generate drm_events on fence signaling */
338
+ },
339
+ };
340
+
341
+ drm_virtgpu_context_init args = {
342
+ .num_params = ARRAY_SIZE(ctx_set_params),
343
+ .pad = 0,
344
+ .ctx_set_params = (uintptr_t) &ctx_set_params,
345
+ };
346
+
347
+ return virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_CONTEXT_INIT, &args);
348
+ }
349
+
350
+ static int virtgpu_ioctl_get_caps(virtgpu * gpu,
351
+ virgl_renderer_capset id,
352
+ uint32_t version,
353
+ void * capset,
354
+ size_t capset_size) {
355
+ drm_virtgpu_get_caps args = {
356
+ .cap_set_id = id,
357
+ .cap_set_ver = version,
358
+ .addr = (uintptr_t) capset,
359
+ .size = (__u32) capset_size,
360
+ .pad = 0,
361
+ };
362
+
363
+ return virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_GET_CAPS, &args);
364
+ }
365
+
366
+ static uint64_t virtgpu_ioctl_getparam(virtgpu * gpu, uint64_t param) {
367
+ /* val must be zeroed because kernel only writes the lower 32 bits */
368
+ uint64_t val = 0;
369
+ drm_virtgpu_getparam args = {
370
+ .param = param,
371
+ .value = (uintptr_t) &val,
372
+ };
373
+
374
+ const int ret = virtgpu_ioctl(gpu, DRM_IOCTL_VIRTGPU_GETPARAM, &args);
375
+ return ret ? 0 : val;
376
+ }
377
+
378
+ apir_encoder * remote_call_prepare(virtgpu * gpu, ApirCommandType apir_cmd_type, int32_t cmd_flags) {
379
+ /*
380
+ * Prepare the command encoder and its buffer
381
+ */
382
+
383
+ thread_local char encoder_buffer[4096];
384
+
385
+ thread_local apir_encoder enc;
386
+ enc = {
387
+ .cur = encoder_buffer,
388
+ .start = encoder_buffer,
389
+ .end = encoder_buffer + sizeof(encoder_buffer),
390
+ .fatal = false,
391
+ };
392
+
393
+ /*
394
+ * Fill the command encoder with the common args:
395
+ * - cmd_type (int32_t)
396
+ * - cmd_flags (int32_t)
397
+ * - reply res id (uint32_t)
398
+ */
399
+
400
+ int32_t cmd_type = apir_cmd_type;
401
+
402
+ // for testing during the hypervisor transition
403
+ if (!gpu->use_apir_capset) {
404
+ cmd_type += VENUS_COMMAND_TYPE_LENGTH;
405
+ }
406
+ apir_encode_int32_t(&enc, &cmd_type);
407
+ apir_encode_int32_t(&enc, &cmd_flags);
408
+
409
+ uint32_t reply_res_id = gpu->reply_shmem.res_id;
410
+ apir_encode_uint32_t(&enc, &reply_res_id);
411
+
412
+ return &enc;
413
+ }
414
+
415
+ void remote_call_finish(virtgpu * gpu, apir_encoder * enc, apir_decoder * dec) {
416
+ UNUSED(gpu);
417
+
418
+ if (!enc) {
419
+ GGML_ABORT(GGML_VIRTGPU "%s: Invalid (null) encoder", __func__);
420
+ }
421
+
422
+ if (!dec) {
423
+ GGML_ABORT(GGML_VIRTGPU "%s: Invalid (null) decoder", __func__);
424
+ }
425
+
426
+ if (apir_encoder_get_fatal(enc)) {
427
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: Failed to encode the output parameters.", __func__);
428
+ }
429
+
430
+ if (apir_decoder_get_fatal(dec)) {
431
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: Failed to decode the input parameters.", __func__);
432
+ }
433
+ }
434
+
435
+ uint32_t remote_call(virtgpu * gpu,
436
+ apir_encoder * encoder,
437
+ apir_decoder ** decoder,
438
+ float max_wait_ms,
439
+ long long * call_duration_ns) {
440
+ /*
441
+ * Prepare the reply notification pointer
442
+ */
443
+
444
+ volatile std::atomic_uint * atomic_reply_notif = (volatile std::atomic_uint *) gpu->reply_shmem.mmap_ptr;
445
+ *atomic_reply_notif = 0;
446
+
447
+ /*
448
+ * Trigger the execbuf ioctl
449
+ */
450
+
451
+ drm_virtgpu_execbuffer args = {
452
+ .flags = VIRTGPU_EXECBUF_RING_IDX,
453
+ .size = (uint32_t) (encoder->cur - encoder->start),
454
+ .command = (uintptr_t) encoder->start,
455
+
456
+ .bo_handles = 0,
457
+ .num_bo_handles = 0,
458
+
459
+ .fence_fd = 0,
460
+ .ring_idx = 0,
461
+ .syncobj_stride = 0,
462
+ .num_in_syncobjs = 0,
463
+ .num_out_syncobjs = 0,
464
+ .in_syncobjs = 0,
465
+ .out_syncobjs = 0,
466
+ };
467
+
468
+ *decoder = NULL;
469
+
470
+ int ret = drmIoctl(gpu->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &args);
471
+
472
+ if (ret != 0) {
473
+ GGML_ABORT(GGML_VIRTGPU "%s: the virtgpu EXECBUFFER ioctl failed (%d)", __func__, ret);
474
+ }
475
+
476
+ /*
477
+ * Wait for the response notification
478
+ */
479
+ timer_data wait_host_reply_timer = { 0, 0, 0 };
480
+
481
+ start_timer(&wait_host_reply_timer);
482
+
483
+ timespec ts_start, ts_end;
484
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
485
+ long long start_time = (long long) ts_start.tv_sec * 1000000000LL + ts_start.tv_nsec;
486
+
487
+ bool timedout = false;
488
+ uint32_t notif_value = 0;
489
+ while (true) {
490
+ notif_value = std::atomic_load_explicit(atomic_reply_notif, std::memory_order_acquire);
491
+
492
+ if (notif_value != 0) {
493
+ break;
494
+ }
495
+
496
+ int64_t base_sleep_us = 15;
497
+
498
+ os_time_sleep(base_sleep_us);
499
+
500
+ if (max_wait_ms) {
501
+ clock_gettime(CLOCK_MONOTONIC, &ts_end);
502
+ long long end_time = (long long) ts_end.tv_sec * 1000000000LL + ts_end.tv_nsec;
503
+ float duration_ms = (end_time - start_time) / 1000000;
504
+
505
+ if (duration_ms > max_wait_ms) {
506
+ timedout = true;
507
+ break;
508
+ }
509
+ }
510
+ }
511
+
512
+ if (call_duration_ns) {
513
+ *call_duration_ns = stop_timer(&wait_host_reply_timer);
514
+ }
515
+
516
+ if (max_wait_ms && timedout) {
517
+ GGML_LOG_ERROR(GGML_VIRTGPU "%s: timed out waiting for the host answer...\n", __func__);
518
+ return APIR_FORWARD_TIMEOUT;
519
+ }
520
+
521
+ /*
522
+ * Prepare the decoder
523
+ */
524
+ static apir_decoder response_dec;
525
+ response_dec.cur = (char *) gpu->reply_shmem.mmap_ptr + sizeof(*atomic_reply_notif);
526
+ response_dec.end = (char *) gpu->reply_shmem.mmap_ptr + gpu->reply_shmem.mmap_size;
527
+ *decoder = &response_dec;
528
+
529
+ // extract the actual return value from the notif flag
530
+ uint32_t returned_value = notif_value - 1;
531
+ return returned_value;
532
+ }
533
+
534
+ static void log_call_duration(long long call_duration_ns, const char * name) {
535
+ double call_duration_ms = (double) call_duration_ns / 1e6; // 1 millisecond = 1e6 nanoseconds
536
+ double call_duration_s = (double) call_duration_ns / 1e9; // 1 second = 1e9 nanoseconds
537
+
538
+ if (call_duration_s > 1) {
539
+ GGML_LOG_INFO(GGML_VIRTGPU "waited %.2fs for the %s host reply...\n", call_duration_s, name);
540
+ } else if (call_duration_ms > 1) {
541
+ GGML_LOG_INFO(GGML_VIRTGPU "waited %.2fms for the %s host reply...\n", call_duration_ms, name);
542
+ } else {
543
+ GGML_LOG_INFO(GGML_VIRTGPU "waited %lldns for the %s host reply...\n", call_duration_ns, name);
544
+ }
545
+ }
backend/llama.cpp/ggml/src/ggml-virtgpu/virtgpu.h ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ // clang-format off
4
+ #include "virtgpu-utils.h"
5
+ #include "virtgpu-shm.h"
6
+ #include "virtgpu-apir.h"
7
+
8
+ #include "backend/shared/api_remoting.h"
9
+ #include "backend/shared/apir_cs.h"
10
+
11
+ #include <fcntl.h>
12
+ #include <stdbool.h>
13
+ #include <stdio.h>
14
+ #include <sys/stat.h>
15
+ #include <sys/sysmacros.h>
16
+ #include <threads.h>
17
+ #include <xf86drm.h>
18
+
19
+ #include <cstring>
20
+
21
+ #define VIRGL_RENDERER_UNSTABLE_APIS 1
22
+ #include "apir_hw.h"
23
+ #include <drm/virtgpu_drm.h>
24
+ #include "venus_hw.h"
25
+ // clang-format on
26
+
27
+ #ifndef VIRTGPU_DRM_CAPSET_APIR
28
+ // Will be defined include/drm/virtgpu_drm.h when
29
+ // https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1590/diffs
30
+ // is merged
31
+ # define VIRTGPU_DRM_CAPSET_APIR 10
32
+ #endif
33
+
34
+ // Mesa/Virlgrenderer Venus internal. Only necessary during the
35
+ // Venus->APIR transition in Virglrenderer
36
+ #define VENUS_COMMAND_TYPE_LENGTH 331
37
+
38
+ #ifndef VIRTGPU_DRM_CAPSET_VENUS // only available with Linux >= v6.16
39
+ # define VIRTGPU_DRM_CAPSET_VENUS 4
40
+ #endif
41
+
42
+ typedef uint32_t virgl_renderer_capset;
43
+
44
+ /* from src/virtio/vulkan/vn_renderer_virtgpu.c */
45
+ #define VIRTGPU_PCI_VENDOR_ID 0x1af4
46
+ #define VIRTGPU_PCI_DEVICE_ID 0x1050
47
+ #define VIRTGPU_BLOB_MEM_GUEST_VRAM 0x0004
48
+ #define VIRTGPU_PARAM_GUEST_VRAM 9
49
+
50
+ #define SHMEM_DATA_SIZE 0x1830000 // 24MiB
51
+ #define SHMEM_REPLY_SIZE 0x4000
52
+
53
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
54
+
55
+ enum virt_gpu_result_t {
56
+ APIR_SUCCESS = 0,
57
+ APIR_ERROR_INITIALIZATION_FAILED = -1,
58
+ };
59
+
60
+ #define PRINTFLIKE(f, a) __attribute__((format(__printf__, f, a)))
61
+
62
+ struct virtgpu {
63
+ bool use_apir_capset;
64
+
65
+ int fd;
66
+
67
+ struct {
68
+ virgl_renderer_capset id;
69
+ uint32_t version;
70
+ virgl_renderer_capset_apir data;
71
+ } capset;
72
+
73
+ util_sparse_array shmem_array;
74
+
75
+ /* APIR communication pages */
76
+ virtgpu_shmem reply_shmem;
77
+ virtgpu_shmem data_shmem;
78
+
79
+ /* Mutex to protect shared data_shmem buffer from concurrent access */
80
+ mtx_t data_shmem_mutex;
81
+
82
+ /* Cached device information to prevent memory leaks and race conditions */
83
+ struct {
84
+ char * description;
85
+ char * name;
86
+ int32_t device_count;
87
+ uint32_t type;
88
+ size_t memory_free;
89
+ size_t memory_total;
90
+ } cached_device_info;
91
+
92
+ /* Cached buffer type information to prevent memory leaks and race conditions */
93
+ struct {
94
+ apir_buffer_type_host_handle_t host_handle;
95
+ char * name;
96
+ size_t alignment;
97
+ size_t max_size;
98
+ } cached_buffer_type;
99
+ };
100
+
101
+ static inline int virtgpu_ioctl(virtgpu * gpu, unsigned long request, void * args) {
102
+ return drmIoctl(gpu->fd, request, args);
103
+ }
104
+
105
+ virtgpu * create_virtgpu();
106
+
107
+ apir_encoder * remote_call_prepare(virtgpu * gpu, ApirCommandType apir_cmd_type, int32_t cmd_flags);
108
+
109
+ uint32_t remote_call(virtgpu * gpu,
110
+ apir_encoder * enc,
111
+ apir_decoder ** dec,
112
+ float max_wait_ms,
113
+ long long * call_duration_ns);
114
+
115
+ void remote_call_finish(virtgpu * gpu, apir_encoder * enc, apir_decoder * dec);
backend/llama.cpp/ggml/src/ggml-vulkan/CMakeLists.txt ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required(VERSION 3.19)
2
+ cmake_policy(SET CMP0114 NEW)
3
+ cmake_policy(SET CMP0116 NEW)
4
+ if (POLICY CMP0147)
5
+ # Parallel build custom build steps
6
+ cmake_policy(SET CMP0147 NEW)
7
+ endif()
8
+
9
+ find_package(Vulkan COMPONENTS glslc REQUIRED)
10
+
11
+ if (DEFINED ENV{VULKAN_SDK})
12
+ list(APPEND CMAKE_PREFIX_PATH "$ENV{VULKAN_SDK}")
13
+ endif()
14
+ find_package(SPIRV-Headers CONFIG REQUIRED)
15
+
16
+ if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
17
+ # Parallel build object files
18
+ add_definitions(/MP)
19
+ endif()
20
+
21
+ function(detect_host_compiler)
22
+ if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
23
+ find_program(HOST_C_COMPILER NAMES cl gcc clang NO_CMAKE_FIND_ROOT_PATH)
24
+ find_program(HOST_CXX_COMPILER NAMES cl g++ clang++ NO_CMAKE_FIND_ROOT_PATH)
25
+ else()
26
+ find_program(HOST_C_COMPILER NAMES gcc clang NO_CMAKE_FIND_ROOT_PATH)
27
+ find_program(HOST_CXX_COMPILER NAMES g++ clang++ NO_CMAKE_FIND_ROOT_PATH)
28
+ endif()
29
+ set(HOST_C_COMPILER "${HOST_C_COMPILER}" PARENT_SCOPE)
30
+ set(HOST_CXX_COMPILER "${HOST_CXX_COMPILER}" PARENT_SCOPE)
31
+ endfunction()
32
+
33
+ # Function to test shader extension support
34
+ # Parameters:
35
+ # EXTENSION_NAME - Name of the extension to test (e.g., "GL_EXT_integer_dot_product")
36
+ # TEST_SHADER_FILE - Path to the test shader file
37
+ # RESULT_VARIABLE - Name of the variable to set (ON/OFF) based on test result
38
+ function(test_shader_extension_support EXTENSION_NAME TEST_SHADER_FILE RESULT_VARIABLE)
39
+ execute_process(
40
+ COMMAND ${Vulkan_GLSLC_EXECUTABLE} -o - -fshader-stage=compute --target-env=vulkan1.3 "${TEST_SHADER_FILE}"
41
+ OUTPUT_VARIABLE glslc_output
42
+ ERROR_VARIABLE glslc_error
43
+ )
44
+
45
+ if (${glslc_error} MATCHES ".*extension not supported: ${EXTENSION_NAME}.*")
46
+ message(STATUS "${EXTENSION_NAME} not supported by glslc")
47
+ set(${RESULT_VARIABLE} OFF PARENT_SCOPE)
48
+ else()
49
+ message(STATUS "${EXTENSION_NAME} supported by glslc")
50
+ set(${RESULT_VARIABLE} ON PARENT_SCOPE)
51
+ add_compile_definitions(${RESULT_VARIABLE})
52
+
53
+ # Ensure the extension support is forwarded to vulkan-shaders-gen
54
+ list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -D${RESULT_VARIABLE}=ON)
55
+ set(VULKAN_SHADER_GEN_CMAKE_ARGS "${VULKAN_SHADER_GEN_CMAKE_ARGS}" PARENT_SCOPE)
56
+ endif()
57
+ endfunction()
58
+
59
+ if (Vulkan_FOUND)
60
+ message(STATUS "Vulkan found")
61
+
62
+ ggml_add_backend_library(ggml-vulkan
63
+ ggml-vulkan.cpp
64
+ ../../include/ggml-vulkan.h
65
+ )
66
+
67
+ set(VULKAN_SHADER_GEN_CMAKE_ARGS "")
68
+
69
+ # Test all shader extensions
70
+ test_shader_extension_support(
71
+ "GL_KHR_cooperative_matrix"
72
+ "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/coopmat.comp"
73
+ "GGML_VULKAN_COOPMAT_GLSLC_SUPPORT"
74
+ )
75
+
76
+ test_shader_extension_support(
77
+ "GL_NV_cooperative_matrix2"
78
+ "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/coopmat2.comp"
79
+ "GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT"
80
+ )
81
+
82
+ test_shader_extension_support(
83
+ "GL_NV_cooperative_matrix_decode_vector"
84
+ "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/coopmat2_decode_vector.comp"
85
+ "GGML_VULKAN_COOPMAT2_DECODE_VECTOR_GLSLC_SUPPORT"
86
+ )
87
+
88
+ test_shader_extension_support(
89
+ "GL_EXT_integer_dot_product"
90
+ "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/integer_dot.comp"
91
+ "GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT"
92
+ )
93
+
94
+ test_shader_extension_support(
95
+ "GL_EXT_bfloat16"
96
+ "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/feature-tests/bfloat16.comp"
97
+ "GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT"
98
+ )
99
+
100
+ target_link_libraries(ggml-vulkan PRIVATE Vulkan::Vulkan)
101
+ target_include_directories(ggml-vulkan PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
102
+
103
+ # Workaround to the "can't dereference invalidated vector iterator" bug in clang-cl debug build
104
+ # Possibly relevant: https://stackoverflow.com/questions/74748276/visual-studio-no-displays-the-correct-length-of-stdvector
105
+ if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
106
+ add_compile_definitions(_ITERATOR_DEBUG_LEVEL=0)
107
+ endif()
108
+
109
+ if (GGML_VULKAN_CHECK_RESULTS)
110
+ add_compile_definitions(GGML_VULKAN_CHECK_RESULTS)
111
+ # the result-checking path computes a CPU reference graph via
112
+ # ggml_graph_compute_with_ctx(), which is defined in ggml-cpu
113
+ target_link_libraries(ggml-vulkan PRIVATE ggml-cpu)
114
+ endif()
115
+
116
+ if (GGML_VULKAN_DEBUG)
117
+ add_compile_definitions(GGML_VULKAN_DEBUG)
118
+ endif()
119
+
120
+ if (GGML_VULKAN_MEMORY_DEBUG)
121
+ add_compile_definitions(GGML_VULKAN_MEMORY_DEBUG)
122
+ endif()
123
+
124
+ if (GGML_VULKAN_SHADER_DEBUG_INFO)
125
+ add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO)
126
+ list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DGGML_VULKAN_SHADER_DEBUG_INFO=ON)
127
+ endif()
128
+
129
+ if (GGML_VULKAN_VALIDATE)
130
+ add_compile_definitions(GGML_VULKAN_VALIDATE)
131
+ endif()
132
+
133
+ if (GGML_VULKAN_RUN_TESTS)
134
+ add_compile_definitions(GGML_VULKAN_RUN_TESTS)
135
+ # the test path also calls ggml_graph_compute_with_ctx() (ggml-cpu)
136
+ target_link_libraries(ggml-vulkan PRIVATE ggml-cpu)
137
+ endif()
138
+
139
+ # Set up toolchain for host compilation whether cross-compiling or not
140
+ if (CMAKE_CROSSCOMPILING)
141
+ if (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN)
142
+ set(HOST_CMAKE_TOOLCHAIN_FILE ${GGML_VULKAN_SHADERS_GEN_TOOLCHAIN})
143
+ else()
144
+ detect_host_compiler()
145
+ if (NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER)
146
+ message(FATAL_ERROR "Host compiler not found")
147
+ else()
148
+ message(STATUS "Host compiler: ${HOST_C_COMPILER} ${HOST_CXX_COMPILER}")
149
+ endif()
150
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/host-toolchain.cmake.in ${CMAKE_BINARY_DIR}/host-toolchain.cmake @ONLY)
151
+ set(HOST_CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/host-toolchain.cmake)
152
+ endif()
153
+ else()
154
+ # For non-cross-compiling, use empty toolchain (use host compiler)
155
+ set(HOST_CMAKE_TOOLCHAIN_FILE "")
156
+ endif()
157
+
158
+ include(ExternalProject)
159
+
160
+ if (CMAKE_CROSSCOMPILING)
161
+ list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${HOST_CMAKE_TOOLCHAIN_FILE})
162
+ message(STATUS "vulkan-shaders-gen toolchain file: ${HOST_CMAKE_TOOLCHAIN_FILE}")
163
+ endif()
164
+
165
+ ExternalProject_Add(
166
+ vulkan-shaders-gen
167
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders
168
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/$<CONFIG>
169
+ -DCMAKE_INSTALL_BINDIR=.
170
+ -DCMAKE_BUILD_TYPE=$<CONFIG>
171
+ ${VULKAN_SHADER_GEN_CMAKE_ARGS}
172
+
173
+ BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
174
+ BUILD_ALWAYS TRUE
175
+
176
+ # NOTE: When DESTDIR is set using Makefile generators and
177
+ # "make install" triggers the build step, vulkan-shaders-gen
178
+ # would be installed into the DESTDIR prefix, so it is unset
179
+ # to ensure that does not happen.
180
+
181
+ INSTALL_COMMAND ${CMAKE_COMMAND} -E env --unset=DESTDIR
182
+ ${CMAKE_COMMAND} --install . --config $<CONFIG>
183
+ )
184
+
185
+ set (_ggml_vk_host_suffix $<IF:$<STREQUAL:${CMAKE_HOST_SYSTEM_NAME},Windows>,.exe,>)
186
+ set (_ggml_vk_genshaders_dir "${CMAKE_BINARY_DIR}/$<CONFIG>")
187
+ set (_ggml_vk_genshaders_cmd "${_ggml_vk_genshaders_dir}/vulkan-shaders-gen${_ggml_vk_host_suffix}")
188
+ set (_ggml_vk_header "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp")
189
+ set (_ggml_vk_input_dir "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders")
190
+ set (_ggml_vk_output_dir "${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv")
191
+
192
+ file(GLOB _ggml_vk_shader_files CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.comp")
193
+
194
+ # Because external projects do not provide source-level tracking,
195
+ # the vulkan-shaders-gen sources need to be explicitly added to
196
+ # ensure that changes will cascade into shader re-generation.
197
+
198
+ file(GLOB _ggml_vk_shaders_gen_sources
199
+ CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.cpp"
200
+ "${_ggml_vk_input_dir}/*.h")
201
+
202
+ add_custom_command(
203
+ OUTPUT ${_ggml_vk_header}
204
+ COMMAND ${_ggml_vk_genshaders_cmd}
205
+ --output-dir ${_ggml_vk_output_dir}
206
+ --target-hpp ${_ggml_vk_header}
207
+ DEPENDS ${_ggml_vk_shaders_gen_sources}
208
+ vulkan-shaders-gen
209
+ COMMENT "Generate vulkan shaders header"
210
+ )
211
+ target_sources(ggml-vulkan PRIVATE ${_ggml_vk_header})
212
+
213
+ foreach (file_full ${_ggml_vk_shader_files})
214
+ get_filename_component(file ${file_full} NAME)
215
+ set (_ggml_vk_target_cpp "${CMAKE_CURRENT_BINARY_DIR}/${file}.cpp")
216
+
217
+ add_custom_command(
218
+ OUTPUT ${_ggml_vk_target_cpp}
219
+ DEPFILE ${_ggml_vk_target_cpp}.d
220
+ COMMAND ${_ggml_vk_genshaders_cmd}
221
+ --glslc ${Vulkan_GLSLC_EXECUTABLE}
222
+ --source ${file_full}
223
+ --output-dir ${_ggml_vk_output_dir}
224
+ --target-hpp ${_ggml_vk_header}
225
+ --target-cpp ${_ggml_vk_target_cpp}
226
+ DEPENDS ${file_full}
227
+ ${_ggml_vk_shaders_gen_sources}
228
+ vulkan-shaders-gen
229
+ COMMENT "Generate vulkan shaders for ${file}"
230
+ )
231
+ target_sources(ggml-vulkan PRIVATE ${_ggml_vk_target_cpp})
232
+ endforeach()
233
+
234
+ else()
235
+ message(WARNING "Vulkan not found")
236
+ endif()
backend/llama.cpp/ggml/src/ggml-vulkan/cmake/host-toolchain.cmake.in ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ set(CMAKE_BUILD_TYPE Release)
2
+ set(CMAKE_C_FLAGS -O2)
3
+ set(CMAKE_CXX_FLAGS -O2)
4
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
5
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
6
+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
7
+ set(CMAKE_C_COMPILER "@HOST_C_COMPILER@")
8
+ set(CMAKE_CXX_COMPILER "@HOST_CXX_COMPILER@")
9
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY @CMAKE_RUNTIME_OUTPUT_DIRECTORY@)
10
+
11
+ if("@CMAKE_C_COMPILER_ID@" STREQUAL "MSVC")
12
+ foreach(CONFIG IN ITEMS DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
13
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
14
+ endforeach()
15
+ endif()
backend/llama.cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp ADDED
The diff for this file is too large to render. See raw diff
 
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required(VERSION 3.19)
2
+ project("vulkan-shaders-gen" C CXX)
3
+
4
+ find_package (Threads REQUIRED)
5
+
6
+ if (GGML_VULKAN_COOPMAT_GLSLC_SUPPORT)
7
+ add_compile_definitions(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT)
8
+ message(STATUS "Enabling coopmat glslc support")
9
+ endif()
10
+ if (GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT)
11
+ add_compile_definitions(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT)
12
+ message(STATUS "Enabling coopmat2 glslc support")
13
+ endif()
14
+ if (GGML_VULKAN_COOPMAT2_DECODE_VECTOR_GLSLC_SUPPORT)
15
+ add_compile_definitions(GGML_VULKAN_COOPMAT2_DECODE_VECTOR_GLSLC_SUPPORT)
16
+ message(STATUS "Enabling coopmat2 decode_vector glslc support")
17
+ endif()
18
+ if (GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT)
19
+ add_compile_definitions(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT)
20
+ message(STATUS "Enabling dot glslc support")
21
+ endif()
22
+ if (GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT)
23
+ add_compile_definitions(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT)
24
+ message(STATUS "Enabling bfloat16 glslc support")
25
+ endif()
26
+ if (GGML_VULKAN_SHADER_DEBUG_INFO)
27
+ add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO)
28
+ message(STATUS "Enabling shader debug info")
29
+ endif()
30
+
31
+ set(TARGET vulkan-shaders-gen)
32
+ add_executable(${TARGET} vulkan-shaders-gen.cpp)
33
+ install(TARGETS ${TARGET} RUNTIME)
34
+ target_compile_features(${TARGET} PRIVATE cxx_std_17)
35
+ target_link_libraries(vulkan-shaders-gen PUBLIC Threads::Threads)
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/acc.comp ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "generic_binary_head.glsl"
5
+
6
+ // false for SET, true for ACC
7
+ layout(constant_id = 1) const bool ACC = true;
8
+
9
+ layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
10
+
11
+ void main() {
12
+ const uint idx = gl_GlobalInvocationID.x;
13
+ if (idx >= p.ne) {
14
+ return;
15
+ }
16
+
17
+ const uint offset = p.param3;
18
+ const uint src1_i = idx - offset;
19
+ const uint i3 = src1_i / p.nb03;
20
+ const uint rem2 = src1_i - i3 * p.nb03;
21
+ const uint i2 = rem2 / p.nb02;
22
+ const uint rem1 = rem2 - i2 * p.nb02;
23
+ const uint i1 = rem1 / p.nb01;
24
+ const uint i0 = rem1 % p.nb01;
25
+
26
+ uint i00, i01, i02, i03;
27
+
28
+ if (i0 < p.ne10 && i1 < p.ne11 && i2 < p.ne12 && i3 < p.ne13) {
29
+ if (ACC) {
30
+ data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + idx]) + FLOAT_TYPE(data_b[get_boffset() + src1_idx(i0, i1, i2, i3)]));
31
+ } else {
32
+ data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_b[get_boffset() + src1_idx(i0, i1, i2, i3)]));
33
+ }
34
+ } else {
35
+ data_d[get_doffset() + idx] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + idx]));
36
+ }
37
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add.comp ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_shader_16bit_storage : require
4
+ #if ADD_RMS
5
+ #extension GL_KHR_shader_subgroup_arithmetic : enable
6
+ #extension GL_KHR_shader_subgroup_basic : enable
7
+ #endif
8
+
9
+ #include "types.glsl"
10
+ #include "generic_binary_head.glsl"
11
+
12
+ const uint num_threads = 256;
13
+
14
+ layout (binding = 3, std430) buffer PartialBuf {float partial_sums[];};
15
+
16
+ layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in;
17
+
18
+ #if ADD_RMS
19
+ // XXX TODO this could be sized based on number of subgroups, but that't not considered a constant
20
+ shared FLOAT_TYPE sumsh[num_threads];
21
+ #endif
22
+
23
+ void main() {
24
+ uint idx = get_idx();
25
+ uint orig_idx = idx;
26
+
27
+ // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation
28
+ const uint num_iter = 2;
29
+
30
+ FLOAT_TYPE sum_sq = 0;
31
+
32
+ [[unroll]] for (uint i = 0; i < num_iter; ++i) {
33
+ if (idx >= p.ne) {
34
+ continue;
35
+ }
36
+ uint i00, i01, i02, i03;
37
+ get_indices(idx, i00, i01, i02, i03);
38
+
39
+ FLOAT_TYPE sum = FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) + FLOAT_TYPE(data_b[get_boffset() + src1_idx(i00, i01, i02, i03)]);
40
+ sum_sq += sum*sum;
41
+
42
+ data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(sum);
43
+
44
+ idx += num_threads;
45
+ }
46
+
47
+ #if ADD_RMS
48
+ if (p.param3 != 0) {
49
+ // reduce the sum within each subgroup, then across subgroups
50
+ const uint NumSubgroups = num_threads / gl_SubgroupSize;
51
+ sum_sq = subgroupAdd(sum_sq);
52
+ if (gl_SubgroupInvocationID == 0) {
53
+ sumsh[gl_SubgroupID] = sum_sq;
54
+ }
55
+ barrier();
56
+ [[unroll]] for (uint s = NumSubgroups / 2; s > 0; s >>= 1) {
57
+ if (gl_SubgroupID < s && gl_SubgroupInvocationID == 0) {
58
+ sum_sq += sumsh[gl_SubgroupID + s];
59
+ sumsh[gl_SubgroupID] = sum_sq;
60
+ }
61
+ barrier();
62
+ }
63
+
64
+ if (gl_SubgroupID == 0 && gl_SubgroupInvocationID == 0) {
65
+ partial_sums[orig_idx / (num_iter * num_threads)] = sum_sq;
66
+ }
67
+ }
68
+ #endif
69
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add1.comp ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_shader_16bit_storage : require
4
+
5
+ #include "types.glsl"
6
+ #include "generic_binary_head.glsl"
7
+
8
+ const uint num_threads = 256;
9
+
10
+ layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in;
11
+
12
+ void main() {
13
+ uint idx = get_idx();
14
+
15
+ const uint num_iter = 2;
16
+
17
+ [[unroll]] for (uint i = 0; i < num_iter; ++i) {
18
+ if (idx >= p.ne) {
19
+ continue;
20
+ }
21
+ uint i00, i01, i02, i03;
22
+ get_indices(idx, i00, i01, i02, i03);
23
+
24
+ data_d[get_doffset() + dst_idx(i00, i01, i02, i03)] = D_TYPE(FLOAT_TYPE(data_a[get_aoffset() + src0_idx(i00, i01, i02, i03)]) + FLOAT_TYPE(data_b[get_boffset()]));
25
+
26
+ idx += num_threads;
27
+ }
28
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/add_id.comp ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_control_flow_attributes : require
4
+
5
+ #include "types.glsl"
6
+
7
+ layout (push_constant) uniform parameter
8
+ {
9
+ uint ne0;
10
+ uint ne1;
11
+ uint s01;
12
+ uint s02;
13
+ uint s11;
14
+ uint s21;
15
+ } p;
16
+
17
+ #define BLOCK_SIZE 512
18
+
19
+ layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in;
20
+
21
+ layout (binding = 0) readonly buffer X {A_TYPE data_a[];};
22
+ layout (binding = 1) readonly buffer Y {B_TYPE data_b[];};
23
+ layout (binding = 2) readonly buffer Z {int32_t data_c[];};
24
+ layout (binding = 3) writeonly buffer D {D_TYPE data_d[];};
25
+
26
+ void main() {
27
+ const uint i1 = gl_WorkGroupID.x;
28
+ const uint i2 = gl_WorkGroupID.y;
29
+
30
+ const uint i11 = data_c[i1 + i2 * p.s21];
31
+
32
+ const uint s1 = p.ne0;
33
+ const uint s2 = p.ne0 * p.ne1;
34
+
35
+ const uint d0 = i1 * s1 + i2 * s2;
36
+ const uint a0 = i1 * p.s01 + i2 * p.s02;
37
+ const uint b0 = i11 * p.s11;
38
+
39
+ for (uint i0 = gl_LocalInvocationID.x; i0 < p.ne0; i0 += BLOCK_SIZE) {
40
+ data_d[d0 + i0] = data_a[a0 + i0] + data_b[b0 + i0];
41
+ }
42
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/arange.comp ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "generic_head.glsl"
4
+ #include "types.glsl"
5
+
6
+ layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
7
+
8
+ layout (binding = 0) writeonly buffer D {D_TYPE data_d[];};
9
+
10
+ void main() {
11
+ const uint i = gl_GlobalInvocationID.x;
12
+
13
+ if (i >= p.KX) {
14
+ return;
15
+ }
16
+
17
+ // p.param1 = start, p.param2 = step
18
+ float value = p.param1 + p.param2 * float(i);
19
+ data_d[i] = D_TYPE(value);
20
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argmax.comp ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "generic_head.glsl"
4
+ #include "types.glsl"
5
+
6
+ #extension GL_EXT_control_flow_attributes : enable
7
+
8
+ #define FLT_MAX 3.402823466e+38F
9
+
10
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
11
+
12
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
13
+ layout (binding = 1) writeonly buffer D {D_TYPE data_d[];};
14
+
15
+ layout (constant_id = 0) const uint BLOCK_SIZE = 32;
16
+
17
+ shared FLOAT_TYPE tmpmax[BLOCK_SIZE];
18
+ shared uint tmp[BLOCK_SIZE];
19
+
20
+ void main() {
21
+ const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x;
22
+ const uint col = gl_LocalInvocationID.x;
23
+
24
+ if (row >= p.KY) {
25
+ return;
26
+ }
27
+
28
+ A_TYPE amax = -FLT_MAX;
29
+ uint acol = col;
30
+
31
+ if (col < p.KX) {
32
+ amax = data_a[row*p.KX + col];
33
+ }
34
+
35
+ for (uint i = col + BLOCK_SIZE; i < p.KX; i += BLOCK_SIZE) {
36
+ A_TYPE val = data_a[row*p.KX + i];
37
+ if (val > amax) {
38
+ amax = val;
39
+ acol = i;
40
+ }
41
+ }
42
+
43
+ tmp[col] = acol;
44
+ tmpmax[col] = amax;
45
+
46
+ barrier();
47
+ [[unroll]] for (int s = int(BLOCK_SIZE) / 2; s > 0; s >>= 1) {
48
+ if (col < s && col + s < p.KX) {
49
+ if (tmpmax[col] < tmpmax[col + s]) {
50
+ tmpmax[col] = tmpmax[col + s];
51
+ tmp[col] = tmp[col + s];
52
+ }
53
+ }
54
+ barrier();
55
+ }
56
+
57
+ if (col == 0) {
58
+ data_d[row] = D_TYPE(tmp[0]);
59
+ }
60
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort.comp ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+ #extension GL_EXT_control_flow_attributes : enable
3
+
4
+ #include "types.glsl"
5
+
6
+ layout(constant_id = 0) const int BLOCK_SIZE = 1024;
7
+ layout(constant_id = 1) const int NCOLS_PADDED_LOG2 = 10;
8
+ #define ASC 0
9
+
10
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
11
+
12
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
13
+ layout (binding = 2) writeonly buffer D {int data_d[];};
14
+
15
+ layout (push_constant) uniform parameter {
16
+ uint ncols;
17
+ uint ncols_padded;
18
+ uint ncols_padded_log2;
19
+ uint nrows;
20
+ uint order;
21
+ uint outer_start;
22
+ uint outer_end;
23
+ uint inner_start;
24
+ uint inner_end;
25
+ } p;
26
+
27
+ shared ivec2 dst_row[BLOCK_SIZE];
28
+
29
+ void argsort(bool needs_bounds_check, const uint row) {
30
+ // bitonic sort
31
+ const int col = int(gl_LocalInvocationID.x);
32
+
33
+ const uint row_offset = row * p.ncols;
34
+
35
+ // initialize indices
36
+ dst_row[col] = ivec2(col, floatBitsToInt(data_a[row_offset + col]));
37
+ barrier();
38
+
39
+ uint num_outer_loop_iters = NCOLS_PADDED_LOG2;
40
+ [[unroll]] for (uint k = 2, outer_idx = 0; outer_idx < num_outer_loop_iters; k *= 2, outer_idx++) {
41
+ uint num_inner_loop_iters = outer_idx + 1;
42
+ [[unroll]] for (uint j = k / 2, inner_idx = 0; inner_idx < num_inner_loop_iters; j /= 2, inner_idx++) {
43
+ const int ixj = int(col ^ j);
44
+
45
+ int idx_0 = (col & k) == 0 ? col : ixj;
46
+ int idx_1 = (col & k) == 0 ? ixj : col;
47
+
48
+ ivec2 sh_idx_0 = dst_row[idx_0];
49
+ ivec2 sh_idx_1 = dst_row[idx_1];
50
+ bool idx_0_oob = needs_bounds_check ? sh_idx_0.x >= p.ncols : false;
51
+ bool idx_1_oob = needs_bounds_check ? sh_idx_1.x >= p.ncols : false;
52
+
53
+ if ((idx_0_oob ||
54
+ (!idx_1_oob && intBitsToFloat(sh_idx_0.y) > intBitsToFloat(sh_idx_1.y))) && (ixj > col)) {
55
+ dst_row[idx_0] = sh_idx_1;
56
+ dst_row[idx_1] = sh_idx_0;
57
+ }
58
+
59
+ barrier();
60
+ }
61
+ }
62
+
63
+ if (col < p.ncols) {
64
+ if (p.order == ASC) {
65
+ data_d[row_offset + col] = dst_row[col].x;
66
+ } else {
67
+ data_d[row_offset + p.ncols - col - 1] = dst_row[col].x;
68
+ }
69
+ }
70
+ }
71
+
72
+ void main() {
73
+ if (p.ncols == BLOCK_SIZE) {
74
+ uint row = gl_WorkGroupID.y;
75
+ while (row < p.nrows) {
76
+ argsort(false, row);
77
+ row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
78
+ }
79
+ } else {
80
+ uint row = gl_WorkGroupID.y;
81
+ while (row < p.nrows) {
82
+ argsort(true, row);
83
+ row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
84
+ }
85
+ }
86
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort_large.comp ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+ #extension GL_EXT_control_flow_attributes : enable
3
+ #extension GL_KHR_memory_scope_semantics : enable
4
+ #pragma use_vulkan_memory_model
5
+
6
+ #include "types.glsl"
7
+
8
+ layout(constant_id = 0) const int BLOCK_SIZE = 1024;
9
+ layout(constant_id = 1) const int WG_UNROLL_FACTOR = 2;
10
+ #define ASC 0
11
+
12
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
13
+
14
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
15
+ layout (binding = 1) workgroupcoherent buffer B {ivec2 tmp_idx[];};
16
+ layout (binding = 2) workgroupcoherent buffer D {int data_d[];};
17
+
18
+ layout (push_constant) uniform parameter {
19
+ uint ncols;
20
+ uint ncols_padded;
21
+ uint ncols_padded_log2;
22
+ uint nrows;
23
+ uint order;
24
+ uint outer_start;
25
+ uint outer_end;
26
+ uint inner_start;
27
+ uint inner_end;
28
+ } p;
29
+
30
+ void argsort(bool needs_bounds_check, const uint row) {
31
+ // bitonic sort
32
+ int col = int(gl_GlobalInvocationID.x);
33
+ col = (col % BLOCK_SIZE) + (col / BLOCK_SIZE) * BLOCK_SIZE * WG_UNROLL_FACTOR;
34
+
35
+ const uint row_offset = row * p.ncols;
36
+ uint idx_offset = row * p.ncols_padded;
37
+
38
+ bool need_barrier = false;
39
+
40
+ // initialize indices
41
+ if (p.outer_start == 0 && p.inner_start == 0) {
42
+ [[unroll]] for (int u = 0; u < WG_UNROLL_FACTOR; ++u) {
43
+ uint c = u*BLOCK_SIZE + col;
44
+ if (c < p.ncols_padded) {
45
+ ivec2 v = ivec2(c, floatBitsToInt(data_a[row_offset + c]));
46
+ tmp_idx[idx_offset + c] = v;
47
+ }
48
+ }
49
+ need_barrier = true;
50
+ }
51
+
52
+ [[unroll]] for (uint outer_idx = p.outer_start, k = (2 << outer_idx); outer_idx < p.outer_end; k *= 2, outer_idx++) {
53
+ uint inner_end = min(p.inner_end, outer_idx + 1);
54
+ for (uint j = k >> (p.inner_start + 1), inner_idx = p.inner_start; inner_idx < inner_end; j /= 2, inner_idx++) {
55
+ if (need_barrier) {
56
+ controlBarrier(gl_ScopeWorkgroup, gl_ScopeWorkgroup, gl_StorageSemanticsBuffer, gl_SemanticsAcquireRelease);
57
+ }
58
+ need_barrier = true;
59
+ [[unroll]] for (int u = 0; u < WG_UNROLL_FACTOR; ++u) {
60
+ int c = u*BLOCK_SIZE + col;
61
+ const int ixj = int(c ^ j);
62
+
63
+ if (ixj < c) {
64
+ continue;
65
+ }
66
+
67
+ int idx_0 = (c & k) == 0 ? c : ixj;
68
+ int idx_1 = (c & k) == 0 ? ixj : c;
69
+
70
+ ivec2 sh_idx_0 = tmp_idx[idx_offset + idx_0];
71
+ ivec2 sh_idx_1 = tmp_idx[idx_offset + idx_1];
72
+ bool idx_0_oob = needs_bounds_check ? sh_idx_0.x >= p.ncols : false;
73
+ bool idx_1_oob = needs_bounds_check ? sh_idx_1.x >= p.ncols : false;
74
+
75
+ if ((idx_0_oob ||
76
+ (!idx_1_oob && intBitsToFloat(sh_idx_0.y) > intBitsToFloat(sh_idx_1.y)))) {
77
+ tmp_idx[idx_offset + idx_0] = sh_idx_1;
78
+ tmp_idx[idx_offset + idx_1] = sh_idx_0;
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ if (p.outer_end == p.ncols_padded_log2 &&
85
+ p.inner_end >= p.ncols_padded_log2 + 1) {
86
+ controlBarrier(gl_ScopeWorkgroup, gl_ScopeWorkgroup, gl_StorageSemanticsBuffer, gl_SemanticsAcquireRelease);
87
+ [[unroll]] for (int u = 0; u < WG_UNROLL_FACTOR; ++u) {
88
+ uint c = u*BLOCK_SIZE + col;
89
+ if (c < p.ncols) {
90
+ if (p.order == ASC) {
91
+ data_d[row_offset + c] = tmp_idx[idx_offset + c].x;
92
+ } else {
93
+ data_d[row_offset + p.ncols - c - 1] = tmp_idx[idx_offset + c].x;
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ void main() {
101
+ if (p.ncols == p.ncols_padded) {
102
+ uint row = gl_WorkGroupID.y;
103
+ while (row < p.nrows) {
104
+ argsort(false, row);
105
+ row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
106
+ }
107
+ } else {
108
+ uint row = gl_WorkGroupID.y;
109
+ while (row < p.nrows) {
110
+ argsort(true, row);
111
+ row += gl_WorkGroupSize.y * gl_NumWorkGroups.y;
112
+ }
113
+ }
114
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+
5
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; // columns: [K_OC, T_in]
6
+ layout (binding = 1) writeonly buffer D {D_TYPE data_d[];}; // output: [T_out, OC]
7
+
8
+ layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
9
+
10
+ layout (push_constant) uniform parameter {
11
+ uint32_t T_out;
12
+ uint32_t OC;
13
+ uint32_t K_OC;
14
+ uint32_t T_in;
15
+ uint32_t K;
16
+ int32_t stride;
17
+ int32_t p0;
18
+ } p;
19
+
20
+ // Load A_TYPE to float
21
+ float load_col(uint32_t idx) {
22
+ #if defined(DATA_A_BF16)
23
+ return bf16_to_fp32(uint32_t(data_a[idx]));
24
+ #else
25
+ return float(data_a[idx]);
26
+ #endif
27
+ }
28
+
29
+ // Store float as D_TYPE
30
+ void store_dst(uint32_t idx, float v) {
31
+ #if defined(DATA_A_BF16)
32
+ data_d[idx] = D_TYPE(fp32_to_bf16(v));
33
+ #else
34
+ data_d[idx] = D_TYPE(v);
35
+ #endif
36
+ }
37
+
38
+ void main() {
39
+ const uint32_t t_out = gl_GlobalInvocationID.x;
40
+ const uint32_t oc = gl_GlobalInvocationID.y;
41
+ if (t_out >= p.T_out || oc >= p.OC) return;
42
+
43
+ const int32_t t_abs = int32_t(t_out) + p.p0; // absolute position in uncropped signal
44
+
45
+ // Gather: only the ceil(K/stride) columns that scatter into t_abs, no modulo
46
+ int32_t t_in_min = (t_abs - int32_t(p.K) + p.stride) / p.stride;
47
+ if (t_in_min < 0) t_in_min = 0;
48
+ int32_t t_in_max = t_abs / p.stride;
49
+ if (t_in_max >= int32_t(p.T_in)) t_in_max = int32_t(p.T_in) - 1;
50
+
51
+ float val = 0.0;
52
+ for (int32_t t_in = t_in_min; t_in <= t_in_max; t_in++) {
53
+ int32_t k = t_abs - t_in * p.stride;
54
+ // col layout: [K_OC, T_in], column index = oc * K + k
55
+ uint32_t col_idx = (oc * p.K + uint32_t(k)) + uint32_t(t_in) * p.K_OC;
56
+ val += load_col(col_idx);
57
+ }
58
+
59
+ // dst layout: [T_out, OC], element (t_out, oc) = t_out + oc * T_out
60
+ store_dst(t_out + oc * p.T_out, val);
61
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/concat.comp ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "generic_binary_head.glsl"
5
+
6
+ layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
7
+
8
+ void main() {
9
+ const uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x;
10
+ const int dim = p.param3;
11
+
12
+ if (idx >= p.ne) {
13
+ return;
14
+ }
15
+
16
+ const uint i3 = idx / (p.ne22*p.ne21*p.ne20);
17
+ const uint i3_offset = i3 * p.ne22*p.ne21*p.ne20;
18
+ const uint i2 = (idx - i3_offset) / (p.ne21*p.ne20);
19
+ const uint i2_offset = i2*p.ne21*p.ne20;
20
+ const uint i1 = (idx - i3_offset - i2_offset) / p.ne20;
21
+ const uint i0 = idx - i3_offset - i2_offset - i1*p.ne20;
22
+
23
+ uint o[4] = {0, 0, 0, 0};
24
+ o[dim] = dim == 0 ? p.ne00 : (dim == 1 ? p.ne01 : (dim == 2 ? p.ne02 : p.ne03));
25
+
26
+ const uint src0_idx = i3*p.nb03 + i2*p.nb02 + i1*p.nb01 + i0*p.nb00;
27
+ const uint src1_idx = (i3 - o[3])*p.nb13 + (i2 - o[2])*p.nb12 + (i1 - o[1])*p.nb11 + (i0 - o[0])*p.nb10;
28
+ const uint dst_idx = i3*p.nb23 + i2*p.nb22 + i1*p.nb21 + i0*p.nb20;
29
+
30
+ const bool is_src0 = i0 < p.ne00 && i1 < p.ne01 && i2 < p.ne02 && i3 < p.ne03;
31
+
32
+ #ifndef OPTIMIZATION_ERROR_WORKAROUND
33
+ data_d[get_doffset() + dst_idx] = D_TYPE(is_src0 ? data_a[get_aoffset() + src0_idx] : data_b[get_boffset() + src1_idx]);
34
+ #else
35
+ if (is_src0) {
36
+ data_d[get_doffset() + dst_idx] = data_a[get_aoffset() + src0_idx];
37
+ } else {
38
+ data_d[get_doffset() + dst_idx] = data_b[get_boffset() + src1_idx];
39
+ }
40
+ #endif
41
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "generic_unary_head.glsl"
5
+
6
+ #extension GL_EXT_control_flow_attributes : require
7
+
8
+ const uint num_threads = 128;
9
+
10
+ layout(local_size_x = num_threads, local_size_y = 1, local_size_z = 1) in;
11
+
12
+ void main() {
13
+ uint idx = get_idx();
14
+
15
+ // num_threads * num_iter must equal 512, to match the wg_denoms and get_idx calculation
16
+ const uint num_iter = 4;
17
+
18
+ // fast path for when all four iterations are in-bounds
19
+ if (idx + (num_iter-1)*num_threads < p.ne) {
20
+ [[unroll]] for (uint i = 0; i < num_iter; ++i) {
21
+
22
+ #if defined(DATA_A_BF16)
23
+ data_d[get_doffset() + idx] = D_TYPE(bf16_to_fp32(uint32_t(data_a[get_aoffset() + idx])));
24
+ #elif defined(DATA_D_BF16)
25
+ float f = float(data_a[get_aoffset() + idx]);
26
+ data_d[get_doffset() + idx] = D_TYPE(fp32_to_bf16(f));
27
+ #elif !defined(OPTIMIZATION_ERROR_WORKAROUND)
28
+ data_d[get_doffset() + idx] = D_TYPE(data_a[get_aoffset() + idx]);
29
+ #else
30
+ data_d[get_doffset() + idx] = data_a[get_aoffset() + idx];
31
+ #endif
32
+ idx += num_threads;
33
+ }
34
+ } else {
35
+ [[unroll]] for (uint i = 0; i < num_iter; ++i) {
36
+ if (idx >= p.ne) {
37
+ continue;
38
+ }
39
+
40
+ #if defined(DATA_A_BF16)
41
+ data_d[get_doffset() + idx] = D_TYPE(bf16_to_fp32(uint32_t(data_a[get_aoffset() + idx])));
42
+ #elif defined(DATA_D_BF16)
43
+ float f = float(data_a[get_aoffset() + idx]);
44
+ data_d[get_doffset() + idx] = D_TYPE(fp32_to_bf16(f));
45
+ #elif !defined(OPTIMIZATION_ERROR_WORKAROUND)
46
+ data_d[get_doffset() + idx] = D_TYPE(data_a[get_aoffset() + idx]);
47
+ #else
48
+ data_d[get_doffset() + idx] = data_a[get_aoffset() + idx];
49
+ #endif
50
+ idx += num_threads;
51
+ }
52
+ }
53
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_dw.comp ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+
5
+ layout (push_constant) uniform parameter
6
+ {
7
+ uint ne;
8
+ uint batches;
9
+ uint channels;
10
+ uint dst_w;
11
+ uint dst_h;
12
+ uint src_w;
13
+ uint src_h;
14
+ uint knl_w;
15
+ uint knl_h;
16
+ int stride_x;
17
+ int stride_y;
18
+ int pad_x;
19
+ int pad_y;
20
+ int dilation_x;
21
+ int dilation_y;
22
+ } p;
23
+
24
+ layout (binding = 0) readonly buffer A {A_TYPE knl_data[];};
25
+ layout (binding = 1) readonly buffer B {B_TYPE src_data[];};
26
+ layout (binding = 2) writeonly buffer D {D_TYPE dst_data[];};
27
+
28
+ layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
29
+
30
+ FLOAT_TYPE conv_2d_dw_whcn(uint idx) {
31
+ uint i0 = idx / p.dst_w;
32
+ uint dst_x = idx - i0 * p.dst_w;
33
+ uint i1 = i0 / p.dst_h;
34
+ uint dst_y = i0 - i1 * p.dst_h;
35
+ uint n = i1 / p.channels;
36
+ uint c = i1 - n * p.channels;
37
+
38
+ uint src_i = n * p.channels * p.src_h * p.src_w + c * p.src_h * p.src_w;
39
+ uint knl_i = c * p.knl_h * p.knl_w;
40
+
41
+ FLOAT_TYPE sum = 0.0;
42
+ for (uint knl_y = 0; knl_y < p.knl_h; ++knl_y) {
43
+ uint src_y = dst_y * p.stride_y + knl_y * p.dilation_y - p.pad_y;
44
+ if (src_y >= p.src_h) { // src_y < 0 will wrap to a large unsigned int
45
+ continue;
46
+ }
47
+ for (uint knl_x = 0; knl_x < p.knl_w; ++knl_x) {
48
+ uint src_x = dst_x * p.stride_x + knl_x * p.dilation_x - p.pad_x;
49
+ if (src_x >= p.src_w) { // src_x < 0 will wrap to a large unsigned int
50
+ continue;
51
+ }
52
+ FLOAT_TYPE v = FLOAT_TYPE(src_data[src_i + src_y * p.src_w + src_x]);
53
+ FLOAT_TYPE k = FLOAT_TYPE(knl_data[knl_i + knl_y * p.knl_w + knl_x]);
54
+ sum = fma(v, k, sum);
55
+ }
56
+ }
57
+ return sum;
58
+ }
59
+
60
+ FLOAT_TYPE conv_2d_dw_cwhn(uint idx) {
61
+ uint i0 = idx / p.channels;
62
+ uint c = idx - i0 * p.channels;
63
+ uint i1 = i0 / p.dst_w;
64
+ uint dst_x = i0 - i1 * p.dst_w;
65
+ uint n = i1 / p.dst_h;
66
+ uint dst_y = i1 - n * p.dst_h;
67
+
68
+ uint src_i = n * p.channels * p.src_h * p.src_w;
69
+ uint src_row = p.src_w * p.channels;
70
+ uint knl_row = p.knl_w * p.channels;
71
+
72
+ FLOAT_TYPE sum = 0.0;
73
+ for (uint knl_y = 0; knl_y < p.knl_h; ++knl_y) {
74
+ uint src_y = dst_y * p.stride_y + knl_y * p.dilation_y - p.pad_y;
75
+ if (src_y >= p.src_h) { // src_y < 0 will wrap to a large unsigned int
76
+ continue;
77
+ }
78
+ for (uint knl_x = 0; knl_x < p.knl_w; ++knl_x) {
79
+ uint src_x = dst_x * p.stride_x + knl_x * p.dilation_x - p.pad_x;
80
+ if (src_x >= p.src_w) { // src_x < 0 will wrap to a large unsigned int
81
+ continue;
82
+ }
83
+ FLOAT_TYPE v = FLOAT_TYPE(src_data[src_i + src_y * src_row + src_x * p.channels + c]);
84
+ FLOAT_TYPE k = FLOAT_TYPE(knl_data[ knl_y * knl_row + knl_x * p.channels + c]);
85
+ sum = fma(v, k, sum);
86
+ }
87
+ }
88
+ return sum;
89
+ }
90
+
91
+ void main() {
92
+ uint idx = gl_GlobalInvocationID.z * 262144 + gl_GlobalInvocationID.y * 512 + gl_GlobalInvocationID.x;
93
+ if (idx >= p.ne) {
94
+ return;
95
+ }
96
+
97
+ FLOAT_TYPE result =
98
+ #ifdef WHCN
99
+ conv_2d_dw_whcn(idx);
100
+ #else
101
+ conv_2d_dw_cwhn(idx);
102
+ #endif
103
+ dst_data[idx] = D_TYPE(result);
104
+ }
105
+
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp ADDED
@@ -0,0 +1,480 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_control_flow_attributes : enable
4
+ #ifdef COOPMAT2
5
+ #extension GL_NV_cooperative_matrix2 : enable
6
+ #extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
7
+ #extension GL_KHR_memory_scope_semantics : enable
8
+ #endif
9
+
10
+ #ifdef COOPMAT
11
+ #extension GL_KHR_cooperative_matrix : enable
12
+ #extension GL_KHR_shader_subgroup_basic : enable
13
+ #extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
14
+ #extension GL_KHR_memory_scope_semantics : enable
15
+ #endif
16
+
17
+ #ifdef USE_COLLECTIVES
18
+ # extension GL_KHR_shader_subgroup_shuffle : enable
19
+ #endif
20
+
21
+ #include "types.glsl"
22
+
23
+ // shape notation: [dim(N), ..., dim(0)] -- stride(dim(j)) >= stride(dim(i)) if i > j
24
+ layout(binding = 0) readonly buffer A {
25
+ A_TYPE knl_data[];
26
+ }; // src0 - kernel: [KW, KH, Cin, Cout] for conv_2d, [KW, KH, Cout, Cin] for conv_transposed_2d
27
+
28
+ layout(binding = 1) readonly buffer B {
29
+ B_TYPE src_data[];
30
+ }; // src1 - input: [W, H, Cin, N] -- channel_first format
31
+
32
+ layout(binding = 2) writeonly buffer D {
33
+ D_TYPE dst_data[];
34
+ }; // dst - result: [OW, OH, Cout, N]
35
+
36
+ layout(push_constant) uniform parameter {
37
+ // I/O channels, batch size
38
+ uint32_t Cout;
39
+ uint32_t Cin;
40
+ uint32_t N;
41
+
42
+ // Tensor spatial sizes: input, output
43
+ uint32_t W;
44
+ uint32_t H;
45
+ uint32_t OW;
46
+ uint32_t OH;
47
+
48
+ // Strides in elements
49
+ uint32_t nb01;
50
+ uint32_t nb02;
51
+ uint32_t nb03;
52
+
53
+ uint32_t nb11;
54
+ uint32_t nb12;
55
+ uint32_t nb13;
56
+
57
+ uint32_t nb1;
58
+ uint32_t nb2;
59
+ uint32_t nb3;
60
+
61
+ // fastdiv helper values
62
+ uint32_t OWmp; uint32_t OWL;
63
+ uint32_t OWOHmp; uint32_t OWOHL;
64
+ }
65
+
66
+ p;
67
+
68
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
69
+ // Blocktile sizes
70
+ layout(constant_id = 1) const uint BS_K = 128;
71
+ layout(constant_id = 2) const uint BS_CRS = 16;
72
+ layout(constant_id = 3) const uint BS_NPQ = 128;
73
+ // Thread-tile sizes
74
+ layout(constant_id = 4) const uint TS_K = 8;
75
+ layout(constant_id = 5) const uint use_collectives = 1;
76
+ layout(constant_id = 6) const uint SHMEM_PAD = 4;
77
+ // Stride, padding, dilation
78
+ layout(constant_id = 7) const uint s0 = 1;
79
+ layout(constant_id = 8) const uint s1 = 1;
80
+ layout(constant_id = 9) const uint p0 = 0;
81
+ layout(constant_id = 10) const uint p1 = 0;
82
+ layout(constant_id = 11) const uint d0 = 1;
83
+ layout(constant_id = 12) const uint d1 = 1;
84
+ // Kernel spatial sizes
85
+ layout(constant_id = 13) const uint KW = 1;
86
+ layout(constant_id = 14) const uint KH = 1;
87
+ // when set, skip bounds checks and address clamps (K/CRS/NPQ are tile-aligned)
88
+ layout(constant_id = 15) const uint aligned = 0;
89
+ // stage cm2 result through shmem (Csh) for coalesced stores. cm1 always does this.
90
+ layout(constant_id = 16) const uint csh_store = 0;
91
+
92
+ #ifdef COOPMAT
93
+ // cm1 subgroup tile: each subgroup computes a WM x WN region as a grid of
94
+ // TM x TN x TK fragments. Requires WM%TM == WN%TN == BS_K%WM == BS_NPQ%WN ==
95
+ // BS_CRS%TK == 0, and WG_SIZE == (BS_K/WM) * (BS_NPQ/WN) * subgroup_size.
96
+ layout(constant_id = 17) const uint WM = 32;
97
+ layout(constant_id = 18) const uint WN = 32;
98
+ const uint TM = 16;
99
+ const uint TN = 16;
100
+ const uint TK = 16;
101
+ const uint cms_per_row = WM / TM;
102
+ const uint cms_per_col = WN / TN;
103
+ const uint warps_M = BS_K / WM;
104
+ const uint warps_N = BS_NPQ / WN;
105
+ #endif
106
+
107
+ // without padding, H_idx/W_idx are in bounds by construction (non-TRANSPOSE only)
108
+ #ifdef TRANSPOSE
109
+ const bool hw_in_bounds = false;
110
+ #else
111
+ const bool hw_in_bounds = (p0 == 0) && (p1 == 0);
112
+ #endif
113
+
114
+ // TRANSPOSE stride alignment is trivially satisfied for stride 1
115
+ #ifdef TRANSPOSE
116
+ const bool stride_in_bounds = (s0 == 1) && (s1 == 1);
117
+ #else
118
+ const bool stride_in_bounds = true;
119
+ #endif
120
+
121
+ uint32_t tid = gl_LocalInvocationID.x;
122
+ const uint32_t WG_SIZE = gl_WorkGroupSize.x;
123
+
124
+ uint splitWork(uint work_size, uint block_size) {
125
+ return (block_size + work_size - 1) / block_size;
126
+ }
127
+
128
+ uint32_t K = p.Cout;
129
+ uint32_t CRS = p.Cin * KH * KW;
130
+ uint32_t NPQ = p.N * p.OH * p.OW;
131
+
132
+ uint32_t n_elems_out = K * NPQ;
133
+
134
+ // Number of blocktiles per input
135
+ uint32_t NB_CRS = splitWork(CRS, BS_CRS);
136
+
137
+ #if defined(COOPMAT2) || defined(COOPMAT)
138
+ #define SHMEM_TYPE float16_t
139
+ #else
140
+ #define SHMEM_TYPE float
141
+ #endif
142
+
143
+ const uint32_t Ash_stride = BS_CRS + SHMEM_PAD;
144
+ const uint32_t Bsh_stride = BS_NPQ + SHMEM_PAD;
145
+
146
+ const uint32_t Ash_numel = BS_K * BS_CRS;
147
+ const uint32_t Bsh_numel = BS_CRS * BS_NPQ;
148
+
149
+ const uint32_t Ash_len = BS_K * Ash_stride;
150
+ const uint32_t Bsh_len = BS_CRS * Bsh_stride;
151
+
152
+ shared SHMEM_TYPE Ash[Ash_len]; // K x CRS
153
+ shared SHMEM_TYPE Bsh[Bsh_len]; // CRS x NPQ
154
+
155
+ #if defined(COOPMAT2) || defined(COOPMAT)
156
+ // stage matC through shmem so global stores are row-major (NPQ-contiguous)
157
+ const uint32_t Csh_stride = BS_NPQ;
158
+ #ifdef COOPMAT
159
+ const uint32_t Csh_len = BS_K * Csh_stride;
160
+ #else
161
+ const uint32_t Csh_len = csh_store != 0 ? BS_K * Csh_stride : 8; // 8 to workaround compiler bug
162
+ #endif
163
+ shared SHMEM_TYPE Csh[Csh_len]; // K x NPQ
164
+ #endif
165
+
166
+ // Threadtile sizes
167
+ const uint32_t TS_NPQ = BS_K * BS_NPQ / WG_SIZE / TS_K;
168
+
169
+ // Number of threadtiles per blocktile
170
+ const uint32_t NT_K = BS_K / TS_K;
171
+ const uint32_t NT_NPQ = BS_NPQ / TS_NPQ;
172
+
173
+ /*
174
+ Compute
175
+ KxCRS @ CRSxNPQ = K x NPQ
176
+ K=Cout
177
+ C=Cin
178
+ R,S=KH,KW
179
+ P,Q=OH,OW
180
+ */
181
+
182
+ uint32_t B_idx_K = gl_WorkGroupID.x;
183
+ uint32_t B_idx_NPQ = gl_WorkGroupID.y + gl_WorkGroupID.z * 512;
184
+
185
+ uint32_t T_y = tid / NT_NPQ;
186
+ uint32_t T_x = tid % NT_NPQ;
187
+
188
+ uint32_t Ar = tid / BS_CRS;
189
+ uint32_t Ac = tid % BS_CRS;
190
+ const uint32_t ArpWg = WG_SIZE / BS_CRS;
191
+
192
+ uint32_t Br = tid / BS_NPQ;
193
+ uint32_t Bc = tid % BS_NPQ;
194
+ const uint32_t BrpWg = WG_SIZE / BS_NPQ;
195
+
196
+ // see init_fastdiv_values in ggml-vulkan.cpp
197
+ uint fastdiv(uint n, uint mp, uint L) {
198
+ uint msbs, lsbs;
199
+ // msbs = mulhi(n, mp)
200
+ umulExtended(n, mp, msbs, lsbs);
201
+ return (msbs + n) >> L;
202
+ }
203
+
204
+ #ifdef COOPMAT2
205
+ #define ACC_TYPE float16_t
206
+
207
+ ACC_TYPE perElemOpStore(const in uint32_t r, const in uint32_t c, const in ACC_TYPE elem)
208
+ {
209
+ uint32_t K_idx = B_idx_K * BS_K + r;
210
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + c;
211
+ uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL); // divide by p.OH * p.OW;
212
+ uint32_t OH_idx = fastdiv(NPQ_idx - N_idx * p.OH * p.OW, p.OWmp, p.OWL); // divide by p.OW;
213
+ uint32_t OW_idx = NPQ_idx - N_idx * p.OH * p.OW - OH_idx * p.OW;
214
+ uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + K_idx * p.nb2 + N_idx * p.nb3;
215
+ if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
216
+ dst_data[dst_idx] = D_TYPE(elem);
217
+ }
218
+ return elem;
219
+ }
220
+ #endif
221
+
222
+ void main() {
223
+ if (B_idx_NPQ * BS_NPQ >= NPQ) {
224
+ return;
225
+ }
226
+
227
+ #ifdef COOPMAT2
228
+ coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator> matC;
229
+ matC = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator>(0.0);
230
+ #elif defined(COOPMAT)
231
+ coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator> sums[cms_per_row * cms_per_col];
232
+ [[unroll]] for (uint i = 0; i < cms_per_row * cms_per_col; i++) {
233
+ sums[i] = coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator>(0.0);
234
+ }
235
+ const uint warp_r = gl_SubgroupID / warps_N;
236
+ const uint warp_c = gl_SubgroupID % warps_N;
237
+ #else
238
+ float regC[TS_K][TS_NPQ];
239
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
240
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
241
+ regC[T_ly][T_lx] = 0.0;
242
+ }
243
+ }
244
+ #endif
245
+ /* Advance block in CRS dim */
246
+ [[dont_unroll]] for (uint32_t B_idx_CRS = 0; B_idx_CRS < NB_CRS; B_idx_CRS++) {
247
+ uint32_t CRS_idx_a;
248
+ uint32_t Cin_idx_a;
249
+ uint32_t KH_idx_a;
250
+ uint32_t KW_idx_a;
251
+
252
+ #ifdef USE_COLLECTIVES
253
+ uint32_t cached_CRS_idx;
254
+ uint32_t cached_Cin_idx;
255
+ uint32_t cached_KH_idx;
256
+ uint32_t cached_KW_idx;
257
+ if (use_collectives == 1) {
258
+ cached_CRS_idx = B_idx_CRS * BS_CRS + gl_SubgroupInvocationID;
259
+ cached_Cin_idx = cached_CRS_idx / (KW * KH);
260
+ uint32_t cached_CRS_remainder = cached_CRS_idx % (KW * KH);
261
+ cached_KH_idx = cached_CRS_remainder / KW;
262
+ cached_KW_idx = cached_CRS_remainder % KW;
263
+
264
+ CRS_idx_a = subgroupShuffle(cached_CRS_idx, Ac);
265
+ Cin_idx_a = subgroupShuffle(cached_Cin_idx, Ac);
266
+ KH_idx_a = subgroupShuffle(cached_KH_idx, Ac);
267
+ KW_idx_a = subgroupShuffle(cached_KW_idx, Ac);
268
+ } else {
269
+ CRS_idx_a = B_idx_CRS * BS_CRS + Ac; // Global CRS_idx_a (column index of A)
270
+ Cin_idx_a = CRS_idx_a / (KW * KH);
271
+ uint32_t CRS_remainder = CRS_idx_a % (KW * KH);
272
+ KH_idx_a = CRS_remainder / KW;
273
+ KW_idx_a = CRS_remainder % KW;
274
+ }
275
+ #else
276
+ CRS_idx_a = B_idx_CRS * BS_CRS + Ac; // Global CRS_idx_a (column index of A)
277
+ Cin_idx_a = CRS_idx_a / (KW * KH);
278
+ CRS_remainder = CRS_idx_a % (KW * KH);
279
+ KH_idx_a = CRS_remainder / KW;
280
+ KW_idx_a = CRS_remainder % KW;
281
+ #endif
282
+
283
+ /* Load kernel to A_block: (BS_K x BS_CRS)*/
284
+ UNROLL for (uint32_t r_offset = 0; r_offset < BS_K; r_offset += ArpWg) {
285
+ uint32_t B_ly = r_offset + Ar;
286
+ uint32_t B_lx = Ac;
287
+ uint32_t K_idx = B_idx_K * BS_K + B_ly; /* Global K_idx (row index of A)*/
288
+ #ifdef TRANSPOSE
289
+ uint32_t knl_idx = KW_idx_a + KH_idx_a * p.nb01 + K_idx * p.nb02 + Cin_idx_a * p.nb03;
290
+ #else
291
+ uint32_t knl_idx = KW_idx_a + KH_idx_a * p.nb01 + Cin_idx_a * p.nb02 + K_idx * p.nb03;
292
+ #endif
293
+ if (aligned == 0) {
294
+ knl_idx = min(knl_idx, K * CRS - 1);
295
+ }
296
+ float val = knl_data[knl_idx];
297
+ if (aligned == 0 && (K_idx >= K || CRS_idx_a >= CRS)) {
298
+ val = 0.0;
299
+ }
300
+ Ash[B_ly * Ash_stride + B_lx] = SHMEM_TYPE(val);
301
+ }
302
+ /* Load input to B_block: (BS_CRS x BS_NPQ) */
303
+ UNROLL for (uint32_t r_offset = 0; r_offset < BS_CRS; r_offset += BrpWg) {
304
+ uint32_t B_ly = r_offset + Br; /* Row index of B block */
305
+ uint32_t B_lx = Bc;
306
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + B_lx; /* Global NPQ index (column index of B) */
307
+ uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL); // divide by p.OH * p.OW;
308
+ uint32_t NPQ_remainder = NPQ_idx - N_idx * p.OH * p.OW;
309
+ uint32_t OH_idx = fastdiv(NPQ_remainder, p.OWmp, p.OWL); // divide by p.OW;
310
+ uint32_t OW_idx = NPQ_remainder - OH_idx * p.OW;
311
+
312
+ uint32_t CRS_idx_b;
313
+ uint32_t Cin_idx_b;
314
+ uint32_t KH_idx_b;
315
+ uint32_t KW_idx_b;
316
+ #ifdef USE_COLLECTIVES
317
+ if (use_collectives == 1) {
318
+ CRS_idx_b = subgroupShuffle(cached_CRS_idx, r_offset + Br);
319
+ Cin_idx_b = subgroupShuffle(cached_Cin_idx, r_offset + Br);
320
+ KH_idx_b = subgroupShuffle(cached_KH_idx, r_offset + Br);
321
+ KW_idx_b = subgroupShuffle(cached_KW_idx, r_offset + Br);
322
+ } else {
323
+ CRS_idx_b = B_idx_CRS * BS_CRS + B_ly; /* Global CRS index (row index of B) */
324
+ Cin_idx_b = CRS_idx_b / (KW * KH);
325
+ uint32_t CRS_remainder = CRS_idx_b % (KW * KH);
326
+ KH_idx_b = CRS_remainder / KW;
327
+ KW_idx_b = CRS_remainder % KW;
328
+ }
329
+ #else
330
+ CRS_idx_b = B_idx_CRS * BS_CRS + B_ly; /* Global CRS index (row index of B) */
331
+ Cin_idx_b = CRS_idx_b / (KW * KH);
332
+ uint32_t CRS_remainder = CRS_idx_b % (KW * KH);
333
+ KH_idx_b = CRS_remainder / KW;
334
+ KW_idx_b = CRS_remainder % KW;
335
+ #endif
336
+
337
+ #ifdef TRANSPOSE
338
+ uint32_t H_idx_x_s1 = OH_idx - KH_idx_b * d1 + p1;
339
+ uint32_t W_idx_x_s0 = OW_idx - KW_idx_b * d0 + p0;
340
+ uint32_t H_idx = H_idx_x_s1 / s1;
341
+ uint32_t W_idx = W_idx_x_s0 / s0;
342
+ #else
343
+ uint32_t H_idx = OH_idx * s1 + KH_idx_b * d1 - p1;
344
+ uint32_t W_idx = OW_idx * s0 + KW_idx_b * d0 - p0;
345
+ #endif
346
+ uint32_t src_idx = W_idx + H_idx * p.nb11 + Cin_idx_b * p.nb12 + N_idx * p.nb13;
347
+ // skip clamp when address can't go OOB
348
+ if (aligned == 0 || !hw_in_bounds || !stride_in_bounds) {
349
+ src_idx = min(max(src_idx, 0), p.Cin * p.N * p.W * p.H - 1);
350
+ }
351
+ float val = src_data[src_idx];
352
+ bool oob = false;
353
+ if (aligned == 0 && (CRS_idx_b >= CRS || NPQ_idx >= NPQ)) {
354
+ oob = true;
355
+ }
356
+ // also catches lower-bound underflow (idx wraps to 0x80000000+)
357
+ if (!hw_in_bounds && (H_idx >= p.H || W_idx >= p.W)) {
358
+ oob = true;
359
+ }
360
+ #ifdef TRANSPOSE
361
+ if (!stride_in_bounds &&
362
+ ((H_idx_x_s1 - H_idx * s1 != 0) || (W_idx_x_s0 - W_idx * s0 != 0))) {
363
+ oob = true;
364
+ }
365
+ #endif
366
+ if (oob) {
367
+ val = 0.0;
368
+ }
369
+ Bsh[B_ly * Bsh_stride + B_lx] = SHMEM_TYPE(val);
370
+ }
371
+ barrier();
372
+ #ifdef COOPMAT2
373
+ coopmat<float16_t, gl_ScopeWorkgroup, BS_K, BS_CRS, gl_MatrixUseA> matA;
374
+ coopmat<float16_t, gl_ScopeWorkgroup, BS_CRS, BS_NPQ, gl_MatrixUseB> matB;
375
+
376
+ coopMatLoad(matA, Ash, 0, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
377
+ coopMatLoad(matB, Bsh, 0, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
378
+ matC = coopMatMulAdd(matA, matB, matC);
379
+ #elif defined(COOPMAT)
380
+ // each subgroup multiplies its grid of fragments per TK-sized CRS chunk
381
+ [[unroll]] for (uint k_step = 0; k_step < BS_CRS / TK; k_step++) {
382
+ coopmat<float16_t, gl_ScopeSubgroup, TM, TK, gl_MatrixUseA> cache_a[cms_per_row];
383
+ [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
384
+ const uint a_off = (warp_r * WM + cm_row * TM) * Ash_stride + k_step * TK;
385
+ coopMatLoad(cache_a[cm_row], Ash, a_off, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
386
+ }
387
+ [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
388
+ coopmat<float16_t, gl_ScopeSubgroup, TK, TN, gl_MatrixUseB> cache_b;
389
+ const uint b_off = k_step * TK * Bsh_stride + warp_c * WN + cm_col * TN;
390
+ coopMatLoad(cache_b, Bsh, b_off, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
391
+ [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
392
+ sums[cm_col * cms_per_row + cm_row] = coopMatMulAdd(cache_a[cm_row], cache_b, sums[cm_col * cms_per_row + cm_row]);
393
+ }
394
+ }
395
+ }
396
+ #else
397
+ if (T_y * TS_K < K) {
398
+ UNROLL for (uint32_t CRS_lidx = 0; CRS_lidx < BS_CRS; CRS_lidx++) {
399
+ float regA[TS_K];
400
+ float regB[TS_NPQ];
401
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
402
+ regA[T_ly] = Ash[(T_y * TS_K + T_ly) * Ash_stride + CRS_lidx];
403
+ }
404
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
405
+ regB[T_lx] = Bsh[CRS_lidx * Bsh_stride + T_x * TS_NPQ + T_lx];
406
+ }
407
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
408
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
409
+ regC[T_ly][T_lx] = fma(regA[T_ly], regB[T_lx], regC[T_ly][T_lx]);
410
+ }
411
+ }
412
+ }
413
+ }
414
+ #endif
415
+ barrier();
416
+ }
417
+ /* Save C* */
418
+ #if defined(COOPMAT2) || defined(COOPMAT)
419
+ // stage matC into Csh, then write to dst with coalesced NPQ-contiguous stores
420
+ #ifdef COOPMAT
421
+ const bool use_staged_store = true;
422
+ #else
423
+ const bool use_staged_store = (csh_store != 0);
424
+ #endif
425
+ if (use_staged_store) {
426
+ #ifdef COOPMAT
427
+ // cm1: each subgroup stores its fragment grid into its Csh slot
428
+ [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
429
+ [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
430
+ const uint csh_off = (warp_r * WM + cm_row * TM) * Csh_stride + warp_c * WN + cm_col * TN;
431
+ coopMatStore(sums[cm_col * cms_per_row + cm_row], Csh, csh_off, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
432
+ }
433
+ }
434
+ #else
435
+ coopMatStore(matC, Csh, 0, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
436
+ #endif
437
+ barrier();
438
+
439
+ // cooperative shmem->global: WG threads spread across BS_NPQ (the
440
+ // contiguous direction of dst), each iter covers store_rows_per_iter K-rows
441
+ const uint32_t store_rows_per_iter = WG_SIZE / BS_NPQ;
442
+ const uint32_t store_iters = BS_K / store_rows_per_iter;
443
+ const uint32_t k_thread_offset = tid / BS_NPQ;
444
+ const uint32_t npq_thread = tid % BS_NPQ;
445
+ [[unroll]] for (uint32_t i = 0; i < store_iters; i++) {
446
+ uint32_t k_local = i * store_rows_per_iter + k_thread_offset;
447
+ uint32_t K_idx = B_idx_K * BS_K + k_local;
448
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + npq_thread;
449
+ uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL);
450
+ uint32_t OH_idx = fastdiv(NPQ_idx - N_idx * p.OH * p.OW, p.OWmp, p.OWL);
451
+ uint32_t OW_idx = NPQ_idx - N_idx * p.OH * p.OW - OH_idx * p.OW;
452
+ uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + K_idx * p.nb2 + N_idx * p.nb3;
453
+ if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
454
+ dst_data[dst_idx] = D_TYPE(Csh[k_local * Csh_stride + npq_thread]);
455
+ }
456
+ }
457
+ }
458
+ #ifdef COOPMAT2
459
+ else {
460
+ coopMatPerElementNV(matC, matC, perElemOpStore);
461
+ }
462
+ #endif
463
+ #else
464
+ if (T_y * TS_K < K) {
465
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
466
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
467
+ uint32_t K_idx = B_idx_K * BS_K + T_y * TS_K + T_ly;
468
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + T_x * TS_NPQ + T_lx;
469
+ uint32_t N_idx = fastdiv(NPQ_idx, p.OWOHmp, p.OWOHL); // divide by p.OH * p.OW;
470
+ uint32_t OH_idx = fastdiv(NPQ_idx - N_idx * p.OH * p.OW, p.OWmp, p.OWL); // divide by p.OW;
471
+ uint32_t OW_idx = NPQ_idx - N_idx * p.OH * p.OW - OH_idx * p.OW;
472
+ uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + K_idx * p.nb2 + N_idx * p.nb3;
473
+ if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
474
+ dst_data[dst_idx] = regC[T_ly][T_lx];
475
+ }
476
+ }
477
+ }
478
+ }
479
+ #endif
480
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp ADDED
@@ -0,0 +1,431 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_control_flow_attributes : enable
4
+ #ifdef COOPMAT2
5
+ #extension GL_NV_cooperative_matrix2 : enable
6
+ #extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
7
+ #extension GL_KHR_memory_scope_semantics : enable
8
+ #endif
9
+
10
+ #ifdef COOPMAT
11
+ #extension GL_KHR_cooperative_matrix : enable
12
+ #extension GL_KHR_shader_subgroup_basic : enable
13
+ #extension GL_EXT_shader_explicit_arithmetic_types_float16 : require
14
+ #extension GL_KHR_memory_scope_semantics : enable
15
+ #endif
16
+
17
+ #include "types.glsl"
18
+
19
+ // shape notation: [dim(N), ..., dim(0)] -- stride(dim(j)) >= stride(dim(i)) if i > j
20
+ layout(binding = 0) readonly buffer A {
21
+ A_TYPE knl_data[];
22
+ }; // src0 - kernel: [KW, KH, KD, IC*OC]
23
+
24
+ layout(binding = 1) readonly buffer B {
25
+ B_TYPE src_data[];
26
+ }; // src1 - input: [IW, IH, ID, IC*N] -- channel_first format
27
+
28
+ layout(binding = 2) writeonly buffer D {
29
+ D_TYPE dst_data[];
30
+ }; // dst - result: [OW, OH, OD, OC*N]
31
+
32
+ layout(push_constant) uniform parameter {
33
+ // I/O channels, batch size
34
+ uint32_t OC;
35
+ uint32_t IC;
36
+ uint32_t N;
37
+
38
+ // Tensor spatial sizes: input, output
39
+ uint32_t IW;
40
+ uint32_t IH;
41
+ uint32_t ID;
42
+ uint32_t OW;
43
+ uint32_t OH;
44
+ uint32_t OD;
45
+
46
+ // Strides in elements
47
+ uint32_t nb01;
48
+ uint32_t nb02;
49
+ uint32_t nb03;
50
+
51
+ uint32_t nb11;
52
+ uint32_t nb12;
53
+ uint32_t nb13;
54
+
55
+ uint32_t nb1;
56
+ uint32_t nb2;
57
+ uint32_t nb3;
58
+
59
+ // fastdiv helper values
60
+ uint32_t OWmp; uint32_t OWL;
61
+ uint32_t OWOHmp; uint32_t OWOHL;
62
+ uint32_t OWOHODmp; uint32_t OWOHODL;
63
+ }
64
+
65
+ p;
66
+
67
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
68
+ // Blocktile sizes
69
+ layout(constant_id = 1) const uint BS_K = 128;
70
+ layout(constant_id = 2) const uint BS_CRS = 16;
71
+ layout(constant_id = 3) const uint BS_NPQ = 128;
72
+ // Thread-tile sizes
73
+ layout(constant_id = 4) const uint TS_K = 8;
74
+ layout(constant_id = 5) const uint SHMEM_PAD = 4;
75
+ // Stride, padding, dilation
76
+ layout(constant_id = 6) const uint s0 = 1;
77
+ layout(constant_id = 7) const uint s1 = 1;
78
+ layout(constant_id = 8) const uint s2 = 1;
79
+ layout(constant_id = 9) const uint p0 = 0;
80
+ layout(constant_id = 10) const uint p1 = 0;
81
+ layout(constant_id = 11) const uint p2 = 0;
82
+ layout(constant_id = 12) const uint d0 = 1;
83
+ layout(constant_id = 13) const uint d1 = 1;
84
+ layout(constant_id = 14) const uint d2 = 1;
85
+ // Kernel spatial sizes
86
+ layout(constant_id = 15) const uint KW = 1;
87
+ layout(constant_id = 16) const uint KH = 1;
88
+ layout(constant_id = 17) const uint KD = 1;
89
+ // when set, skip bounds checks and address clamps (K/CRS/NPQ are tile-aligned)
90
+ layout(constant_id = 18) const uint aligned = 0;
91
+ // stage cm2 result through shmem (Csh) for coalesced stores. cm1 always does this.
92
+ layout(constant_id = 19) const uint csh_store = 0;
93
+
94
+ #ifdef COOPMAT
95
+ // cm1 subgroup tile: each subgroup computes a WM x WN region as a grid of
96
+ // TM x TN x TK fragments. Requires WM%TM == WN%TN == BS_K%WM == BS_NPQ%WN ==
97
+ // BS_CRS%TK == 0, and WG_SIZE == (BS_K/WM) * (BS_NPQ/WN) * subgroup_size.
98
+ layout(constant_id = 20) const uint WM = 32;
99
+ layout(constant_id = 21) const uint WN = 32;
100
+ const uint TM = 16;
101
+ const uint TN = 16;
102
+ const uint TK = 16;
103
+ const uint cms_per_row = WM / TM;
104
+ const uint cms_per_col = WN / TN;
105
+ const uint warps_M = BS_K / WM;
106
+ const uint warps_N = BS_NPQ / WN;
107
+ #endif
108
+
109
+ // without padding, ID_idx/IH_idx/IW_idx are in bounds by construction
110
+ const bool dhw_in_bounds = (p0 == 0) && (p1 == 0) && (p2 == 0);
111
+
112
+ uint32_t tid = gl_LocalInvocationID.x;
113
+ const uint32_t WG_SIZE = gl_WorkGroupSize.x;
114
+
115
+ uint splitWork(uint work_size, uint block_size) {
116
+ return (block_size + work_size - 1) / block_size;
117
+ }
118
+
119
+ uint32_t K = p.OC;
120
+ uint32_t CRS = p.IC * KD * KH * KW;
121
+ uint32_t NPQ = p.N * p.OD * p.OH * p.OW;
122
+
123
+ // Number of blocktiles per input
124
+ uint32_t NB_CRS = splitWork(CRS, BS_CRS);
125
+
126
+ #if defined(COOPMAT2) || defined(COOPMAT)
127
+ #define SHMEM_TYPE float16_t
128
+ #else
129
+ #define SHMEM_TYPE float
130
+ #endif
131
+
132
+ const uint32_t Ash_stride = BS_CRS + SHMEM_PAD;
133
+ const uint32_t Bsh_stride = BS_NPQ + SHMEM_PAD;
134
+
135
+ const uint32_t Ash_len = BS_K * Ash_stride;
136
+ const uint32_t Bsh_len = BS_CRS * Bsh_stride;
137
+
138
+ shared SHMEM_TYPE Ash[Ash_len]; // K x CRS
139
+ shared SHMEM_TYPE Bsh[Bsh_len]; // CRS x NPQ
140
+
141
+ #if defined(COOPMAT2) || defined(COOPMAT)
142
+ // stage matC through shmem so global stores are row-major (NPQ-contiguous)
143
+ const uint32_t Csh_stride = BS_NPQ;
144
+ #ifdef COOPMAT
145
+ const uint32_t Csh_len = BS_K * Csh_stride;
146
+ #else
147
+ const uint32_t Csh_len = csh_store != 0 ? BS_K * Csh_stride : 8; // 8 to workaround compiler bug
148
+ #endif
149
+ shared SHMEM_TYPE Csh[Csh_len]; // K x NPQ
150
+ #endif
151
+
152
+ // Threadtile sizes
153
+ const uint32_t TS_NPQ = BS_K * BS_NPQ / WG_SIZE / TS_K;
154
+
155
+ // Number of threadtiles per blocktile
156
+ const uint32_t NT_NPQ = BS_NPQ / TS_NPQ;
157
+
158
+ /*
159
+ Compute
160
+ KxCRS @ CRSxNPQ = K x NPQ
161
+ K=OC
162
+ C=IC
163
+ D,R,S=KD,KH,KW
164
+ Z,P,Q=OD,OH,OW
165
+ */
166
+
167
+ uint32_t B_idx_K = gl_WorkGroupID.x;
168
+ uint32_t B_idx_NPQ = gl_WorkGroupID.y + gl_WorkGroupID.z * 512;
169
+
170
+ uint32_t T_y = tid / NT_NPQ;
171
+ uint32_t T_x = tid % NT_NPQ;
172
+
173
+ uint32_t Ar = tid / BS_CRS;
174
+ uint32_t Ac = tid % BS_CRS;
175
+ const uint32_t ArpWg = WG_SIZE / BS_CRS;
176
+
177
+ uint32_t Br = tid / BS_NPQ;
178
+ uint32_t Bc = tid % BS_NPQ;
179
+ const uint32_t BrpWg = WG_SIZE / BS_NPQ;
180
+
181
+ // see init_fastdiv_values in ggml-vulkan.cpp
182
+ uint fastdiv(uint n, uint mp, uint L) {
183
+ uint msbs, lsbs;
184
+ // msbs = mulhi(n, mp)
185
+ umulExtended(n, mp, msbs, lsbs);
186
+ return (msbs + n) >> L;
187
+ }
188
+
189
+ void split_crs(uint32_t crs_idx, out uint32_t ic, out uint32_t kd, out uint32_t kh, out uint32_t kw) {
190
+ const uint32_t KHKW = KH * KW;
191
+ const uint32_t KDKHKW = KD * KHKW;
192
+ ic = crs_idx / KDKHKW;
193
+ uint32_t rem = crs_idx - ic * KDKHKW;
194
+ kd = rem / KHKW;
195
+ rem = rem - kd * KHKW;
196
+ kh = rem / KW;
197
+ kw = rem - kh * KW;
198
+ }
199
+
200
+ void split_npq(uint32_t npq_idx, out uint32_t n, out uint32_t od, out uint32_t oh, out uint32_t ow) {
201
+ const uint32_t OWOH = p.OW * p.OH;
202
+ n = fastdiv(npq_idx, p.OWOHODmp, p.OWOHODL);
203
+ uint32_t rem = npq_idx - n * p.OD * OWOH;
204
+ od = fastdiv(rem, p.OWOHmp, p.OWOHL);
205
+ rem = rem - od * OWOH;
206
+ oh = fastdiv(rem, p.OWmp, p.OWL);
207
+ ow = rem - oh * p.OW;
208
+ }
209
+
210
+ #ifdef COOPMAT2
211
+ #define ACC_TYPE float16_t
212
+
213
+ ACC_TYPE perElemOpStore(const in uint32_t r, const in uint32_t c, const in ACC_TYPE elem)
214
+ {
215
+ uint32_t K_idx = B_idx_K * BS_K + r;
216
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + c;
217
+ uint32_t N_idx;
218
+ uint32_t OD_idx;
219
+ uint32_t OH_idx;
220
+ uint32_t OW_idx;
221
+ split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
222
+ uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + OD_idx * p.nb2 + (N_idx * p.OC + K_idx) * p.nb3;
223
+ if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
224
+ dst_data[dst_idx] = D_TYPE(elem);
225
+ }
226
+ return elem;
227
+ }
228
+ #endif
229
+
230
+ void main() {
231
+ if (B_idx_NPQ * BS_NPQ >= NPQ) {
232
+ return;
233
+ }
234
+
235
+ #ifdef COOPMAT2
236
+ coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator> matC;
237
+ matC = coopmat<ACC_TYPE, gl_ScopeWorkgroup, BS_K, BS_NPQ, gl_MatrixUseAccumulator>(0.0);
238
+ #elif defined(COOPMAT)
239
+ coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator> sums[cms_per_row * cms_per_col];
240
+ [[unroll]] for (uint i = 0; i < cms_per_row * cms_per_col; i++) {
241
+ sums[i] = coopmat<float16_t, gl_ScopeSubgroup, TM, TN, gl_MatrixUseAccumulator>(0.0);
242
+ }
243
+ const uint warp_r = gl_SubgroupID / warps_N;
244
+ const uint warp_c = gl_SubgroupID % warps_N;
245
+ #else
246
+ float regC[TS_K][TS_NPQ];
247
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
248
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
249
+ regC[T_ly][T_lx] = 0.0;
250
+ }
251
+ }
252
+ #endif
253
+ /* Advance block in CRS dim */
254
+ [[dont_unroll]] for (uint32_t B_idx_CRS = 0; B_idx_CRS < NB_CRS; B_idx_CRS++) {
255
+ uint32_t CRS_idx_a = B_idx_CRS * BS_CRS + Ac;
256
+ uint32_t IC_idx_a;
257
+ uint32_t KD_idx_a;
258
+ uint32_t KH_idx_a;
259
+ uint32_t KW_idx_a;
260
+ split_crs(CRS_idx_a, IC_idx_a, KD_idx_a, KH_idx_a, KW_idx_a);
261
+
262
+ /* Load kernel to A_block: (BS_K x BS_CRS)*/
263
+ UNROLL for (uint32_t r_offset = 0; r_offset < BS_K; r_offset += ArpWg) {
264
+ uint32_t B_ly = r_offset + Ar;
265
+ uint32_t B_lx = Ac;
266
+ uint32_t K_idx = B_idx_K * BS_K + B_ly; /* Global K_idx (row index of A)*/
267
+ uint32_t knl_idx = KW_idx_a + KH_idx_a * p.nb01 + KD_idx_a * p.nb02 + (K_idx * p.IC + IC_idx_a) * p.nb03;
268
+ if (aligned == 0) {
269
+ knl_idx = min(knl_idx, K * CRS - 1);
270
+ }
271
+ float val = knl_data[knl_idx];
272
+ if (aligned == 0 && (K_idx >= K || CRS_idx_a >= CRS)) {
273
+ val = 0.0;
274
+ }
275
+ Ash[B_ly * Ash_stride + B_lx] = SHMEM_TYPE(val);
276
+ }
277
+ /* Load input to B_block: (BS_CRS x BS_NPQ) */
278
+ UNROLL for (uint32_t r_offset = 0; r_offset < BS_CRS; r_offset += BrpWg) {
279
+ uint32_t B_ly = r_offset + Br; /* Row index of B block */
280
+ uint32_t B_lx = Bc;
281
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + B_lx; /* Global NPQ index (column index of B) */
282
+ uint32_t N_idx;
283
+ uint32_t OD_idx;
284
+ uint32_t OH_idx;
285
+ uint32_t OW_idx;
286
+ split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
287
+
288
+ uint32_t CRS_idx_b = B_idx_CRS * BS_CRS + B_ly;
289
+ uint32_t IC_idx_b;
290
+ uint32_t KD_idx_b;
291
+ uint32_t KH_idx_b;
292
+ uint32_t KW_idx_b;
293
+ split_crs(CRS_idx_b, IC_idx_b, KD_idx_b, KH_idx_b, KW_idx_b);
294
+
295
+ uint32_t ID_idx = OD_idx * s2 + KD_idx_b * d2 - p2;
296
+ uint32_t IH_idx = OH_idx * s1 + KH_idx_b * d1 - p1;
297
+ uint32_t IW_idx = OW_idx * s0 + KW_idx_b * d0 - p0;
298
+
299
+ uint32_t src_idx = IW_idx + IH_idx * p.nb11 + ID_idx * p.nb12 + (N_idx * p.IC + IC_idx_b) * p.nb13;
300
+ // skip clamp when address can't go OOB
301
+ if (aligned == 0 || !dhw_in_bounds) {
302
+ src_idx = min(src_idx, p.IC * p.N * p.IW * p.IH * p.ID - 1);
303
+ }
304
+ float val = src_data[src_idx];
305
+ bool oob = false;
306
+ if (aligned == 0 && (CRS_idx_b >= CRS || NPQ_idx >= NPQ)) {
307
+ oob = true;
308
+ }
309
+ // also catches lower-bound underflow (idx wraps to 0x80000000+)
310
+ if (!dhw_in_bounds && (ID_idx >= p.ID || IH_idx >= p.IH || IW_idx >= p.IW)) {
311
+ oob = true;
312
+ }
313
+ if (oob) {
314
+ val = 0.0;
315
+ }
316
+ Bsh[B_ly * Bsh_stride + B_lx] = SHMEM_TYPE(val);
317
+ }
318
+ barrier();
319
+ #ifdef COOPMAT2
320
+ coopmat<float16_t, gl_ScopeWorkgroup, BS_K, BS_CRS, gl_MatrixUseA> matA;
321
+ coopmat<float16_t, gl_ScopeWorkgroup, BS_CRS, BS_NPQ, gl_MatrixUseB> matB;
322
+
323
+ coopMatLoad(matA, Ash, 0, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
324
+ coopMatLoad(matB, Bsh, 0, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
325
+ matC = coopMatMulAdd(matA, matB, matC);
326
+ #elif defined(COOPMAT)
327
+ // each subgroup multiplies its grid of fragments per TK-sized CRS chunk
328
+ [[unroll]] for (uint k_step = 0; k_step < BS_CRS / TK; k_step++) {
329
+ coopmat<float16_t, gl_ScopeSubgroup, TM, TK, gl_MatrixUseA> cache_a[cms_per_row];
330
+ [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
331
+ const uint a_off = (warp_r * WM + cm_row * TM) * Ash_stride + k_step * TK;
332
+ coopMatLoad(cache_a[cm_row], Ash, a_off, Ash_stride, gl_CooperativeMatrixLayoutRowMajor);
333
+ }
334
+ [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
335
+ coopmat<float16_t, gl_ScopeSubgroup, TK, TN, gl_MatrixUseB> cache_b;
336
+ const uint b_off = k_step * TK * Bsh_stride + warp_c * WN + cm_col * TN;
337
+ coopMatLoad(cache_b, Bsh, b_off, Bsh_stride, gl_CooperativeMatrixLayoutRowMajor);
338
+ [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
339
+ sums[cm_col * cms_per_row + cm_row] = coopMatMulAdd(cache_a[cm_row], cache_b, sums[cm_col * cms_per_row + cm_row]);
340
+ }
341
+ }
342
+ }
343
+ #else
344
+ if (T_y * TS_K < K) {
345
+ UNROLL for (uint32_t CRS_lidx = 0; CRS_lidx < BS_CRS; CRS_lidx++) {
346
+ float regA[TS_K];
347
+ float regB[TS_NPQ];
348
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
349
+ regA[T_ly] = Ash[(T_y * TS_K + T_ly) * Ash_stride + CRS_lidx];
350
+ }
351
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
352
+ regB[T_lx] = Bsh[CRS_lidx * Bsh_stride + T_x * TS_NPQ + T_lx];
353
+ }
354
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
355
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
356
+ regC[T_ly][T_lx] = fma(regA[T_ly], regB[T_lx], regC[T_ly][T_lx]);
357
+ }
358
+ }
359
+ }
360
+ }
361
+ #endif
362
+ barrier();
363
+ }
364
+ /* Save C* */
365
+ #if defined(COOPMAT2) || defined(COOPMAT)
366
+ // stage matC into Csh, then write to dst with coalesced NPQ-contiguous stores
367
+ #ifdef COOPMAT
368
+ const bool use_staged_store = true;
369
+ #else
370
+ const bool use_staged_store = (csh_store != 0);
371
+ #endif
372
+ if (use_staged_store) {
373
+ #ifdef COOPMAT
374
+ // cm1: each subgroup stores its fragment grid into its Csh slot
375
+ [[unroll]] for (uint cm_row = 0; cm_row < cms_per_row; cm_row++) {
376
+ [[unroll]] for (uint cm_col = 0; cm_col < cms_per_col; cm_col++) {
377
+ const uint csh_off = (warp_r * WM + cm_row * TM) * Csh_stride + warp_c * WN + cm_col * TN;
378
+ coopMatStore(sums[cm_col * cms_per_row + cm_row], Csh, csh_off, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
379
+ }
380
+ }
381
+ #else
382
+ coopMatStore(matC, Csh, 0, Csh_stride, gl_CooperativeMatrixLayoutRowMajor);
383
+ #endif
384
+ barrier();
385
+
386
+ // cooperative shmem->global: WG threads spread across BS_NPQ (the
387
+ // contiguous direction of dst), each iter covers store_rows_per_iter K-rows
388
+ const uint32_t store_rows_per_iter = WG_SIZE / BS_NPQ;
389
+ const uint32_t store_iters = BS_K / store_rows_per_iter;
390
+ const uint32_t k_thread_offset = tid / BS_NPQ;
391
+ const uint32_t npq_thread = tid % BS_NPQ;
392
+ [[unroll]] for (uint32_t i = 0; i < store_iters; i++) {
393
+ uint32_t k_local = i * store_rows_per_iter + k_thread_offset;
394
+ uint32_t K_idx = B_idx_K * BS_K + k_local;
395
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + npq_thread;
396
+ uint32_t N_idx;
397
+ uint32_t OD_idx;
398
+ uint32_t OH_idx;
399
+ uint32_t OW_idx;
400
+ split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
401
+ uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + OD_idx * p.nb2 + (N_idx * p.OC + K_idx) * p.nb3;
402
+ if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
403
+ dst_data[dst_idx] = D_TYPE(Csh[k_local * Csh_stride + npq_thread]);
404
+ }
405
+ }
406
+ }
407
+ #ifdef COOPMAT2
408
+ else {
409
+ coopMatPerElementNV(matC, matC, perElemOpStore);
410
+ }
411
+ #endif
412
+ #else
413
+ if (T_y * TS_K < K) {
414
+ for (uint32_t T_ly = 0; T_ly < TS_K; T_ly++) {
415
+ for (uint32_t T_lx = 0; T_lx < TS_NPQ; T_lx++) {
416
+ uint32_t K_idx = B_idx_K * BS_K + T_y * TS_K + T_ly;
417
+ uint32_t NPQ_idx = B_idx_NPQ * BS_NPQ + T_x * TS_NPQ + T_lx;
418
+ uint32_t N_idx;
419
+ uint32_t OD_idx;
420
+ uint32_t OH_idx;
421
+ uint32_t OW_idx;
422
+ split_npq(NPQ_idx, N_idx, OD_idx, OH_idx, OW_idx);
423
+ uint32_t dst_idx = OW_idx + OH_idx * p.nb1 + OD_idx * p.nb2 + (N_idx * p.OC + K_idx) * p.nb3;
424
+ if (aligned != 0 || (K_idx < K && NPQ_idx < NPQ)) {
425
+ dst_data[dst_idx] = D_TYPE(regC[T_ly][T_lx]);
426
+ }
427
+ }
428
+ }
429
+ }
430
+ #endif
431
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv_transpose_1d.comp ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+
5
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];}; // src0 - kernel: [K, Cout, Cin]
6
+ layout (binding = 1) readonly buffer B {B_TYPE data_b[];}; // src1 - input: [L, Cin]
7
+ layout (binding = 2) writeonly buffer D {D_TYPE data_d[];}; // dst - result [KL, Cout]
8
+
9
+ layout(local_size_x = 128 , local_size_y = 1, local_size_z = 1) in;
10
+
11
+ layout (push_constant) uniform parameter {
12
+ uint32_t Cout;
13
+ uint32_t Cin;
14
+ uint32_t K;
15
+ uint32_t L;
16
+ uint32_t KL;
17
+
18
+ uint32_t nb01;
19
+ uint32_t nb02;
20
+ uint32_t nb11;
21
+ uint32_t nb1;
22
+
23
+ int32_t s0;
24
+ } p;
25
+
26
+
27
+ uint32_t Cout_idx = gl_WorkGroupID.x;
28
+ const uint32_t bs = gl_WorkGroupSize.x;
29
+ uint32_t tid = gl_LocalInvocationID.x;
30
+ // Code is more straightforward if we assume it is bs*s0+K instead of (bs-1)*s0+K.
31
+ uint32_t tmp_len = bs*p.s0+p.K;
32
+ shared D_TYPE tmp[4096];
33
+
34
+ uint splitWork(uint workSize){
35
+ return (bs + workSize -1) / bs;
36
+ }
37
+
38
+ void main(){
39
+ for(uint32_t i = 0; i < splitWork(tmp_len); i++){
40
+ uint32_t idx = i*bs+tid;
41
+ if(idx < tmp_len){
42
+ tmp[idx] = 0.0;
43
+ }
44
+ }
45
+
46
+ uint32_t L_blocks = splitWork(p.L);
47
+ for(uint32_t L_block_id = 0; L_block_id < L_blocks; L_block_id++){
48
+ if(L_block_id > 0){
49
+ barrier();
50
+ // Shift values in tmp to the current processing window
51
+ for(int i = 0; i < splitWork(tmp_len); i++){
52
+ uint32_t idx = i*bs+tid;
53
+ if(idx >= bs*p.s0 && idx < tmp_len){
54
+ tmp[idx-bs*p.s0] = tmp[idx];
55
+ tmp[idx] = 0.0;
56
+ }else if(idx >= p.K && idx < bs*p.s0){
57
+ tmp[idx] = 0.0;
58
+ }
59
+ }
60
+ }
61
+ barrier();
62
+
63
+ // Save contributions of the block to tmp
64
+ uint32_t L_idx = L_block_id*bs + tid;
65
+ for(uint32_t K_idx = 0; K_idx < p.K; K_idx++){
66
+ D_TYPE dp = 0.0;
67
+ for(uint32_t Cin_idx = 0; Cin_idx < p.Cin; Cin_idx++){
68
+ A_TYPE elemKrn = data_a[K_idx + Cout_idx * p.nb01 + Cin_idx * p.nb02];
69
+ if(L_idx < p.L){
70
+ B_TYPE elemInp = data_b[L_idx + Cin_idx*p.nb11];
71
+ dp = fma(elemKrn, elemInp, dp);
72
+ }
73
+ }
74
+ tmp[tid*p.s0 + K_idx] += dp;
75
+ barrier();
76
+ }
77
+
78
+ // Save the computed values except the last block that can have different size
79
+ uint32_t KLb_idx = L_block_id*bs*p.s0;
80
+ if(L_block_id < L_blocks-1){
81
+ for(uint32_t s0_idx = 0; s0_idx < p.s0; s0_idx++){
82
+ uint32_t sh_idx = p.s0*tid+s0_idx;
83
+ uint32_t KL_idx = KLb_idx+sh_idx;
84
+ if(KL_idx < p.KL){
85
+ data_d[KL_idx + Cout_idx*p.nb1] = tmp[sh_idx];
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ for(uint32_t i = 0; i < splitWork(tmp_len); i++){
92
+ uint32_t idx = i*bs+tid;
93
+ uint32_t KL_idx = (L_blocks-1)*bs*p.s0+idx;
94
+ if(KL_idx < p.KL){
95
+ data_d[KL_idx + Cout_idx*p.nb1] = tmp[idx];
96
+ }
97
+ }
98
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy.comp ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "generic_unary_head.glsl"
5
+
6
+ layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
7
+
8
+ void main() {
9
+ const uint idx = get_idx();
10
+
11
+ if (idx >= p.ne) {
12
+ return;
13
+ }
14
+
15
+ #if defined(DATA_A_BF16)
16
+ data_d[get_doffset() + dst_idx(idx)] = D_TYPE(bf16_to_fp32(uint32_t(data_a[get_aoffset() + src0_idx(idx)])));
17
+ #elif defined(DATA_D_BF16)
18
+ float f = float(data_a[get_aoffset() + src0_idx(idx)]);
19
+ data_d[get_doffset() + dst_idx(idx)] = D_TYPE(fp32_to_bf16(f));
20
+ #elif !defined(OPTIMIZATION_ERROR_WORKAROUND)
21
+ data_d[get_doffset() + dst_idx(idx)] = D_TYPE(data_a[get_aoffset() + src0_idx(idx)]);
22
+ #else
23
+ data_d[get_doffset() + dst_idx(idx)] = data_a[get_aoffset() + src0_idx(idx)];
24
+ #endif
25
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "generic_unary_head.glsl"
5
+ #include "dequant_funcs.glsl"
6
+
7
+ #if defined(DATA_A_IQ4_NL) || defined(DATA_A_MXFP4) || defined(DATA_A_NVFP4)
8
+ // 16 invocations needed for init_iq_shmem
9
+ layout(local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
10
+ #else
11
+ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
12
+ #endif
13
+
14
+ void main() {
15
+ #ifdef NEEDS_INIT_IQ_SHMEM
16
+ init_iq_shmem(gl_WorkGroupSize);
17
+ if (gl_LocalInvocationIndex.x != 0) {
18
+ return;
19
+ }
20
+ #endif
21
+
22
+ const uint idx = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * QUANT_K;
23
+
24
+ if (idx >= p.ne) {
25
+ return;
26
+ }
27
+
28
+ uint dst_idx = get_doffset() + dst_idx(idx);
29
+ uint src_idx = src0_idx_quant(idx, QUANT_K);
30
+
31
+ const uint a_offset = 0;
32
+ const uint ib = src_idx;
33
+ const vec2 dm = get_dm(ib, a_offset);
34
+
35
+ [[unroll]] for (int j = 0; j < QUANT_K; j += 4) {
36
+ vec4 v = dequantize4(ib, j / QUANT_R, a_offset);
37
+ v = v * dm.x + vec4(dm.y);
38
+
39
+ #if QUANT_R == 2
40
+ data_d[dst_idx + j/2 + 0] = v[0];
41
+ data_d[dst_idx + j/2 + QUANT_K/2 + 0] = v[1];
42
+ data_d[dst_idx + j/2 + 1] = v[2];
43
+ data_d[dst_idx + j/2 + QUANT_K/2 + 1] = v[3];
44
+ #else
45
+ data_d[dst_idx + j + 0] = v[0];
46
+ data_d[dst_idx + j + 1] = v[1];
47
+ data_d[dst_idx + j + 2] = v[2];
48
+ data_d[dst_idx + j + 3] = v[3];
49
+ #endif
50
+ }
51
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+
5
+ #if defined(SET_ROWS) && QUANT_K == 1
6
+ layout(local_size_x = 512, local_size_y = 1, local_size_z = 1) in;
7
+ const uint BLOCK_SIZE = 512;
8
+ #else
9
+ layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
10
+ const uint BLOCK_SIZE = 32;
11
+ #endif
12
+
13
+ layout (binding = 0) readonly buffer S {float data_s[];};
14
+
15
+ #if defined(SET_ROWS)
16
+ #include "generic_binary_head.glsl"
17
+ layout (binding = 1) readonly buffer C {B_TYPE data_i[];};
18
+ layout (binding = 2) writeonly buffer Q {A_TYPE data_q[];};
19
+
20
+ #if B_SIZE == 64
21
+ #define DATA_I_SWIZZLE .x
22
+ #else
23
+ #define DATA_I_SWIZZLE
24
+ #endif
25
+
26
+ #else
27
+ #include "generic_unary_head.glsl"
28
+ layout (binding = 1) writeonly buffer Q {A_TYPE data_q[];};
29
+ #endif
30
+
31
+ #if defined(DATA_A_Q4_0)
32
+ void quantize(uint dst_idx, uint src_idx)
33
+ {
34
+ float amax = 0.0;
35
+ float vmax = 0.0;
36
+
37
+ [[unroll]] for (int j = 0; j < QUANT_K_Q4_0; ++j) {
38
+ const float v = data_s[src_idx + j];
39
+ if (amax < abs(v)) {
40
+ amax = abs(v);
41
+ vmax = v;
42
+ }
43
+ }
44
+
45
+ const float d = vmax / -8;
46
+ const float id = (d != 0.0) ? 1.0/d : 0.0;
47
+
48
+ data_q[dst_idx].d = float16_t(d);
49
+
50
+ [[unroll]] for (int j = 0; j < QUANT_K_Q4_0/2; ++j) {
51
+ const float x0 = data_s[src_idx + 0 + j]*id;
52
+ const float x1 = data_s[src_idx + QUANT_K_Q4_0/2 + j]*id;
53
+
54
+ const uint xi0 = min(15, int(x0 + 8.5));
55
+ const uint xi1 = min(15, int(x1 + 8.5));
56
+
57
+ data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4));
58
+ }
59
+ }
60
+ #endif
61
+
62
+ #if defined(DATA_A_Q4_1)
63
+ void quantize(uint dst_idx, uint src_idx)
64
+ {
65
+ float vmin = 1.0/0.0;
66
+ float vmax = -vmin;
67
+
68
+ [[unroll]] for (int j = 0; j < QUANT_K_Q4_1; ++j) {
69
+ const float v = data_s[src_idx + j];
70
+
71
+ if (v < vmin) vmin = v;
72
+ if (v > vmax) vmax = v;
73
+ }
74
+
75
+ const float d = (vmax - vmin) / ((1 << 4) - 1);
76
+ const float id = (d != 0.0) ? 1.0/d : 0.0;
77
+
78
+ data_q[dst_idx].d = float16_t(d);
79
+ data_q[dst_idx].m = float16_t(vmin);
80
+
81
+ [[unroll]] for (int j = 0; j < QUANT_K_Q4_1/2; ++j) {
82
+ const float x0 = (data_s[src_idx + 0 + j] - vmin)*id;
83
+ const float x1 = (data_s[src_idx + QUANT_K_Q4_1/2 + j] - vmin)*id;
84
+
85
+ const uint xi0 = min(15, int(x0 + 0.5));
86
+ const uint xi1 = min(15, int(x1 + 0.5));
87
+
88
+ data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4));
89
+ }
90
+ }
91
+ #endif
92
+
93
+ #if defined(DATA_A_Q5_0)
94
+ void quantize(uint dst_idx, uint src_idx)
95
+ {
96
+ float amax = 0.0;
97
+ float vmax = 0.0;
98
+
99
+ [[unroll]] for (int j = 0; j < QUANT_K_Q5_0; ++j) {
100
+ const float v = data_s[src_idx + j];
101
+ if (amax < abs(v)) {
102
+ amax = abs(v);
103
+ vmax = v;
104
+ }
105
+ }
106
+
107
+ const float d = vmax / -16;
108
+ const float id = (d != 0.0) ? 1.0/d : 0.0;
109
+
110
+ data_q[dst_idx].d = float16_t(d);
111
+
112
+ uint32_t qh = 0;
113
+ [[unroll]] for (int j = 0; j < QUANT_K_Q5_0/2; ++j) {
114
+ const float x0 = data_s[src_idx + 0 + j]*id;
115
+ const float x1 = data_s[src_idx + QUANT_K_Q5_0/2 + j]*id;
116
+
117
+ const uint xi0 = min(31, int(x0 + 16.5));
118
+ const uint xi1 = min(31, int(x1 + 16.5));
119
+
120
+ data_q[dst_idx].qs[j] = uint8_t((xi0 & 0xf) | ((xi1 & 0xf) << 4));
121
+ qh |= ((xi0 & 0x10u) >> 4) << (j + 0);
122
+ qh |= ((xi1 & 0x10u) >> 4) << (j + QUANT_K_Q5_0/2);
123
+ }
124
+ data_q[dst_idx].qh[0] = uint16_t(qh & 0xFFFF);
125
+ data_q[dst_idx].qh[1] = uint16_t(qh >> 16);
126
+ }
127
+ #endif
128
+
129
+ #if defined(DATA_A_Q5_1)
130
+ void quantize(uint dst_idx, uint src_idx)
131
+ {
132
+ float min = data_s[src_idx + 0];
133
+ float max = min;
134
+
135
+ [[unroll]] for (int j = 1; j < QUANT_K_Q5_1; ++j) {
136
+ const float v = data_s[src_idx + j];
137
+ min = v < min ? v : min;
138
+ max = v > max ? v : max;
139
+ }
140
+
141
+ const float d = (max - min) / 31;
142
+ const float id = (d != 0) ? 1.0/d : 0.0;
143
+
144
+ data_q[dst_idx].d = float16_t(d);
145
+ data_q[dst_idx].m = float16_t(min);
146
+
147
+ uint32_t qh = 0;
148
+ [[unroll]] for (int j = 0; j < QUANT_K_Q5_1/2; ++j) {
149
+ const float x0 = (data_s[src_idx + 0 + j] - min)*id;
150
+ const float x1 = (data_s[src_idx + QUANT_K_Q5_1/2 + j] - min)*id;
151
+
152
+ const uint xi0 = uint(x0 + 0.5);
153
+ const uint xi1 = uint(x1 + 0.5);
154
+
155
+ data_q[dst_idx].qs[j] = uint8_t((xi0 & 0xf) | ((xi1 & 0xf) << 4));
156
+ qh |= ((xi0 & 0x10u) >> 4) << (j + 0);
157
+ qh |= ((xi1 & 0x10u) >> 4) << (j + QUANT_K_Q5_1/2);
158
+ }
159
+ data_q[dst_idx].qh = qh;
160
+ }
161
+ #endif
162
+
163
+ #if defined(DATA_A_Q8_0)
164
+ void quantize(uint dst_idx, uint src_idx)
165
+ {
166
+ float amax = 0.0; // absolute max
167
+
168
+ [[unroll]] for (int j = 0; j < QUANT_K_Q8_0; j++) {
169
+ const float v = data_s[src_idx + j];
170
+ amax = max(amax, abs(v));
171
+ }
172
+
173
+ const float d = amax / ((1 << 7) - 1);
174
+ const float id = (d != 0.0) ? 1.0/d : 0.0;
175
+
176
+ data_q[dst_idx].d = float16_t(d);
177
+
178
+ [[unroll]] for (int j = 0; j < QUANT_K_Q8_0; ++j) {
179
+ const float x0 = data_s[src_idx + j]*id;
180
+
181
+ data_q[dst_idx].qs[j] = int8_t(round(x0));
182
+ }
183
+ }
184
+ #endif
185
+
186
+ #if defined(DATA_A_Q1_0)
187
+ void quantize(uint dst_idx, uint src_idx)
188
+ {
189
+ float sum_abs = 0.0;
190
+
191
+ [[unroll]] for (int j = 0; j < QUANT_K_Q1_0; j++) {
192
+ sum_abs += abs(data_s[src_idx + j]);
193
+ }
194
+
195
+ const float d = sum_abs / QUANT_K_Q1_0;
196
+
197
+ data_q[dst_idx].d = float16_t(d);
198
+
199
+ [[unroll]] for (int j = 0; j < QUANT_K_Q1_0 / 8; ++j) {
200
+ data_q[dst_idx].qs[j] = uint8_t(0);
201
+ }
202
+
203
+ [[unroll]] for (int j = 0; j < QUANT_K_Q1_0; ++j) {
204
+ if (data_s[src_idx + j] >= 0.0) {
205
+ data_q[dst_idx].qs[j / 8] |= uint8_t(1 << (j % 8));
206
+ }
207
+ }
208
+ }
209
+ #endif
210
+
211
+ #if defined(DATA_A_IQ4_NL)
212
+ uint best_index(float x) {
213
+ if (x <= kvalues_iq4nl[0]) return 0;
214
+ if (x >= kvalues_iq4nl[15]) return 15;
215
+ int ml = 0, mu = 15;
216
+ while (mu-ml > 1) {
217
+ int mav = (ml+mu)/2;
218
+ if (x < kvalues_iq4nl[mav]) mu = mav; else ml = mav;
219
+ }
220
+ return x - kvalues_iq4nl[mu-1] < kvalues_iq4nl[mu] - x ? mu-1 : mu;
221
+ }
222
+
223
+ void quantize(uint dst_idx, uint src_idx)
224
+ {
225
+ float amax = 0.0;
226
+ float vmax = 0.0;
227
+
228
+ [[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL; ++j) {
229
+ const float v = data_s[src_idx + j];
230
+ if (amax < abs(v)) {
231
+ amax = abs(v);
232
+ vmax = v;
233
+ }
234
+ }
235
+
236
+ float d = vmax / kvalues_iq4nl[0];
237
+ const float id = (d != 0.0) ? 1.0/d : 0.0;
238
+
239
+ float sumqx = 0, sumq2 = 0;
240
+ [[unroll]] for (int j = 0; j < QUANT_K_IQ4_NL/2; ++j) {
241
+ const float x0 = data_s[src_idx + 0 + j]*id;
242
+ const float x1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*id;
243
+ const uint xi0 = best_index(x0);
244
+ const uint xi1 = best_index(x1);
245
+ data_q[dst_idx].qs[j] = uint8_t(xi0 | (xi1 << 4));
246
+ const float v0 = kvalues_iq4nl[xi0];
247
+ const float v1 = kvalues_iq4nl[xi1];
248
+ const float w0 = data_s[src_idx + 0 + j]*data_s[src_idx + 0 + j];
249
+ const float w1 = data_s[src_idx + QUANT_K_IQ4_NL/2 + j]*data_s[src_idx + QUANT_K_IQ4_NL/2 + j];
250
+ sumqx += w0*v0*data_s[src_idx + j] + w1*v1*data_s[src_idx + QUANT_K_IQ4_NL/2 + j];
251
+ sumq2 += w0*v0*v0 + w1*v1*v1;
252
+ }
253
+
254
+ data_q[dst_idx].d = float16_t(sumq2 > 0 ? sumqx/sumq2 : d);
255
+
256
+ }
257
+ #endif
258
+
259
+ #if defined(DATA_A_F32) || defined(DATA_A_F16)
260
+ void quantize(uint dst_idx, uint src_idx)
261
+ {
262
+ data_q[dst_idx] = A_TYPE(data_s[src_idx]);
263
+ }
264
+ #endif
265
+
266
+ #if defined(DATA_A_BF16)
267
+ void quantize(uint dst_idx, uint src_idx)
268
+ {
269
+ data_q[dst_idx] = A_TYPE(fp32_to_bf16(data_s[src_idx]));
270
+ }
271
+ #endif
272
+
273
+ #if defined(SET_ROWS)
274
+
275
+ void main() {
276
+ #ifdef NEEDS_INIT_IQ_SHMEM
277
+ init_iq_shmem(gl_WorkGroupSize);
278
+ #endif
279
+
280
+ const uint idx = ((gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x) * BLOCK_SIZE + gl_LocalInvocationID.x) * QUANT_K;
281
+
282
+ if (idx >= p.ne) {
283
+ return;
284
+ }
285
+
286
+ uint i00, i01, i02, i03;
287
+ get_indices(idx, i00, i01, i02, i03);
288
+
289
+ uint i12 = fastmod(i03, p.ne12);
290
+ uint i11 = fastmod(i02, p.ne11);
291
+ uint i10 = i01;
292
+
293
+ uint i1 = data_i[src1_idx(i10, i11, i12, 0) + get_boffset()] DATA_I_SWIZZLE;
294
+
295
+ uint src0_idx = src0_idx(i00, i01, i02, i03) + get_aoffset();
296
+ uint dst_idx = dst_idx(i00 / QUANT_K, i1, i02, i03) + get_doffset();
297
+
298
+ quantize(dst_idx, src0_idx);
299
+ }
300
+
301
+ #else
302
+
303
+ void main() {
304
+ #ifdef NEEDS_INIT_IQ_SHMEM
305
+ init_iq_shmem(gl_WorkGroupSize);
306
+ #endif
307
+
308
+ const uint idx = (gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x) * QUANT_K;
309
+
310
+ if (idx >= p.ne) {
311
+ return;
312
+ }
313
+
314
+ uint dst_idx = dst_idx_quant(idx, QUANT_K);
315
+ uint src_idx = get_aoffset() + src0_idx(idx);
316
+
317
+ quantize(dst_idx, src_idx);
318
+ }
319
+
320
+ #endif
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_transpose.comp ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "generic_unary_head.glsl"
5
+
6
+ // workgroup does 32x32 tile, but uses 32x8 threads
7
+ #define TILE_DIM 32
8
+ layout(local_size_x = 32, local_size_y = 8, local_size_z = 1) in;
9
+
10
+ shared uint sh[TILE_DIM][TILE_DIM + 1];
11
+
12
+ void iter(uvec3 wg_id) {
13
+ const uint tile_col = wg_id.x;
14
+ const uint tile_row = wg_id.y;
15
+
16
+ const uint tid_col = gl_LocalInvocationID.x;
17
+ const uint tid_row = gl_LocalInvocationID.y;
18
+
19
+ const uint i2 = wg_id.z % p.ne12;
20
+ const uint i3 = wg_id.z / p.ne12;
21
+ const uint i02 = i2;
22
+ const uint i03 = i3;
23
+
24
+ // The workgroup does TILE_DIM x TILE_DIM, but swaps the LSBs of the
25
+ // src coords to make memory accesses contiguous, dst has tid.x in i0,
26
+ // src has tid.x in i01
27
+
28
+ [[unroll]] for (uint y = 0; y < 4; ++y) {
29
+ const uint i00 = tile_col * TILE_DIM + tid_row + 8 * y;
30
+ const uint i01 = tile_row * TILE_DIM + tid_col;
31
+ if (i00 < p.ne00 && i01 < p.ne01 && i02 < p.ne02 && i03 < p.ne03) {
32
+ const uint src_idx = i00 * p.nb00 + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
33
+ sh[tid_row + 8 * y][tid_col] = uint(data_a[get_aoffset() + src_idx]);
34
+ }
35
+ }
36
+
37
+ barrier();
38
+
39
+ [[unroll]] for (uint y = 0; y < 4; ++y) {
40
+ const uint i0 = tile_col * TILE_DIM + tid_col;
41
+ const uint i1 = tile_row * TILE_DIM + tid_row + 8 * y;
42
+ if (i0 < p.ne10 && i1 < p.ne11 && i2 < p.ne12 && i3 < p.ne13) {
43
+ const uint dst_idx = i0 * p.nb10 + i1 * p.nb11 + i2 * p.nb12 + i3 * p.nb13;
44
+ // load transposed
45
+ data_d[get_doffset() + dst_idx] = D_TYPE(sh[tid_col][tid_row + 8 * y]);
46
+ }
47
+ }
48
+ }
49
+
50
+ #define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
51
+
52
+ void main() {
53
+ uint z = gl_WorkGroupID.z;
54
+ uint y = gl_WorkGroupID.y;
55
+ bool need_barrier = false;
56
+ for (uint z = gl_WorkGroupID.z; z < p.ne12 * p.ne13; z += gl_NumWorkGroups.z) {
57
+ for (uint y = gl_WorkGroupID.y; y < CEIL_DIV(p.ne11, TILE_DIM); y += gl_NumWorkGroups.y) {
58
+ for (uint x = gl_WorkGroupID.x; x < CEIL_DIV(p.ne10, TILE_DIM); x += gl_NumWorkGroups.x) {
59
+ if (need_barrier) {
60
+ barrier();
61
+ }
62
+ need_barrier = true;
63
+ iter(uvec3(x, y, z));
64
+ }
65
+ }
66
+ }
67
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_equal.comp ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_control_flow_attributes : enable
4
+
5
+ #include "types.glsl"
6
+ #include "generic_head.glsl"
7
+
8
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
9
+
10
+ layout (binding = 0) readonly buffer X {A_TYPE data_a[];};
11
+ layout (binding = 1) readonly buffer Y {B_TYPE data_b[];};
12
+ layout (binding = 2) buffer D {D_TYPE data_d[];};
13
+
14
+ const uint CHUNK_SIZE = 512;
15
+
16
+ void main() {
17
+ const uint base = gl_WorkGroupID.x * CHUNK_SIZE;
18
+ const uint col = gl_LocalInvocationID.x;
19
+
20
+ uint count = 0;
21
+ [[unroll]]
22
+ for (uint i = 0; i < CHUNK_SIZE; i += gl_WorkGroupSize.x) {
23
+ const uint idx = base + i + col;
24
+ if (idx >= p.KX) {
25
+ break;
26
+ }
27
+ count += uint(data_a[idx] == data_b[idx]);
28
+ }
29
+
30
+ atomicAdd(data_d[0], D_TYPE(count));
31
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_experts.comp ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_control_flow_attributes : enable
4
+
5
+ #include "types.glsl"
6
+
7
+ layout (push_constant) uniform parameter
8
+ {
9
+ uint32_t ne00;
10
+ uint32_t ne01;
11
+ uint32_t nb00;
12
+ uint32_t nb01;
13
+ uint32_t a_offset;
14
+ } p;
15
+
16
+ #define BLOCK_SIZE 256
17
+
18
+ layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in;
19
+
20
+ layout (binding = 0) readonly buffer A {uint data_a[];};
21
+ layout (binding = 1) writeonly buffer D {uint data_d[];};
22
+
23
+ shared uint vals[BLOCK_SIZE];
24
+
25
+ void main() {
26
+ const uint expert_id = gl_WorkGroupID.x;
27
+ const uint num_elements = p.ne00 * p.ne01;
28
+ const uint tid = gl_LocalInvocationID.x;
29
+
30
+ uint count = 0;
31
+ for (uint idx = tid; idx < num_elements; idx += BLOCK_SIZE) {
32
+ const uint i01 = idx / p.ne00;
33
+ const uint i00 = idx % p.ne00;
34
+ const uint a = data_a[p.a_offset + i01 * p.nb01 + i00 * p.nb00];
35
+
36
+ count += uint(a == expert_id);
37
+ }
38
+
39
+ vals[tid] = count;
40
+ barrier();
41
+ [[unroll]] for (uint s = BLOCK_SIZE / 2; s > 0; s >>= 1) {
42
+ if (tid < s) {
43
+ vals[tid] += vals[tid + s];
44
+ }
45
+ barrier();
46
+ }
47
+
48
+ if (tid == 0) {
49
+ data_d[expert_id] = vals[0];
50
+ }
51
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum.comp ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "sum_rows.glsl"
5
+
6
+ #extension GL_EXT_control_flow_attributes : enable
7
+ #extension GL_KHR_shader_subgroup_arithmetic : enable
8
+ #extension GL_KHR_shader_subgroup_basic : enable
9
+
10
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
11
+
12
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
13
+ layout (binding = 1) writeonly buffer D {D_TYPE data_d[];};
14
+
15
+ layout (constant_id = 0) const uint BLOCK_SIZE = 128;
16
+ layout (constant_id = 1) const uint SUBGROUP_SIZE = 32;
17
+ layout (constant_id = 2) const uint ELEM_PER_THREAD = 4;
18
+
19
+ #define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
20
+
21
+ shared FLOAT_TYPE partial[BLOCK_SIZE / SUBGROUP_SIZE];
22
+ shared FLOAT_TYPE last_sum;
23
+
24
+ void main() {
25
+ const uint row = gl_WorkGroupID.z * 262144 + gl_WorkGroupID.y * 512 + gl_WorkGroupID.x;
26
+ const uint tid = gl_LocalInvocationID.x;
27
+
28
+ const uint i03 = fastdiv(row, p.ne0_12mp, p.ne0_12L);
29
+ const uint i03_offset = i03 * p.ne01*p.ne02;
30
+ const uint i02 = fastdiv(row - i03_offset, p.ne0_1mp, p.ne0_1L);
31
+ const uint i01 = row - i03_offset - i02*p.ne01;
32
+
33
+ const uint src_idx = get_aoffset() + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
34
+ const uint dst_idx = get_doffset() + i01 * p.nb11 + i02 * p.nb12 + i03 * p.nb13;
35
+
36
+ uint subgroup_id = tid / SUBGROUP_SIZE;
37
+
38
+ if (tid == 0) {
39
+ last_sum = 0;
40
+ }
41
+
42
+ uint col = tid * ELEM_PER_THREAD;
43
+ uint num_iter = CEIL_DIV(p.n_cols, BLOCK_SIZE * ELEM_PER_THREAD);
44
+ for (int i = 0; i < num_iter; ++i) {
45
+ FLOAT_TYPE v[ELEM_PER_THREAD];
46
+ FLOAT_TYPE thread_sum = 0;
47
+ [[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
48
+ if (col + j < p.n_cols) {
49
+ thread_sum += FLOAT_TYPE(data_a[src_idx + col + j]);
50
+ }
51
+ v[j] = thread_sum;
52
+ }
53
+
54
+ thread_sum = subgroupExclusiveAdd(thread_sum);
55
+ [[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
56
+ v[j] += thread_sum;
57
+ }
58
+ // Store the largest partial sum for each subgroup, then add the partials for all
59
+ // lower subgroups and the final partial sum from the previous iteration.
60
+ if (gl_SubgroupInvocationID == SUBGROUP_SIZE - 1) {
61
+ partial[subgroup_id] = v[ELEM_PER_THREAD - 1];
62
+ }
63
+ barrier();
64
+ for (int s = 0; s < subgroup_id; ++s) {
65
+ [[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
66
+ v[j] += partial[s];
67
+ }
68
+ }
69
+ [[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
70
+ v[j] += last_sum;
71
+ }
72
+ barrier();
73
+ if (tid == BLOCK_SIZE - 1) {
74
+ last_sum = v[ELEM_PER_THREAD - 1];
75
+ }
76
+ [[unroll]] for (uint j = 0; j < ELEM_PER_THREAD; ++j) {
77
+ if (col + j < p.n_cols) {
78
+ data_d[dst_idx + col + j] = D_TYPE(v[j]);
79
+ }
80
+ }
81
+ col += BLOCK_SIZE * ELEM_PER_THREAD;
82
+ }
83
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass1.comp ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "sum_rows.glsl"
5
+
6
+ #extension GL_EXT_control_flow_attributes : enable
7
+ #extension GL_KHR_shader_subgroup_arithmetic : enable
8
+ #extension GL_KHR_shader_subgroup_basic : enable
9
+
10
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
11
+
12
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
13
+ layout (binding = 1) writeonly buffer D {D_TYPE data_d[];};
14
+ layout (binding = 2) writeonly buffer T {D_TYPE data_t[];};
15
+
16
+ layout (constant_id = 0) const uint BLOCK_SIZE = 128;
17
+ layout (constant_id = 1) const uint SUBGROUP_SIZE = 32;
18
+
19
+ #define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
20
+
21
+ shared FLOAT_TYPE partial[BLOCK_SIZE / SUBGROUP_SIZE];
22
+
23
+ void main() {
24
+ const uint row = gl_WorkGroupID.y;
25
+ const uint tid = gl_LocalInvocationID.x;
26
+ const uint col = gl_GlobalInvocationID.x;
27
+
28
+ const uint i03 = fastdiv(row, p.ne0_12mp, p.ne0_12L);
29
+ const uint i03_offset = i03 * p.ne01*p.ne02;
30
+ const uint i02 = fastdiv(row - i03_offset, p.ne0_1mp, p.ne0_1L);
31
+ const uint i01 = row - i03_offset - i02*p.ne01;
32
+
33
+ const uint src_idx = get_aoffset() + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
34
+ const uint dst_idx = get_doffset() + i01 * p.nb11 + i02 * p.nb12 + i03 * p.nb13;
35
+
36
+ uint subgroup_id = tid / SUBGROUP_SIZE;
37
+
38
+ FLOAT_TYPE v = 0;
39
+ if (col < p.n_cols) {
40
+ v = FLOAT_TYPE(data_a[src_idx + col]);
41
+ }
42
+ v = subgroupInclusiveAdd(v);
43
+
44
+ // Store the largest partial sum for each subgroup, then add the partials for all
45
+ // lower subgroups and the final partial sum from the previous iteration.
46
+ if (gl_SubgroupInvocationID == SUBGROUP_SIZE - 1) {
47
+ partial[subgroup_id] = v;
48
+ }
49
+ barrier();
50
+ for (int j = 0; j < subgroup_id; ++j) {
51
+ v += partial[j];
52
+ }
53
+ barrier();
54
+ if (tid == BLOCK_SIZE - 1) {
55
+ data_t[gl_WorkGroupID.x + gl_NumWorkGroups.x * row] = v;
56
+ }
57
+ if (col < p.n_cols) {
58
+ data_d[dst_idx + col] = D_TYPE(v);
59
+ }
60
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass2.comp ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "types.glsl"
4
+ #include "sum_rows.glsl"
5
+
6
+ #extension GL_EXT_control_flow_attributes : enable
7
+ #extension GL_KHR_shader_subgroup_arithmetic : enable
8
+ #extension GL_KHR_shader_subgroup_basic : enable
9
+
10
+ layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
11
+
12
+ layout (binding = 0) readonly buffer A {A_TYPE data_a[];};
13
+ layout (binding = 1) buffer D {D_TYPE data_d[];};
14
+ layout (binding = 2) readonly buffer T {D_TYPE data_t[];};
15
+
16
+ layout (constant_id = 0) const uint BLOCK_SIZE = 128;
17
+ layout (constant_id = 1) const uint SUBGROUP_SIZE = 32;
18
+
19
+ #define CEIL_DIV(a, b) (((a) + (b) - 1) / (b))
20
+
21
+ shared FLOAT_TYPE temp[BLOCK_SIZE / SUBGROUP_SIZE];
22
+
23
+ void main() {
24
+ const uint row = gl_WorkGroupID.y;
25
+ const uint tid = gl_LocalInvocationID.x;
26
+
27
+ const uint i03 = fastdiv(row, p.ne0_12mp, p.ne0_12L);
28
+ const uint i03_offset = i03 * p.ne01*p.ne02;
29
+ const uint i02 = fastdiv(row - i03_offset, p.ne0_1mp, p.ne0_1L);
30
+ const uint i01 = row - i03_offset - i02*p.ne01;
31
+
32
+ const uint src_idx = get_aoffset() + i01 * p.nb01 + i02 * p.nb02 + i03 * p.nb03;
33
+ const uint dst_idx = get_doffset() + i01 * p.nb11 + i02 * p.nb12 + i03 * p.nb13;
34
+
35
+ const uint col = gl_GlobalInvocationID.x;
36
+
37
+ float v = 0;
38
+ // prefetch value we're adding to
39
+ if (col < p.n_cols) {
40
+ v = data_d[dst_idx + col];
41
+ }
42
+
43
+ // compute the sum of all previous blocks
44
+ uint c = tid;
45
+ float sum = 0;
46
+ while (c < gl_WorkGroupID.x) {
47
+ sum += data_t[c + gl_NumWorkGroups.x * row];
48
+ c += BLOCK_SIZE;
49
+ }
50
+
51
+ sum = subgroupAdd(sum);
52
+ if (gl_SubgroupInvocationID == 0) {
53
+ temp[gl_SubgroupID] = sum;
54
+ }
55
+ barrier();
56
+ sum = 0;
57
+ [[unroll]] for (uint s = 0; s < BLOCK_SIZE / SUBGROUP_SIZE; ++s) {
58
+ sum += temp[s];
59
+ }
60
+
61
+ // Add the sum to what the first pass computed
62
+ if (col < p.n_cols) {
63
+ data_d[dst_idx + col] = v + sum;
64
+ }
65
+ }
66
+
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_f32.comp ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "dequant_head.glsl"
4
+
5
+ layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
6
+
7
+ layout (binding = 0) readonly buffer A {float data_a[];};
8
+ layout (binding = 1) writeonly buffer D {D_TYPE data_b[];};
9
+
10
+ void main() {
11
+ const uint i = gl_GlobalInvocationID.x * 16;
12
+
13
+ if (i >= p.nel) {
14
+ return;
15
+ }
16
+
17
+ [[unroll]] for (uint l = 0; l < 16; l++) {
18
+ data_b[i + l] = D_TYPE(data_a[i + l]);
19
+ }
20
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl ADDED
@@ -0,0 +1,692 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(DATA_A_F32) && !defined(DATA_A_F16)
2
+ #extension GL_EXT_shader_explicit_arithmetic_types_int8 : require
3
+ #endif
4
+
5
+ #include "types.glsl"
6
+
7
+ #if defined(DATA_A_F32)
8
+ FLOAT_TYPE dequantize1(uint ib, uint iqs, uint a_offset) {
9
+ return data_a[a_offset + ib];
10
+ }
11
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
12
+ return vec2(data_a[a_offset + ib], data_a[a_offset + ib + 1]);
13
+ }
14
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
15
+ return vec4(data_a[a_offset + ib ], data_a[a_offset + ib + 1],
16
+ data_a[a_offset + ib + 2], data_a[a_offset + ib + 3]);
17
+ }
18
+ vec4 dequantize4_2aligned(uint ib, uint iqs, uint a_offset) {
19
+ return vec4(data_a[a_offset + ib ], data_a[a_offset + ib + 1],
20
+ data_a[a_offset + ib + 2], data_a[a_offset + ib + 3]);
21
+ }
22
+
23
+ #endif
24
+
25
+ #if defined(DATA_A_F16)
26
+ FLOAT_TYPE dequantize1(uint ib, uint iqs, uint a_offset) {
27
+ return data_a[a_offset + ib];
28
+ }
29
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
30
+ return vec2(data_a[a_offset + ib], data_a[a_offset + ib + 1]);
31
+ }
32
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
33
+ return vec4(data_a[a_offset + ib ], data_a[a_offset + ib + 1],
34
+ data_a[a_offset + ib + 2], data_a[a_offset + ib + 3]);
35
+ }
36
+ vec4 dequantize4_2aligned(uint ib, uint iqs, uint a_offset) {
37
+ const vec2 a = data_a_packed32[(a_offset + ib)/2];
38
+ const vec2 b = data_a_packed32[(a_offset + ib)/2 + 1];
39
+ return vec4(a, b);
40
+ }
41
+ #endif
42
+
43
+ #if defined(DATA_A_BF16)
44
+ FLOAT_TYPE dequantize1(uint ib, uint iqs, uint a_offset) {
45
+ return bf16_to_fp32(data_a[a_offset + ib]);
46
+ }
47
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
48
+ return vec2(bf16_to_fp32(data_a[a_offset + ib]), bf16_to_fp32(data_a[a_offset + ib + 1]));
49
+ }
50
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
51
+ return vec4(bf16_to_fp32(data_a[a_offset + ib ]), bf16_to_fp32(data_a[a_offset + ib + 1]),
52
+ bf16_to_fp32(data_a[a_offset + ib + 2]), bf16_to_fp32(data_a[a_offset + ib + 3]));
53
+ }
54
+ vec4 dequantize4_2aligned(uint ib, uint iqs, uint a_offset) {
55
+ const uint a = data_a_packed32[(a_offset + ib)/2];
56
+ const uint b = data_a_packed32[(a_offset + ib)/2 + 1];
57
+ return vec4(uintBitsToFloat((a & 0x0000ffff) << 16),
58
+ uintBitsToFloat( a & 0xffff0000),
59
+ uintBitsToFloat((b & 0x0000ffff) << 16),
60
+ uintBitsToFloat( b & 0xffff0000));
61
+ }
62
+ #endif
63
+
64
+ #if defined(DATA_A_Q4_0)
65
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
66
+ const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
67
+ return (vec2(vui & 0xF, vui >> 4) - 8.0f);
68
+ }
69
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
70
+ const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
71
+ return (vec4(vui & 0xF, (vui >> 4) & 0xF, (vui >> 8) & 0xF, vui >> 12) - 8.0f);
72
+ }
73
+ #endif
74
+
75
+ #if defined(DATA_A_Q4_1)
76
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
77
+ const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
78
+ return vec2(vui & 0xF, vui >> 4);
79
+ }
80
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
81
+ const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
82
+ return vec4(vui & 0xF, (vui >> 4) & 0xF, (vui >> 8) & 0xF, vui >> 12);
83
+ }
84
+ #endif
85
+
86
+ #if defined(DATA_A_Q5_0)
87
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
88
+ const uint uint_qh = uint(data_a[a_offset + ib].qh[1]) << 16 | data_a[a_offset + ib].qh[0];
89
+ const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
90
+ const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
91
+ return (vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y) - 16.0f);
92
+ }
93
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
94
+ const uint uint_qh = uint(data_a_packed16[a_offset + ib].qh[1]) << 16 | data_a_packed16[a_offset + ib].qh[0];
95
+ const ivec2 qh0 = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
96
+ const ivec2 qh1 = ivec2(((uint_qh >> (iqs + 1)) << 4) & 0x10, (uint_qh >> (iqs + 13)) & 0x10);
97
+ const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
98
+ return (vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y) - 16.0f);
99
+ }
100
+ #endif
101
+
102
+ #if defined(DATA_A_Q5_1)
103
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
104
+ const uint uint_qh = data_a[a_offset + ib].qh;
105
+ const ivec2 qh = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
106
+ const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
107
+ return vec2((vui & 0xF) | qh.x, (vui >> 4) | qh.y);
108
+ }
109
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
110
+ const uint uint_qh = data_a_packed16[a_offset + ib].qh;
111
+ const ivec2 qh0 = ivec2(((uint_qh >> iqs) << 4) & 0x10, (uint_qh >> (iqs + 12)) & 0x10);
112
+ const ivec2 qh1 = ivec2(((uint_qh >> (iqs + 1)) << 4) & 0x10, (uint_qh >> (iqs + 13)) & 0x10);
113
+ const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
114
+ return vec4((vui & 0xF) | qh0.x, ((vui >> 4) & 0xF) | qh0.y, ((vui >> 8) & 0xF) | qh1.x, (vui >> 12) | qh1.y);
115
+ }
116
+ #endif
117
+
118
+ #if defined(DATA_A_Q8_0)
119
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
120
+ return vec2(int(data_a[a_offset + ib].qs[iqs]), int(data_a[a_offset + ib].qs[iqs + 1]));
121
+ }
122
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
123
+ const i8vec2 v0 = unpack8(int32_t(data_a_packed16[a_offset + ib].qs[iqs/2])).xy; // vec4 used due to #12147
124
+ const i8vec2 v1 = unpack8(int32_t(data_a_packed16[a_offset + ib].qs[iqs/2 + 1])).xy;
125
+ return vec4(v0.x, v0.y, v1.x, v1.y);
126
+ }
127
+ #endif
128
+
129
+ #if defined(DATA_A_Q1_0)
130
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
131
+ const uint bits = uint(data_a[a_offset + ib].qs[iqs / 8u]) >> (iqs % 8u);
132
+ return vec2(
133
+ (bits & 1u) != 0u ? 1.0f : -1.0f,
134
+ (bits & 2u) != 0u ? 1.0f : -1.0f);
135
+ }
136
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
137
+ const uint bits = uint(data_a[a_offset + ib].qs[iqs / 8u]) >> (iqs % 8u);
138
+ return vec4(
139
+ (bits & 1u) != 0u ? 1.0f : -1.0f,
140
+ (bits & 2u) != 0u ? 1.0f : -1.0f,
141
+ (bits & 4u) != 0u ? 1.0f : -1.0f,
142
+ (bits & 8u) != 0u ? 1.0f : -1.0f);
143
+ }
144
+ #endif
145
+
146
+ #if defined(DATA_A_IQ1_S)
147
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
148
+ const uint ib32 = iqs / 32;
149
+ const uint ib8 = iqs / 8;
150
+ const int i8 = int(iqs % 8);
151
+ const uint qh = data_a[a_offset + ib].qh[ib32];
152
+ const uint qs = data_a[a_offset + ib].qs[ib8];
153
+ const float dl = float(2 * bitfieldExtract(qh, 12, 3) + 1);
154
+ const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
155
+ const uint idxhi = bitfieldExtract(qh, 3 * int(ib8 & 3), 3);
156
+ const int16_t grid = int16_t(iq1s_grid[qs | (idxhi << 8)]);
157
+ // Signed bitfield extract.
158
+ const ivec2 gvec = ivec2(
159
+ bitfieldExtract(grid, 2 * (i8), 2),
160
+ bitfieldExtract(grid, 2 * (i8 + 1), 2)
161
+ );
162
+ return dl * (vec2(gvec) + delta);
163
+ }
164
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
165
+ const uint ib32 = iqs / 32;
166
+ const uint ib8 = iqs / 8;
167
+ const int i8 = int(iqs % 8);
168
+ const uint qh = data_a[a_offset + ib].qh[ib32];
169
+ const uint qs = data_a[a_offset + ib].qs[ib8];
170
+ const float dl = 2 * bitfieldExtract(qh, 12, 3) + 1;
171
+ const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
172
+ const int16_t grid = int16_t(iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)]);
173
+ // Signed bitfield extract.
174
+ const ivec4 gvec = ivec4(
175
+ bitfieldExtract(grid, 2 * (i8), 2),
176
+ bitfieldExtract(grid, 2 * (i8 + 1), 2),
177
+ bitfieldExtract(grid, 2 * (i8 + 2), 2),
178
+ bitfieldExtract(grid, 2 * (i8 + 3), 2)
179
+ );
180
+ return dl * (vec4(gvec) + delta);
181
+ }
182
+ #endif
183
+
184
+ #if defined(DATA_A_IQ1_M)
185
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
186
+ const uint ib8 = iqs / 8;
187
+ const uint ib16 = iqs / 16;
188
+ const int i8 = int(iqs % 8);
189
+ const uint sc = data_a[a_offset + ib].scales[iqs / 64];
190
+ const uint qs = data_a[a_offset + ib].qs[ib8];
191
+ const uint qh = data_a[a_offset + ib].qh[ib16] >> (4 * (ib8 & 1));
192
+ const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1;
193
+ const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA;
194
+ const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]);
195
+ // Signed bitfield extract.
196
+ const ivec2 gvec = ivec2(
197
+ bitfieldExtract(grid, 2 * (i8), 2),
198
+ bitfieldExtract(grid, 2 * (i8 + 1), 2)
199
+ );
200
+ return dl * (vec2(gvec) + delta);
201
+ }
202
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
203
+ const uint ib8 = iqs / 8;
204
+ const uint ib16 = iqs / 16;
205
+ const int i8 = int(iqs % 8);
206
+ const uint sc = data_a[a_offset + ib].scales[iqs / 64];
207
+ const uint qs = data_a[a_offset + ib].qs[ib8];
208
+ const uint qh = data_a[a_offset + ib].qh[ib16] >> (4 * (ib8 & 1));
209
+ const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1;
210
+ const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA;
211
+ const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]);
212
+ // Signed bitfield extract.
213
+ const ivec4 gvec = ivec4(
214
+ bitfieldExtract(grid, 2 * (i8), 2),
215
+ bitfieldExtract(grid, 2 * (i8 + 1), 2),
216
+ bitfieldExtract(grid, 2 * (i8 + 2), 2),
217
+ bitfieldExtract(grid, 2 * (i8 + 3), 2)
218
+ );
219
+ return dl * (vec4(gvec) + delta);
220
+ }
221
+ #endif
222
+
223
+ #if defined(DATA_A_IQ2_XXS)
224
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
225
+ const uint ib32 = iqs / 32;
226
+ const uint ib8 = (iqs / 8) % 4;
227
+ const uint qs = data_a[a_offset + ib].qs[8 * ib32 + ib8];
228
+ // Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale)
229
+ const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[4 * ib32 + 2],
230
+ data_a_packed16[a_offset + ib].qs[4 * ib32 + 3]));
231
+ const float db = 0.25 * (0.5 + (signs >> 28));
232
+ const uint sign7 = bitfieldExtract(signs, 7 * int(ib8), 7);
233
+ // Add parity bit
234
+ const uint sign8 = sign7 | (bitCount(sign7) << 7);
235
+ const uint sign = sign8 >> (iqs % 8);
236
+ const u8vec4 grid = unpack8(iq2xxs_grid[qs][(iqs % 8) / 4] >> (8 * (iqs % 4)));
237
+ bool sign0 = (sign & 1) != 0;
238
+ bool sign1 = (sign & 2) != 0;
239
+ return db * vec2(
240
+ grid.x * (sign0 ? -1.0 : 1.0),
241
+ grid.y * (sign1 ? -1.0 : 1.0)
242
+ );
243
+ }
244
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
245
+ const uint ib32 = iqs / 32;
246
+ const uint ib8 = (iqs / 8) % 4;
247
+ const uint qs = data_a[a_offset + ib].qs[8 * ib32 + ib8];
248
+ // Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale)
249
+ const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[4 * ib32 + 2],
250
+ data_a_packed16[a_offset + ib].qs[4 * ib32 + 3]));
251
+ const float db = 0.25 * (0.5 + (signs >> 28));
252
+ const uint sign7 = bitfieldExtract(signs, 7 * int(ib8), 7);
253
+ // Add parity bit
254
+ const uint sign8 = sign7 | (bitCount(sign7) << 7);
255
+ const uint sign = sign8 >> (iqs % 8);
256
+ const u8vec4 grid = unpack8(iq2xxs_grid[qs][(iqs % 8) / 4] >> (8 * (iqs % 4)));
257
+ bool sign0 = (sign & 1) != 0;
258
+ bool sign1 = (sign & 2) != 0;
259
+ bool sign2 = (sign & 4) != 0;
260
+ bool sign3 = (sign & 8) != 0;
261
+ return db * vec4(
262
+ grid.x * (sign0 ? -1.0 : 1.0),
263
+ grid.y * (sign1 ? -1.0 : 1.0),
264
+ grid.z * (sign2 ? -1.0 : 1.0),
265
+ grid.w * (sign3 ? -1.0 : 1.0)
266
+ );
267
+ }
268
+ #endif
269
+
270
+ #if defined(DATA_A_IQ2_XS)
271
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
272
+ const uint scale = (data_a[a_offset + ib].scales[iqs / 32] >> (4 * ((iqs / 16) & 1))) & 0xf;
273
+ const uint qs = data_a[a_offset + ib].qs[iqs / 8];
274
+ const float db = 0.25 * (0.5 + scale);
275
+ const uint sign7 = qs >> 9;
276
+ // Add parity bit
277
+ const uint sign8 = sign7 | (bitCount(sign7) << 7);
278
+ const uint sign = sign8 >> (iqs % 8);
279
+ const u8vec4 grid = unpack8(iq2xs_grid[qs & 511][(iqs % 8) / 4] >> (8 * (iqs % 4)));
280
+ bool sign0 = (sign & 1) != 0;
281
+ bool sign1 = (sign & 2) != 0;
282
+ return db * vec2(
283
+ grid.x * (sign0 ? -1.0 : 1.0),
284
+ grid.y * (sign1 ? -1.0 : 1.0)
285
+ );
286
+ }
287
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
288
+ const uint scale = (data_a[a_offset + ib].scales[iqs / 32] >> (4 * ((iqs / 16) & 1))) & 0xf;
289
+ const uint qs = data_a[a_offset + ib].qs[iqs / 8];
290
+ const float db = 0.25 * (0.5 + scale);
291
+ const uint sign7 = qs >> 9;
292
+ // Add parity bit
293
+ const uint sign8 = sign7 | (bitCount(sign7) << 7);
294
+ const uint sign = sign8 >> (iqs % 8);
295
+ const u8vec4 grid = unpack8(iq2xs_grid[qs & 511][(iqs % 8) / 4] >> (8 * (iqs % 4)));
296
+ bool sign0 = (sign & 1) != 0;
297
+ bool sign1 = (sign & 2) != 0;
298
+ bool sign2 = (sign & 4) != 0;
299
+ bool sign3 = (sign & 8) != 0;
300
+ return db * vec4(
301
+ grid.x * (sign0 ? -1.0 : 1.0),
302
+ grid.y * (sign1 ? -1.0 : 1.0),
303
+ grid.z * (sign2 ? -1.0 : 1.0),
304
+ grid.w * (sign3 ? -1.0 : 1.0)
305
+ );
306
+ }
307
+ #endif
308
+
309
+ #if defined(DATA_A_IQ2_S)
310
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
311
+ const uint ib32 = iqs / 32;
312
+ const uint ib8 = iqs / 8;
313
+
314
+ const uint scale = (data_a[a_offset + ib].scales[ib32] >> (4 * ((iqs / 16) & 1))) & 0xf;
315
+ const uint qs = data_a[a_offset + ib].qs[ib8];
316
+ const uint qh = data_a[a_offset + ib].qh[ib32];
317
+ const uint qhshift = 2 * (ib8 % 4);
318
+ const uint sign = data_a[a_offset + ib].qs[QUANT_K / 8 + ib8] >> (iqs % 8);
319
+
320
+ const float db = 0.25 * (0.5 + scale);
321
+ const u8vec4 grid = unpack8(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(iqs % 8) / 4]);
322
+ bool sign0 = (sign & 1) != 0;
323
+ bool sign1 = (sign & 2) != 0;
324
+ return db * vec2(
325
+ grid[iqs % 4] * (sign0 ? -1.0 : 1.0),
326
+ grid[(iqs % 4) + 1] * (sign1 ? -1.0 : 1.0)
327
+ );
328
+ }
329
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
330
+ const uint ib32 = iqs / 32;
331
+ const uint ib8 = iqs / 8;
332
+
333
+ const uint scale = (data_a[a_offset + ib].scales[ib32] >> (4 * ((iqs / 16) & 1))) & 0xf;
334
+ const uint qs = data_a[a_offset + ib].qs[ib8];
335
+ const uint qh = data_a[a_offset + ib].qh[ib32];
336
+ const uint qhshift = 2 * (ib8 % 4);
337
+ const uint sign = data_a[a_offset + ib].qs[QUANT_K / 8 + ib8] >> (iqs % 8);
338
+
339
+ const float db = 0.25 * (0.5 + scale);
340
+ const u8vec4 grid = unpack8(iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(iqs % 8) / 4]);
341
+ bool sign0 = (sign & 1) != 0;
342
+ bool sign1 = (sign & 2) != 0;
343
+ bool sign2 = (sign & 4) != 0;
344
+ bool sign3 = (sign & 8) != 0;
345
+ return db * vec4(
346
+ grid.x * (sign0 ? -1.0 : 1.0),
347
+ grid.y * (sign1 ? -1.0 : 1.0),
348
+ grid.z * (sign2 ? -1.0 : 1.0),
349
+ grid.w * (sign3 ? -1.0 : 1.0)
350
+ );
351
+ }
352
+ #endif
353
+
354
+ #if defined(DATA_A_IQ3_XXS)
355
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
356
+ const uint ib4 = iqs / 4;
357
+ const uint ib32 = iqs / 32;
358
+ const uint is = QUANT_K / 4 + 4 * ib32;
359
+ const uint qs = data_a[a_offset + ib].qs[ib4];
360
+ // Scales are stored as packed 7+7+7+7+4 bits (4 sign tuples and 1 int4 scale)
361
+ const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[is / 2],
362
+ data_a_packed16[a_offset + ib].qs[is / 2 + 1]));
363
+ const float db = 0.5 * (0.5 + (signs >> 28));
364
+ const uint sign7 = bitfieldExtract(signs, 7 * (int(ib4 / 2) % 4), 7);
365
+ // Add parity bit
366
+ const uint sign8 = sign7 | (bitCount(sign7) << 7);
367
+ const uint sign = sign8 >> (iqs % 8);
368
+ const u8vec4 grid = unpack8(iq3xxs_grid[qs] >> (8 * (iqs % 4)));
369
+ bool sign0 = (sign & 1) != 0;
370
+ bool sign1 = (sign & 2) != 0;
371
+ return db * vec2(
372
+ grid.x * (sign0 ? -1.0 : 1.0),
373
+ grid.y * (sign1 ? -1.0 : 1.0)
374
+ );
375
+ }
376
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
377
+ const uint ib4 = iqs / 4;
378
+ const uint ib32 = iqs / 32;
379
+ const uint is = QUANT_K / 4 + 4 * ib32;
380
+ const uint qs = data_a[a_offset + ib].qs[ib4];
381
+ const uint signs = pack32(u16vec2(data_a_packed16[a_offset + ib].qs[is / 2],
382
+ data_a_packed16[a_offset + ib].qs[is / 2 + 1]));
383
+ const float db = 0.5 * (0.5 + (signs >> 28));
384
+ const uint sign7 = bitfieldExtract(signs, 7 * (int(ib4 / 2) % 4), 7);
385
+ // Add parity bit
386
+ const uint sign8 = sign7 | (bitCount(sign7) << 7);
387
+ const uint sign = sign8 >> (iqs % 8);
388
+ const u8vec4 grid = unpack8(iq3xxs_grid[qs]);
389
+ bool sign0 = (sign & 1) != 0;
390
+ bool sign1 = (sign & 2) != 0;
391
+ bool sign2 = (sign & 4) != 0;
392
+ bool sign3 = (sign & 8) != 0;
393
+ return db * vec4(
394
+ grid.x * (sign0 ? -1.0 : 1.0),
395
+ grid.y * (sign1 ? -1.0 : 1.0),
396
+ grid.z * (sign2 ? -1.0 : 1.0),
397
+ grid.w * (sign3 ? -1.0 : 1.0)
398
+ );
399
+ }
400
+ #endif
401
+
402
+ #if defined(DATA_A_IQ3_S)
403
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
404
+ const uint qs = data_a[a_offset + ib].qs[iqs / 4];
405
+ const uint qh = data_a[a_offset + ib].qh[iqs / 32];
406
+ const uint sign = data_a[a_offset + ib].signs[iqs / 8] >> (iqs % 8);
407
+ const uint scale = data_a[a_offset + ib].scales[iqs / 64];
408
+ bool sign0 = (sign & 1) != 0;
409
+ bool sign1 = (sign & 2) != 0;
410
+ const float db = 1 + 2 * ((scale >> (4 * ((iqs / 32) & 1))) & 0xf);
411
+ const uint32_t grid = iq3s_grid[qs | ((qh << (8 - ((iqs / 4) % 8))) & 256)] >> (8 * (iqs % 4));
412
+ return db * vec2(
413
+ int(grid & 0xFF) * (sign0 ? -1.0 : 1.0),
414
+ int((grid >> 8) & 0xFF) * (sign1 ? -1.0 : 1.0)
415
+ );
416
+ }
417
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
418
+ const uint ib4 = iqs / 4;
419
+ const uint ib32 = iqs / 32;
420
+ const uint qs = data_a[a_offset + ib].qs[ib4];
421
+ const uint qh = data_a[a_offset + ib].qh[ib32];
422
+ const uint sign = data_a[a_offset + ib].signs[iqs / 8] >> (iqs % 8);
423
+ const uint scale = data_a[a_offset + ib].scales[ib32 / 2];
424
+ bool sign0 = (sign & 1) != 0;
425
+ bool sign1 = (sign & 2) != 0;
426
+ bool sign2 = (sign & 4) != 0;
427
+ bool sign3 = (sign & 8) != 0;
428
+ const float db = 1 + 2 * ((scale >> (4 * (ib32 & 1))) & 0xf);
429
+ const uint32_t grid = iq3s_grid[qs | ((qh << (8 - ib4 % 8)) & 256)] >> (8 * (iqs % 4));
430
+ return db * vec4(
431
+ int(grid & 0xFF) * (sign0 ? -1.0 : 1.0),
432
+ int((grid >> 8) & 0xFF) * (sign1 ? -1.0 : 1.0),
433
+ int((grid >> 16) & 0xFF) * (sign2 ? -1.0 : 1.0),
434
+ int((grid >> 24) & 0xFF) * (sign3 ? -1.0 : 1.0)
435
+ );
436
+ }
437
+ #endif
438
+
439
+ #if defined(DATA_A_IQ4_XS)
440
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
441
+ const uint ib32 = iqs / 32;
442
+ const uint iq = 16 * ib32 + (iqs % 16);
443
+
444
+ const uint sl = (data_a[a_offset + ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF;
445
+ const uint sh = (data_a[a_offset + ib].scales_h >> (2 * ib32)) & 3;
446
+ const uint qshift = (iqs & 16) >> 2;
447
+ u8vec2 qs = u8vec2(data_a[a_offset + ib].qs[iq], data_a[a_offset + ib].qs[iq + 1]);
448
+ qs = (qs >> qshift) & uint8_t(0xF);
449
+
450
+ const float dl = float(int(sl | (sh << 4)) - 32);
451
+ return dl * vec2(kvalues_iq4nl[qs.x], kvalues_iq4nl[qs.y]);
452
+ }
453
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
454
+ const uint ib32 = iqs / 32;
455
+ const uint iq = 16 * ib32 + (iqs % 16);
456
+
457
+ const uint sl = (data_a[a_offset + ib].scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF;
458
+ const uint sh = (data_a[a_offset + ib].scales_h >> (2 * ib32)) & 3;
459
+ const uint qshift = (iqs & 16) >> 2;
460
+ const u8vec4 qs = unpack8((data_a_packed32[a_offset + ib].qs[iq/4] >> qshift) & 0x0F0F0F0F);
461
+
462
+ const float dl = float(int(sl | (sh << 4)) - 32);
463
+ return dl * vec4(
464
+ kvalues_iq4nl[qs.x], kvalues_iq4nl[qs.y],
465
+ kvalues_iq4nl[qs.z], kvalues_iq4nl[qs.w]);
466
+ }
467
+ #endif
468
+
469
+ #if defined(DATA_A_IQ4_NL)
470
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
471
+ const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
472
+ return vec2(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[vui >> 4]);
473
+ }
474
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
475
+ const uint vui = uint(data_a_packed16[a_offset + ib].qs[iqs/2]);
476
+ return vec4(kvalues_iq4nl[vui & 0xF], kvalues_iq4nl[(vui >> 4) & 0xF], kvalues_iq4nl[(vui >> 8) & 0xF], kvalues_iq4nl[vui >> 12]);
477
+ }
478
+ #endif
479
+
480
+ #if defined(DATA_A_MXFP4)
481
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
482
+ const uint vui = uint(data_a[a_offset + ib].qs[iqs]);
483
+ return vec2(kvalues_mxfp4[vui & 0xF], kvalues_mxfp4[vui >> 4]) * 0.5;
484
+ }
485
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
486
+ vec2 v0 = dequantize(ib, iqs, a_offset);
487
+ vec2 v1 = dequantize(ib, iqs + 1, a_offset);
488
+ return vec4(v0.x, v0.y, v1.x, v1.y);
489
+ }
490
+ #endif
491
+
492
+ #if defined(DATA_A_NVFP4)
493
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
494
+ const uint sub = iqs >> 4;
495
+ const float d = ue4m3_to_fp32(data_a[a_offset + ib].d[sub]);
496
+ const uint j = iqs & 7;
497
+ const uint shift = (iqs & 8) >> 1; // 0 or 4
498
+ const uint vui0 = uint(data_a[a_offset + ib].qs[sub * 8u + j]);
499
+ const uint vui1 = uint(data_a[a_offset + ib].qs[sub * 8u + j + 1]);
500
+ const uint qs0 = (vui0 >> shift) & 0xF;
501
+ const uint qs1 = (vui1 >> shift) & 0xF;
502
+ return vec2(float(kvalues_mxfp4[qs0]), float(kvalues_mxfp4[qs1])) * d * 0.5;
503
+ }
504
+ vec4 dequantize4(uint ib, uint iqs, uint a_offset) {
505
+ const vec2 v0 = dequantize(ib, iqs, a_offset);
506
+ const vec2 v1 = dequantize(ib, iqs + 2u, a_offset);
507
+ return vec4(v0.x, v0.y, v1.x, v1.y);
508
+ }
509
+ #endif
510
+
511
+ #if defined(DATA_A_F32) || defined(DATA_A_F16) || defined(DATA_A_BF16)
512
+ vec2 get_dm(uint ib, uint a_offset) {
513
+ return vec2(0, 0);
514
+ }
515
+ #endif
516
+
517
+ #if defined(DATA_A_IQ1_M)
518
+ vec2 get_dm(uint ib, uint a_offset) {
519
+ const uint16_t[4] scales = data_a[a_offset + ib].scales;
520
+ const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12;
521
+ const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x);
522
+ return vec2(d, 0);
523
+ }
524
+ #endif
525
+
526
+ #if defined(DATA_A_Q4_0) || defined(DATA_A_Q5_0) || defined(DATA_A_Q8_0) || defined(DATA_A_IQ1_S) || defined(DATA_A_IQ2_XXS) || defined(DATA_A_IQ2_XS) || defined(DATA_A_IQ2_S) || defined(DATA_A_IQ3_XXS) || defined(DATA_A_IQ3_S) || defined(DATA_A_IQ4_XS) || defined(DATA_A_IQ4_NL)
527
+ vec2 get_dm(uint ib, uint a_offset) {
528
+ return vec2(float(data_a[a_offset + ib].d), 0);
529
+ }
530
+ #endif
531
+
532
+ #if defined(DATA_A_Q1_0)
533
+ vec2 get_dm(uint ib, uint a_offset) {
534
+ const float d = float(data_a[a_offset + ib].d);
535
+ return vec2(d, 0);
536
+ }
537
+ #endif
538
+
539
+ #if defined(DATA_A_MXFP4)
540
+ vec2 get_dm(uint ib, uint a_offset) {
541
+ return vec2(e8m0_to_fp32(data_a[a_offset + ib].e), 0);
542
+ }
543
+ #endif
544
+
545
+ #if defined(DATA_A_NVFP4)
546
+ vec2 get_dm(uint ib, uint a_offset) {
547
+ return vec2(1.0, 0.0);
548
+ }
549
+ #endif
550
+
551
+ #if defined(DATA_A_Q4_1) || defined(DATA_A_Q5_1)
552
+ vec2 get_dm(uint ib, uint a_offset) {
553
+ const vec2 dm = vec2(data_a_packed32[a_offset + ib].dm);
554
+ return dm;
555
+ }
556
+ #endif
557
+
558
+ #if defined(DATA_A_Q2_K)
559
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
560
+ iqs /= 2;
561
+ const uint qsi = (iqs / 64) * 32 + (iqs % 16) * 2; // 0,2,4..30
562
+ const uint scalesi = iqs / 8; // 0..15
563
+ const uint qsshift = ((iqs % 64) / 16) * 2; // 0,2,4,6
564
+
565
+ const uvec2 qs = uvec2(data_a[a_offset + ib].qs[qsi], data_a[a_offset + ib].qs[qsi + 1]);
566
+ const uint scales = data_a[a_offset + ib].scales[scalesi];
567
+ const vec2 dm = vec2(data_a[a_offset + ib].dm);
568
+
569
+ return dm.x * float(scales & 0xF) * vec2((qs >> qsshift) & 3) - dm.y * float(scales >> 4);
570
+ }
571
+ vec2 get_dm(uint ib, uint a_offset) {
572
+ return vec2(1, 0);
573
+ }
574
+ #endif
575
+
576
+ #if defined(DATA_A_Q3_K)
577
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
578
+ iqs /= 2;
579
+ const uint n = iqs / 64; // 0,1
580
+ const uint qsi = n * 32 + (iqs % 16) * 2; // 0,2,4..62
581
+ const uint hmi = (iqs % 16) * 2; // 0,2,4..30
582
+ const uint j = (iqs % 64) / 4; // 0..3
583
+ const uint is = iqs / 8; // 0..15
584
+ const uint halfsplit = ((iqs % 64) / 16); // 0,1,2,3
585
+ const uint qsshift = halfsplit * 2; // 0,2,4,6
586
+ const uint m = 1 << (4 * n + halfsplit); // 1,2,4,8,16,32,64,128
587
+
588
+ const int8_t us = int8_t(((data_a[a_offset + ib].scales[is % 8] >> (4 * int(is / 8))) & 0xF)
589
+ | (((data_a[a_offset + ib].scales[8 + (is % 4)] >> (2 * int(is / 4))) & 3) << 4));
590
+ const float dl = float(data_a[a_offset + ib].d) * float(us - 32);
591
+
592
+ return vec2(dl * float(int8_t((data_a[a_offset + ib].qs[qsi ] >> qsshift) & 3) - (((data_a[a_offset + ib].hmask[hmi ] & m) != 0) ? 0 : 4)),
593
+ dl * float(int8_t((data_a[a_offset + ib].qs[qsi + 1] >> qsshift) & 3) - (((data_a[a_offset + ib].hmask[hmi + 1] & m) != 0) ? 0 : 4)));
594
+ }
595
+ vec2 get_dm(uint ib, uint a_offset) {
596
+ return vec2(1, 0);
597
+ }
598
+ #endif
599
+
600
+ #if defined(DATA_A_Q4_K)
601
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
602
+ iqs /= 2;
603
+ const uint n = iqs / 32; // 0,1,2,3
604
+ const uint b = (iqs % 32) / 16; // 0,1
605
+ const uint is = 2 * n + b; // 0..7
606
+ const uint qsi = n * 32 + (iqs % 16) * 2; // 0,2,4..126
607
+
608
+ const vec2 loadd = vec2(data_a[a_offset + ib].dm);
609
+
610
+ const uint scidx0 = (is < 4) ? is : (is + 4);
611
+ const uint scidx1 = (is < 4) ? is : (is - 4);
612
+ const uint scidxmask1 = (is < 4) ? 0x30 : 0xC0;
613
+ const uint scidxshift1 = (is < 4) ? 0 : 2;
614
+ const uint mbidx0 = is + 4;
615
+ const uint mbidx1 = (is < 4) ? is + 4 : is;
616
+ const uint mbidxmask0 = (is < 4) ? 0xF : 0xF0;
617
+ const uint mbidxshift0 = (is < 4) ? 0 : 4;
618
+ const uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0;
619
+ const uint mbidxshift1 = (is < 4) ? 0 : 2;
620
+
621
+ const uint8_t sc = uint8_t((data_a[a_offset + ib].scales[scidx0] & 0xF) | ((data_a[a_offset + ib].scales[scidx1] & scidxmask1) >> scidxshift1));
622
+ const uint8_t mbyte = uint8_t((data_a[a_offset + ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0 | ((data_a[a_offset + ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1));
623
+
624
+ const float d = loadd.x * sc;
625
+ const float m = -loadd.y * mbyte;
626
+
627
+ return vec2(fma(d, float((data_a[a_offset + ib].qs[qsi ] >> (b * 4)) & 0xF), m),
628
+ fma(d, float((data_a[a_offset + ib].qs[qsi + 1] >> (b * 4)) & 0xF), m));
629
+ }
630
+ vec2 get_dm(uint ib, uint a_offset) {
631
+ return vec2(1, 0);
632
+ }
633
+ #endif
634
+
635
+ #if defined(DATA_A_Q5_K)
636
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
637
+ iqs /= 2;
638
+ const uint n = iqs / 32; // 0,1,2,3
639
+ const uint b = (iqs % 32) / 16; // 0,1
640
+ const uint is = 2 * n + b; // 0..7
641
+ const uint qsi = n * 32 + (iqs % 16) * 2; // 0,2,4..126
642
+ const uint qhi = (iqs % 16) * 2; // 0,2,4..30
643
+
644
+ const uint8_t hm = uint8_t(1 << (iqs / 16));
645
+
646
+ const vec2 loadd = vec2(data_a[a_offset + ib].dm);
647
+
648
+ const uint scidx0 = (is < 4) ? is : (is + 4);
649
+ const uint scidx1 = (is < 4) ? is : (is - 4);
650
+ const uint scidxmask1 = (is < 4) ? 0x30 : 0xC0;
651
+ const uint scidxshift1 = (is < 4) ? 0 : 2;
652
+ const uint mbidx0 = is + 4;
653
+ const uint mbidx1 = (is < 4) ? is + 4 : is;
654
+ const uint mbidxmask0 = (is < 4) ? 0xF : 0xF0;
655
+ const uint mbidxshift0 = (is < 4) ? 0 : 4;
656
+ const uint mbidxmask1 = (is < 4) ? 0x30 : 0xC0;
657
+ const uint mbidxshift1 = (is < 4) ? 0 : 2;
658
+
659
+ const uint8_t sc = uint8_t((data_a[a_offset + ib].scales[scidx0] & 0xF) | ((data_a[a_offset + ib].scales[scidx1] & scidxmask1) >> scidxshift1));
660
+ const uint8_t mbyte = uint8_t(((data_a[a_offset + ib].scales[mbidx0] & mbidxmask0) >> mbidxshift0) | ((data_a[a_offset + ib].scales[mbidx1] & mbidxmask1) >> mbidxshift1));
661
+
662
+ const float d = loadd.x * sc;
663
+ const float m = -loadd.y * mbyte;
664
+
665
+ return vec2(fma(d, float((data_a[a_offset + ib].qs[qsi ] >> (b * 4)) & 0xF) + float((data_a[a_offset + ib].qh[qhi ] & hm) != 0 ? 16 : 0), m),
666
+ fma(d, float((data_a[a_offset + ib].qs[qsi + 1] >> (b * 4)) & 0xF) + float((data_a[a_offset + ib].qh[qhi + 1] & hm) != 0 ? 16 : 0), m));
667
+ }
668
+ vec2 get_dm(uint ib, uint a_offset) {
669
+ return vec2(1, 0);
670
+ }
671
+ #endif
672
+
673
+ #if defined(DATA_A_Q6_K)
674
+ vec2 dequantize(uint ib, uint iqs, uint a_offset) {
675
+ iqs /= 2;
676
+ const uint n = iqs / 64; // 0,1
677
+ const uint b = (iqs % 64) / 32; // 0,1
678
+ const uint is_b = (iqs % 16) / 8; // 0,1
679
+ const uint qhshift = ((iqs % 64) / 16) * 2; // 0,2,4,6
680
+ const uint is = 8 * n + qhshift + is_b; // 0..15
681
+ const uint qsi = n * 64 + (iqs % 32) * 2; // 0,2,4..126
682
+ const uint qhi = n * 32 + (iqs % 16) * 2; // 0,2,4..62
683
+
684
+ const float dscale = float(data_a[a_offset + ib].d) * float(data_a[a_offset + ib].scales[is]);
685
+
686
+ return vec2(dscale * float(int8_t(((data_a[a_offset + ib].ql[qsi ] >> (b * 4)) & 0xF) | (((data_a[a_offset + ib].qh[qhi ] >> qhshift) & 3) << 4)) - 32),
687
+ dscale * float(int8_t(((data_a[a_offset + ib].ql[qsi + 1] >> (b * 4)) & 0xF) | (((data_a[a_offset + ib].qh[qhi + 1] >> qhshift) & 3) << 4)) - 32));
688
+ }
689
+ vec2 get_dm(uint ib, uint a_offset) {
690
+ return vec2(1, 0);
691
+ }
692
+ #endif
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl ADDED
@@ -0,0 +1,1376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ // Each format defines a scalar dequantFunc<T> plus a V=4 dequantFunc<T>_v
3
+ // passed as the optional vector decoder to coopMatLoadTensorNV via
4
+ // GL_NV_cooperative_matrix_decode_vector. When the driver doesn't support
5
+ // the extension, ggml-vulkan.cpp strips it from the compiled SPIR-V.
6
+ #ifdef GL_NV_cooperative_matrix_decode_vector
7
+ #extension GL_NV_cooperative_matrix_decode_vector : enable
8
+ #endif
9
+
10
+ #include "types.glsl"
11
+
12
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufF32 {
13
+ vec4 block;
14
+ };
15
+
16
+ float16_t dequantFuncF32(const in decodeBufF32 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
17
+ {
18
+ const vec4 v = bl.block;
19
+ const uint idx = coordInBlock[1];
20
+ const f16vec4 vf16 = f16vec4(v);
21
+ return vf16[idx];
22
+ }
23
+
24
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ1_0 {
25
+ block_q1_0 block;
26
+ };
27
+
28
+ float16_t dequantFuncQ1_0(const in decodeBufQ1_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
29
+ {
30
+ const float16_t d = bl.block.d;
31
+ const uint idx = coordInBlock[1];
32
+ const uint bit = (uint(bl.block.qs[(idx & 0x78) >> 3]) >> (idx & 0x7)) & 1u;
33
+ return bit != 0u ? d : -d;
34
+ }
35
+
36
+ f16vec4 dequantFuncQ1_0_v(const in decodeBufQ1_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
37
+ {
38
+ const float16_t d = bl.block.d;
39
+ const float16_t md = -d;
40
+ const uint idx = coordInBlock[1];
41
+ const uint qs_nib = uint(bl.block.qs[idx >> 3]) >> (idx & 0x4u);
42
+ return f16vec4(
43
+ (qs_nib & 1u) != 0u ? d : md,
44
+ (qs_nib & 2u) != 0u ? d : md,
45
+ (qs_nib & 4u) != 0u ? d : md,
46
+ (qs_nib & 8u) != 0u ? d : md);
47
+ }
48
+
49
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ4_0 {
50
+ block_q4_0_packed16 block;
51
+ };
52
+
53
+ float16_t dequantFuncQ4_0(const in decodeBufQ4_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
54
+ {
55
+ const float16_t d = bl.block.d;
56
+ const uint idx = coordInBlock[1];
57
+ const uint shift = (idx & 0x10) >> 2;
58
+ uint32_t qs = uint32_t(bl.block.qs[(idx & 0xE) >> 1]);
59
+ qs >>= shift;
60
+ qs &= 0x0F0F;
61
+ qs = unpack8(qs)[idx & 1];
62
+ float16_t ret = (float16_t(qs) - float16_t(8)) * d;
63
+ return ret;
64
+ }
65
+
66
+ f16vec4 dequantFuncQ4_0_v(const in decodeBufQ4_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
67
+ {
68
+ const float16_t d = bl.block.d;
69
+ const uint idx = coordInBlock[1];
70
+ const uint shift = (idx & 0x10) >> 2; // 0 or 4
71
+ const uint qs_i = (idx & 0xE) >> 1; // even, in {0,2,4,6}
72
+ const uint qsw = uint32_t(bl.block.qs[qs_i ])
73
+ | (uint32_t(bl.block.qs[qs_i + 1u]) << 16);
74
+ // shift in {0,4}: per-byte mask 0x0F isolates the wanted nibble in each byte.
75
+ const uint q4 = (qsw >> shift) & 0x0F0F0F0Fu;
76
+ const u8vec4 q = unpack8(q4);
77
+ return f16vec4((vec4(q) - vec4(8.0)) * vec4(float(d)));
78
+ }
79
+
80
+ layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ4_1 {
81
+ block_q4_1 block;
82
+ };
83
+
84
+ layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ4_1_packed32 {
85
+ block_q4_1_packed32 block;
86
+ };
87
+
88
+ float16_t dequantFuncQ4_1(const in decodeBufQ4_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
89
+ {
90
+ const float16_t d = bl.block.d;
91
+ const float16_t m = bl.block.m;
92
+ const uint idx = coordInBlock[1];
93
+ const uint iqs = idx & 0xF;
94
+ const uint shift = (idx & 0x10) >> 2;
95
+ uint32_t qs = bl.block.qs[iqs];
96
+ qs >>= shift;
97
+ qs &= 0xF;
98
+ float16_t ret = float16_t(qs) * d + m;
99
+ return ret;
100
+ }
101
+
102
+ f16vec4 dequantFuncQ4_1_v(const in decodeBufQ4_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
103
+ {
104
+ decodeBufQ4_1_packed32 bl32 = decodeBufQ4_1_packed32(bl);
105
+ const float16_t d = bl.block.d;
106
+ const float16_t m = bl.block.m;
107
+ const uint idx = coordInBlock[1];
108
+ const uint shift = (idx & 0x10) >> 2; // 0 or 4
109
+ const uint qs_w = (idx & 0xC) >> 2; // iqs / 4 in [0,4)
110
+ const uint qsw = uint32_t(bl32.block.qs[qs_w]);
111
+ const u8vec4 q = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
112
+ return f16vec4(vec4(q) * vec4(float(d)) + vec4(float(m)));
113
+ }
114
+
115
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ5_0 {
116
+ block_q5_0 block;
117
+ };
118
+
119
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ5_0_packed16 {
120
+ block_q5_0_packed16 block;
121
+ };
122
+
123
+ float16_t dequantFuncQ5_0(const in decodeBufQ5_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
124
+ {
125
+ const float16_t d = bl.block.d;
126
+ const uint idx = coordInBlock[1];
127
+ const uint iqs = idx & 0xF;
128
+
129
+ const uint uint_qh = uint(bl.block.qh[1]) << 16 | bl.block.qh[0];
130
+ const uint qh = ((uint_qh >> idx) << 4) & 0x10;
131
+
132
+ const uint shift = (idx & 0x10) >> 2;
133
+ uint32_t qs = bl.block.qs[iqs];
134
+ qs >>= shift;
135
+ qs &= 0xF;
136
+
137
+ float16_t ret = (float16_t(qs | qh) - float16_t(16)) * d;
138
+ return ret;
139
+ }
140
+
141
+ f16vec4 dequantFuncQ5_0_v(const in decodeBufQ5_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
142
+ {
143
+ decodeBufQ5_0_packed16 bl16 = decodeBufQ5_0_packed16(bl);
144
+ const float16_t d = bl.block.d;
145
+ const uint idx = coordInBlock[1];
146
+ const uint shift = (idx & 0x10) >> 2; // 0 or 4
147
+ const uint qs_i = (idx & 0xC) >> 1; // packed16 word index, in {0,2,4,6}
148
+ const uint qsw = uint32_t(bl16.block.qs[qs_i ])
149
+ | (uint32_t(bl16.block.qs[qs_i + 1u]) << 16);
150
+ const u8vec4 ql = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
151
+
152
+ const uint uint_qh = uint(bl16.block.qh[1]) << 16 | uint(bl16.block.qh[0]);
153
+ const uint qh_pack = uint_qh >> idx; // bits 0..3 = element idx..idx+3 high bits
154
+ const uvec4 qh_high = (uvec4(qh_pack, qh_pack >> 1u, qh_pack >> 2u, qh_pack >> 3u) & uvec4(0x01u)) << 4u;
155
+
156
+ return f16vec4((vec4(ql) + vec4(qh_high) - vec4(16.0)) * vec4(float(d)));
157
+ }
158
+
159
+ layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufQ5_1 {
160
+ block_q5_1 block;
161
+ };
162
+
163
+ layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufQ5_1_packed32 {
164
+ block_q5_1_packed32 block;
165
+ };
166
+
167
+ float16_t dequantFuncQ5_1(const in decodeBufQ5_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
168
+ {
169
+ const float16_t d = bl.block.d;
170
+ const float16_t m = bl.block.m;
171
+ const uint idx = coordInBlock[1];
172
+ const uint iqs = idx & 0xF;
173
+
174
+ const uint uint_qh = bl.block.qh;
175
+ const uint qh = ((uint_qh >> idx) << 4) & 0x10;
176
+
177
+ const uint shift = (idx & 0x10) >> 2;
178
+ uint32_t qs = bl.block.qs[iqs];
179
+ qs >>= shift;
180
+ qs &= 0xF;
181
+
182
+ float16_t ret = float16_t(qs | qh) * d + m;
183
+ return ret;
184
+ }
185
+
186
+ f16vec4 dequantFuncQ5_1_v(const in decodeBufQ5_1 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
187
+ {
188
+ decodeBufQ5_1_packed32 bl32 = decodeBufQ5_1_packed32(bl);
189
+ const float16_t d = bl.block.d;
190
+ const float16_t m = bl.block.m;
191
+ const uint idx = coordInBlock[1];
192
+ const uint shift = (idx & 0x10) >> 2; // 0 or 4
193
+ const uint qs_w = (idx & 0xC) >> 2; // iqs / 4 in [0,4)
194
+ const uint qsw = uint32_t(bl32.block.qs[qs_w]);
195
+ const u8vec4 ql = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
196
+
197
+ const uint qh_pack = bl.block.qh >> idx; // bits 0..3 = element idx..idx+3 high bits
198
+ const uvec4 qh_high = (uvec4(qh_pack, qh_pack >> 1u, qh_pack >> 2u, qh_pack >> 3u) & uvec4(0x01u)) << 4u;
199
+
200
+ return f16vec4((vec4(ql) + vec4(qh_high)) * vec4(float(d)) + vec4(float(m)));
201
+ }
202
+
203
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ8_0 {
204
+ block_q8_0_packed16 block;
205
+ };
206
+
207
+ float16_t dequantFuncQ8_0(const in decodeBufQ8_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
208
+ {
209
+ const float16_t d = bl.block.d;
210
+ const uint idx = coordInBlock[1];
211
+ const uint iqs = idx;
212
+
213
+ // Load 16b and select the byte for this element
214
+ int32_t qs = unpack8(bl.block.qs[(iqs & 0x1E) >> 1])[iqs & 1];
215
+ float16_t ret = float16_t(qs) * d;
216
+ return ret;
217
+ }
218
+
219
+ f16vec4 dequantFuncQ8_0_v(const in decodeBufQ8_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
220
+ {
221
+ const float16_t d = bl.block.d;
222
+ const uint idx = coordInBlock[1];
223
+ const uint base = idx >> 1u;
224
+ const uint w = uint(uint16_t(bl.block.qs[base]))
225
+ | (uint(uint16_t(bl.block.qs[base + 1u])) << 16u);
226
+ const i8vec4 qi = unpack8(int32_t(w));
227
+ return f16vec4(vec4(qi) * vec4(float(d)));
228
+ }
229
+
230
+ layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ2_K {
231
+ block_q2_K block;
232
+ };
233
+
234
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ2_K_packed16 {
235
+ block_q2_K_packed16 block;
236
+ };
237
+
238
+ layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufQ2_K_packed32 {
239
+ block_q2_K_packed32 block;
240
+ };
241
+
242
+ float16_t dequantFuncQ2_K(const in decodeBufQ2_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
243
+ {
244
+ decodeBufQ2_K_packed16 bl16 = decodeBufQ2_K_packed16(bl);
245
+ const f16vec2 dm = bl.block.dm;
246
+ const uint idx = coordInBlock[1];
247
+
248
+ const uint scalesi = (idx & 0xF0) >> 4; // 0..15
249
+ const uint qsshift = (idx & 0x60) >> 4; // 0,2,4,6
250
+
251
+ uint qs = uint32_t(bl16.block.qs[((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1)]);
252
+ qs = (qs >> qsshift) & 0x0303;
253
+ qs = unpack8(qs)[idx & 1];
254
+
255
+ const uint scales = bl.block.scales[scalesi];
256
+ float16_t ret = dm.x * float16_t(scales & 0xF) * float16_t(qs) - dm.y * float16_t(scales >> 4);
257
+ return ret;
258
+ }
259
+
260
+ f16vec4 dequantFuncQ2_K_v(const in decodeBufQ2_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
261
+ {
262
+ decodeBufQ2_K_packed32 bl32 = decodeBufQ2_K_packed32(bl);
263
+ const f16vec2 dm = bl.block.dm;
264
+ const uint idx = coordInBlock[1];
265
+
266
+ const uint scalesi = idx >> 4; // 0..15
267
+ const uint qsshift = (idx & 0x60) >> 4; // 0,2,4,6
268
+
269
+ // qs_i (packed16) = ((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1) is even for idx % 4 == 0,
270
+ // so qs_w (packed32) = qs_i / 2 = ((idx & 0x80) >> 4) + ((idx & 0x1Cu) >> 2).
271
+ const uint qs_w = ((idx & 0x80) >> 4) + ((idx & 0x1Cu) >> 2);
272
+ const uint qsw = uint32_t(bl32.block.qs[qs_w]);
273
+ const uint qs4 = (qsw >> qsshift) & 0x03030303u;
274
+ const u8vec4 qi = unpack8(qs4);
275
+
276
+ const uint scales = bl.block.scales[scalesi];
277
+ const float16_t d_sub = dm.x * float16_t(scales & 0xF);
278
+ const float16_t m_sub = dm.y * float16_t(scales >> 4);
279
+ return f16vec4(vec4(qi) * vec4(float(d_sub)) - vec4(float(m_sub)));
280
+ }
281
+
282
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ3_K {
283
+ block_q3_K block;
284
+ };
285
+
286
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ3_K_packed16 {
287
+ block_q3_K_packed16 block;
288
+ };
289
+
290
+ float16_t dequantFuncQ3_K(const in decodeBufQ3_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
291
+ {
292
+ const uint idx = coordInBlock[1];
293
+ const uint iqs = idx;
294
+
295
+ const uint n = iqs / 128; // 0,1
296
+ const uint qsi = n * 32 + (iqs % 32); // 0..63
297
+ const uint hmi = (iqs % 32); // 0..31
298
+ const uint j = (iqs % 128) / 8; // 0..15
299
+ const uint is = iqs / 16; // 0..15
300
+ const uint halfsplit = ((iqs % 128) / 32); // 0,1,2,3
301
+ const uint qsshift = halfsplit * 2; // 0,2,4,6
302
+ const uint m = 1 << (4 * n + halfsplit); // 1,2,4,8,16,32,64,128
303
+
304
+ uint32_t scaleidx0 = (is < 8) ? is : (is-8);
305
+ uint32_t scaleidx0shift = (is < 8) ? 0 : 4;
306
+ uint32_t scaleidx1 = is + 8 - (is/4)*4;
307
+ uint32_t scaleidx1shift = (is/4)*2;
308
+
309
+ const int8_t us = int8_t(((bl.block.scales[scaleidx0] >> scaleidx0shift) & 0xF) | (((bl.block.scales[scaleidx1] >> scaleidx1shift) & 3) << 4));
310
+
311
+ const float16_t dl = bl.block.d * float16_t(us - 32);
312
+
313
+ float16_t ret = dl * float16_t(int8_t((bl.block.qs[qsi ] >> qsshift) & 3) - (((bl.block.hmask[hmi ] & m) != 0) ? 0 : 4));
314
+
315
+ return ret;
316
+ }
317
+
318
+ f16vec4 dequantFuncQ3_K_v(const in decodeBufQ3_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
319
+ {
320
+ decodeBufQ3_K_packed16 bl16 = decodeBufQ3_K_packed16(bl);
321
+ const uint idx = coordInBlock[1];
322
+
323
+ const uint n = idx >> 7; // 0,1
324
+ const uint is = idx >> 4; // 0..15
325
+ const uint halfsplit = (idx & 0x60) >> 5; // 0,1,2,3
326
+ const uint qsshift = halfsplit << 1; // 0,2,4,6
327
+ const uint hbit = (n << 2) + halfsplit; // 0..7 (bit position in hmask byte)
328
+
329
+ uint32_t scaleidx0 = (is < 8) ? is : (is - 8);
330
+ uint32_t scaleidx0shift = (is < 8) ? 0u : 4u;
331
+ uint32_t scaleidx1 = is + 8 - (is / 4) * 4;
332
+ uint32_t scaleidx1shift = (is / 4) * 2;
333
+
334
+ const int8_t us = int8_t(
335
+ ((bl.block.scales[scaleidx0] >> scaleidx0shift) & 0xF) |
336
+ (((bl.block.scales[scaleidx1] >> scaleidx1shift) & 3) << 4));
337
+ const float16_t dl = bl.block.d * float16_t(int(us) - 32);
338
+
339
+ // For idx % 4 == 0: (idx & 0x1F) == (idx & 0x1C) is a multiple of 4.
340
+ const uint qsi = (n << 5) + (idx & 0x1Cu);
341
+ const uint hmi = (idx & 0x1Cu);
342
+
343
+ // Two adjacent uint16 packed16 reads, combined into a uint32 in registers.
344
+ // After this: byte j of qsw / hmw holds the data for element idx+j.
345
+ const uint qsw = uint32_t(bl16.block.qs[qsi >> 1])
346
+ | (uint32_t(bl16.block.qs[(qsi >> 1) + 1u]) << 16);
347
+ const uint hmw = uint32_t(bl16.block.hmask[hmi >> 1])
348
+ | (uint32_t(bl16.block.hmask[(hmi >> 1) + 1u]) << 16);
349
+
350
+ // qsshift in {0,2,4,6} and hbit in {0..7}: per-byte masks isolate the wanted bits
351
+ // with no inter-byte leakage.
352
+ const uint ql4 = (qsw >> qsshift) & 0x03030303u;
353
+ const uint qh4 = (hmw >> hbit) & 0x01010101u;
354
+
355
+ const ivec4 q = ivec4(unpack8(ql4 | (qh4 << 2))) - ivec4(4);
356
+ return f16vec4(vec4(q) * vec4(float(dl)));
357
+ }
358
+
359
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K {
360
+ block_q4_K block;
361
+ };
362
+
363
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed16 {
364
+ block_q4_K_packed16 block;
365
+ };
366
+
367
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed32 {
368
+ block_q4_K_packed32 block;
369
+ };
370
+
371
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ4_K_packed128 {
372
+ block_q4_K_packed128 block;
373
+ };
374
+
375
+ #if defined(IS_MUL_MM2)
376
+
377
+ // For Q4_K and Q5_K in the mat-mul shader, we decode a tile's worth of scales
378
+ // into shared memory and then process the whole tile using those scales.
379
+ // There is a fetch function that loads into private variables and then a store
380
+ // function that stores into shared memory.
381
+ // Q4_K and Q5_K have the same encoding of scales, so everything is shared except
382
+ // the part that fetches from the structure (which has a different block layout).
383
+ #if defined(DATA_A_Q4_K) || defined(DATA_A_Q5_K)
384
+ const uint shAscales_stride = (BM + 2);
385
+ // 1 scale per 32 elements -> 8 scales per block, per row
386
+ shared vec2 shAscales[8 * shAscales_stride];
387
+ uvec4 row_v;
388
+ #endif
389
+
390
+ #if defined(DATA_A_Q4_K)
391
+ layout (binding = 0) readonly buffer A_Q4_K_128 {block_q4_K_packed128 data_a_q4_k_packed128[];};
392
+
393
+ void fetch_scalesQ4_K(uint ir_BM, uint pos_a, uint stride_a, uint block_k, uint tid, bool in_bounds)
394
+ {
395
+ uint tids_per_row = BLOCK_SIZE / BM;
396
+ uint is_per_tid = 8 / tids_per_row;
397
+ uint is_start = is_per_tid * (tid % tids_per_row);
398
+ uint tid_row = tid / tids_per_row;
399
+
400
+ uint row = ir_BM + tid_row;
401
+ uint block_index = pos_a + row * stride_a + (block_k / QUANT_K);
402
+ if (in_bounds || row < p.M) {
403
+ row_v = data_a_q4_k_packed128[block_index].q4k[0];
404
+ }
405
+ }
406
+ #endif
407
+ #if defined(DATA_A_Q5_K)
408
+ layout (binding = 0) readonly buffer A_Q5_K_128 {block_q5_K_packed128 data_a_q5_k_packed128[];};
409
+
410
+ void fetch_scalesQ5_K(uint ir_BM, uint pos_a, uint stride_a, uint block_k, uint tid, bool in_bounds)
411
+ {
412
+ uint tids_per_row = BLOCK_SIZE / BM;
413
+ uint is_per_tid = 8 / tids_per_row;
414
+ uint is_start = is_per_tid * (tid % tids_per_row);
415
+ uint tid_row = tid / tids_per_row;
416
+
417
+ uint row = ir_BM + tid_row;
418
+ uint block_index = pos_a + row * stride_a + (block_k / QUANT_K);
419
+ if (in_bounds || row < p.M) {
420
+ row_v = data_a_q5_k_packed128[block_index].q5k[0];
421
+ }
422
+ }
423
+ #endif
424
+
425
+ #if defined(DATA_A_Q4_K) || defined(DATA_A_Q5_K)
426
+ void store_scalesQ4_K(uint tid)
427
+ {
428
+ barrier();
429
+
430
+ uint tids_per_row = BLOCK_SIZE / BM;
431
+ uint is_per_tid = 8 / tids_per_row;
432
+ uint is_start = is_per_tid * (tid % tids_per_row);
433
+ uint tid_row = tid / tids_per_row;
434
+
435
+ [[unroll]] for (uint idx = 0; idx < is_per_tid; ++idx) {
436
+ uint is = idx + is_start;
437
+ uvec4 v = row_v;
438
+ const vec2 loadd = vec2(unpackFloat2x16(v.x));
439
+
440
+ uint32_t sc;
441
+ uint32_t mbyte;
442
+
443
+ uint32_t scale0 = v.y;
444
+ uint32_t scale4 = v.z;
445
+ uint32_t scale8 = v.w;
446
+
447
+ uint32_t sc_lo = scale0;
448
+ uint32_t mb_lo = scale4;
449
+ uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
450
+ uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
451
+
452
+ sc = is < 4 ? sc_lo : sc_hi;
453
+ mbyte = is < 4 ? mb_lo : mb_hi;
454
+ sc = sc >> (8 * (is & 3));
455
+ mbyte = mbyte >> (8 * (is & 3));
456
+ sc &= 0x3F;
457
+ mbyte &= 0x3F;
458
+
459
+ const float d = loadd.x * float(sc);
460
+ const float m = loadd.y * float(mbyte);
461
+ shAscales[is * shAscales_stride + tid_row] = vec2(d,m);
462
+ }
463
+
464
+ barrier();
465
+ }
466
+ #endif
467
+
468
+ #endif
469
+
470
+ float16_t dequantFuncQ4_K(const in decodeBufQ4_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
471
+ {
472
+ decodeBufQ4_K_packed16 bl16 = decodeBufQ4_K_packed16(bl);
473
+ decodeBufQ4_K_packed128 bl128 = decodeBufQ4_K_packed128(bl);
474
+ const uint idx = coordInBlock[1];
475
+
476
+ const uint b = (idx & 0x20) >> 5; // 0,1
477
+ const uint is = (idx & 0xE0) >> 5; // 0..7
478
+
479
+ #if defined(IS_MUL_MM2) && defined(DATA_A_Q4_K)
480
+ vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
481
+ float d = v.x;
482
+ float m = v.y;
483
+ #else
484
+ uvec4 v = bl128.block.q4k[0];
485
+ const vec2 loadd = vec2(unpackFloat2x16(v.x));
486
+
487
+ uint32_t sc;
488
+ uint32_t mbyte;
489
+
490
+ uint32_t scale0 = v.y;
491
+ uint32_t scale4 = v.z;
492
+ uint32_t scale8 = v.w;
493
+
494
+ uint32_t sc_lo = scale0;
495
+ uint32_t mb_lo = scale4;
496
+ uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
497
+ uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
498
+
499
+ sc = is < 4 ? sc_lo : sc_hi;
500
+ mbyte = is < 4 ? mb_lo : mb_hi;
501
+ sc = sc >> (8 * (is & 3));
502
+ mbyte = mbyte >> (8 * (is & 3));
503
+ sc &= 0x3F;
504
+ mbyte &= 0x3F;
505
+
506
+ const float d = loadd.x * float(sc);
507
+ const float m = loadd.y * float(mbyte);
508
+ #endif
509
+
510
+ uint qs = uint32_t(bl16.block.qs[((idx & 0xC0) >> 2) + ((idx & 0x1E) >> 1)]);
511
+ qs = (qs >> (b * 4 + 8 * (idx & 1))) & 0xF;
512
+
513
+ float ret = d * float(qs) - m;
514
+
515
+ return float16_t(ret);
516
+ }
517
+
518
+ f16vec4 dequantFuncQ4_K_v(const in decodeBufQ4_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
519
+ {
520
+ decodeBufQ4_K_packed32 bl32 = decodeBufQ4_K_packed32(bl);
521
+ decodeBufQ4_K_packed128 bl128 = decodeBufQ4_K_packed128(bl);
522
+ const uint idx = coordInBlock[1];
523
+
524
+ const uint is = idx >> 5; // 0..7
525
+
526
+ #if defined(IS_MUL_MM2) && defined(DATA_A_Q4_K)
527
+ vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
528
+ float d = v.x;
529
+ float m = v.y;
530
+ #else
531
+ uvec4 v = bl128.block.q4k[0];
532
+ const vec2 loadd = vec2(unpackFloat2x16(v.x));
533
+
534
+ uint32_t sc;
535
+ uint32_t mbyte;
536
+
537
+ uint32_t scale0 = v.y;
538
+ uint32_t scale4 = v.z;
539
+ uint32_t scale8 = v.w;
540
+
541
+ uint32_t sc_lo = scale0;
542
+ uint32_t mb_lo = scale4;
543
+ uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
544
+ uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
545
+
546
+ sc = is < 4 ? sc_lo : sc_hi;
547
+ mbyte = is < 4 ? mb_lo : mb_hi;
548
+ sc = sc >> (8 * (is & 3));
549
+ mbyte = mbyte >> (8 * (is & 3));
550
+ sc &= 0x3F;
551
+ mbyte &= 0x3F;
552
+
553
+ const float d = loadd.x * float(sc);
554
+ const float m = loadd.y * float(mbyte);
555
+ #endif
556
+
557
+ // idx in [0,256); vector decode uses idx a multiple of 4. packed32 word index:
558
+ // (qs_i >> 1) == (idx >> 6) * 8 + ((idx & 0x1E) >> 2). sh is 0 or 4 only, so a
559
+ // single (w >> sh) & 0x0F0F0F0F isolates all four nibbles without inter-byte leakage.
560
+ const uint sh = (idx & 0x20u) >> 3u;
561
+ const uint w = uint32_t(bl32.block.qs[(idx >> 6) * 8u + ((idx & 0x1Eu) >> 2)]);
562
+ const u8vec4 q = unpack8((w >> sh) & 0x0F0F0F0Fu);
563
+
564
+ return f16vec4(vec4(d) * vec4(q) - vec4(m));
565
+ }
566
+
567
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K {
568
+ block_q5_K block;
569
+ };
570
+
571
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed16 {
572
+ block_q5_K_packed16 block;
573
+ };
574
+
575
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed128 {
576
+ block_q5_K_packed128 block;
577
+ };
578
+
579
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ5_K_packed32 {
580
+ block_q5_K_packed32 block;
581
+ };
582
+
583
+ float16_t dequantFuncQ5_K(const in decodeBufQ5_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
584
+ {
585
+ decodeBufQ5_K_packed16 bl16 = decodeBufQ5_K_packed16(bl);
586
+ decodeBufQ5_K_packed128 bl128 = decodeBufQ5_K_packed128(bl);
587
+ const uint idx = coordInBlock[1];
588
+
589
+ const uint b = (idx & 0x20) >> 5; // 0,1
590
+ const uint is = (idx & 0xE0) >> 5; // 0..7
591
+
592
+ #if defined(IS_MUL_MM2) && defined(DATA_A_Q5_K)
593
+ vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
594
+ float d = v.x;
595
+ float m = v.y;
596
+ #else
597
+ uvec4 v = bl128.block.q5k[0];
598
+
599
+ const f16vec2 loadd = unpackFloat2x16(v.x);
600
+
601
+ uint32_t sc;
602
+ uint32_t mbyte;
603
+
604
+ uint32_t scale0 = v.y;
605
+ uint32_t scale4 = v.z;
606
+ uint32_t scale8 = v.w;
607
+
608
+ uint32_t sc_lo = scale0;
609
+ uint32_t mb_lo = scale4;
610
+ uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
611
+ uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
612
+
613
+ sc = is < 4 ? sc_lo : sc_hi;
614
+ mbyte = is < 4 ? mb_lo : mb_hi;
615
+ sc = sc >> (8 * (is & 3));
616
+ mbyte = mbyte >> (8 * (is & 3));
617
+ sc &= 0x3F;
618
+ mbyte &= 0x3F;
619
+
620
+ const float16_t d = loadd.x * float16_t(sc);
621
+ const float16_t m = loadd.y * float16_t(mbyte);
622
+ #endif
623
+
624
+ uint qh = uint32_t(bl16.block.qh[(idx & 0x1E) >> 1]);
625
+ qh = ((qh >> is) & 0x101) << 4;
626
+
627
+ uint qs = uint32_t(bl16.block.qs[((idx & 0xC0) >> 2) + ((idx & 0x1E) >> 1)]);
628
+ qs = (qs >> (b * 4)) & 0x0F0F;
629
+ qs = unpack8(qs | qh)[idx & 1];
630
+
631
+ float ret = d * float(qs) - m;
632
+
633
+ return float16_t(ret);
634
+ }
635
+
636
+ f16vec4 dequantFuncQ5_K_v(const in decodeBufQ5_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
637
+ {
638
+ decodeBufQ5_K_packed32 bl32 = decodeBufQ5_K_packed32(bl);
639
+ decodeBufQ5_K_packed128 bl128 = decodeBufQ5_K_packed128(bl);
640
+ const uint idx = coordInBlock[1];
641
+ const uint is = idx >> 5;
642
+
643
+ #if defined(IS_MUL_MM2) && defined(DATA_A_Q5_K)
644
+ vec2 v = shAscales[is * shAscales_stride + (blockCoords[0] % BM)];
645
+ float d = v.x;
646
+ float m = v.y;
647
+ #else
648
+ uvec4 v = bl128.block.q5k[0];
649
+
650
+ const f16vec2 loadd = unpackFloat2x16(v.x);
651
+
652
+ uint32_t sc;
653
+ uint32_t mbyte;
654
+
655
+ uint32_t scale0 = v.y;
656
+ uint32_t scale4 = v.z;
657
+ uint32_t scale8 = v.w;
658
+
659
+ uint32_t sc_lo = scale0;
660
+ uint32_t mb_lo = scale4;
661
+ uint32_t sc_hi = (scale8 & 0x0F0F0F0F) | ((scale0 & 0xC0C0C0C0) >> 2);
662
+ uint32_t mb_hi = ((scale8 & 0xF0F0F0F0) >> 4) | ((scale4 & 0xC0C0C0C0) >> 2);
663
+
664
+ sc = is < 4 ? sc_lo : sc_hi;
665
+ mbyte = is < 4 ? mb_lo : mb_hi;
666
+ sc = sc >> (8 * (is & 3));
667
+ mbyte = mbyte >> (8 * (is & 3));
668
+ sc &= 0x3F;
669
+ mbyte &= 0x3F;
670
+
671
+ const float16_t d = loadd.x * float16_t(sc);
672
+ const float16_t m = loadd.y * float16_t(mbyte);
673
+ #endif
674
+
675
+ // sh is 0 or 4; mask 0x0F0F0F0F covers the four nibbles regardless (no inter-byte leakage).
676
+ const uint sh = (idx & 0x20u) >> 3u;
677
+ const uint qs_w = (idx >> 6) * 8u + ((idx & 0x1Eu) >> 2);
678
+ const uint qh_w = (idx & 0x1Eu) >> 2;
679
+
680
+ const uint ql4 = (uint32_t(bl32.block.qs[qs_w]) >> sh) & 0x0F0F0F0Fu;
681
+ // qh stores bit `is` per element across 4 consecutive bytes; one shift+mask handles all 4.
682
+ const uint qh4 = ((uint32_t(bl32.block.qh[qh_w]) >> is) & 0x01010101u) << 4u;
683
+
684
+ const u8vec4 qi = unpack8(ql4 | qh4);
685
+ return f16vec4(vec4(qi) * vec4(d) - vec4(m));
686
+ }
687
+
688
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufQ6_K {
689
+ block_q6_K block;
690
+ };
691
+
692
+ layout(buffer_reference, std430, buffer_reference_align = 16) buffer decodeBufQ6_K_packed16 {
693
+ block_q6_K_packed16 block;
694
+ };
695
+
696
+ float16_t dequantFuncQ6_K(const in decodeBufQ6_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
697
+ {
698
+ decodeBufQ6_K_packed16 bl16 = decodeBufQ6_K_packed16(bl);
699
+ const uint idx = coordInBlock[1];
700
+
701
+ const uint b = (idx & 0x40) >> 6; // 0,1
702
+ const uint qhshift = (idx & 0x60) >> 4; // 0,2,4,6
703
+ const uint is = (idx & 0xF0) >> 4; // 0..15
704
+
705
+ const float16_t dscale = bl.block.d * float16_t(bl.block.scales[is]);
706
+
707
+ uint ql = uint32_t(bl16.block.ql[((idx & 0x80) >> 2) + ((idx & 0x3E) >> 1)]);
708
+ ql = (ql >> (b * 4)) & 0x0F0F;
709
+
710
+ uint qh = uint32_t(bl16.block.qh[((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1)]);
711
+ qh = ((qh >> qhshift) & 0x0303) << 4;
712
+
713
+ int q = unpack8(ql | qh)[idx & 1];
714
+
715
+ float16_t ret = dscale * float16_t(q - 32);
716
+
717
+ return ret;
718
+ }
719
+
720
+ f16vec4 dequantFuncQ6_K_v(const in decodeBufQ6_K bl, const in uint blockCoords[2], const in uint coordInBlock[2])
721
+ {
722
+ decodeBufQ6_K_packed16 bl16 = decodeBufQ6_K_packed16(bl);
723
+ const uint idx = coordInBlock[1];
724
+
725
+ const uint b = (idx & 0x40) >> 6;
726
+ const uint qhshift = (idx & 0x60) >> 4; // 0,2,4,6
727
+ const uint is = idx >> 4;
728
+ const uint sh = b * 4; // 0 or 4
729
+
730
+ const float16_t dscale = bl.block.d * float16_t(bl.block.scales[is]);
731
+
732
+ const uint ql_i = ((idx & 0x80) >> 2) + ((idx & 0x3E) >> 1);
733
+ const uint qh_i = ((idx & 0x80) >> 3) + ((idx & 0x1E) >> 1);
734
+
735
+ // Two adjacent uint16 packed16 reads, combined into a uint32 in registers.
736
+ // After this: byte j of qlw / qhw holds the data for element idx+j.
737
+ const uint qlw = uint32_t(bl16.block.ql[ql_i ]) | (uint32_t(bl16.block.ql[ql_i + 1]) << 16);
738
+ const uint qhw = uint32_t(bl16.block.qh[qh_i ]) | (uint32_t(bl16.block.qh[qh_i + 1]) << 16);
739
+
740
+ // sh in {0,4} and qhshift in {0,2,4,6}: per-byte masks 0x0F / 0x03 keep only the
741
+ // wanted bits with no inter-byte leakage; place qh's 2 bits at nibble high position.
742
+ const uint ql4 = (qlw >> sh) & 0x0F0F0F0Fu;
743
+ const uint qh4 = ((qhw >> qhshift) & 0x03030303u) << 4u;
744
+
745
+ const ivec4 qi = ivec4(unpack8(ql4 | qh4));
746
+ return f16vec4((vec4(qi) - vec4(32.0f)) * vec4(float(dscale)));
747
+ }
748
+
749
+ #if defined(DATA_A_IQ1_S)
750
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ1_S {
751
+ block_iq1_s block;
752
+ };
753
+
754
+ float16_t dequantFuncIQ1_S(const in decodeBufIQ1_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
755
+ {
756
+ const float16_t d = bl.block.d;
757
+ const uint idx = coordInBlock[1];
758
+
759
+ const uint ib32 = (idx & 0xE0) >> 5;
760
+ const uint ib8 = (idx & 0xF8) >> 3;
761
+
762
+ const uint qh = bl.block.qh[ib32];
763
+ const uint qs = bl.block.qs[ib8];
764
+ const float dl = d * float(2 * bitfieldExtract(qh, 12, 3) + 1);
765
+ const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
766
+ const uint grid = iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)];
767
+
768
+ float16_t ret = float16_t(dl) * (float16_t(bitfieldExtract(int(grid), 2 * int(idx % 8), 2)) + float16_t(delta));
769
+ return ret;
770
+ }
771
+
772
+ f16vec4 dequantFuncIQ1_S_v(const in decodeBufIQ1_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
773
+ {
774
+ const float16_t d = bl.block.d;
775
+ const uint idx = coordInBlock[1];
776
+
777
+ const uint ib32 = idx >> 5;
778
+ const uint ib8 = idx >> 3;
779
+ const int i8b = int(idx & 4); // 0 or 4
780
+
781
+ const uint qh = bl.block.qh[ib32];
782
+ const uint qs = bl.block.qs[ib8];
783
+ const float dl = float(d) * float(2 * bitfieldExtract(qh, 12, 3) + 1);
784
+ const float delta = ((qh & 0x8000u) != 0u) ? -IQ1S_DELTA : IQ1S_DELTA;
785
+ const uint grid = iq1s_grid[qs | (bitfieldExtract(qh, 3 * int(ib8 & 3), 3) << 8)];
786
+
787
+ const ivec4 q = ivec4(
788
+ bitfieldExtract(int(grid), 2 * (i8b + 0), 2),
789
+ bitfieldExtract(int(grid), 2 * (i8b + 1), 2),
790
+ bitfieldExtract(int(grid), 2 * (i8b + 2), 2),
791
+ bitfieldExtract(int(grid), 2 * (i8b + 3), 2));
792
+ return f16vec4((vec4(q) + vec4(delta)) * dl);
793
+ }
794
+ #endif
795
+
796
+ #if defined(DATA_A_IQ1_M)
797
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ1_M {
798
+ block_iq1_m block;
799
+ };
800
+
801
+ layout(buffer_reference, std430, buffer_reference_align = 8) buffer decodeBufIQ1_M_packed64 {
802
+ block_iq1_m_packed64 block;
803
+ };
804
+
805
+ float16_t dequantFuncIQ1_M(const in decodeBufIQ1_M bl, const in uint blockCoords[2], const in uint coordInBlock[2])
806
+ {
807
+ decodeBufIQ1_M_packed64 bl64 = decodeBufIQ1_M_packed64(bl);
808
+ const uint idx = coordInBlock[1];
809
+
810
+ uvec2 scales = unpack32(bl64.block.scales);
811
+ const float16_t d = uint16BitsToHalf(uint16_t(((scales.x & 0xF000) >> 12) | ((scales.x & 0xF0000000) >> 24) | ((scales.y & 0xF000) >> 4) | ((scales.y & 0xF0000000) >> 16)));
812
+
813
+ const uint ib8 = (idx & 0xF8) >> 3;
814
+ const uint ib16 = (idx & 0xF0) >> 4;
815
+ const int i8 = int(idx % 8);
816
+ const uint sc = bl.block.scales[ib8 / 8];
817
+ const uint qs = bl.block.qs[ib8];
818
+ const uint qh = bl.block.qh[ib16] >> (4 * (ib8 & 1));
819
+ const float dl = 2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1;
820
+ const float delta = ((qh & 8) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
821
+ const uint grid = iq1s_grid[qs | ((qh & 7) << 8)];
822
+
823
+ float16_t ret = d * float16_t(dl) * (float16_t(bitfieldExtract(int(grid), 2 * i8, 2)) + float16_t(delta));
824
+ return ret;
825
+ }
826
+
827
+ f16vec4 dequantFuncIQ1_M_v(const in decodeBufIQ1_M bl, const in uint blockCoords[2], const in uint coordInBlock[2])
828
+ {
829
+ decodeBufIQ1_M_packed64 bl64 = decodeBufIQ1_M_packed64(bl);
830
+ const uint idx = coordInBlock[1];
831
+
832
+ uvec2 scales = unpack32(bl64.block.scales);
833
+ const float16_t d = uint16BitsToHalf(uint16_t(((scales.x & 0xF000) >> 12) | ((scales.x & 0xF0000000) >> 24) | ((scales.y & 0xF000) >> 4) | ((scales.y & 0xF0000000) >> 16)));
834
+
835
+ const uint ib8 = idx >> 3;
836
+ const uint ib16 = idx >> 4;
837
+ const int i8b = int(idx & 4); // 0 or 4 -- i8 base for the V=4 group
838
+
839
+ const uint sc = bl.block.scales[ib8 / 8];
840
+ const uint qs = bl.block.qs[ib8];
841
+ const uint qh = bl.block.qh[ib16] >> (4 * (ib8 & 1));
842
+ const float dl = 2.0 * float(bitfieldExtract(sc, 3 * int(ib16 & 3), 3)) + 1.0;
843
+ const float delta = ((qh & 8u) != 0u) ? -IQ1S_DELTA : IQ1S_DELTA;
844
+ const uint grid = iq1s_grid[qs | ((qh & 7u) << 8)];
845
+
846
+ const ivec4 q = ivec4(
847
+ bitfieldExtract(int(grid), 2 * (i8b + 0), 2),
848
+ bitfieldExtract(int(grid), 2 * (i8b + 1), 2),
849
+ bitfieldExtract(int(grid), 2 * (i8b + 2), 2),
850
+ bitfieldExtract(int(grid), 2 * (i8b + 3), 2));
851
+ return f16vec4((vec4(q) + vec4(delta)) * (float(d) * dl));
852
+ }
853
+ #endif
854
+
855
+ #if defined(DATA_A_IQ2_XXS)
856
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XXS {
857
+ block_iq2_xxs block;
858
+ };
859
+
860
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XXS_packed16 {
861
+ block_iq2_xxs_packed16 block;
862
+ };
863
+
864
+ float16_t dequantFuncIQ2_XXS(const in decodeBufIQ2_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
865
+ {
866
+ decodeBufIQ2_XXS_packed16 bl16 = decodeBufIQ2_XXS_packed16(bl);
867
+ const float16_t d = bl.block.d;
868
+ const uint idx = coordInBlock[1];
869
+
870
+ const uint ib32 = (idx & 0xE0) >> 5; // 0..7
871
+ const uint ib8 = (idx & 0x18) >> 3; // 0..3
872
+ const uint iqs = 8 * ib32 + ib8;
873
+
874
+ const uint qs = bl.block.qs[iqs];
875
+ const uint signscale = pack32(u16vec2(bl16.block.qs[4*ib32+2], bl16.block.qs[4*ib32+3]));
876
+
877
+ const float dscale = float(bl.block.d) * 0.25 * (0.5 + float(signscale >> 28));
878
+ uint sign = bitfieldExtract(signscale, 7 * int(ib8), 7);
879
+ sign |= bitCount(sign) << 7;
880
+
881
+ uint g2 = iq2xxs_grid[qs][(idx & 4) >> 2];
882
+ g2 >>= (idx & 2) * 8;
883
+ const vec2 g = vec2(unpack8(g2));
884
+
885
+ vec2 ret = dscale * g * ((sign & (1 << (idx & 7))) != 0 ? -1.0hf : 1.0hf);
886
+ return float16_t(ret[idx & 1]);
887
+ }
888
+
889
+ f16vec4 dequantFuncIQ2_XXS_v(const in decodeBufIQ2_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
890
+ {
891
+ decodeBufIQ2_XXS_packed16 bl16 = decodeBufIQ2_XXS_packed16(bl);
892
+ const uint idx = coordInBlock[1];
893
+
894
+ const uint ib32 = idx >> 5;
895
+ const uint ib8 = (idx & 0x18) >> 3;
896
+ const uint iqs = 8 * ib32 + ib8;
897
+
898
+ const uint qs = bl.block.qs[iqs];
899
+ const uint signscale = pack32(u16vec2(bl16.block.qs[4*ib32+2], bl16.block.qs[4*ib32+3]));
900
+ const float dscale = float(bl.block.d) * 0.25 * (0.5 + float(signscale >> 28));
901
+
902
+ uint sign = bitfieldExtract(signscale, 7 * int(ib8), 7);
903
+ sign |= bitCount(sign) << 7;
904
+ const uint sb = sign >> (idx & 7u);
905
+
906
+ const uint g2 = iq2xxs_grid[qs][(idx & 4) >> 2];
907
+ const u8vec4 g = unpack8(g2);
908
+
909
+ return f16vec4(
910
+ dscale * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
911
+ dscale * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
912
+ dscale * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
913
+ dscale * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
914
+ }
915
+ #endif
916
+
917
+ #if defined(DATA_A_IQ2_XS)
918
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_XS {
919
+ block_iq2_xs block;
920
+ };
921
+
922
+ float16_t dequantFuncIQ2_XS(const in decodeBufIQ2_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
923
+ {
924
+ const float16_t d = bl.block.d;
925
+ const uint idx = coordInBlock[1];
926
+
927
+ const uint is = (idx & 0xE0) >> 5; // 0..8
928
+ const uint sshift = (idx & 0x10) >> 2; // 0,4
929
+ const uint iqs = (idx & 0xF8) >> 3; // 0..63
930
+
931
+ const uint16_t qs = bl.block.qs[iqs];
932
+ const float dscale = float(bl.block.d) * 0.25 * (0.5 + float((bl.block.scales[is] >> sshift) & 0xF));
933
+
934
+ uint sign = uint(qs >> 9);
935
+ sign |= bitCount(sign) << 7;
936
+ uint g2 = iq2xs_grid[qs & 0x1FF][(idx & 4) >> 2];
937
+ g2 >>= (idx & 2) * 8;
938
+ const vec2 g = vec2(unpack8(g2));
939
+
940
+ vec2 ret = dscale * g * ((sign & (1 << (idx & 7))) != 0 ? -1.0hf : 1.0hf);
941
+ return float16_t(ret[idx & 1]);
942
+ }
943
+
944
+ f16vec4 dequantFuncIQ2_XS_v(const in decodeBufIQ2_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
945
+ {
946
+ const uint idx = coordInBlock[1];
947
+
948
+ const uint is = idx >> 5;
949
+ const uint sshift = (idx & 0x10) >> 2;
950
+ const uint iqs = idx >> 3;
951
+
952
+ const uint16_t qs = bl.block.qs[iqs];
953
+ const float dscale = float(bl.block.d) * 0.25 * (0.5 + float((bl.block.scales[is] >> sshift) & 0xF));
954
+
955
+ uint sign = uint(qs >> 9);
956
+ sign |= bitCount(sign) << 7;
957
+ const uint sb = sign >> (idx & 7u);
958
+
959
+ const uint g2 = iq2xs_grid[qs & 0x1FF][(idx & 4) >> 2];
960
+ const u8vec4 g = unpack8(g2);
961
+
962
+ return f16vec4(
963
+ dscale * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
964
+ dscale * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
965
+ dscale * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
966
+ dscale * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
967
+ }
968
+ #endif
969
+
970
+ #if defined(DATA_A_IQ2_S)
971
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ2_S {
972
+ block_iq2_s block;
973
+ };
974
+
975
+ float16_t dequantFuncIQ2_S(const in decodeBufIQ2_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
976
+ {
977
+ uint idx = coordInBlock[1];
978
+
979
+ const uint ib32 = (idx & 0xE0) >> 5; // 0..7
980
+ const uint ib8 = (idx & 0xF8) >> 3; // 0..31
981
+ const uint qhshift = 2 * (ib8 % 4);
982
+
983
+ const uint scale = (bl.block.scales[ib32] >> ((idx & 0x10) >> 2)) & 0xf;
984
+ const uint qs = bl.block.qs[ib8];
985
+ const uint qh = bl.block.qh[ib32];
986
+ const uint sign = bl.block.qs[QUANT_K / 8 + ib8] >> (idx & 0x6);
987
+
988
+ const float d = float(bl.block.d);
989
+ const float db = d * 0.25 * (0.5 + scale);
990
+ const ivec2 sign01 = 1 - (2 & ivec2(sign << 1, sign));
991
+ uint g2 = iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(idx & 4) >> 2];
992
+ g2 >>= (idx & 2) * 8;
993
+ const vec2 v = db * vec2(sign01) * vec2(unpack8(g2));
994
+ return float16_t(v[idx & 1]);
995
+ }
996
+
997
+ f16vec4 dequantFuncIQ2_S_v(const in decodeBufIQ2_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
998
+ {
999
+ const uint idx = coordInBlock[1];
1000
+
1001
+ const uint ib32 = idx >> 5;
1002
+ const uint ib8 = idx >> 3;
1003
+ const uint qhshift = 2 * (ib8 % 4);
1004
+
1005
+ const uint scale = (bl.block.scales[ib32] >> ((idx & 0x10) >> 2)) & 0xf;
1006
+ const uint qs = bl.block.qs[ib8];
1007
+ const uint qh = bl.block.qh[ib32];
1008
+ const uint sb = uint(bl.block.qs[QUANT_K / 8 + ib8]) >> (idx & 0x6u);
1009
+
1010
+ const float d = float(bl.block.d);
1011
+ const float db = d * 0.25 * (0.5 + scale);
1012
+
1013
+ const uint g2 = iq2s_grid[qs | ((qh << (8 - qhshift)) & 0x300)][(idx & 4) >> 2];
1014
+ const u8vec4 g = unpack8(g2);
1015
+
1016
+ return f16vec4(
1017
+ db * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
1018
+ db * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
1019
+ db * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
1020
+ db * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
1021
+ }
1022
+ #endif
1023
+
1024
+ #if defined(DATA_A_IQ3_XXS)
1025
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_XXS {
1026
+ block_iq3_xxs block;
1027
+ };
1028
+
1029
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_XXS_packed16 {
1030
+ block_iq3_xxs_packed16 block;
1031
+ };
1032
+
1033
+ float16_t dequantFuncIQ3_XXS(const in decodeBufIQ3_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1034
+ {
1035
+ decodeBufIQ3_XXS_packed16 bl16 = decodeBufIQ3_XXS_packed16(bl);
1036
+ uint idx = coordInBlock[1];
1037
+
1038
+ const uint iqs = (idx & 0xFC) >> 2; // 0..63
1039
+ const uint is = QUANT_K / 4 + ((idx & 0xE0) >> 3);// 8 values
1040
+
1041
+ const float d = float(bl.block.d);
1042
+ const uint qs = bl.block.qs[iqs];
1043
+ const uint signs = pack32(u16vec2(
1044
+ bl16.block.qs[is/2+0],
1045
+ bl16.block.qs[is/2+1]
1046
+ ));
1047
+ const float db = d * 0.5 * (0.5 + (signs >> 28));
1048
+ const uint32_t sign7 = bitfieldExtract(signs, 7 * (int(iqs / 2) % 4), 7);
1049
+ const uint sign = (sign7 | (bitCount(sign7) << 7)) >> (idx & 0x6);
1050
+ const ivec2 sign01 = ivec2(1 - (2 & ivec2(sign << 1, sign)));
1051
+ const uint grid = iq3xxs_grid[qs] >> (16 * ((idx & 2) >> 1));
1052
+ const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy);
1053
+ return float16_t(v[idx & 1]);
1054
+ }
1055
+
1056
+ f16vec4 dequantFuncIQ3_XXS_v(const in decodeBufIQ3_XXS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1057
+ {
1058
+ decodeBufIQ3_XXS_packed16 bl16 = decodeBufIQ3_XXS_packed16(bl);
1059
+ const uint idx = coordInBlock[1];
1060
+
1061
+ const uint iqs = idx >> 2;
1062
+ const uint is = QUANT_K / 4 + ((idx & 0xE0) >> 3);
1063
+
1064
+ const float d = float(bl.block.d);
1065
+ const uint qs = bl.block.qs[iqs];
1066
+ const uint signs = pack32(u16vec2(bl16.block.qs[is/2+0], bl16.block.qs[is/2+1]));
1067
+ const float db = d * 0.5 * (0.5 + (signs >> 28));
1068
+
1069
+ const uint sign7 = bitfieldExtract(signs, 7 * (int(iqs / 2) % 4), 7);
1070
+ const uint sb = (sign7 | (bitCount(sign7) << 7)) >> (idx & 0x6u);
1071
+
1072
+ const uint grid = iq3xxs_grid[qs];
1073
+ const u8vec4 g = unpack8(grid);
1074
+
1075
+ return f16vec4(
1076
+ db * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
1077
+ db * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
1078
+ db * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
1079
+ db * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
1080
+ }
1081
+ #endif
1082
+
1083
+ #if defined(DATA_A_IQ3_S)
1084
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ3_S {
1085
+ block_iq3_s block;
1086
+ };
1087
+
1088
+ float16_t dequantFuncIQ3_S(const in decodeBufIQ3_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1089
+ {
1090
+ uint idx = coordInBlock[1];
1091
+
1092
+ const uint iqs = (idx & 0xFC) >> 2; // 0..63
1093
+ const uint iqh = (idx & 0xE0) >> 5;
1094
+
1095
+ const float d = float(bl.block.d);
1096
+ const uint qs = bl.block.qs[iqs];
1097
+ const uint qh = bl.block.qh[iqh];
1098
+ const int8_t sign = int8_t(bl.block.signs[iqs / 2] >> (idx & 0x6));
1099
+ const uint scale = bl.block.scales[iqs / 16];
1100
+ const ivec2 sign01 = ivec2(1 - (2 & ivec2(sign << 1, sign)));
1101
+ const float db = d * (1 + 2 * ((scale >> (4 * (iqh & 1))) & 0xf));
1102
+ const uint32_t grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)] >> ((idx & 2) << 3);
1103
+ const vec2 v = db * vec2(sign01) * vec2(unpack8(grid).xy);
1104
+
1105
+ return float16_t(v[idx & 1]);
1106
+ }
1107
+
1108
+ f16vec4 dequantFuncIQ3_S_v(const in decodeBufIQ3_S bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1109
+ {
1110
+ const uint idx = coordInBlock[1];
1111
+
1112
+ const uint iqs = idx >> 2;
1113
+ const uint iqh = idx >> 5;
1114
+
1115
+ const float d = float(bl.block.d);
1116
+ const uint qs = bl.block.qs[iqs];
1117
+ const uint qh = bl.block.qh[iqh];
1118
+ const uint sb = uint(bl.block.signs[iqs / 2]) >> (idx & 0x6u);
1119
+ const uint scale = bl.block.scales[iqs / 16];
1120
+ const float db = d * (1 + 2 * ((scale >> (4 * (iqh & 1))) & 0xf));
1121
+
1122
+ const uint grid = iq3s_grid[qs | ((qh << (8 - (iqs % 8))) & 256)];
1123
+ const u8vec4 g = unpack8(grid);
1124
+
1125
+ return f16vec4(
1126
+ db * float(g.x) * ((sb & 1u) != 0u ? -1.0 : 1.0),
1127
+ db * float(g.y) * ((sb & 2u) != 0u ? -1.0 : 1.0),
1128
+ db * float(g.z) * ((sb & 4u) != 0u ? -1.0 : 1.0),
1129
+ db * float(g.w) * ((sb & 8u) != 0u ? -1.0 : 1.0));
1130
+ }
1131
+ #endif
1132
+
1133
+ #if defined(DATA_A_IQ4_XS)
1134
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_XS {
1135
+ block_iq4_xs block;
1136
+ };
1137
+
1138
+ layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufIQ4_XS_packed32 {
1139
+ block_iq4_xs_packed32 block;
1140
+ };
1141
+
1142
+ float16_t dequantFuncIQ4_XS(const in decodeBufIQ4_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1143
+ {
1144
+ const float16_t d = bl.block.d;
1145
+ const uint idx = coordInBlock[1];
1146
+
1147
+ const uint ib32 = (idx & 0xE0) >> 5; // 0..7
1148
+
1149
+ const uint sl = (bl.block.scales_l[ib32/2] >> (4 * (ib32 & 1))) & 0xF;
1150
+ const uint sh = ((bl.block.scales_h) >> (2 * ib32)) & 3;
1151
+ const uint qshift = (idx & 16) >> 2;
1152
+ const uint q = (bl.block.qs[16 * ib32 + (idx % 16)] >> qshift) & 0xF;
1153
+
1154
+ float16_t ret = d * float16_t(int(sl | (sh << 4)) - 32) * float16_t(kvalues_iq4nl[q]);
1155
+ return ret;
1156
+ }
1157
+
1158
+ f16vec4 dequantFuncIQ4_XS_v(const in decodeBufIQ4_XS bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1159
+ {
1160
+ decodeBufIQ4_XS_packed32 bl32 = decodeBufIQ4_XS_packed32(bl);
1161
+ const float16_t d = bl.block.d;
1162
+ const uint idx = coordInBlock[1];
1163
+
1164
+ const uint ib32 = idx >> 5; // 0..7
1165
+ const uint sl = (bl32.block.scales_l >> (4 * ib32)) & 0xF;
1166
+ const uint sh = (uint(bl32.block.scales_h) >> (2 * ib32)) & 0x3;
1167
+ const uint qshift = (idx & 0x10) >> 2; // {0, 4}
1168
+ const uint qs_w = 4 * ib32 + ((idx & 0xC) >> 2); // iqs / 4, in [0,32)
1169
+
1170
+ const float16_t dl = d * float16_t(int(sl | (sh << 4)) - 32);
1171
+
1172
+ const uint qsw = bl32.block.qs[qs_w];
1173
+ const u8vec4 qv = unpack8((qsw >> qshift) & 0x0F0F0F0Fu);
1174
+ const vec4 ret = vec4(
1175
+ float(kvalues_iq4nl[qv.x]),
1176
+ float(kvalues_iq4nl[qv.y]),
1177
+ float(kvalues_iq4nl[qv.z]),
1178
+ float(kvalues_iq4nl[qv.w])) * float(dl);
1179
+ return f16vec4(ret);
1180
+ }
1181
+ #endif
1182
+
1183
+ #if defined(DATA_A_IQ4_NL)
1184
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_NL {
1185
+ block_iq4_nl block;
1186
+ };
1187
+
1188
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufIQ4_NL_packed16 {
1189
+ block_iq4_nl_packed16 block;
1190
+ };
1191
+
1192
+ float16_t dequantFuncIQ4_NL(const in decodeBufIQ4_NL bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1193
+ {
1194
+ const float16_t d = bl.block.d;
1195
+ const uint idx = coordInBlock[1];
1196
+ const uint iqs = idx & 0xF;
1197
+ const uint shift = (idx & 0x10) >> 2;
1198
+ uint32_t qs = bl.block.qs[iqs];
1199
+ qs >>= shift;
1200
+ qs &= 0xF;
1201
+ float16_t ret = float16_t(kvalues_iq4nl[qs]) * d;
1202
+ return ret;
1203
+ }
1204
+
1205
+ f16vec4 dequantFuncIQ4_NL_v(const in decodeBufIQ4_NL bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1206
+ {
1207
+ decodeBufIQ4_NL_packed16 bl16 = decodeBufIQ4_NL_packed16(bl);
1208
+ const float16_t d = bl.block.d;
1209
+ const uint idx = coordInBlock[1];
1210
+ const uint shift = (idx & 0x10) >> 2; // 0 or 4
1211
+ const uint qs_i = (idx & 0xC) >> 1; // packed16 word index, in {0,2,4,6}
1212
+ const uint qsw = uint32_t(bl16.block.qs[qs_i ])
1213
+ | (uint32_t(bl16.block.qs[qs_i + 1u]) << 16);
1214
+ // shift in {0,4}: per-byte mask 0x0F isolates the wanted nibble in each byte.
1215
+ const u8vec4 q = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
1216
+ return f16vec4(
1217
+ float(d) * float(kvalues_iq4nl[q.x]),
1218
+ float(d) * float(kvalues_iq4nl[q.y]),
1219
+ float(d) * float(kvalues_iq4nl[q.z]),
1220
+ float(d) * float(kvalues_iq4nl[q.w]));
1221
+ }
1222
+ #endif
1223
+
1224
+ #if defined(DATA_A_MXFP4)
1225
+ layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufMXFP4 {
1226
+ block_mxfp4 block;
1227
+ };
1228
+
1229
+ float16_t dequantFuncMXFP4(const in decodeBufMXFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1230
+ {
1231
+ const float d = e8m0_to_fp32(bl.block.e);
1232
+ const uint idx = coordInBlock[1];
1233
+ const uint iqs = idx & 0xF;
1234
+ const uint shift = (idx & 0x10) >> 2;
1235
+ uint32_t qs = bl.block.qs[iqs];
1236
+ qs >>= shift;
1237
+ qs &= 0xF;
1238
+ float16_t ret = float16_t(kvalues_mxfp4[qs] * d * 0.5);
1239
+ return ret;
1240
+ }
1241
+
1242
+ f16vec4 dequantFuncMXFP4_v(const in decodeBufMXFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1243
+ {
1244
+ const float d = e8m0_to_fp32(bl.block.e);
1245
+ const uint idx = coordInBlock[1];
1246
+ const uint iqs = idx & 0xF;
1247
+ const uint shift = (idx & 0x10) >> 2;
1248
+ uvec4 qv = uvec4(
1249
+ uint(bl.block.qs[iqs]),
1250
+ uint(bl.block.qs[iqs + 1u]),
1251
+ uint(bl.block.qs[iqs + 2u]),
1252
+ uint(bl.block.qs[iqs + 3u]));
1253
+ qv = (qv >> shift) & 0xFu;
1254
+ const vec4 ret = vec4(
1255
+ float(kvalues_mxfp4[qv.x]),
1256
+ float(kvalues_mxfp4[qv.y]),
1257
+ float(kvalues_mxfp4[qv.z]),
1258
+ float(kvalues_mxfp4[qv.w])) * d * 0.5f;
1259
+ return f16vec4(ret);
1260
+ }
1261
+ #endif
1262
+
1263
+ #if defined(DATA_A_NVFP4)
1264
+ layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufNVFP4 {
1265
+ block_nvfp4 block;
1266
+ };
1267
+
1268
+ layout(buffer_reference, std430, buffer_reference_align = 4) buffer decodeBufNVFP4_packed32 {
1269
+ block_nvfp4_packed32 block;
1270
+ };
1271
+
1272
+ float16_t dequantFuncNVFP4(const in decodeBufNVFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1273
+ {
1274
+ const uint idx = coordInBlock[1];
1275
+ const uint sub = (idx & 0x30) >> 4;
1276
+ const uint iqs = ((idx & 0x30) >> 1) + (idx & 0x7);
1277
+ const uint shift = (idx & 0x8) >> 1;
1278
+ const float d = ue4m3_to_fp32(bl.block.d[sub]);
1279
+ uint qs = uint(bl.block.qs[iqs]);
1280
+ qs = (qs >> shift) & 0xF;
1281
+ return float16_t(kvalues_mxfp4[qs] * d * 0.5);
1282
+ }
1283
+
1284
+ f16vec4 dequantFuncNVFP4_v(const in decodeBufNVFP4 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
1285
+ {
1286
+ decodeBufNVFP4_packed32 bl32 = decodeBufNVFP4_packed32(bl);
1287
+ const uint idx = coordInBlock[1];
1288
+ const uint sub = idx >> 4;
1289
+ const uint qs_w = ((idx & 0x30) >> 3) + ((idx & 0x4u) >> 2); // iqs / 4, in [0,8)
1290
+ const uint shift = (idx & 0x8) >> 1;
1291
+ const float d = ue4m3_to_fp32(bl.block.d[sub]);
1292
+
1293
+ const uint qsw = uint32_t(bl32.block.qs[qs_w]);
1294
+ const u8vec4 qv = unpack8((qsw >> shift) & 0x0F0F0F0Fu);
1295
+ const vec4 ret = vec4(
1296
+ float(kvalues_mxfp4[qv.x]),
1297
+ float(kvalues_mxfp4[qv.y]),
1298
+ float(kvalues_mxfp4[qv.z]),
1299
+ float(kvalues_mxfp4[qv.w])) * d * 0.5f;
1300
+ return f16vec4(ret);
1301
+ }
1302
+ #endif
1303
+
1304
+ #if defined(DATA_A_Q1_0)
1305
+ #define dequantFuncA dequantFuncQ1_0
1306
+ #define dequantFuncA_v dequantFuncQ1_0_v
1307
+ #elif defined(DATA_A_Q4_0)
1308
+ #define dequantFuncA dequantFuncQ4_0
1309
+ #define dequantFuncA_v dequantFuncQ4_0_v
1310
+ #elif defined(DATA_A_Q4_1)
1311
+ #define dequantFuncA dequantFuncQ4_1
1312
+ #define dequantFuncA_v dequantFuncQ4_1_v
1313
+ #elif defined(DATA_A_Q5_0)
1314
+ #define dequantFuncA dequantFuncQ5_0
1315
+ #define dequantFuncA_v dequantFuncQ5_0_v
1316
+ #elif defined(DATA_A_Q5_1)
1317
+ #define dequantFuncA dequantFuncQ5_1
1318
+ #define dequantFuncA_v dequantFuncQ5_1_v
1319
+ #elif defined(DATA_A_Q8_0)
1320
+ #define dequantFuncA dequantFuncQ8_0
1321
+ #define dequantFuncA_v dequantFuncQ8_0_v
1322
+ #elif defined(DATA_A_Q2_K)
1323
+ #define dequantFuncA dequantFuncQ2_K
1324
+ #define dequantFuncA_v dequantFuncQ2_K_v
1325
+ #elif defined(DATA_A_Q3_K)
1326
+ #define dequantFuncA dequantFuncQ3_K
1327
+ #define dequantFuncA_v dequantFuncQ3_K_v
1328
+ #elif defined(DATA_A_Q4_K)
1329
+ #define dequantFuncA dequantFuncQ4_K
1330
+ #define dequantFuncA_v dequantFuncQ4_K_v
1331
+ #define fetch_scales fetch_scalesQ4_K
1332
+ #define store_scales store_scalesQ4_K
1333
+ #elif defined(DATA_A_Q5_K)
1334
+ #define dequantFuncA dequantFuncQ5_K
1335
+ #define dequantFuncA_v dequantFuncQ5_K_v
1336
+ #define fetch_scales fetch_scalesQ5_K
1337
+ #define store_scales store_scalesQ4_K
1338
+ #elif defined(DATA_A_Q6_K)
1339
+ #define dequantFuncA dequantFuncQ6_K
1340
+ #define dequantFuncA_v dequantFuncQ6_K_v
1341
+ #elif defined(DATA_A_IQ1_S)
1342
+ #define dequantFuncA dequantFuncIQ1_S
1343
+ #define dequantFuncA_v dequantFuncIQ1_S_v
1344
+ #elif defined(DATA_A_IQ1_M)
1345
+ #define dequantFuncA dequantFuncIQ1_M
1346
+ #define dequantFuncA_v dequantFuncIQ1_M_v
1347
+ #elif defined(DATA_A_IQ2_XXS)
1348
+ #define dequantFuncA dequantFuncIQ2_XXS
1349
+ #define dequantFuncA_v dequantFuncIQ2_XXS_v
1350
+ #elif defined(DATA_A_IQ2_XS)
1351
+ #define dequantFuncA dequantFuncIQ2_XS
1352
+ #define dequantFuncA_v dequantFuncIQ2_XS_v
1353
+ #elif defined(DATA_A_IQ2_S)
1354
+ #define dequantFuncA dequantFuncIQ2_S
1355
+ #define dequantFuncA_v dequantFuncIQ2_S_v
1356
+ #elif defined(DATA_A_IQ3_XXS)
1357
+ #define dequantFuncA dequantFuncIQ3_XXS
1358
+ #define dequantFuncA_v dequantFuncIQ3_XXS_v
1359
+ #elif defined(DATA_A_IQ3_S)
1360
+ #define dequantFuncA dequantFuncIQ3_S
1361
+ #define dequantFuncA_v dequantFuncIQ3_S_v
1362
+ #elif defined(DATA_A_IQ4_XS)
1363
+ #define dequantFuncA dequantFuncIQ4_XS
1364
+ #define dequantFuncA_v dequantFuncIQ4_XS_v
1365
+ #elif defined(DATA_A_IQ4_NL)
1366
+ #define dequantFuncA dequantFuncIQ4_NL
1367
+ #define dequantFuncA_v dequantFuncIQ4_NL_v
1368
+ #elif defined(DATA_A_MXFP4)
1369
+ #define dequantFuncA dequantFuncMXFP4
1370
+ #define dequantFuncA_v dequantFuncMXFP4_v
1371
+ #elif defined(DATA_A_NVFP4)
1372
+ #define dequantFuncA dequantFuncNVFP4
1373
+ #define dequantFuncA_v dequantFuncNVFP4_v
1374
+ #elif defined(DATA_A_F32)
1375
+ #define dequantFuncA dequantFuncF32
1376
+ #endif
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_head.glsl ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #extension GL_EXT_control_flow_attributes : require
2
+ #extension GL_EXT_shader_16bit_storage : require
3
+
4
+ layout (push_constant) uniform parameter
5
+ {
6
+ uint M;
7
+ uint K;
8
+ uint stride_a;
9
+ uint stride_b;
10
+ uint nel;
11
+ } p;
12
+
13
+ #include "types.glsl"
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_m.comp ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #extension GL_EXT_shader_explicit_arithmetic_types_int16 : require
4
+
5
+ #include "dequant_head.glsl"
6
+
7
+ layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
8
+
9
+ layout (binding = 0) readonly buffer A {block_iq1_m data_a[];};
10
+ layout (binding = 1) writeonly buffer D {D_TYPE data_b[];};
11
+
12
+ void main() {
13
+ // Each thread handles 1 subblock (32 values with 2 scales)
14
+ const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8;
15
+
16
+ init_iq_shmem(gl_WorkGroupSize);
17
+
18
+ if (ib >= p.nel / 256) {
19
+ return;
20
+ }
21
+
22
+ const uint ib32 = gl_LocalInvocationID.x % 8;
23
+ const uint ib64 = ib32 / 2;
24
+ const uint b_idx = 256 * ib + 32 * ib32;
25
+
26
+ const uint16_t[4] scales = data_a[ib].scales;
27
+ const u16vec4 s = u16vec4(scales[0], scales[1], scales[2], scales[3]) >> 12;
28
+ const float d = float(unpackHalf2x16(s.x | (s.y << 4) | (s.z << 8) | (s.w << 12)).x);
29
+
30
+ const uint sc = data_a[ib].scales[ib64];
31
+ [[unroll]] for (int l = 0; l < 4; ++l) {
32
+ const uint ib16 = 2 * ib32 + l / 2;
33
+ const float dl = d * (2 * bitfieldExtract(sc, 3 * int(ib16 & 3), 3) + 1);
34
+ const uint qh = data_a[ib].qh[ib16] >> (4 * (l & 1));
35
+ const uint qs = data_a[ib].qs[4 * ib32 + l];
36
+ const float delta = ((qh & 8) != 0) ? -IQ1M_DELTA : IQ1M_DELTA;
37
+ const int16_t grid = int16_t(iq1s_grid[qs | ((qh & 7) << 8)]);
38
+ [[unroll]] for (int j = 0; j < 8; ++j) {
39
+ data_b[b_idx + 8 * l + j] = D_TYPE(dl * (bitfieldExtract(grid, 2*j, 2) + delta));
40
+ }
41
+ }
42
+ }
backend/llama.cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_s.comp ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #version 450
2
+
3
+ #include "dequant_head.glsl"
4
+
5
+ layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
6
+
7
+ layout (binding = 0) readonly buffer A {block_iq1_s data_a[];};
8
+ layout (binding = 1) writeonly buffer D {D_TYPE data_b[];};
9
+
10
+ void main() {
11
+ // Each thread handles 1 subblock (32 values with 2 scales)
12
+ const uint ib = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x / 8;
13
+
14
+ init_iq_shmem(gl_WorkGroupSize);
15
+
16
+ if (ib >= p.nel / 256) {
17
+ return;
18
+ }
19
+
20
+ const uint ib32 = gl_LocalInvocationID.x % 8;
21
+ const uint b_idx = 256 * ib + 32 * ib32;
22
+
23
+ uint qh = data_a[ib].qh[ib32];
24
+ const float d = float(data_a[ib].d);
25
+ const float dl = d * float(2 * bitfieldExtract(qh, 12, 3) + 1);
26
+ const float delta = ((qh & 0x8000) != 0) ? -IQ1S_DELTA : IQ1S_DELTA;
27
+ [[unroll]] for (uint l = 0; l < 4; ++l) {
28
+ const uint qs = data_a[ib].qs[4 * ib32 + l];
29
+ const uint hi = bitfieldExtract(qh, 3 * int(l), 3);
30
+ const int16_t grid = int16_t(iq1s_grid[qs | (hi << 8)]);
31
+ [[unroll]] for (int j = 0; j < 8; ++j) {
32
+ data_b[b_idx + 8 * l + j] = D_TYPE(dl * (bitfieldExtract(grid, 2*j, 2) + delta));
33
+ }
34
+ }
35
+ }