yum-archive/TaSTT-Whisper
High-performance GPGPU inference of OpenAI's Whisper automatic speech recognition (ASR) model
git clone https://git.yummers.dev/yum-archive/TaSTT-Whisper
8c4603c
master
1using System . Runtime . CompilerServices ; 2namespace CompressShaders ; 3 4record struct sShaderBinary 5{ 6public string name ; 7public byte [] data ; 8 9public sShaderBinary ( string path ) 10{ 11name = Path . GetFileNameWithoutExtension ( path ); 12data = File . ReadAllBytes ( path ); 13} 14 15public bool wave64 => name . EndsWith ( "64" ); 16public string uniqueName => wave64 ? name . Substring ( 0 , name . Length - 2 ) : name ; 17} 18 19sealed class FoundShaders 20{ 21public readonly sShaderBinary [] binaries ; 22public readonly string [] names ; 23public readonly int [] wave32 , wave64 ; 24 25public FoundShaders ( IEnumerable < sShaderBinary > found ) 26{ 27binaries = found 28. OrderBy ( b=> b . name ) 29. ToArray (); 30 31names = binaries 32. Select ( b=> b . uniqueName ) 33. Distinct () 34. ToArray (); 35 36wave32 = new int [ names . Length ]; 37wave64 = new int [ names . Length ]; 38for ( int i = 0 ; i < names . Length ; i ++ ) 39{ 40int i32 = findIndex ( names [ i ], false ); 41int i64 = findIndex ( names [ i ], true ); 42if ( i32 >= 0 && i64 >= 0 ) 43{ 44wave32 [ i ] = i32 ; 45wave64 [ i ] = i64 ; 46continue ; 47} 48if ( i32 >= 0 ) 49{ 50wave32 [ i ] = wave64 [ i ] = i32 ; 51continue ; 52} 53throw new ApplicationException ( $"Wave64 shader { names [ i ]} doesn't have the corresponding Wave32 one" ); 54} 55} 56 57int findIndex ( string name , bool wave64 ) 58{ 59for ( int i = 0 ; i < binaries . Length ; i ++ ) 60{ 61sShaderBinary sb = binaries [ i ]; 62if ( sb . uniqueName != name ) 63continue ; 64if ( sb . wave64 == wave64 ) 65return i ; 66} 67return - 1 ; 68} 69} 70 71class Program 72{ 73static string getSolutionRoot ( [ CallerFilePath ] string ? path = null ) 74{ 75string ? dir = Path . GetDirectoryName ( path ); 76dir = Path . GetDirectoryName ( dir ); 77dir = Path . GetDirectoryName ( dir ); 78return dir ?? throw new ApplicationException (); 79} 80 81#ifDEBUG 82const string config = "Debug" ; 83#else 84const string config = "Release" ; 85#endif 86 87static string shadersBinDir ( string root ) 88{ 89return Path . Combine ( root , "ComputeShaders" , "x64" , config ); 90} 91 92static IEnumerable < sShaderBinary > readShaders ( string root ) 93{ 94string dir = shadersBinDir ( root ); 95foreach ( string path in Directory . EnumerateFiles ( dir , "*.cso" ) ) 96yield return new sShaderBinary ( path ); 97} 98 99static void writeHeader ( string root , IEnumerable < string > names ) 100{ 101string path = Path . Combine ( root , "Whisper" , "D3D" , "shaderNames.h" ); 102using var stream = File . CreateText ( path ); 103stream . WriteLine ( @"// This header is generated by a tool 104#pragma once 105#include <stdint.h> 106 107namespace DirectCompute 108{ 109enum struct eComputeShader: uint16_t 110{" ); 111 112int id = 0 ; 113foreach ( string name in names ) 114{ 115stream . WriteLine ( "\t\t{0} = {1}," , name , id ); 116id ++ ; 117} 118stream . Write ( @" }; 119 120const char* computeShaderName( eComputeShader cs ); 121}" ); 122} 123 124static void writeCpp ( string root , IEnumerable < string > names ) 125{ 126string path = Path . Combine ( root , "Whisper" , "D3D" , "shaderNames.cpp" ); 127ShaderNames . write ( path , names ); 128} 129 130static void writePayloadIDs ( StreamWriter stream , string varName , int [] ids ) 131{ 132stream . Write ( @" 133static const std::array<uint8_t, {0}> {1} = {{" , ids . Length , varName ); 134 135for ( int i = 0 ; i < ids . Length ; i ++ ) 136{ 137if ( 0 == i % 16 ) 138stream . Write ( "\r\n\t" ); 139else 140stream . Write ( ' ' ); 141stream . Write ( "{0}," , ids [ i ] ); 142} 143stream . Write ( @" 144};" ); 145} 146 147static void writePayload ( string root , FoundShaders shaders , out int cbSource , out int cbCompressed ) 148{ 149MemoryStream ms = new MemoryStream (); 150List < int > offsets = new List < int > (); 151foreach ( var bin in shaders . binaries ) 152{ 153offsets . Add ( ( int ) ms . Length ); 154ms . Write ( bin . data ); 155} 156offsets . Add ( ( int ) ms . Length ); 157 158byte [] dxbc = ms . ToArray (); 159byte [] compressed = Cabinet . compressBuffer ( dxbc ); 160cbSource = dxbc . Length ; 161cbCompressed = compressed . Length ; 162 163string path = Path . Combine ( root , "Whisper" , "D3D" , $"shaderData- { config } .inl" ); 164using var stream = File . CreateText ( path ); 165stream . Write ( @"// This source file is generated by a tool 166 167// This array contains concatenated and compressed DXBC binaries for all compiled compute shaders 168static const std::array<uint8_t, {0}> s_compressedShaders = 169{{" , compressed . Length ); 170 171for ( int i = 0 ; i < compressed . Length ; i ++ ) 172{ 173if ( 0 == i % 16 ) 174stream . Write ( "\r\n\t" ); 175else 176stream . Write ( ' ' ); 177stream . Write ( "0x{0:X02}," , compressed [ i ] ); 178} 179 180stream . Write ( @" 181}}; 182 183// This array contains start offsets of shader binaries in the decompressed DXBC blob. 184// It includes one more entry for the end of the complete decompressed blob. 185static const std::array<uint32_t, {0}> s_shaderOffsets = {{" , offsets . Count ); 186 187for ( int i = 0 ; i < offsets . Count ; i ++ ) 188{ 189if ( 0 == i % 16 ) 190stream . Write ( "\r\n\t" ); 191else 192stream . Write ( ' ' ); 193stream . Write ( "{0}," , offsets [ i ] ); 194} 195stream . Write ( @" 196};" ); 197 198stream . Write ( @" 199// Index = eComputeShader enum value, value = index of the shader binary to use on nVidia and Intel GPUs" ); 200writePayloadIDs ( stream , "s_shaderBlobs32" , shaders . wave32 ); 201stream . Write ( @" 202// Index = eComputeShader enum value, value = index of the shader binary to use on AMD GPUs" ); 203writePayloadIDs ( stream , "s_shaderBlobs64" , shaders . wave64 ); 204 205ulong fp64Flags = 0 ; 206for ( int i = 0 ; i < shaders . binaries . Length ; i ++ ) 207{ 208bool fp64 = DetectFp64 . usesFp64 ( shaders . binaries [ i ]. data ); 209if ( fp64 ) 210fp64Flags |= ( ulong ) 1 << i ; 211} 212 213stream . Write ( @" 214// Bitmap of the shader binaries which use FP64 arithmetic instructions 215constexpr uint64_t fp64ShadersBitmap = 0x{0:X}ull;" , fp64Flags ); 216} 217 218static void mainImpl () 219{ 220string root = getSolutionRoot (); 221LanguageCodes . produce ( root ); 222 223FoundShaders shaders = new FoundShaders ( readShaders ( root ) ); 224 225writeHeader ( root , shaders . names ); 226writeCpp ( root , shaders . names ); 227writePayload ( root , shaders , out int cbIn , out int cbOut ); 228Console . WriteLine ( "Compressed {0} compute shaders, {1:F1} kb -> {2:F1} kb" , shaders . binaries . Length , cbIn / 1024.0 , cbOut / 1024.0 ); 229} 230 231static int Main ( string [] args ) 232{ 233try 234{ 235mainImpl (); 236return 0 ; 237} 238catch ( Exception ex ) 239{ 240Console . WriteLine ( ex . Message ); 241return ex . HResult ; 242} 243} 244}