char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
91f6a6cf3
char/aliceai-t5-moe
1#include <iostream> 2#include <fstream> 3#include <sstream> 4#include <string> 5#include <stdexcept> 6#include <array> 7#include <vector> 8#include <map> 9#include <thread> 10#include <mutex> 11#include <future> 12#include <queue> 13#include <condition_variable> 14#include <atomic> 15#include <cstdio> 16#include <cstring> 17#include <cstdlib> 18#include <cassert> 19#include <algorithm> 20#include <sys/stat.h> 21#include <sys/types.h> 22#include <filesystem> 23 24#ifdef _WIN32 25#define NOMINMAX 26#include <windows.h> 27#include <direct.h> // For _mkdir on Windows 28#else 29#include <unistd.h> 30#include <sys/wait.h> 31#include <fcntl.h> 32#endif 33 34#define ASYNCIO_CONCURRENCY 64 35 36std::mutex lock ; 37std::vector < std::pair < std::string , std::string >> shader_fnames ; 38// Set when any shader subprocess fails (non-zero exit / stderr / launch failure) so the 39// build is stopped instead of silently producing a broken libggml-vulkan. (issue #24393) 40static std::atomic < bool > compile_failed {false}; 41std::locale c_locale ("C" ); 42 43std::string GLSLC = "glslc" ; 44std::string input_filepath = "" ; 45std::string output_dir = "/tmp" ; 46std::string target_hpp = "" ; 47std::string target_cpp = "" ; 48 49const std::vector < std::string > type_names = { 50"f32" , 51"f16" , 52"q1_0" , 53"q2_0" , 54"q4_0" , 55"q4_1" , 56"q5_0" , 57"q5_1" , 58"q8_0" , 59"q2_k" , 60"q3_k" , 61"q4_k" , 62"q5_k" , 63"q6_k" , 64"iq1_s" , 65"iq1_m" , 66"iq2_xxs" , 67"iq2_xs" , 68"iq2_s" , 69"iq3_xxs" , 70"iq3_s" , 71"iq4_xs" , 72"iq4_nl" , 73"mxfp4" , 74"nvfp4" , 75"tq1_0" , 76"tq2_0" , 77"bf16" , 78}; 79 80enum MatMulIdType { 81NONE , 82DEFAULT , 83SUBGROUP , 84}; 85 86namespace { 87 88int execute_command (std::vector < std::string >& command , std::string & stdout_str , std::string & stderr_str ) { 89#ifdef _WIN32 90HANDLE stdout_read ,stdout_write ; 91HANDLE stderr_read ,stderr_write ; 92SECURITY_ATTRIBUTES sa = {sizeof (SECURITY_ATTRIBUTES ),NULL , TRUE }; 93 94if (!CreatePipe (& stdout_read ,& stdout_write ,& sa ,0 )|| 95 !SetHandleInformation (stdout_read ,HANDLE_FLAG_INHERIT ,0 )) { 96throw std::runtime_error ("Failed to create stdout pipe" ); 97 } 98 99if (!CreatePipe (& stderr_read ,& stderr_write ,& sa ,0 )|| 100 !SetHandleInformation (stderr_read ,HANDLE_FLAG_INHERIT ,0 )) { 101throw std::runtime_error ("Failed to create stderr pipe" ); 102 } 103 104PROCESS_INFORMATION pi ; 105STARTUPINFOA si = {}; 106si .cb = sizeof (STARTUPINFOA ); 107si .dwFlags = STARTF_USESTDHANDLES ; 108si .hStdOutput = stdout_write ; 109si .hStdError = stderr_write ; 110 111 std::string cmd ; 112for (const auto & part :command ) { 113cmd += part + " " ; 114 } 115 116if (!CreateProcessA (NULL ,cmd .data (),NULL ,NULL , TRUE,0 ,NULL ,NULL ,& si ,& pi )) { 117throw std::runtime_error ("Failed to create process" ); 118 } 119 120CloseHandle (stdout_write ); 121CloseHandle (stderr_write ); 122 123 std::array < char ,128 > buffer ; 124DWORD bytes_read ; 125 126while (ReadFile (stdout_read ,buffer .data (), (DWORD )buffer .size (),& bytes_read ,NULL )&& bytes_read > 0 ) { 127stdout_str .append (buffer .data (),bytes_read ); 128 } 129 130while (ReadFile (stderr_read ,buffer .data (), (DWORD )buffer .size (),& bytes_read ,NULL )&& bytes_read > 0 ) { 131stderr_str .append (buffer .data (),bytes_read ); 132 } 133 134CloseHandle (stdout_read ); 135CloseHandle (stderr_read ); 136WaitForSingleObject (pi .hProcess ,INFINITE ); 137DWORD exit_code = 1 ; 138GetExitCodeProcess (pi .hProcess ,& exit_code ); 139CloseHandle (pi .hProcess ); 140CloseHandle (pi .hThread ); 141return (int )exit_code ; 142#else 143int stdout_pipe [2 ]; 144int stderr_pipe [2 ]; 145 146if (pipe (stdout_pipe )!= 0 || pipe (stderr_pipe )!= 0 ) { 147throw std::runtime_error ("Failed to create pipes" ); 148 } 149 150pid_t pid = fork (); 151if (pid < 0 ) { 152 std::cerr <<strerror (errno ) <<"\n" ; 153throw std::runtime_error ("Failed to fork process" ); 154 } 155 156 std::vector < char *> argv ; 157for (std::string & part :command ) { 158argv .push_back (part .data ()); 159 } 160argv .push_back (nullptr ); 161 162if (pid == 0 ) { 163close (stdout_pipe [0 ]); 164close (stderr_pipe [0 ]); 165dup2 (stdout_pipe [1 ],STDOUT_FILENO ); 166dup2 (stderr_pipe [1 ],STDERR_FILENO ); 167close (stdout_pipe [1 ]); 168close (stderr_pipe [1 ]); 169execvp (argv [0 ],argv .data ()); 170_exit (EXIT_FAILURE ); 171 }else { 172close (stdout_pipe [1 ]); 173close (stderr_pipe [1 ]); 174 175 std::array < char ,128 > buffer ; 176ssize_t bytes_read ; 177 178while ((bytes_read = read (stdout_pipe [0 ],buffer .data (),buffer .size ()))> 0 ) { 179stdout_str .append (buffer .data (),bytes_read ); 180 } 181 182while ((bytes_read = read (stderr_pipe [0 ],buffer .data (),buffer .size ()))> 0 ) { 183stderr_str .append (buffer .data (),bytes_read ); 184 } 185 186close (stdout_pipe [0 ]); 187close (stderr_pipe [0 ]); 188int status = 0 ; 189waitpid (pid ,& status ,0 ); 190return WIFEXITED (status ) ?WEXITSTATUS (status ) :-1 ; 191 } 192#endif 193} 194 195bool directory_exists (const std::string & path ) { 196struct stat info ; 197if (stat (path .c_str (),& info )!= 0 ) { 198return false;// Path doesn't exist or can't be accessed 199 } 200return (info .st_mode & S_IFDIR )!= 0 ;// Check if it is a directory 201} 202 203bool create_directory (const std::string & path ) { 204#ifdef _WIN32 205return _mkdir (path .c_str ())== 0 || errno == EEXIST ;// EEXIST means the directory already exists 206#else 207return mkdir (path .c_str (),0755 )== 0 || errno == EEXIST ;// 0755 is the directory permissions 208#endif 209} 210 211std::string to_uppercase (const std::string & input ) { 212 std::string result = input ; 213for (char & c :result ) { 214c = std::toupper (c ); 215 } 216return result ; 217} 218 219bool string_starts_with (const std::string & str ,const std::string & prefix ) { 220if (prefix .size ()> str .size ()) { 221return false; 222 } 223return std::equal (prefix .begin (),prefix .end (),str .begin ()); 224} 225 226bool string_ends_with (const std::string & str ,const std::string & suffix ) { 227if (suffix .size ()> str .size ()) { 228return false; 229 } 230return std::equal (suffix .rbegin (),suffix .rend (),str .rbegin ()); 231} 232 233bool is_quantized_type (const std::string & type_name ) { 234return type_name != "f32" && type_name != "f16" && type_name != "bf16" ; 235} 236 237bool is_legacy_quant (const std::string & type_name ) { 238return type_name == "q2_0" || type_name == "q4_0" || type_name == "q4_1" || type_name == "q5_0" || type_name == "q5_1" || type_name == "q8_0" ; 239} 240 241bool is_k_quant (const std::string & type_name ) { 242return string_ends_with (type_name ,"_k" ); 243} 244 245bool is_iq_quant (const std::string & type_name ) { 246return string_starts_with (type_name ,"iq" ); 247} 248 249bool is_lut_quant (const std::string & type_name ) { 250return is_iq_quant (type_name )|| type_name == "mxfp4" || type_name == "nvfp4" ; 251} 252 253std::string lut_load_vec_a (const std::string & type_name ) { 254if (type_name == "iq1_s" || type_name == "iq1_m" || type_name == "iq2_xxs" || type_name == "iq2_xs" || type_name == "iq2_s" ) { 255return "8" ; 256 } 257return "4" ; 258} 259 260static const char path_separator = '/' ; 261 262std::string join_paths (const std::string & path1 ,const std::string & path2 ) { 263return path1 + path_separator + path2 ; 264} 265 266std::string basename (const std::string & path ) { 267return path .substr (path .find_last_of ("/\\" )+ 1 ); 268} 269 270std::stringstream make_generic_stringstream () { 271 std::stringstream ss ; 272ss .imbue (c_locale ); 273return ss ; 274} 275 276std::string read_binary_file (const std::string & path ,bool may_not_exist = false) { 277FILE * f = fopen (path .c_str (),"rb" ); 278if (!f ) { 279if (!may_not_exist ) { 280 std::cerr <<"Error opening file: " <<path <<" (" <<strerror (errno ) <<")\n" ; 281 } 282return {}; 283 } 284 285fseek (f ,0 ,SEEK_END ); 286size_t size = ftell (f ); 287fseek (f ,0 ,SEEK_SET ); 288 289 std::string data (size ,'\0' ); 290size_t read_size = fread (data .data (),1 ,size ,f ); 291fclose (f ); 292if (read_size != size ) { 293 std::cerr <<"Error reading file: " <<path <<" (" <<strerror (errno ) <<")\n" ; 294return {}; 295 } 296 297return data ; 298} 299 300void write_binary_file (const std::string & path ,const std::string & content ) { 301FILE * f = fopen (path .c_str (),"wb" ); 302if (!f ) { 303 std::cerr <<"Error opening file for writing: " <<path <<" (" <<strerror (errno ) <<")\n" ; 304return ; 305 } 306 307size_t write_size = fwrite (content .data (),1 ,content .size (),f ); 308fclose (f ); 309if (write_size != content .size ()) { 310 std::cerr <<"Error writing file: " <<path <<" (" <<strerror (errno ) <<")\n" ; 311return ; 312 } 313} 314 315void write_file_if_changed (const std::string & path ,const std::string & content ) { 316 std::string existing = read_binary_file (path , true); 317if (existing != content ) { 318write_binary_file (path ,content ); 319 } 320} 321 322 323// variables to track number of compiles in progress 324static uint32_t compile_count = 0 ; 325static std::mutex compile_count_mutex ; 326static std::condition_variable compile_count_cond ; 327static bool generate_dep_file = true; 328 329void decrement_compile_count (uint32_t * count ) { 330if (count ) { 331 std::lock_guard < std::mutex > guard (compile_count_mutex ); 332assert (compile_count > 0 ); 333compile_count -- ; 334compile_count_cond .notify_all (); 335 } 336} 337 338using compile_count_guard = std::unique_ptr < uint32_t , decltype(& decrement_compile_count )> ; 339 340compile_count_guard acquire_compile_slot () { 341// wait until fewer than N compiles are in progress. 342// 16 is an arbitrary limit, the goal is to avoid "failed to create pipe" errors. 343uint32_t N = std::max (1u , std::min (16u , std::thread::hardware_concurrency ())); 344 std::unique_lock < std::mutex > guard (compile_count_mutex ); 345compile_count_cond .wait (guard , [N ] {return compile_count < N ; }); 346compile_count ++ ; 347return compile_count_guard (& compile_count ,& decrement_compile_count ); 348} 349 350void string_to_spv_func (std::string name , std::string in_path , std::string out_path , std::map < std::string , std::string > defines ,bool coopmat ,bool dep_file ,compile_count_guard slot ) { 351 std::string target_env = (name .find ("_cm2" )!= std::string::npos ) ?"--target-env=vulkan1.3" :"--target-env=vulkan1.2" ; 352 353#ifdef _WIN32 354 std::vector < std::string > cmd = {GLSLC ,"-fshader-stage=compute" ,target_env ,"\"" + in_path + "\"" ,"-o" ,"\"" + out_path + "\"" }; 355#else 356 std::vector < std::string > cmd = {GLSLC ,"-fshader-stage=compute" ,target_env ,in_path ,"-o" ,out_path }; 357#endif 358 359// disable spirv-opt for coopmat shaders for https://github.com/ggml-org/llama.cpp/issues/10734 360// disable spirv-opt for bf16 shaders for https://github.com/ggml-org/llama.cpp/issues/15344 361// disable spirv-opt for rope shaders for https://github.com/ggml-org/llama.cpp/issues/16860 362// disable spirv-opt for dot2 shaders (spirv-opt doesn't recognize SPV_VALVE_mixed_float_dot_product capability) 363if (!coopmat && name .find ("bf16" )== std::string::npos && name .find ("rope" )== std::string::npos && name .find ("_dot2" )== std::string::npos ) { 364cmd .push_back ("-O" ); 365 } 366 367if (dep_file ) { 368cmd .push_back ("-MD" ); 369cmd .push_back ("-MF" ); 370#ifdef _WIN32 371cmd .push_back ("\"" + target_cpp + ".d\"" ); 372#else 373cmd .push_back (target_cpp + ".d" ); 374#endif 375 } 376 377#ifdef GGML_VULKAN_SHADER_DEBUG_INFO 378cmd .push_back ("-g" ); 379#endif 380 381for (const auto & define :defines ) { 382cmd .push_back ("-D" + define .first + "=" + define .second ); 383 } 384 385 std::string command ; 386for (const auto & part :cmd ) { 387command += part + " " ; 388 } 389 390 std::string stdout_str ,stderr_str ; 391try { 392// std::cout << "Executing command: "; 393// for (const auto& part : cmd) { 394// std::cout << part << " "; 395// } 396// std::cout << std::endl; 397 398int exit_code = execute_command (cmd ,stdout_str ,stderr_str ); 399if (exit_code != 0 || !stderr_str .empty ()) { 400 std::cerr <<"cannot compile " <<name <<" (exit code " <<exit_code <<")\n\n" ; 401for (const auto & part :cmd ) { 402 std::cerr <<part <<" " ; 403 } 404 std::cerr <<"\n\n" <<stderr_str << std::endl ; 405compile_failed = true; 406return ; 407 } 408 409if (dep_file ) { 410// replace .spv output path with the embed .cpp path which is used as output in CMakeLists.txt 411 std::string dep = read_binary_file (target_cpp + ".d" , true); 412if (!dep .empty ()) { 413size_t pos = dep .find (out_path ); 414if (pos != std::string::npos ) { 415dep .replace (pos ,out_path .length (),target_cpp ); 416 } 417write_binary_file (target_cpp + ".d" ,dep ); 418 } 419 } 420 421 std::lock_guard < std::mutex > guard (lock ); 422shader_fnames .push_back (std::make_pair (name ,out_path )); 423 }catch (const std::exception & e ) { 424 std::cerr <<"Error executing command for " <<name <<": " <<e .what () << std::endl ; 425compile_failed = true; 426 } 427} 428 429std::map < std::string , std::string > merge_maps (const std::map < std::string , std::string >& a ,const std::map < std::string , std::string >& b ) { 430 std::map < std::string , std::string > result = a ; 431result .insert (b .begin (),b .end ()); 432return result ; 433} 434 435static std::deque < std::future < void >> compiles ; 436void string_to_spv (std::string name ,const std::string & source ,const std::map < std::string , std::string >& defines ,bool fp16 = true,bool coopmat = false,bool coopmat2 = false,bool f16acc = false,const std::string & suffix = "" ) { 437name = name + (f16acc ?"_f16acc" :"" )+ (coopmat ?"_cm1" :"" )+ (coopmat2 ?"_cm2" : (fp16 ?"" :"_fp32" ))+ suffix ; 438 std::string out_path = join_paths (output_dir ,name + ".spv" ); 439 440if (input_filepath == "" ) { 441// No input source to compile, only generate header for all shaders 442shader_fnames .push_back (std::pair (name ,out_path )); 443return ; 444 }else if (basename (input_filepath )!= source ) { 445// Only compile shader variants matching the input filename 446return ; 447 } 448 449compile_count_guard slot = acquire_compile_slot (); 450compiles .push_back (std::async ( 451string_to_spv_func ,name ,input_filepath ,out_path ,defines ,coopmat ,generate_dep_file , std::move (slot ))); 452// Don't write the same dep file from multiple processes 453generate_dep_file = false; 454 455// Clean up completed futures - don't accumulate virtual memory for completed threads' stacks. 456while (!compiles .empty ()&& compiles .front ().wait_for (std::chrono::seconds (0 ))== std::future_status::ready ) { 457compiles .pop_front (); 458 } 459} 460 461void matmul_shaders (bool fp16 ,MatMulIdType matmul_id_type ,bool coopmat ,bool coopmat2 ,bool f16acc ,bool dot2 = false) { 462 std::string load_vec = coopmat2 ?"1" :fp16 ?"8" :"4" ; 463 std::string aligned_b_type_f32 = coopmat2 ?"float" :fp16 ?"mat2x4" :"vec4" ; 464 std::string aligned_b_type_f16 = coopmat2 ?"float16_t" :fp16 ?"f16mat2x4" :"f16vec4" ; 465 std::string dot2_sfx = dot2 ?"_dot2" :"" ; 466 467 std::map < std::string , std::string > base_dict ; 468 std::string shader_name = "matmul" ; 469 470if (matmul_id_type == MatMulIdType ::DEFAULT ) { 471base_dict ["MUL_MAT_ID" ]= "1" ; 472shader_name = "matmul_id" ; 473 }else if (matmul_id_type == MatMulIdType ::SUBGROUP ) { 474base_dict ["MUL_MAT_ID" ]= "1" ; 475base_dict ["MUL_MAT_ID_USE_SUBGROUPS" ]= "1" ; 476shader_name = "matmul_id_subgroup" ; 477 } 478 479if (fp16 ) { 480base_dict ["FLOAT16" ]= "1" ; 481 } 482 483base_dict ["ACC_TYPE" ]= f16acc ?"float16_t" :"float" ; 484base_dict ["ACC_TYPEV2" ]= f16acc ?"f16vec2" :"vec2" ; 485if (f16acc ) { 486base_dict ["ACC_TYPE_MAX" ]= "float16_t(65504.0)" ; 487 } 488 489if (coopmat ) { 490base_dict ["COOPMAT" ]= "1" ; 491 } 492#if defined(GGML_VULKAN_COOPMAT2_DECODE_VECTOR_GLSLC_SUPPORT ) 493if (coopmat2 ) { 494base_dict ["GGML_VULKAN_COOPMAT2_DECODE_VECTOR" ]= "1" ; 495 } 496#endif 497 498if (dot2 ) { 499base_dict ["DOT2_F16" ]= "1" ; 500 } 501 502const std::string source_name = coopmat2 ?"mul_mm_cm2.comp" :"mul_mm.comp" ; 503 504auto const & FLOAT_TYPE = [& ](int vec ,const std::string & t )-> std::string { 505switch (vec ) { 506case 1 : 507if (t == "bf16" ) { 508// scalar path promotes to float 509if (!coopmat && !coopmat2 ) { 510return "float" ; 511 } 512return "bfloat16_t" ; 513 } 514if (coopmat2 || fp16 ) { 515return "float16_t" ; 516 } 517return "float" ; 518case 2 : 519if (t == "bf16" ) { 520// scalar path promotes to float 521if (!coopmat && !coopmat2 ) { 522return "vec2" ; 523 } 524return "bf16vec2" ; 525 } 526if (coopmat2 || fp16 ) { 527return "f16vec2" ; 528 } 529return "vec2" ; 530case 4 : 531if (t == "bf16" ) { 532// scalar path promotes to float 533if (!coopmat && !coopmat2 ) { 534return "vec4" ; 535 } 536return "bf16vec4" ; 537 } 538if (coopmat2 || fp16 ) { 539return "f16vec4" ; 540 } 541return "vec4" ; 542case 8 : 543if (t == "bf16" ) { 544// scalar path promotes to float 545if (!coopmat && !coopmat2 ) { 546return "mat2x4" ; 547 } 548throw std::runtime_error ("bf16 vec8 not supported" ); 549 } 550if (coopmat2 || fp16 ) { 551return "f16mat2x4" ; 552 } 553return "mat2x4" ; 554default : 555throw std::runtime_error ("invalid vector size" ); 556 } 557 }; 558 559const std::map < std::string , std::string > float_type_dict_f16 = { 560 {"FLOAT_TYPE" ,FLOAT_TYPE (1 ,"f16" )}, 561 {"FLOAT_TYPEV2" ,FLOAT_TYPE (2 ,"f16" )}, 562 {"FLOAT_TYPEV4" ,FLOAT_TYPE (4 ,"f16" )}, 563 {"FLOAT_TYPEV8" ,FLOAT_TYPE (8 ,"f16" )}, 564 }; 565 566// Shaders with f16 B_TYPE 567string_to_spv (shader_name + "_f32_f16" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict_f16 ), {{"DATA_A_F32" ,"1" }, {"LOAD_VEC_A" ,load_vec }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f16 }, {"B_TYPE_SCALAR" ,"float16_t" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 568 569string_to_spv (shader_name + "_f16" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict_f16 ), {{"DATA_A_F16" ,"1" }, {"LOAD_VEC_A" ,load_vec }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f16 }, {"B_TYPE_SCALAR" ,"float16_t" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 570 571// bf16 572 { 573// For aligned matmul loads 574 std::string load_vec_a = coopmat2 ?"1" :"4" ; 575 576// scalar path promotes to float 577 std::string to_float_type = (coopmat || coopmat2 ) ?"uintBitsToBFloat16EXT" :"bf16_to_fp32" ; 578 579const std::map < std::string , std::string > float_type_dict_bf16 = { 580 {"FLOAT_TYPE" ,FLOAT_TYPE (1 ,"bf16" )}, 581 {"FLOAT_TYPEV2" ,FLOAT_TYPE (2 ,"bf16" )}, 582 {"FLOAT_TYPEV4" ,FLOAT_TYPE (4 ,"bf16" )}, 583 }; 584 585// If bfloat16 is not supported, then only compile the scalar (promote to fp32) shader 586#if !defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT ) 587if (!(coopmat || coopmat2 )) 588#endif 589 { 590if (!dot2 ) { 591string_to_spv (shader_name + "_bf16" ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict_bf16 ), {{"TO_FLOAT_TYPE" ,to_float_type }, {"DATA_A_BF16" ,"1" }, {"LOAD_VEC_A" ,load_vec_a }, {"LOAD_VEC_B" ,"4" }, {"B_TYPE" ,coopmat2 ?"bfloat16_t" :"u16vec4" }, {"B_TYPE_SCALAR" ,coopmat2 ?"bfloat16_t" :"uint16_t" }, {"B_TYPEV4" ,"bf16vec4" }, {"D_TYPE" ,"float" }, {"B_IS_FLOAT" ,"1" }, {"DATA_B_BF16" ,"1" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 592 } 593 } 594 } 595 596for (const auto & tname :type_names ) { 597if (tname == "bf16" ) { 598continue ; 599 } 600 601// Float types keep per-type compilation (different accumulation loop structure) 602if (tname == "f32" || tname == "f16" ) { 603 std::string data_a_key = "DATA_A_" + to_uppercase (tname ); 604 605const std::map < std::string , std::string > float_type_dict = { 606 {"FLOAT_TYPE" ,FLOAT_TYPE (1 ,tname )}, 607 {"FLOAT_TYPEV2" ,FLOAT_TYPE (2 ,tname )}, 608 {"FLOAT_TYPEV4" ,FLOAT_TYPE (4 ,tname )}, 609 {"FLOAT_TYPEV8" ,FLOAT_TYPE (8 ,tname )}, 610 }; 611 612if (!coopmat2 ) { 613string_to_spv (shader_name + "_" + tname + "_f32" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict ), {{data_a_key ,"1" }, {"LOAD_VEC_A" ,load_vec }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f32 }, {"B_TYPE_SCALAR" ,"float" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 614 } 615continue ; 616 } 617 618 std::string data_a_key = "DATA_A_" + to_uppercase (tname ); 619const std::map < std::string , std::string > float_type_dict = { 620 {"FLOAT_TYPE" ,FLOAT_TYPE (1 ,tname )}, 621 {"FLOAT_TYPEV2" ,FLOAT_TYPE (2 ,tname )}, 622 {"FLOAT_TYPEV4" ,FLOAT_TYPE (4 ,tname )}, 623 {"FLOAT_TYPEV8" ,FLOAT_TYPE (8 ,tname )}, 624 }; 625 626#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT ) 627if (!f16acc && !coopmat && !coopmat2 && !dot2 && (is_legacy_quant (tname )|| is_k_quant (tname )|| tname == "mxfp4" )) { 628string_to_spv (shader_name + "_" + tname + "_q8_1" ,"mul_mmq.comp" ,merge_maps (merge_maps (base_dict ,float_type_dict ), {{data_a_key ,"1" }, {"D_TYPE" ,"float" },}),fp16 ,coopmat ,coopmat2 ,f16acc ); 629 } 630#endif 631 632if (is_lut_quant (tname )) { 633 std::string lva = lut_load_vec_a (tname ); 634 635string_to_spv (shader_name + "_" + tname + "_f16" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict ), {{data_a_key ,"1" }, {"LOAD_VEC_A" ,lva }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f16 }, {"B_TYPE_SCALAR" ,"float16_t" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 636 637if (!coopmat2 ) { 638string_to_spv (shader_name + "_" + tname + "_f32" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict ), {{data_a_key ,"1" }, {"LOAD_VEC_A" ,lva }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f32 }, {"B_TYPE_SCALAR" ,"float" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 639 } 640 641#if defined(GGML_VULKAN_FLOAT_E2M1_GLSLC_SUPPORT )&& defined(GGML_VULKAN_FLOAT_E4M3_GLSLC_SUPPORT ) 642if ((tname == "mxfp4" || tname == "nvfp4" )&& (coopmat || coopmat2 )) { 643string_to_spv (shader_name + "_" + tname + "_f16_ocp" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict ), {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"LOAD_VEC_A" ,lva }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f16 }, {"B_TYPE_SCALAR" ,"float16_t" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 644if (!coopmat2 ) { 645string_to_spv (shader_name + "_" + tname + "_f32_ocp" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict ), {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"LOAD_VEC_A" ,lva }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f32 }, {"B_TYPE_SCALAR" ,"float" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 646 } 647 } 648#endif 649continue ; 650 } 651 652// dedicated shader needed due to regression on Ampere 653if (coopmat2 && (tname == "q4_k" || tname == "q5_k" )) { 654string_to_spv (shader_name + "_" + tname + "_f16" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,float_type_dict ), {{data_a_key ,"1" }, {"LOAD_VEC_A" ,load_vec }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f16 }, {"B_TYPE_SCALAR" ,"float16_t" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 655 } 656 } 657 658// Quant shader: one SPIR-V for all quant types, selected via MmTypeA spec constant 659 { 660const std::map < std::string , std::string > quant_float_type_dict = { 661 {"FLOAT_TYPE" ,FLOAT_TYPE (1 ,"q4_0" )}, 662 {"FLOAT_TYPEV2" ,FLOAT_TYPE (2 ,"q4_0" )}, 663 {"FLOAT_TYPEV4" ,FLOAT_TYPE (4 ,"q4_0" )}, 664 {"FLOAT_TYPEV8" ,FLOAT_TYPE (8 ,"q4_0" )}, 665 }; 666 667string_to_spv (shader_name + "_quant_f16" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,quant_float_type_dict ), {{"MULMAT_QUANT" ,"1" }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f16 }, {"B_TYPE_SCALAR" ,"float16_t" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 668 669if (!coopmat2 ) { 670string_to_spv (shader_name + "_quant_f32" + dot2_sfx ,source_name ,merge_maps (merge_maps (base_dict ,quant_float_type_dict ), {{"MULMAT_QUANT" ,"1" }, {"LOAD_VEC_B" ,load_vec }, {"B_TYPE" ,aligned_b_type_f32 }, {"B_TYPE_SCALAR" ,"float" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }}),fp16 ,coopmat ,coopmat2 ,f16acc ); 671 } 672 } 673} 674 675void process_shaders () { 676// matmul 677for (const MatMulIdType & matmul_id_type : {MatMulIdType ::NONE ,MatMulIdType ::DEFAULT ,MatMulIdType ::SUBGROUP }) { 678// No coopmats 679// fp32 680matmul_shaders (false,matmul_id_type , false, false, false); 681 682// fp16, fp32acc and fp16acc 683matmul_shaders (true,matmul_id_type , false, false, false); 684matmul_shaders (true,matmul_id_type , false, false, true); 685 686// dot2 variants (scalar fp16 only) 687matmul_shaders (true,matmul_id_type , false, false, false, true); 688matmul_shaders (true,matmul_id_type , false, false, true, true); 689 690if (matmul_id_type != MatMulIdType ::DEFAULT ) { 691#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT ) 692// Coopmat, fp32acc and fp16acc 693matmul_shaders (true,matmul_id_type , true, false, false); 694matmul_shaders (true,matmul_id_type , true, false, true); 695#endif 696 697#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT ) 698// Coopmat2, fp32acc and fp16acc 699matmul_shaders (true,matmul_id_type , false, true, false); 700matmul_shaders (true,matmul_id_type , false, true, true); 701#endif 702 } 703 } 704 705for (const bool & fp16 : {false, true}) { 706 std::map < std::string , std::string > base_dict ; 707if (fp16 ) { 708base_dict = {{"FLOAT_TYPE" ,"float16_t" }, {"FLOAT_TYPEV2" ,"f16vec2" }, {"FLOAT_TYPEV4" ,"f16vec4" }, {"FLOAT16" ,"1" }, {"FLOAT_TYPE_MAX" ,"float16_t(65504.0)" }}; 709 }else { 710base_dict = {{"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }, {"FLOAT_TYPEV4" ,"vec4" }}; 711 } 712 713// flash attention 714for (const bool & f16acc : {false, true}) { 715 std::map < std::string , std::string > fa_base_dict = base_dict ; 716fa_base_dict ["ACC_TYPE" ]= fp16 && f16acc ?"float16_t" :"float" ; 717fa_base_dict ["ACC_TYPEV2" ]= fp16 && f16acc ?"f16vec2" :"vec2" ; 718fa_base_dict ["ACC_TYPEV4" ]= fp16 && f16acc ?"f16vec4" :"vec4" ; 719// Compile IQ4_NL support into all FA variants so its shared LUT is available when K or V uses it. 720fa_base_dict ["DATA_A_IQ4_NL" ]= "1" ; 721if (fp16 && f16acc ) { 722fa_base_dict ["ACC_TYPE_MAX" ]= "float16_t(65504.0)" ; 723 } 724 725if (fp16 ) { 726#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT ) 727string_to_spv ("flash_attn_f32_f16" ,"flash_attn_cm2.comp" , 728merge_maps (fa_base_dict , {{"Q_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_TYPEV4" ,"vec4" }}),fp16 , false, true,f16acc ); 729#endif 730 731#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT ) 732string_to_spv ("flash_attn_f32_f16" ,"flash_attn_cm1.comp" , 733merge_maps (fa_base_dict , {{"Q_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_TYPEV4" ,"vec4" }, {"COOPMAT" ,"1" }}),fp16 , true, false,f16acc ); 734#endif 735 } 736 737string_to_spv ("flash_attn_f32_f16" ,"flash_attn.comp" , 738merge_maps (fa_base_dict , {{"Q_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_TYPEV4" ,"vec4" }}),fp16 , false, false,f16acc ); 739 740if (fp16 ) { 741string_to_spv ("flash_attn_f32_f16_dot2" ,"flash_attn.comp" , 742merge_maps (fa_base_dict , {{"Q_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_TYPEV4" ,"vec4" }, {"DOT2_F16" ,"1" }}),fp16 , false, false,f16acc ); 743 } 744 745#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT ) 746string_to_spv ("flash_attn_f32_f16" ,"flash_attn.comp" , 747merge_maps (fa_base_dict , {{"Q_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_TYPEV4" ,"vec4" }, {"MMQ" ,"1" }, {"FA_MMQ_MIXED" ,"1" }}),fp16 , false, false,f16acc ,"_int8" ); 748#endif 749 } 750 } 751 752const std::map < std::string , std::string > fa_bf16_dict = { 753 {"FLOAT_TYPE" ,"bfloat16_t" }, 754 {"FLOAT_TYPEV2" ,"bf16vec2" }, 755 {"FLOAT_TYPEV4" ,"bf16vec4" }, 756 {"ACC_TYPE" ,"float" }, 757 {"ACC_TYPEV2" ,"vec2" }, 758 {"ACC_TYPEV4" ,"vec4" }, 759 {"BFLOAT16" ,"1" }, 760 }; 761 762#if defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT )&& defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT ) 763string_to_spv ("flash_attn_f32_f16_bf16" ,"flash_attn_cm1.comp" , 764merge_maps (fa_bf16_dict , {{"Q_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_TYPEV4" ,"vec4" }, {"COOPMAT" ,"1" }}), 765 true, true, false, false); 766#endif 767 768#if defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT )&& defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT ) 769string_to_spv ("flash_attn_f32_f16_bf16" ,"flash_attn_cm2.comp" , 770merge_maps (fa_bf16_dict , {{"Q_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_TYPEV4" ,"vec4" }}), 771 true, false, true, false); 772#endif 773 774 std::map < std::string , std::string > base_dict = {{"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }}; 775 776for (const auto & tname :type_names ) { 777// mul mat vec 778 std::string data_a_key = "DATA_A_" + to_uppercase (tname ); 779 std::string shader = (string_ends_with (tname ,"_k" )|| string_starts_with (tname ,"iq1_" )|| string_starts_with (tname ,"iq2_" )|| string_starts_with (tname ,"iq3_" )|| tname == "iq4_xs" || tname == "tq2_0" || tname == "tq1_0" ) ?"mul_mat_vec_" + tname + ".comp" :"mul_mat_vec.comp" ; 780 781string_to_spv ("mul_mat_vec_" + tname + "_f32_f32" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }})); 782string_to_spv ("mul_mat_vec_" + tname + "_f16_f32" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"B_TYPE" ,"float16_t" }, {"B_TYPEV2" ,"f16vec2" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }})); 783 784string_to_spv ("mul_mat_vec_" + tname + "_f32_f32_subgroup" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 785string_to_spv ("mul_mat_vec_" + tname + "_f16_f32_subgroup" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"B_TYPE" ,"float16_t" }, {"B_TYPEV2" ,"f16vec2" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 786 787string_to_spv ("mul_mat_vec_" + tname + "_f32_f32_subgroup_no_shmem" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 788string_to_spv ("mul_mat_vec_" + tname + "_f16_f32_subgroup_no_shmem" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"B_TYPE" ,"float16_t" }, {"B_TYPEV2" ,"f16vec2" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 789 790#if defined(GGML_VULKAN_FLOAT_E2M1_GLSLC_SUPPORT )&& defined(GGML_VULKAN_FLOAT_E4M3_GLSLC_SUPPORT ) 791if (tname == "mxfp4" || tname == "nvfp4" ) { 792string_to_spv ("mul_mat_vec_" + tname + "_f32_f32_ocp" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }})); 793string_to_spv ("mul_mat_vec_" + tname + "_f16_f32_ocp" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float16_t" }, {"B_TYPEV2" ,"f16vec2" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }})); 794string_to_spv ("mul_mat_vec_" + tname + "_f32_f32_ocp_subgroup" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 795string_to_spv ("mul_mat_vec_" + tname + "_f16_f32_ocp_subgroup" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float16_t" }, {"B_TYPEV2" ,"f16vec2" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 796string_to_spv ("mul_mat_vec_" + tname + "_f32_f32_ocp_subgroup_no_shmem" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 797string_to_spv ("mul_mat_vec_" + tname + "_f16_f32_ocp_subgroup_no_shmem" ,shader ,merge_maps (base_dict , {{data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float16_t" }, {"B_TYPEV2" ,"f16vec2" }, {"B_TYPEV4" ,"f16vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 798string_to_spv ("mul_mat_vec_id_" + tname + "_f32_f32_ocp" ,shader ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }})); 799string_to_spv ("mul_mat_vec_id_" + tname + "_f32_f32_ocp_subgroup" ,shader ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 800string_to_spv ("mul_mat_vec_id_" + tname + "_f32_f32_ocp_subgroup_no_shmem" ,shader ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"USE_OCP_FP4" ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 801 } 802#endif 803 804string_to_spv ("mul_mat_vec_id_" + tname + "_f32_f32" ,shader ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }})); 805string_to_spv ("mul_mat_vec_id_" + tname + "_f32_f32_subgroup" ,shader ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 806string_to_spv ("mul_mat_vec_id_" + tname + "_f32_f32_subgroup_no_shmem" ,shader ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"B_TYPE" ,"float" }, {"B_TYPEV2" ,"vec2" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 807 808// mul mat vec with integer dot product 809#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT ) 810if (is_legacy_quant (tname )|| tname == "mxfp4" || is_k_quant (tname )|| tname == "iq1_s" || tname == "iq1_m" ) { 811string_to_spv ("mul_mat_vec_" + tname + "_q8_1_f32" ,"mul_mat_vecq.comp" ,merge_maps (base_dict , {{data_a_key ,"1" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }, {"ACC_TYPE" ,"float" }})); 812string_to_spv ("mul_mat_vec_" + tname + "_q8_1_f32_subgroup" ,"mul_mat_vecq.comp" ,merge_maps (base_dict , {{data_a_key ,"1" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }, {"ACC_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 813string_to_spv ("mul_mat_vec_" + tname + "_q8_1_f32_subgroup_no_shmem" ,"mul_mat_vecq.comp" ,merge_maps (base_dict , {{data_a_key ,"1" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }, {"ACC_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 814 815string_to_spv ("mul_mat_vec_id_" + tname + "_q8_1_f32" ,"mul_mat_vecq.comp" ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }, {"ACC_TYPE" ,"float" }})); 816string_to_spv ("mul_mat_vec_id_" + tname + "_q8_1_f32_subgroup" ,"mul_mat_vecq.comp" ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }, {"ACC_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }})); 817string_to_spv ("mul_mat_vec_id_" + tname + "_q8_1_f32_subgroup_no_shmem" ,"mul_mat_vecq.comp" ,merge_maps (base_dict , {{"MUL_MAT_ID" ,"1" }, {data_a_key ,"1" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV2" ,"vec2" }, {"ACC_TYPE" ,"float" }, {"USE_SUBGROUP_ADD_NO_SHMEM" ,"1" }})); 818 } 819#endif 820 821// Dequant shaders 822if (tname != "f16" && tname != "bf16" ) { 823string_to_spv ("dequant_" + tname ,"dequant_" + tname + ".comp" ,merge_maps (base_dict , {{data_a_key ,"1" }, {"D_TYPE" ,"float16_t" }})); 824 } 825// Fused dequant+transpose variant for FA quant-KV (per-head-contiguous f16 scratch). 826if (tname == "q8_0" ) { 827string_to_spv ("dequant_" + tname + "_transpose" ,"dequant_" + tname + ".comp" ,merge_maps (base_dict , {{data_a_key ,"1" }, {"D_TYPE" ,"float16_t" }, {"DEQUANT_TRANSPOSE" ,"1" }})); 828 } 829 830shader = (tname == "f32" || tname == "f16" || tname == "bf16" ) ?"get_rows.comp" :"get_rows_quant.comp" ; 831 832if (tname == "f16" ) { 833string_to_spv ("get_rows_" + tname ,shader ,merge_maps (base_dict , {{"TEMP_TYPE" ,"FLOAT_TYPE" }, {data_a_key ,"1" }, {"B_TYPE" ,"int" }, {"D_TYPE" ,"float16_t" }, {"OPTIMIZATION_ERROR_WORKAROUND" ,"1" }})); 834 }else { 835string_to_spv ("get_rows_" + tname ,shader ,merge_maps (base_dict , {{"TEMP_TYPE" ,"FLOAT_TYPE" }, {data_a_key ,"1" }, {"B_TYPE" ,"int" }, {"D_TYPE" ,"float16_t" }})); 836 } 837string_to_spv ("get_rows_" + tname + "_f32" ,shader ,merge_maps (base_dict , {{"TEMP_TYPE" ,"FLOAT_TYPE" }, {data_a_key ,"1" }, {"B_TYPE" ,"int" }, {"D_TYPE" ,"float" }})); 838 } 839 840string_to_spv ("get_rows_i32" ,"get_rows.comp" , {{"TEMP_TYPE" ,"uint" }, {"A_TYPE" ,"uint" }, {"B_TYPE" ,"int" }, {"D_TYPE" ,"uint" }}); 841 842string_to_spv ("mul_mat_vec_p021_f16_f32_subgroup_add" ,"mul_mat_vec_p021.comp" , {{"A_TYPE" ,"float16_t" }, {"A_TYPEV4" ,"f16vec4" }, {"B_TYPE" ,"float" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }}); 843string_to_spv ("mul_mat_vec_p021_f16_f32" ,"mul_mat_vec_p021.comp" , {{"A_TYPE" ,"float16_t" }, {"A_TYPEV4" ,"f16vec4" }, {"B_TYPE" ,"float" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }}); 844string_to_spv ("mul_mat_vec_nc_f16_f32" ,"mul_mat_vec_nc.comp" , {{"A_TYPE" ,"float16_t" }, {"A_TYPEV4" ,"f16vec4" }, {"B_TYPE" ,"float" }, {"B_TYPEV4" ,"vec4" }, {"D_TYPE" ,"float" }}); 845 846// Norms 847string_to_spv ("norm_f32" ,"norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 848string_to_spv ("group_norm_f32" ,"group_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 849string_to_spv ("rms_norm_f32" ,"rms_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 850string_to_spv ("rms_norm_mul_add_f32" ,"rms_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"RMS_NORM_ADD_FUSION" ,"1" }})); 851string_to_spv ("rms_norm_mul_add_partials_f32" ,"rms_norm_partials.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"RMS_NORM_ADD_FUSION" ,"1" }})); 852string_to_spv ("rms_norm_set_rows_f32_f32" ,"rms_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"RMS_NORM_SET_ROWS_FUSION" ,"1" }})); 853string_to_spv ("rms_norm_set_rows_f32_f16" ,"rms_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float16_t" }, {"RMS_NORM_SET_ROWS_FUSION" ,"1" }})); 854string_to_spv ("rms_norm_partials_f32" ,"rms_norm_partials.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 855string_to_spv ("rms_norm_mul_rope_f32_f32" ,"rms_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float" }, {"RMS_NORM_ROPE_FUSION" ,"1" }})); 856string_to_spv ("rms_norm_mul_rope_f32_f16" ,"rms_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float16_t" }, {"RMS_NORM_ROPE_FUSION" ,"1" }})); 857string_to_spv ("rms_norm_back_f32" ,"rms_norm_back.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 858string_to_spv ("l2_norm_f32" ,"l2_norm.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 859 860string_to_spv ("cpy_f32_f32" ,"copy.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 861string_to_spv ("cpy_f32_f16" ,"copy.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float16_t" }}); 862string_to_spv ("cpy_f16_f16" ,"copy.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OPTIMIZATION_ERROR_WORKAROUND" ,"1" }}); 863string_to_spv ("cpy_f16_f32" ,"copy.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float" }, {"OPTIMIZATION_ERROR_WORKAROUND" ,"1" }}); 864string_to_spv ("cpy_f32_bf16" ,"copy.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"uint16_t" }, {"DATA_D_BF16" ,"1" }}); 865string_to_spv ("cpy_bf16_f32" ,"copy.comp" , {{"A_TYPE" ,"uint16_t" }, {"D_TYPE" ,"float" }, {"DATA_A_BF16" ,"1" }}); 866string_to_spv ("contig_cpy_f32_f32" ,"contig_copy.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 867string_to_spv ("contig_cpy_f32_i32" ,"contig_copy.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"int" }}); 868string_to_spv ("contig_cpy_i32_f32" ,"contig_copy.comp" , {{"A_TYPE" ,"int" }, {"D_TYPE" ,"float" }}); 869string_to_spv ("contig_cpy_f32_f16" ,"contig_copy.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float16_t" }}); 870string_to_spv ("contig_cpy_f16_f16" ,"contig_copy.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OPTIMIZATION_ERROR_WORKAROUND" ,"1" }}); 871string_to_spv ("contig_cpy_f16_f32" ,"contig_copy.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float" }, {"OPTIMIZATION_ERROR_WORKAROUND" ,"1" }}); 872string_to_spv ("contig_cpy_f32_bf16" ,"contig_copy.comp" ,{{"A_TYPE" ,"float" }, {"D_TYPE" ,"uint16_t" }, {"DATA_D_BF16" ,"1" }}); 873string_to_spv ("contig_cpy_bf16_f32" ,"contig_copy.comp" ,{{"A_TYPE" ,"uint16_t" }, {"D_TYPE" ,"float" }, {"DATA_A_BF16" ,"1" }}); 874string_to_spv ("cpy_f32_i32" ,"copy.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"int" }}); 875string_to_spv ("cpy_i32_f32" ,"copy.comp" , {{"A_TYPE" ,"int" }, {"D_TYPE" ,"float" }}); 876 877string_to_spv ("cpy_transpose_16" ,"copy_transpose.comp" , {{"A_TYPE" ,"uint16_t" }, {"D_TYPE" ,"uint16_t" }}); 878string_to_spv ("cpy_transpose_32" ,"copy_transpose.comp" , {{"A_TYPE" ,"uint" }, {"D_TYPE" ,"uint" }}); 879string_to_spv ("cpy_transpose_02_16" ,"copy_transpose_02.comp" , {{"A_TYPE" ,"uint16_t" }, {"D_TYPE" ,"uint16_t" }}); 880string_to_spv ("cpy_transpose_02_32" ,"copy_transpose_02.comp" , {{"A_TYPE" ,"uint" }, {"D_TYPE" ,"uint" }}); 881 882for (std::string t : {"q1_0" ,"q2_0" ,"q4_0" ,"q4_1" ,"q5_0" ,"q5_1" ,"q8_0" ,"iq4_nl" }) { 883string_to_spv ("cpy_f32_" + t ,"copy_to_quant.comp" , {{"DATA_A_" + to_uppercase (t ),"1" }, {"S_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 884string_to_spv ("cpy_" + t + "_f32" ,"copy_from_quant.comp" , {{"DATA_A_" + to_uppercase (t ),"1" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 885 } 886 887for (auto src : {std::pair {"f32" ,"float" }, std::pair {"f16" ,"float16_t" }}) { 888for (std::string dst : {"f32" ,"f16" ,"bf16" ,"q1_0" ,"q2_0" ,"q4_0" ,"q4_1" ,"q5_0" ,"q5_1" ,"q8_0" ,"iq4_nl" }) { 889string_to_spv ("set_rows_" + std::string (src .first )+ "_" + dst + "_i32" ,"copy_to_quant.comp" , {{"SET_ROWS" ,"1" }, {"DATA_A_" + to_uppercase (dst ),"1" }, {"B_TYPE" ,"uint" }, {"B_SIZE" ,"32" }, {"S_TYPE" ,src .second }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 890string_to_spv ("set_rows_" + std::string (src .first )+ "_" + dst + "_i64" ,"copy_to_quant.comp" , {{"SET_ROWS" ,"1" }, {"DATA_A_" + to_uppercase (dst ),"1" }, {"B_TYPE" ,"uvec2" }, {"B_SIZE" ,"64" }, {"S_TYPE" ,src .second }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 891 } 892 } 893 894auto get_type_str = [](bool f16 ) { 895return f16 ?"float16_t" :"float" ; 896 }; 897auto get_suffix = [](bool src0_f16 ,bool src1_f16 ,bool dst_f16 ) { 898 std::string s ; 899s += std::string (src0_f16 ?"_f16" :"_f32" ); 900s += std::string (src1_f16 ?"_f16" :"_f32" ); 901s += std::string (dst_f16 ?"_f16" :"_f32" ); 902return s ; 903 }; 904for (std::string op : {"add" ,"sub" ,"mul" ,"div" ,"add_rms" , }) { 905for (auto src0_f16 : {false, true}) { 906for (auto src1_f16 : {false, true}) { 907for (auto dst_f16 : {false, true}) { 908auto source = op == "add_rms" ? std::string ("add" ) :op ; 909auto name = op + get_suffix (src0_f16 ,src1_f16 ,dst_f16 ); 910auto add_rms = op == "add_rms" ?"1" :"0" ; 911string_to_spv (name .c_str (),source + ".comp" , {{"A_TYPE" ,get_type_str (src0_f16 )}, {"B_TYPE" ,get_type_str (src1_f16 )}, {"D_TYPE" ,get_type_str (dst_f16 )}, {"FLOAT_TYPE" ,"float" }, {"ADD_RMS" ,add_rms }}); 912 } 913 } 914 } 915 } 916 917string_to_spv ("sub_f32" ,"sub.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 918 919string_to_spv ("acc_f32" ,"acc.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 920 921string_to_spv ("split_k_reduce" ,"mul_mat_split_k_reduce.comp" , {}); 922string_to_spv ("fa_split_k_reduce" ,"flash_attn_split_k_reduce.comp" , {}); 923 924string_to_spv ("fa_mask_opt" ,"flash_attn_mask_opt.comp" , {}); 925 926string_to_spv ("quantize_q8_1" ,"quantize_q8_1.comp" , {}); 927string_to_spv ("quantize_q8_1_subgroup" ,"quantize_q8_1.comp" , {{"USE_SUBGROUPS" ,"1" }}); 928 929string_to_spv ("quantize_q8_1_x4" ,"quantize_q8_1.comp" , {{"QBLOCK_X4" ,"1" }}); 930string_to_spv ("quantize_q8_1_x4_subgroup" ,"quantize_q8_1.comp" , {{"QBLOCK_X4" ,"1" }, {"USE_SUBGROUPS" ,"1" }}); 931 932string_to_spv ("mul_f32" ,"mul.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 933 934string_to_spv ("div_f32" ,"div.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 935 936string_to_spv ("repeat_i32" ,"repeat.comp" , {{"A_TYPE" ,"int32_t" }, {"D_TYPE" ,"int32_t" }}); 937string_to_spv ("repeat_back_f32" ,"repeat_back.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 938string_to_spv ("get_rows_back_f32" ,"get_rows_back.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"int" }, {"D_TYPE" ,"float" }}); 939 940string_to_spv ("repeat_i16" ,"repeat.comp" , {{"A_TYPE" ,"int16_t" }, {"D_TYPE" ,"int16_t" }}); 941 942string_to_spv ("scale_f32" ,"scale.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 943 944string_to_spv ("pad_f32" ,"pad.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 945string_to_spv ("pad_reflect_1d_f32" ,"pad_reflect_1d.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 946 947string_to_spv ("concat_i8" ,"concat.comp" , {{"A_TYPE" ,"uint8_t" }, {"B_TYPE" ,"uint8_t" }, {"D_TYPE" ,"uint8_t" }}); 948string_to_spv ("concat_i16" ,"concat.comp" , {{"A_TYPE" ,"uint16_t" }, {"B_TYPE" ,"uint16_t" }, {"D_TYPE" ,"uint16_t" }}); 949string_to_spv ("concat_i32" ,"concat.comp" , {{"A_TYPE" ,"uint" }, {"B_TYPE" ,"uint" }, {"D_TYPE" ,"uint" }}); 950string_to_spv ("concat_i64" ,"concat.comp" , {{"A_TYPE" ,"uvec2" }, {"B_TYPE" ,"uvec2" }, {"D_TYPE" ,"uvec2" }}); 951 952string_to_spv ("upscale_f32" ,"upscale.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 953 954string_to_spv ("exp_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_exp" }}); 955string_to_spv ("exp_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_exp" }}); 956string_to_spv ("expm1_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_expm1" }}); 957string_to_spv ("expm1_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_expm1" }}); 958 959string_to_spv ("log_f16" ,"log.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 960string_to_spv ("log_f32" ,"log.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 961string_to_spv ("gelu_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_gelu" }}); 962string_to_spv ("gelu_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_gelu" }}); 963string_to_spv ("gelu_erf_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_gelu_erf" }}); 964string_to_spv ("gelu_erf_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_gelu_erf" }}); 965string_to_spv ("gelu_quick_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_gelu_quick" }}); 966string_to_spv ("gelu_quick_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_gelu_quick" }}); 967string_to_spv ("silu_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_silu" }}); 968string_to_spv ("silu_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_silu" }}); 969string_to_spv ("relu_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_relu" }}); 970string_to_spv ("relu_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_relu" }}); 971string_to_spv ("sqr_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_sqr" }}); 972string_to_spv ("sqr_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_sqr" }}); 973string_to_spv ("sqrt_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_sqrt" }}); 974string_to_spv ("sqrt_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_sqrt" }}); 975string_to_spv ("sin_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_sin" }}); 976string_to_spv ("sin_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_sin" }}); 977string_to_spv ("cos_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_cos" }}); 978string_to_spv ("cos_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_cos" }}); 979string_to_spv ("clamp_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_clamp" }}); 980string_to_spv ("clamp_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_clamp" }}); 981string_to_spv ("leaky_relu_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_leaky_relu" }}); 982string_to_spv ("leaky_relu_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_leaky_relu" }}); 983string_to_spv ("neg_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_neg" }}); 984string_to_spv ("neg_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_neg" }}); 985string_to_spv ("tanh_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_tanh" }}); 986string_to_spv ("tanh_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_tanh" }}); 987string_to_spv ("sigmoid_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_sigmoid" }}); 988string_to_spv ("sigmoid_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_sigmoid" }}); 989string_to_spv ("hardsigmoid_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_hardsigmoid" }}); 990string_to_spv ("hardsigmoid_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_hardsigmoid" }}); 991string_to_spv ("hardswish_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_hardswish" }}); 992string_to_spv ("hardswish_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_hardswish" }}); 993string_to_spv ("abs_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_abs" }}); 994string_to_spv ("abs_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_abs" }}); 995string_to_spv ("elu_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_elu" }}); 996string_to_spv ("elu_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_elu" }}); 997string_to_spv ("xielu_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_xielu" }}); 998string_to_spv ("xielu_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_xielu" }}); 999string_to_spv ("sgn_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_sgn" }}); 1000string_to_spv ("sgn_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_sgn" }}); 1001 1002string_to_spv ("tri_f16" ,"tri.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1003string_to_spv ("tri_f32" ,"tri.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1004string_to_spv ("diag_f16" ,"diag.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1005string_to_spv ("diag_f32" ,"diag.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1006 1007string_to_spv ("softplus_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_softplus" }}); 1008string_to_spv ("softplus_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_softplus" }}); 1009 1010string_to_spv ("gelu_mul_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_gelu" }, {"UNARY_MUL_FUSION" ,"1" }}); 1011string_to_spv ("gelu_mul_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_gelu" }, {"UNARY_MUL_FUSION" ,"1" }}); 1012string_to_spv ("sigmoid_mul_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_sigmoid" }, {"UNARY_MUL_FUSION" ,"1" }}); 1013string_to_spv ("sigmoid_mul_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_sigmoid" }, {"UNARY_MUL_FUSION" ,"1" }}); 1014string_to_spv ("silu_mul_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_silu" }, {"UNARY_MUL_FUSION" ,"1" }}); 1015string_to_spv ("silu_mul_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_silu" }, {"UNARY_MUL_FUSION" ,"1" }}); 1016string_to_spv ("softplus_mul_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_softplus" }, {"UNARY_MUL_FUSION" ,"1" }}); 1017string_to_spv ("softplus_mul_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"FLOAT_TYPE" ,"float" }, {"OP" ,"op_softplus" }, {"UNARY_MUL_FUSION" ,"1" }}); 1018 1019string_to_spv ("add1_f16_f16" ,"add1.comp" , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"FLOAT_TYPE" ,"float" }}); 1020string_to_spv ("add1_f16_f32" ,"add1.comp" , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float16_t" }, {"FLOAT_TYPE" ,"float" }}); 1021string_to_spv ("add1_f32_f32" ,"add1.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 1022string_to_spv ("arange_f32" ,"arange.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 1023string_to_spv ("fill_f32" ,"fill.comp" , {{"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }}); 1024string_to_spv ("fill_f16" ,"fill.comp" , {{"D_TYPE" ,"float16_t" }, {"FLOAT_TYPE" ,"float" }}); 1025string_to_spv ("step_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_step" }}); 1026string_to_spv ("step_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_step" }}); 1027string_to_spv ("round_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_round" }}); 1028string_to_spv ("round_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_round" }}); 1029string_to_spv ("ceil_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_ceil" }}); 1030string_to_spv ("ceil_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_ceil" }}); 1031string_to_spv ("floor_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_floor" }}); 1032string_to_spv ("floor_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_floor" }}); 1033string_to_spv ("trunc_f16" ,"unary.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }, {"OP" ,"op_trunc" }}); 1034string_to_spv ("trunc_f32" ,"unary.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"OP" ,"op_trunc" }}); 1035 1036string_to_spv ("geglu_f16" ,"geglu.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1037string_to_spv ("geglu_f32" ,"geglu.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1038string_to_spv ("reglu_f16" ,"reglu.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1039string_to_spv ("reglu_f32" ,"reglu.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1040string_to_spv ("swiglu_f16" ,"swiglu.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1041string_to_spv ("swiglu_f32" ,"swiglu.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1042string_to_spv ("swiglu_oai_f16" ,"swiglu_oai.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1043string_to_spv ("swiglu_oai_f32" ,"swiglu_oai.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1044string_to_spv ("swiglu_clamp_f16" ,"swiglu_clamp.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1045string_to_spv ("swiglu_clamp_f32" ,"swiglu_clamp.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1046string_to_spv ("geglu_erf_f16" ,"geglu_erf.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1047string_to_spv ("geglu_erf_f32" ,"geglu_erf.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1048string_to_spv ("geglu_quick_f16" ,"geglu_quick.comp" , {{"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1049string_to_spv ("geglu_quick_f32" ,"geglu_quick.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1050 1051string_to_spv ("silu_back_f32" ,"silu_back.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1052 1053string_to_spv ("diag_mask_inf_f32" ,"diag_mask_inf.comp" , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1054 1055string_to_spv ("soft_max_f32" ,"soft_max.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1056string_to_spv ("soft_max_f32_f16" ,"soft_max.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float" }})); 1057string_to_spv ("soft_max_back_f32" ,"soft_max_back.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1058 1059string_to_spv ("soft_max_large1_f32" ,"soft_max_large1.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1060string_to_spv ("soft_max_large2_f32" ,"soft_max_large2.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1061string_to_spv ("soft_max_large3_f32" ,"soft_max_large3.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1062string_to_spv ("soft_max_large1_f32_f16" ,"soft_max_large1.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float" }})); 1063string_to_spv ("soft_max_large2_f32_f16" ,"soft_max_large2.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float" }})); 1064string_to_spv ("soft_max_large3_f32_f16" ,"soft_max_large3.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float16_t" }, {"D_TYPE" ,"float" }})); 1065 1066string_to_spv ("rope_norm_f32" ,"rope_norm.comp" , {{"A_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float" }}); 1067string_to_spv ("rope_norm_f16" ,"rope_norm.comp" , {{"A_TYPE" ,"float16_t" }, {"ROPE_D_TYPE" ,"float16_t" }}); 1068string_to_spv ("rope_norm_f32_f16" ,"rope_norm.comp" , {{"A_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float16_t" }}); 1069 1070string_to_spv ("rope_neox_f32" ,"rope_neox.comp" , {{"A_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float" }}); 1071string_to_spv ("rope_neox_f16" ,"rope_neox.comp" , {{"A_TYPE" ,"float16_t" }, {"ROPE_D_TYPE" ,"float16_t" }}); 1072string_to_spv ("rope_neox_f32_f16" ,"rope_neox.comp" , {{"A_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float16_t" }}); 1073 1074string_to_spv ("rope_multi_f32" ,"rope_multi.comp" , {{"A_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float" }}); 1075string_to_spv ("rope_multi_f16" ,"rope_multi.comp" , {{"A_TYPE" ,"float16_t" }, {"ROPE_D_TYPE" ,"float16_t" }}); 1076string_to_spv ("rope_multi_f32_f16" ,"rope_multi.comp" , {{"A_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float16_t" }}); 1077 1078string_to_spv ("rope_vision_f32" ,"rope_vision.comp" , {{"A_TYPE" ,"float" }, {"ROPE_D_TYPE" ,"float" }}); 1079string_to_spv ("rope_vision_f16" ,"rope_vision.comp" , {{"A_TYPE" ,"float16_t" }, {"ROPE_D_TYPE" ,"float16_t" }}); 1080 1081string_to_spv ("argsort_f32" ,"argsort.comp" , {{"A_TYPE" ,"float" }}); 1082string_to_spv ("argsort_large_f32" ,"argsort_large.comp" , {{"A_TYPE" ,"float" }}); 1083 1084string_to_spv ("topk_argsort_f32" ,"topk_argsort.comp" , {{"A_TYPE" ,"float" }}); 1085string_to_spv ("topk_nary_search_f32" ,"topk_nary_search.comp" , {{"A_TYPE" ,"float" }}); 1086string_to_spv ("topk_radix_select_f32" ,"topk_radix_select.comp" , {{"A_TYPE" ,"float" }}); 1087 1088string_to_spv ("argmax_f32" ,"argmax.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"int" }})); 1089string_to_spv ("sum_rows_f32" ,"sum_rows.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1090string_to_spv ("cross_entropy_loss_f32" ,"cross_entropy_loss.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1091string_to_spv ("cross_entropy_loss_back_f32" ,"cross_entropy_loss_back.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1092string_to_spv ("fwht_f32" ,"fwht.comp" , {}); 1093string_to_spv ("fwht_shmem_f32" ,"fwht.comp" , {{"FWHT_SHMEM" ,"1" }}); 1094string_to_spv ("count_equal_i32" ,"count_equal.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"int" }, {"B_TYPE" ,"int" }, {"D_TYPE" ,"int" }})); 1095string_to_spv ("dsv4_hc_comb_f32" ,"dsv4_hc_comb.comp" , {}); 1096string_to_spv ("dsv4_hc_pre_f32" ,"dsv4_hc_pre.comp" , {}); 1097string_to_spv ("dsv4_hc_post_f32" ,"dsv4_hc_post.comp" , {}); 1098string_to_spv ("cumsum_f32" ,"cumsum.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1099string_to_spv ("cumsum_multipass1_f32" ,"cumsum_multipass1.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1100string_to_spv ("cumsum_multipass2_f32" ,"cumsum_multipass2.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1101 1102string_to_spv ("count_experts" ,"count_experts.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"uint" }, {"D_TYPE" ,"uint" }})); 1103string_to_spv ("count_experts_subgroup" ,"count_experts.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"uint" }, {"D_TYPE" ,"uint" }, {"USE_SUBGROUPS" ,"1" }})); 1104 1105for (std::string dim_str : {"" ,"_3d" }) { 1106for (bool bda : {false, true}) { 1107 std::string bda_str = bda ?"_bda" :"" ; 1108 std::string bda_def = bda ?"1" :"0" ; 1109string_to_spv ("im2col" + dim_str + "_f32" + bda_str ,"im2col" + dim_str + ".comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"D_SIZE" ,"4" }, {"BDA" ,bda_def }})); 1110string_to_spv ("im2col" + dim_str + "_f32_f16" + bda_str ,"im2col" + dim_str + ".comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float16_t" }, {"D_SIZE" ,"2" }, {"BDA" ,bda_def }})); 1111 } 1112 } 1113 1114string_to_spv ("out_prod_f32" ,"out_prod.comp" , {}); 1115 1116string_to_spv ("timestep_embedding_f32" ,"timestep_embedding.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1117 1118string_to_spv ("conv_transpose_1d_f32" ,"conv_transpose_1d.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1119string_to_spv ("col2im_1d_f32" ,"col2im_1d.comp" , {{"DATA_A_F32" ,"1" }, {"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1120string_to_spv ("col2im_1d_f16" ,"col2im_1d.comp" , {{"DATA_A_F16" ,"1" }, {"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1121string_to_spv ("col2im_1d_bf16" ,"col2im_1d.comp" , {{"DATA_A_BF16" ,"1" }, {"A_TYPE" ,"uint16_t" }, {"D_TYPE" ,"uint16_t" }}); 1122 1123string_to_spv ("snake_f32" ,"snake.comp" , {{"DATA_A_F32" ,"1" }, {"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }}); 1124string_to_spv ("snake_f16" ,"snake.comp" , {{"DATA_A_F16" ,"1" }, {"A_TYPE" ,"float16_t" }, {"D_TYPE" ,"float16_t" }}); 1125string_to_spv ("snake_bf16" ,"snake.comp" , {{"DATA_A_BF16" ,"1" }, {"DATA_D_BF16" ,"1" }, {"A_TYPE" ,"uint16_t" }, {"D_TYPE" ,"uint16_t" }}); 1126 1127string_to_spv ("pool1d_f32" ,"pool1d.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1128string_to_spv ("pool2d_f32" ,"pool2d.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1129 1130string_to_spv ("rwkv_wkv6_f32" ,"wkv6.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }})); 1131 1132string_to_spv ("gated_linear_attn_f32" ,"gla.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }})); 1133 1134// Compile IQ4_NL support in so its shared LUT is available when K uses it. 1135// K quant type is selected at runtime via the FaTypeK spec constant. 1136 std::map < std::string , std::string > li_dict = {{"FLOAT_TYPE" ,"float" }, {"FLOAT_TYPEV4" ,"vec4" }, {"DATA_A_IQ4_NL" ,"1" }}; 1137string_to_spv ("lightning_indexer_f32" ,"lightning_indexer.comp" ,li_dict ); 1138string_to_spv ("lightning_indexer_subgroup_f32" ,"lightning_indexer.comp" ,merge_maps (li_dict , {{"USE_SUBGROUP_ADD" ,"1" }})); 1139 1140string_to_spv ("rwkv_wkv7_f32" ,"wkv7.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }})); 1141 1142string_to_spv ("gated_delta_net_f32" ,"gated_delta_net.comp" ,merge_maps (base_dict , {{"FLOAT_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }, {"USE_SUBGROUP_CLUSTERED" ,"1" }})); 1143string_to_spv ("gated_delta_net_f32_nocluster" ,"gated_delta_net.comp" ,merge_maps (base_dict , {{"FLOAT_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }, {"USE_SUBGROUP_CLUSTERED" ,"0" }})); 1144string_to_spv ("gated_delta_net_f32_shmem" ,"gated_delta_net.comp" ,merge_maps (base_dict , {{"FLOAT_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"0" }, {"USE_SUBGROUP_CLUSTERED" ,"0" }})); 1145 1146string_to_spv ("opt_step_adamw_f32" ,"opt_step_adamw.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }})); 1147string_to_spv ("opt_step_sgd_f32" ,"opt_step_sgd.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }})); 1148 1149string_to_spv ("solve_tri_f32" ,"solve_tri.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1150 1151for (auto transpose : {false, true}) { 1152for (auto unroll : {false, true}) { 1153for (auto a_f16 : {false, true}) { 1154 std::map < std::string , std::string > defines = { 1155 {"A_TYPE" ,a_f16 ?"float16_t" :"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, 1156 {"USE_COLLECTIVES" ,"1" }, {"UNROLL" ,unroll ?"[[unroll]]" :"" }, 1157 }; 1158if (transpose )defines ["TRANSPOSE" ]= "1" ; 1159 std::string name = std::string (transpose ?"conv_transpose_2d" :"conv2d" ) 1160+ (a_f16 ?"_f16" :"" )+ "_f32" ; 1161string_to_spv (name + (unroll ?"_unroll" :"" ),"conv2d_mm.comp" ,defines ); 1162#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT ) 1163if (unroll ) { 1164auto cm2_defines = defines ; 1165cm2_defines ["COOPMAT2" ]= "1" ; 1166string_to_spv (name ,"conv2d_mm.comp" ,cm2_defines , true, false, true); 1167 } 1168#endif 1169#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT ) 1170if (unroll ) { 1171auto cm1_defines = defines ; 1172cm1_defines ["COOPMAT" ]= "1" ; 1173string_to_spv (name ,"conv2d_mm.comp" ,cm1_defines , true, true, false); 1174 } 1175#endif 1176 } 1177 } 1178 } 1179 1180for (auto unroll : {false, true}) { 1181for (auto a_f16 : {false, true}) { 1182 std::map < std::string , std::string > defines = { 1183 {"A_TYPE" ,a_f16 ?"float16_t" :"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, 1184 {"UNROLL" ,unroll ?"[[unroll]]" :"" }, 1185 }; 1186 std::string name = std::string ("conv3d" )+ (a_f16 ?"_f16" :"" )+ "_f32" ; 1187string_to_spv (name + (unroll ?"_unroll" :"" ),"conv3d_mm.comp" ,defines ); 1188#if defined(GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT ) 1189if (unroll ) { 1190auto cm2_defines = defines ; 1191cm2_defines ["COOPMAT2" ]= "1" ; 1192string_to_spv (name ,"conv3d_mm.comp" ,cm2_defines , true, false, true); 1193 } 1194#endif 1195#if defined(GGML_VULKAN_COOPMAT_GLSLC_SUPPORT ) 1196if (unroll ) { 1197auto cm1_defines = defines ; 1198cm1_defines ["COOPMAT" ]= "1" ; 1199string_to_spv (name ,"conv3d_mm.comp" ,cm1_defines , true, true, false); 1200 } 1201#endif 1202 } 1203 } 1204 1205string_to_spv ("conv2d_dw_whcn_f32" ,"conv2d_dw.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"WHCN" ,"1" }})); 1206string_to_spv ("conv2d_dw_cwhn_f32" ,"conv2d_dw.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"CWHN" ,"1" }})); 1207string_to_spv ("conv2d_dw_whcn_f16_f32" ,"conv2d_dw.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"WHCN" ,"1" }})); 1208string_to_spv ("conv2d_dw_cwhn_f16_f32" ,"conv2d_dw.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float16_t" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"CWHN" ,"1" }})); 1209 1210string_to_spv ("roll_f32" ,"roll.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1211 1212string_to_spv ("add_id_f32" ,"add_id.comp" ,merge_maps (base_dict , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }})); 1213 1214string_to_spv ("multi_add_f32" ,"multi_add.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"ADD_RMS" ,"0" }}); 1215string_to_spv ("multi_add_rms_f32" ,"multi_add.comp" , {{"A_TYPE" ,"float" }, {"B_TYPE" ,"float" }, {"D_TYPE" ,"float" }, {"FLOAT_TYPE" ,"float" }, {"ADD_RMS" ,"1" }}); 1216 1217string_to_spv ("ssm_scan_f32" ,"ssm_scan.comp" , {{"A_TYPE" ,"float" }}); 1218string_to_spv ("ssm_scan_subgroup_f32" ,"ssm_scan.comp" , {{"A_TYPE" ,"float" }, {"USE_SUBGROUP_ADD" ,"1" }}); 1219 1220string_to_spv ("ssm_conv_f32" ,"ssm_conv.comp" , {{"A_TYPE" ,"float" }}); 1221 1222string_to_spv ("topk_moe_f32" ,"topk_moe.comp" , {}); 1223 1224for (auto & c :compiles ) { 1225c .wait (); 1226 } 1227} 1228 1229void write_output_files () { 1230 std::stringstream hdr = make_generic_stringstream (); 1231 std::stringstream src = make_generic_stringstream (); 1232 1233hdr <<"#include <cstdint>\n\n" ; 1234src <<"#include \"" <<basename (target_hpp ) <<"\"\n\n" ; 1235 1236 std::sort (shader_fnames .begin (),shader_fnames .end ()); 1237for (const auto & pair :shader_fnames ) { 1238const std::string & name = pair .first ; 1239#ifdef _WIN32 1240 std::string path = pair .second ; 1241 std::replace (path .begin (),path .end (),'/' ,'\\' ); 1242#else 1243const std::string & path = pair .second ; 1244#endif 1245 1246hdr <<"extern const uint64_t " <<name <<"_len;\n" ; 1247hdr <<"extern const unsigned char " <<name <<"_data[];\n\n" ; 1248 1249if (input_filepath != "" ) { 1250 std::string data = read_binary_file (path ); 1251if (data .empty ()) { 1252continue ; 1253 } 1254 1255src <<"const uint64_t " <<name <<"_len = " <<data .size () <<";\n" ; 1256src <<"const unsigned char " <<name <<"_data[" <<data .size () <<"] = {\n" << std::hex ; 1257auto bytes = reinterpret_cast < const uint8_t *> (data .data ()); 1258for (size_t i = 0 ;i < data .size ();++ i ) { 1259src <<"0x" <<static_cast < int > (bytes [i ]) <<"," ; 1260if ((i + 1 ) %12 == 0 )src <<"\n" ; 1261 } 1262src << std::dec <<"\n};\n\n" ; 1263 } 1264 } 1265 1266 std::string suffixes [2 ]= {"_f32" ,"_f16" }; 1267for (std::string op : {"add" ,"sub" ,"mul" ,"div" ,"add_rms" }) { 1268hdr <<"extern const void * " <<op <<"_data[2][2][2];\n" ; 1269hdr <<"extern const uint64_t " <<op <<"_len[2][2][2];\n" ; 1270 1271 std::string op_file = op == "add_rms" ?"add.comp" : std::string (op )+ ".comp" ; 1272if (basename (input_filepath )!= op_file ) { 1273continue ; 1274 } 1275 std::stringstream data = make_generic_stringstream (); 1276 std::stringstream len = make_generic_stringstream (); 1277data <<"const void * " <<op <<"_data[2][2][2] = " ; 1278len <<"const uint64_t " <<op <<"_len[2][2][2] = " ; 1279for (uint32_t t0 = 0 ;t0 < 2 ;++ t0 ) { 1280if (t0 == 0 ) { 1281data <<"{" ; 1282len <<"{" ; 1283 } 1284for (uint32_t t1 = 0 ;t1 < 2 ;++ t1 ) { 1285if (t1 == 0 ) { 1286data <<"{" ; 1287len <<"{" ; 1288 } 1289for (uint32_t t2 = 0 ;t2 < 2 ;++ t2 ) { 1290if (t2 == 0 ) { 1291data <<"{" ; 1292len <<"{" ; 1293 } 1294data <<op <<suffixes [t0 ] <<suffixes [t1 ] <<suffixes [t2 ]; 1295len <<op <<suffixes [t0 ] <<suffixes [t1 ] <<suffixes [t2 ]; 1296data <<"_data," ; 1297len <<"_len," ; 1298if (t2 == 1 ) { 1299data <<"}, " ; 1300len <<"}, " ; 1301 } 1302 } 1303if (t1 == 1 ) { 1304data <<"}, " ; 1305len <<"}, " ; 1306 } 1307 } 1308if (t0 == 1 ) { 1309data <<"};\n" ; 1310len <<"};\n" ; 1311 } 1312 } 1313src <<data .str (); 1314src <<len .str (); 1315 } 1316 1317 std::vector < std::string > btypes = {"f16" ,"f32" }; 1318 1319#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT ) 1320btypes .push_back ("q8_1" ); 1321#endif 1322 1323for (const std::string & btype :btypes ) { 1324for (const auto & tname :type_names ) { 1325if (btype == "q8_1" && !is_legacy_quant (tname )&& tname != "mxfp4" && !is_k_quant (tname )&& tname != "iq1_s" && tname != "iq1_m" ) { 1326continue ; 1327 } 1328hdr <<"extern const void * arr_dmmv_" <<tname <<"_" <<btype <<"_f32_data[3];\n" ; 1329hdr <<"extern const uint64_t arr_dmmv_" <<tname <<"_" <<btype <<"_f32_len[3];\n" ; 1330if (basename (input_filepath )== "mul_mat_vec.comp" ) { 1331src <<"const void * arr_dmmv_" <<tname <<"_" <<btype <<"_f32_data[3] = {mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_data, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_subgroup_data, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_subgroup_no_shmem_data};\n" ; 1332src <<"const uint64_t arr_dmmv_" <<tname <<"_" <<btype <<"_f32_len[3] = {mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_len, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_subgroup_len, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_subgroup_no_shmem_len};\n" ; 1333 } 1334 1335if (btype == "f16" ) { 1336continue ; 1337 } 1338hdr <<"extern const void * arr_dmmv_id_" <<tname <<"_" <<btype <<"_f32_data[3];\n" ; 1339hdr <<"extern const uint64_t arr_dmmv_id_" <<tname <<"_" <<btype <<"_f32_len[3];\n" ; 1340if (basename (input_filepath )== "mul_mat_vec.comp" ) { 1341src <<"const void * arr_dmmv_id_" <<tname <<"_" <<btype <<"_f32_data[3] = {mul_mat_vec_id_" <<tname <<"_" <<btype <<"_f32_data, mul_mat_vec_id_" <<tname <<"_" <<btype <<"_f32_subgroup_data, mul_mat_vec_id_" <<tname <<"_" <<btype <<"_f32_subgroup_no_shmem_data};\n" ; 1342src <<"const uint64_t arr_dmmv_id_" <<tname <<"_" <<btype <<"_f32_len[3] = {mul_mat_vec_id_" <<tname <<"_" <<btype <<"_f32_len, mul_mat_vec_id_" <<tname <<"_" <<btype <<"_f32_subgroup_len, mul_mat_vec_id_" <<tname <<"_" <<btype <<"_f32_subgroup_no_shmem_len};\n" ; 1343 } 1344 } 1345 } 1346 1347#if defined(GGML_VULKAN_FLOAT_E2M1_GLSLC_SUPPORT )&& defined(GGML_VULKAN_FLOAT_E4M3_GLSLC_SUPPORT ) 1348for (const std::string & btype : {"f16" ,"f32" }) { 1349for (const std::string & tname : {"mxfp4" ,"nvfp4" }) { 1350hdr <<"extern const void * arr_dmmv_" <<tname <<"_" <<btype <<"_f32_ocp_data[3];\n" ; 1351hdr <<"extern const uint64_t arr_dmmv_" <<tname <<"_" <<btype <<"_f32_ocp_len[3];\n" ; 1352if (basename (input_filepath )== "mul_mat_vec.comp" ) { 1353src <<"const void * arr_dmmv_" <<tname <<"_" <<btype <<"_f32_ocp_data[3] = {mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_ocp_data, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_ocp_subgroup_data, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_ocp_subgroup_no_shmem_data};\n" ; 1354src <<"const uint64_t arr_dmmv_" <<tname <<"_" <<btype <<"_f32_ocp_len[3] = {mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_ocp_len, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_ocp_subgroup_len, mul_mat_vec_" <<tname <<"_" <<btype <<"_f32_ocp_subgroup_no_shmem_len};\n" ; 1355 } 1356 } 1357 } 1358for (const std::string & tname : {"mxfp4" ,"nvfp4" }) { 1359hdr <<"extern const void * arr_dmmv_id_" <<tname <<"_f32_f32_ocp_data[3];\n" ; 1360hdr <<"extern const uint64_t arr_dmmv_id_" <<tname <<"_f32_f32_ocp_len[3];\n" ; 1361if (basename (input_filepath )== "mul_mat_vec.comp" ) { 1362src <<"const void * arr_dmmv_id_" <<tname <<"_f32_f32_ocp_data[3] = {mul_mat_vec_id_" <<tname <<"_f32_f32_ocp_data, mul_mat_vec_id_" <<tname <<"_f32_f32_ocp_subgroup_data, mul_mat_vec_id_" <<tname <<"_f32_f32_ocp_subgroup_no_shmem_data};\n" ; 1363src <<"const uint64_t arr_dmmv_id_" <<tname <<"_f32_f32_ocp_len[3] = {mul_mat_vec_id_" <<tname <<"_f32_f32_ocp_len, mul_mat_vec_id_" <<tname <<"_f32_f32_ocp_subgroup_len, mul_mat_vec_id_" <<tname <<"_f32_f32_ocp_subgroup_no_shmem_len};\n" ; 1364 } 1365 } 1366#endif 1367 1368if (input_filepath == "" ) { 1369write_file_if_changed (target_hpp ,hdr .str ()); 1370 } 1371if (target_cpp != "" ) { 1372write_binary_file (target_cpp ,src .str ()); 1373 } 1374} 1375 1376}// namespace 1377 1378int main (int argc ,char ** argv ) { 1379 std::map < std::string , std::string > args ; 1380for (int i = 1 ;i < argc ;++ i ) { 1381 std::string arg = argv [i ]; 1382if (arg .rfind ("--" ,0 )== 0 ) { 1383if (i + 1 < argc && argv [i + 1 ][0 ]!= '-' ) { 1384args [arg ]= argv [i + 1 ]; 1385++ i ; 1386 }else { 1387args [arg ]= "" ; 1388 } 1389 } 1390 } 1391 1392if (args .find ("--glslc" )!= args .end ()) { 1393GLSLC = args ["--glslc" ];// Path to glslc 1394 } 1395if (args .find ("--source" )!= args .end ()) { 1396input_filepath = args ["--source" ];// The shader source file to compile 1397 } 1398if (args .find ("--output-dir" )!= args .end ()) { 1399output_dir = args ["--output-dir" ];// Directory for containing SPIR-V output 1400 } 1401if (args .find ("--target-hpp" )!= args .end ()) { 1402target_hpp = args ["--target-hpp" ];// Path to generated header file 1403 } 1404if (args .find ("--target-cpp" )!= args .end ()) { 1405target_cpp = args ["--target-cpp" ];// Path to generated cpp file 1406 } 1407 1408if (!directory_exists (output_dir )) { 1409if (!create_directory (output_dir )) { 1410 std::cerr <<"Error creating output directory: " <<output_dir <<"\n" ; 1411return EXIT_FAILURE ; 1412 } 1413 } 1414 1415process_shaders (); 1416 1417if (compile_failed ) { 1418 std::cerr <<"vulkan-shaders-gen: one or more shaders failed to compile" << std::endl ; 1419return EXIT_FAILURE ; 1420 } 1421 1422write_output_files (); 1423 1424return EXIT_SUCCESS ; 1425}