smolv.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109
  1. // smol-v - public domain - https://github.com/aras-p/smol-v
  2. // authored 2016-2020 by Aras Pranckevicius
  3. // no warranty implied; use at your own risk
  4. // See end of file for license information.
  5. #include "smolv.h"
  6. #include <stdint.h>
  7. #include <vector>
  8. #include <algorithm>
  9. #include <cstdio>
  10. #include <cstring>
  11. #if !defined(_MSC_VER) && __cplusplus < 201103L
  12. #define static_assert(x,y)
  13. #endif
  14. #define _SMOLV_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
  15. // --------------------------------------------------------------------------------------------
  16. // Metadata about known SPIR-V operations
  17. enum SpvOp
  18. {
  19. SpvOpNop = 0,
  20. SpvOpUndef = 1,
  21. SpvOpSourceContinued = 2,
  22. SpvOpSource = 3,
  23. SpvOpSourceExtension = 4,
  24. SpvOpName = 5,
  25. SpvOpMemberName = 6,
  26. SpvOpString = 7,
  27. SpvOpLine = 8,
  28. SpvOpExtension = 10,
  29. SpvOpExtInstImport = 11,
  30. SpvOpExtInst = 12,
  31. SpvOpVectorShuffleCompact = 13, // not in SPIR-V, added for SMOL-V!
  32. SpvOpMemoryModel = 14,
  33. SpvOpEntryPoint = 15,
  34. SpvOpExecutionMode = 16,
  35. SpvOpCapability = 17,
  36. SpvOpTypeVoid = 19,
  37. SpvOpTypeBool = 20,
  38. SpvOpTypeInt = 21,
  39. SpvOpTypeFloat = 22,
  40. SpvOpTypeVector = 23,
  41. SpvOpTypeMatrix = 24,
  42. SpvOpTypeImage = 25,
  43. SpvOpTypeSampler = 26,
  44. SpvOpTypeSampledImage = 27,
  45. SpvOpTypeArray = 28,
  46. SpvOpTypeRuntimeArray = 29,
  47. SpvOpTypeStruct = 30,
  48. SpvOpTypeOpaque = 31,
  49. SpvOpTypePointer = 32,
  50. SpvOpTypeFunction = 33,
  51. SpvOpTypeEvent = 34,
  52. SpvOpTypeDeviceEvent = 35,
  53. SpvOpTypeReserveId = 36,
  54. SpvOpTypeQueue = 37,
  55. SpvOpTypePipe = 38,
  56. SpvOpTypeForwardPointer = 39,
  57. SpvOpConstantTrue = 41,
  58. SpvOpConstantFalse = 42,
  59. SpvOpConstant = 43,
  60. SpvOpConstantComposite = 44,
  61. SpvOpConstantSampler = 45,
  62. SpvOpConstantNull = 46,
  63. SpvOpSpecConstantTrue = 48,
  64. SpvOpSpecConstantFalse = 49,
  65. SpvOpSpecConstant = 50,
  66. SpvOpSpecConstantComposite = 51,
  67. SpvOpSpecConstantOp = 52,
  68. SpvOpFunction = 54,
  69. SpvOpFunctionParameter = 55,
  70. SpvOpFunctionEnd = 56,
  71. SpvOpFunctionCall = 57,
  72. SpvOpVariable = 59,
  73. SpvOpImageTexelPointer = 60,
  74. SpvOpLoad = 61,
  75. SpvOpStore = 62,
  76. SpvOpCopyMemory = 63,
  77. SpvOpCopyMemorySized = 64,
  78. SpvOpAccessChain = 65,
  79. SpvOpInBoundsAccessChain = 66,
  80. SpvOpPtrAccessChain = 67,
  81. SpvOpArrayLength = 68,
  82. SpvOpGenericPtrMemSemantics = 69,
  83. SpvOpInBoundsPtrAccessChain = 70,
  84. SpvOpDecorate = 71,
  85. SpvOpMemberDecorate = 72,
  86. SpvOpDecorationGroup = 73,
  87. SpvOpGroupDecorate = 74,
  88. SpvOpGroupMemberDecorate = 75,
  89. SpvOpVectorExtractDynamic = 77,
  90. SpvOpVectorInsertDynamic = 78,
  91. SpvOpVectorShuffle = 79,
  92. SpvOpCompositeConstruct = 80,
  93. SpvOpCompositeExtract = 81,
  94. SpvOpCompositeInsert = 82,
  95. SpvOpCopyObject = 83,
  96. SpvOpTranspose = 84,
  97. SpvOpSampledImage = 86,
  98. SpvOpImageSampleImplicitLod = 87,
  99. SpvOpImageSampleExplicitLod = 88,
  100. SpvOpImageSampleDrefImplicitLod = 89,
  101. SpvOpImageSampleDrefExplicitLod = 90,
  102. SpvOpImageSampleProjImplicitLod = 91,
  103. SpvOpImageSampleProjExplicitLod = 92,
  104. SpvOpImageSampleProjDrefImplicitLod = 93,
  105. SpvOpImageSampleProjDrefExplicitLod = 94,
  106. SpvOpImageFetch = 95,
  107. SpvOpImageGather = 96,
  108. SpvOpImageDrefGather = 97,
  109. SpvOpImageRead = 98,
  110. SpvOpImageWrite = 99,
  111. SpvOpImage = 100,
  112. SpvOpImageQueryFormat = 101,
  113. SpvOpImageQueryOrder = 102,
  114. SpvOpImageQuerySizeLod = 103,
  115. SpvOpImageQuerySize = 104,
  116. SpvOpImageQueryLod = 105,
  117. SpvOpImageQueryLevels = 106,
  118. SpvOpImageQuerySamples = 107,
  119. SpvOpConvertFToU = 109,
  120. SpvOpConvertFToS = 110,
  121. SpvOpConvertSToF = 111,
  122. SpvOpConvertUToF = 112,
  123. SpvOpUConvert = 113,
  124. SpvOpSConvert = 114,
  125. SpvOpFConvert = 115,
  126. SpvOpQuantizeToF16 = 116,
  127. SpvOpConvertPtrToU = 117,
  128. SpvOpSatConvertSToU = 118,
  129. SpvOpSatConvertUToS = 119,
  130. SpvOpConvertUToPtr = 120,
  131. SpvOpPtrCastToGeneric = 121,
  132. SpvOpGenericCastToPtr = 122,
  133. SpvOpGenericCastToPtrExplicit = 123,
  134. SpvOpBitcast = 124,
  135. SpvOpSNegate = 126,
  136. SpvOpFNegate = 127,
  137. SpvOpIAdd = 128,
  138. SpvOpFAdd = 129,
  139. SpvOpISub = 130,
  140. SpvOpFSub = 131,
  141. SpvOpIMul = 132,
  142. SpvOpFMul = 133,
  143. SpvOpUDiv = 134,
  144. SpvOpSDiv = 135,
  145. SpvOpFDiv = 136,
  146. SpvOpUMod = 137,
  147. SpvOpSRem = 138,
  148. SpvOpSMod = 139,
  149. SpvOpFRem = 140,
  150. SpvOpFMod = 141,
  151. SpvOpVectorTimesScalar = 142,
  152. SpvOpMatrixTimesScalar = 143,
  153. SpvOpVectorTimesMatrix = 144,
  154. SpvOpMatrixTimesVector = 145,
  155. SpvOpMatrixTimesMatrix = 146,
  156. SpvOpOuterProduct = 147,
  157. SpvOpDot = 148,
  158. SpvOpIAddCarry = 149,
  159. SpvOpISubBorrow = 150,
  160. SpvOpUMulExtended = 151,
  161. SpvOpSMulExtended = 152,
  162. SpvOpAny = 154,
  163. SpvOpAll = 155,
  164. SpvOpIsNan = 156,
  165. SpvOpIsInf = 157,
  166. SpvOpIsFinite = 158,
  167. SpvOpIsNormal = 159,
  168. SpvOpSignBitSet = 160,
  169. SpvOpLessOrGreater = 161,
  170. SpvOpOrdered = 162,
  171. SpvOpUnordered = 163,
  172. SpvOpLogicalEqual = 164,
  173. SpvOpLogicalNotEqual = 165,
  174. SpvOpLogicalOr = 166,
  175. SpvOpLogicalAnd = 167,
  176. SpvOpLogicalNot = 168,
  177. SpvOpSelect = 169,
  178. SpvOpIEqual = 170,
  179. SpvOpINotEqual = 171,
  180. SpvOpUGreaterThan = 172,
  181. SpvOpSGreaterThan = 173,
  182. SpvOpUGreaterThanEqual = 174,
  183. SpvOpSGreaterThanEqual = 175,
  184. SpvOpULessThan = 176,
  185. SpvOpSLessThan = 177,
  186. SpvOpULessThanEqual = 178,
  187. SpvOpSLessThanEqual = 179,
  188. SpvOpFOrdEqual = 180,
  189. SpvOpFUnordEqual = 181,
  190. SpvOpFOrdNotEqual = 182,
  191. SpvOpFUnordNotEqual = 183,
  192. SpvOpFOrdLessThan = 184,
  193. SpvOpFUnordLessThan = 185,
  194. SpvOpFOrdGreaterThan = 186,
  195. SpvOpFUnordGreaterThan = 187,
  196. SpvOpFOrdLessThanEqual = 188,
  197. SpvOpFUnordLessThanEqual = 189,
  198. SpvOpFOrdGreaterThanEqual = 190,
  199. SpvOpFUnordGreaterThanEqual = 191,
  200. SpvOpShiftRightLogical = 194,
  201. SpvOpShiftRightArithmetic = 195,
  202. SpvOpShiftLeftLogical = 196,
  203. SpvOpBitwiseOr = 197,
  204. SpvOpBitwiseXor = 198,
  205. SpvOpBitwiseAnd = 199,
  206. SpvOpNot = 200,
  207. SpvOpBitFieldInsert = 201,
  208. SpvOpBitFieldSExtract = 202,
  209. SpvOpBitFieldUExtract = 203,
  210. SpvOpBitReverse = 204,
  211. SpvOpBitCount = 205,
  212. SpvOpDPdx = 207,
  213. SpvOpDPdy = 208,
  214. SpvOpFwidth = 209,
  215. SpvOpDPdxFine = 210,
  216. SpvOpDPdyFine = 211,
  217. SpvOpFwidthFine = 212,
  218. SpvOpDPdxCoarse = 213,
  219. SpvOpDPdyCoarse = 214,
  220. SpvOpFwidthCoarse = 215,
  221. SpvOpEmitVertex = 218,
  222. SpvOpEndPrimitive = 219,
  223. SpvOpEmitStreamVertex = 220,
  224. SpvOpEndStreamPrimitive = 221,
  225. SpvOpControlBarrier = 224,
  226. SpvOpMemoryBarrier = 225,
  227. SpvOpAtomicLoad = 227,
  228. SpvOpAtomicStore = 228,
  229. SpvOpAtomicExchange = 229,
  230. SpvOpAtomicCompareExchange = 230,
  231. SpvOpAtomicCompareExchangeWeak = 231,
  232. SpvOpAtomicIIncrement = 232,
  233. SpvOpAtomicIDecrement = 233,
  234. SpvOpAtomicIAdd = 234,
  235. SpvOpAtomicISub = 235,
  236. SpvOpAtomicSMin = 236,
  237. SpvOpAtomicUMin = 237,
  238. SpvOpAtomicSMax = 238,
  239. SpvOpAtomicUMax = 239,
  240. SpvOpAtomicAnd = 240,
  241. SpvOpAtomicOr = 241,
  242. SpvOpAtomicXor = 242,
  243. SpvOpPhi = 245,
  244. SpvOpLoopMerge = 246,
  245. SpvOpSelectionMerge = 247,
  246. SpvOpLabel = 248,
  247. SpvOpBranch = 249,
  248. SpvOpBranchConditional = 250,
  249. SpvOpSwitch = 251,
  250. SpvOpKill = 252,
  251. SpvOpReturn = 253,
  252. SpvOpReturnValue = 254,
  253. SpvOpUnreachable = 255,
  254. SpvOpLifetimeStart = 256,
  255. SpvOpLifetimeStop = 257,
  256. SpvOpGroupAsyncCopy = 259,
  257. SpvOpGroupWaitEvents = 260,
  258. SpvOpGroupAll = 261,
  259. SpvOpGroupAny = 262,
  260. SpvOpGroupBroadcast = 263,
  261. SpvOpGroupIAdd = 264,
  262. SpvOpGroupFAdd = 265,
  263. SpvOpGroupFMin = 266,
  264. SpvOpGroupUMin = 267,
  265. SpvOpGroupSMin = 268,
  266. SpvOpGroupFMax = 269,
  267. SpvOpGroupUMax = 270,
  268. SpvOpGroupSMax = 271,
  269. SpvOpReadPipe = 274,
  270. SpvOpWritePipe = 275,
  271. SpvOpReservedReadPipe = 276,
  272. SpvOpReservedWritePipe = 277,
  273. SpvOpReserveReadPipePackets = 278,
  274. SpvOpReserveWritePipePackets = 279,
  275. SpvOpCommitReadPipe = 280,
  276. SpvOpCommitWritePipe = 281,
  277. SpvOpIsValidReserveId = 282,
  278. SpvOpGetNumPipePackets = 283,
  279. SpvOpGetMaxPipePackets = 284,
  280. SpvOpGroupReserveReadPipePackets = 285,
  281. SpvOpGroupReserveWritePipePackets = 286,
  282. SpvOpGroupCommitReadPipe = 287,
  283. SpvOpGroupCommitWritePipe = 288,
  284. SpvOpEnqueueMarker = 291,
  285. SpvOpEnqueueKernel = 292,
  286. SpvOpGetKernelNDrangeSubGroupCount = 293,
  287. SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
  288. SpvOpGetKernelWorkGroupSize = 295,
  289. SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
  290. SpvOpRetainEvent = 297,
  291. SpvOpReleaseEvent = 298,
  292. SpvOpCreateUserEvent = 299,
  293. SpvOpIsValidEvent = 300,
  294. SpvOpSetUserEventStatus = 301,
  295. SpvOpCaptureEventProfilingInfo = 302,
  296. SpvOpGetDefaultQueue = 303,
  297. SpvOpBuildNDRange = 304,
  298. SpvOpImageSparseSampleImplicitLod = 305,
  299. SpvOpImageSparseSampleExplicitLod = 306,
  300. SpvOpImageSparseSampleDrefImplicitLod = 307,
  301. SpvOpImageSparseSampleDrefExplicitLod = 308,
  302. SpvOpImageSparseSampleProjImplicitLod = 309,
  303. SpvOpImageSparseSampleProjExplicitLod = 310,
  304. SpvOpImageSparseSampleProjDrefImplicitLod = 311,
  305. SpvOpImageSparseSampleProjDrefExplicitLod = 312,
  306. SpvOpImageSparseFetch = 313,
  307. SpvOpImageSparseGather = 314,
  308. SpvOpImageSparseDrefGather = 315,
  309. SpvOpImageSparseTexelsResident = 316,
  310. SpvOpNoLine = 317,
  311. SpvOpAtomicFlagTestAndSet = 318,
  312. SpvOpAtomicFlagClear = 319,
  313. SpvOpImageSparseRead = 320,
  314. SpvOpSizeOf = 321,
  315. SpvOpTypePipeStorage = 322,
  316. SpvOpConstantPipeStorage = 323,
  317. SpvOpCreatePipeFromPipeStorage = 324,
  318. SpvOpGetKernelLocalSizeForSubgroupCount = 325,
  319. SpvOpGetKernelMaxNumSubgroups = 326,
  320. SpvOpTypeNamedBarrier = 327,
  321. SpvOpNamedBarrierInitialize = 328,
  322. SpvOpMemoryNamedBarrier = 329,
  323. SpvOpModuleProcessed = 330,
  324. SpvOpExecutionModeId = 331,
  325. SpvOpDecorateId = 332,
  326. SpvOpGroupNonUniformElect = 333,
  327. SpvOpGroupNonUniformAll = 334,
  328. SpvOpGroupNonUniformAny = 335,
  329. SpvOpGroupNonUniformAllEqual = 336,
  330. SpvOpGroupNonUniformBroadcast = 337,
  331. SpvOpGroupNonUniformBroadcastFirst = 338,
  332. SpvOpGroupNonUniformBallot = 339,
  333. SpvOpGroupNonUniformInverseBallot = 340,
  334. SpvOpGroupNonUniformBallotBitExtract = 341,
  335. SpvOpGroupNonUniformBallotBitCount = 342,
  336. SpvOpGroupNonUniformBallotFindLSB = 343,
  337. SpvOpGroupNonUniformBallotFindMSB = 344,
  338. SpvOpGroupNonUniformShuffle = 345,
  339. SpvOpGroupNonUniformShuffleXor = 346,
  340. SpvOpGroupNonUniformShuffleUp = 347,
  341. SpvOpGroupNonUniformShuffleDown = 348,
  342. SpvOpGroupNonUniformIAdd = 349,
  343. SpvOpGroupNonUniformFAdd = 350,
  344. SpvOpGroupNonUniformIMul = 351,
  345. SpvOpGroupNonUniformFMul = 352,
  346. SpvOpGroupNonUniformSMin = 353,
  347. SpvOpGroupNonUniformUMin = 354,
  348. SpvOpGroupNonUniformFMin = 355,
  349. SpvOpGroupNonUniformSMax = 356,
  350. SpvOpGroupNonUniformUMax = 357,
  351. SpvOpGroupNonUniformFMax = 358,
  352. SpvOpGroupNonUniformBitwiseAnd = 359,
  353. SpvOpGroupNonUniformBitwiseOr = 360,
  354. SpvOpGroupNonUniformBitwiseXor = 361,
  355. SpvOpGroupNonUniformLogicalAnd = 362,
  356. SpvOpGroupNonUniformLogicalOr = 363,
  357. SpvOpGroupNonUniformLogicalXor = 364,
  358. SpvOpGroupNonUniformQuadBroadcast = 365,
  359. SpvOpGroupNonUniformQuadSwap = 366,
  360. };
  361. static const int kKnownOpsCount = SpvOpGroupNonUniformQuadSwap+1;
  362. static const char* kSpirvOpNames[] =
  363. {
  364. "Nop",
  365. "Undef",
  366. "SourceContinued",
  367. "Source",
  368. "SourceExtension",
  369. "Name",
  370. "MemberName",
  371. "String",
  372. "Line",
  373. "#9",
  374. "Extension",
  375. "ExtInstImport",
  376. "ExtInst",
  377. "VectorShuffleCompact",
  378. "MemoryModel",
  379. "EntryPoint",
  380. "ExecutionMode",
  381. "Capability",
  382. "#18",
  383. "TypeVoid",
  384. "TypeBool",
  385. "TypeInt",
  386. "TypeFloat",
  387. "TypeVector",
  388. "TypeMatrix",
  389. "TypeImage",
  390. "TypeSampler",
  391. "TypeSampledImage",
  392. "TypeArray",
  393. "TypeRuntimeArray",
  394. "TypeStruct",
  395. "TypeOpaque",
  396. "TypePointer",
  397. "TypeFunction",
  398. "TypeEvent",
  399. "TypeDeviceEvent",
  400. "TypeReserveId",
  401. "TypeQueue",
  402. "TypePipe",
  403. "TypeForwardPointer",
  404. "#40",
  405. "ConstantTrue",
  406. "ConstantFalse",
  407. "Constant",
  408. "ConstantComposite",
  409. "ConstantSampler",
  410. "ConstantNull",
  411. "#47",
  412. "SpecConstantTrue",
  413. "SpecConstantFalse",
  414. "SpecConstant",
  415. "SpecConstantComposite",
  416. "SpecConstantOp",
  417. "#53",
  418. "Function",
  419. "FunctionParameter",
  420. "FunctionEnd",
  421. "FunctionCall",
  422. "#58",
  423. "Variable",
  424. "ImageTexelPointer",
  425. "Load",
  426. "Store",
  427. "CopyMemory",
  428. "CopyMemorySized",
  429. "AccessChain",
  430. "InBoundsAccessChain",
  431. "PtrAccessChain",
  432. "ArrayLength",
  433. "GenericPtrMemSemantics",
  434. "InBoundsPtrAccessChain",
  435. "Decorate",
  436. "MemberDecorate",
  437. "DecorationGroup",
  438. "GroupDecorate",
  439. "GroupMemberDecorate",
  440. "#76",
  441. "VectorExtractDynamic",
  442. "VectorInsertDynamic",
  443. "VectorShuffle",
  444. "CompositeConstruct",
  445. "CompositeExtract",
  446. "CompositeInsert",
  447. "CopyObject",
  448. "Transpose",
  449. "#85",
  450. "SampledImage",
  451. "ImageSampleImplicitLod",
  452. "ImageSampleExplicitLod",
  453. "ImageSampleDrefImplicitLod",
  454. "ImageSampleDrefExplicitLod",
  455. "ImageSampleProjImplicitLod",
  456. "ImageSampleProjExplicitLod",
  457. "ImageSampleProjDrefImplicitLod",
  458. "ImageSampleProjDrefExplicitLod",
  459. "ImageFetch",
  460. "ImageGather",
  461. "ImageDrefGather",
  462. "ImageRead",
  463. "ImageWrite",
  464. "Image",
  465. "ImageQueryFormat",
  466. "ImageQueryOrder",
  467. "ImageQuerySizeLod",
  468. "ImageQuerySize",
  469. "ImageQueryLod",
  470. "ImageQueryLevels",
  471. "ImageQuerySamples",
  472. "#108",
  473. "ConvertFToU",
  474. "ConvertFToS",
  475. "ConvertSToF",
  476. "ConvertUToF",
  477. "UConvert",
  478. "SConvert",
  479. "FConvert",
  480. "QuantizeToF16",
  481. "ConvertPtrToU",
  482. "SatConvertSToU",
  483. "SatConvertUToS",
  484. "ConvertUToPtr",
  485. "PtrCastToGeneric",
  486. "GenericCastToPtr",
  487. "GenericCastToPtrExplicit",
  488. "Bitcast",
  489. "#125",
  490. "SNegate",
  491. "FNegate",
  492. "IAdd",
  493. "FAdd",
  494. "ISub",
  495. "FSub",
  496. "IMul",
  497. "FMul",
  498. "UDiv",
  499. "SDiv",
  500. "FDiv",
  501. "UMod",
  502. "SRem",
  503. "SMod",
  504. "FRem",
  505. "FMod",
  506. "VectorTimesScalar",
  507. "MatrixTimesScalar",
  508. "VectorTimesMatrix",
  509. "MatrixTimesVector",
  510. "MatrixTimesMatrix",
  511. "OuterProduct",
  512. "Dot",
  513. "IAddCarry",
  514. "ISubBorrow",
  515. "UMulExtended",
  516. "SMulExtended",
  517. "#153",
  518. "Any",
  519. "All",
  520. "IsNan",
  521. "IsInf",
  522. "IsFinite",
  523. "IsNormal",
  524. "SignBitSet",
  525. "LessOrGreater",
  526. "Ordered",
  527. "Unordered",
  528. "LogicalEqual",
  529. "LogicalNotEqual",
  530. "LogicalOr",
  531. "LogicalAnd",
  532. "LogicalNot",
  533. "Select",
  534. "IEqual",
  535. "INotEqual",
  536. "UGreaterThan",
  537. "SGreaterThan",
  538. "UGreaterThanEqual",
  539. "SGreaterThanEqual",
  540. "ULessThan",
  541. "SLessThan",
  542. "ULessThanEqual",
  543. "SLessThanEqual",
  544. "FOrdEqual",
  545. "FUnordEqual",
  546. "FOrdNotEqual",
  547. "FUnordNotEqual",
  548. "FOrdLessThan",
  549. "FUnordLessThan",
  550. "FOrdGreaterThan",
  551. "FUnordGreaterThan",
  552. "FOrdLessThanEqual",
  553. "FUnordLessThanEqual",
  554. "FOrdGreaterThanEqual",
  555. "FUnordGreaterThanEqual",
  556. "#192",
  557. "#193",
  558. "ShiftRightLogical",
  559. "ShiftRightArithmetic",
  560. "ShiftLeftLogical",
  561. "BitwiseOr",
  562. "BitwiseXor",
  563. "BitwiseAnd",
  564. "Not",
  565. "BitFieldInsert",
  566. "BitFieldSExtract",
  567. "BitFieldUExtract",
  568. "BitReverse",
  569. "BitCount",
  570. "#206",
  571. "DPdx",
  572. "DPdy",
  573. "Fwidth",
  574. "DPdxFine",
  575. "DPdyFine",
  576. "FwidthFine",
  577. "DPdxCoarse",
  578. "DPdyCoarse",
  579. "FwidthCoarse",
  580. "#216",
  581. "#217",
  582. "EmitVertex",
  583. "EndPrimitive",
  584. "EmitStreamVertex",
  585. "EndStreamPrimitive",
  586. "#222",
  587. "#223",
  588. "ControlBarrier",
  589. "MemoryBarrier",
  590. "#226",
  591. "AtomicLoad",
  592. "AtomicStore",
  593. "AtomicExchange",
  594. "AtomicCompareExchange",
  595. "AtomicCompareExchangeWeak",
  596. "AtomicIIncrement",
  597. "AtomicIDecrement",
  598. "AtomicIAdd",
  599. "AtomicISub",
  600. "AtomicSMin",
  601. "AtomicUMin",
  602. "AtomicSMax",
  603. "AtomicUMax",
  604. "AtomicAnd",
  605. "AtomicOr",
  606. "AtomicXor",
  607. "#243",
  608. "#244",
  609. "Phi",
  610. "LoopMerge",
  611. "SelectionMerge",
  612. "Label",
  613. "Branch",
  614. "BranchConditional",
  615. "Switch",
  616. "Kill",
  617. "Return",
  618. "ReturnValue",
  619. "Unreachable",
  620. "LifetimeStart",
  621. "LifetimeStop",
  622. "#258",
  623. "GroupAsyncCopy",
  624. "GroupWaitEvents",
  625. "GroupAll",
  626. "GroupAny",
  627. "GroupBroadcast",
  628. "GroupIAdd",
  629. "GroupFAdd",
  630. "GroupFMin",
  631. "GroupUMin",
  632. "GroupSMin",
  633. "GroupFMax",
  634. "GroupUMax",
  635. "GroupSMax",
  636. "#272",
  637. "#273",
  638. "ReadPipe",
  639. "WritePipe",
  640. "ReservedReadPipe",
  641. "ReservedWritePipe",
  642. "ReserveReadPipePackets",
  643. "ReserveWritePipePackets",
  644. "CommitReadPipe",
  645. "CommitWritePipe",
  646. "IsValidReserveId",
  647. "GetNumPipePackets",
  648. "GetMaxPipePackets",
  649. "GroupReserveReadPipePackets",
  650. "GroupReserveWritePipePackets",
  651. "GroupCommitReadPipe",
  652. "GroupCommitWritePipe",
  653. "#289",
  654. "#290",
  655. "EnqueueMarker",
  656. "EnqueueKernel",
  657. "GetKernelNDrangeSubGroupCount",
  658. "GetKernelNDrangeMaxSubGroupSize",
  659. "GetKernelWorkGroupSize",
  660. "GetKernelPreferredWorkGroupSizeMultiple",
  661. "RetainEvent",
  662. "ReleaseEvent",
  663. "CreateUserEvent",
  664. "IsValidEvent",
  665. "SetUserEventStatus",
  666. "CaptureEventProfilingInfo",
  667. "GetDefaultQueue",
  668. "BuildNDRange",
  669. "ImageSparseSampleImplicitLod",
  670. "ImageSparseSampleExplicitLod",
  671. "ImageSparseSampleDrefImplicitLod",
  672. "ImageSparseSampleDrefExplicitLod",
  673. "ImageSparseSampleProjImplicitLod",
  674. "ImageSparseSampleProjExplicitLod",
  675. "ImageSparseSampleProjDrefImplicitLod",
  676. "ImageSparseSampleProjDrefExplicitLod",
  677. "ImageSparseFetch",
  678. "ImageSparseGather",
  679. "ImageSparseDrefGather",
  680. "ImageSparseTexelsResident",
  681. "NoLine",
  682. "AtomicFlagTestAndSet",
  683. "AtomicFlagClear",
  684. "ImageSparseRead",
  685. "SizeOf",
  686. "TypePipeStorage",
  687. "ConstantPipeStorage",
  688. "CreatePipeFromPipeStorage",
  689. "GetKernelLocalSizeForSubgroupCount",
  690. "GetKernelMaxNumSubgroups",
  691. "TypeNamedBarrier",
  692. "NamedBarrierInitialize",
  693. "MemoryNamedBarrier",
  694. "ModuleProcessed",
  695. "ExecutionModeId",
  696. "DecorateId",
  697. "GroupNonUniformElect",
  698. "GroupNonUniformAll",
  699. "GroupNonUniformAny",
  700. "GroupNonUniformAllEqual",
  701. "GroupNonUniformBroadcast",
  702. "GroupNonUniformBroadcastFirst",
  703. "GroupNonUniformBallot",
  704. "GroupNonUniformInverseBallot",
  705. "GroupNonUniformBallotBitExtract",
  706. "GroupNonUniformBallotBitCount",
  707. "GroupNonUniformBallotFindLSB",
  708. "GroupNonUniformBallotFindMSB",
  709. "GroupNonUniformShuffle",
  710. "GroupNonUniformShuffleXor",
  711. "GroupNonUniformShuffleUp",
  712. "GroupNonUniformShuffleDown",
  713. "GroupNonUniformIAdd",
  714. "GroupNonUniformFAdd",
  715. "GroupNonUniformIMul",
  716. "GroupNonUniformFMul",
  717. "GroupNonUniformSMin",
  718. "GroupNonUniformUMin",
  719. "GroupNonUniformFMin",
  720. "GroupNonUniformSMax",
  721. "GroupNonUniformUMax",
  722. "GroupNonUniformFMax",
  723. "GroupNonUniformBitwiseAnd",
  724. "GroupNonUniformBitwiseOr",
  725. "GroupNonUniformBitwiseXor",
  726. "GroupNonUniformLogicalAnd",
  727. "GroupNonUniformLogicalOr",
  728. "GroupNonUniformLogicalXor",
  729. "GroupNonUniformQuadBroadcast",
  730. "GroupNonUniformQuadSwap",
  731. };
  732. static_assert(_SMOLV_ARRAY_SIZE(kSpirvOpNames) == kKnownOpsCount, "kSpirvOpNames table mismatch with known SpvOps");
  733. struct OpData
  734. {
  735. uint8_t hasResult; // does it have result ID?
  736. uint8_t hasType; // does it have type ID?
  737. uint8_t deltaFromResult; // How many words after (optional) type+result to write out as deltas from result?
  738. uint8_t varrest; // should the rest of words be written in varint encoding?
  739. };
  740. static const OpData kSpirvOpData[] =
  741. {
  742. {0, 0, 0, 0}, // Nop
  743. {1, 1, 0, 0}, // Undef
  744. {0, 0, 0, 0}, // SourceContinued
  745. {0, 0, 0, 1}, // Source
  746. {0, 0, 0, 0}, // SourceExtension
  747. {0, 0, 0, 0}, // Name
  748. {0, 0, 0, 0}, // MemberName
  749. {0, 0, 0, 0}, // String
  750. {0, 0, 0, 1}, // Line
  751. {1, 1, 0, 0}, // #9
  752. {0, 0, 0, 0}, // Extension
  753. {1, 0, 0, 0}, // ExtInstImport
  754. {1, 1, 0, 1}, // ExtInst
  755. {1, 1, 2, 1}, // VectorShuffleCompact - new in SMOLV
  756. {0, 0, 0, 1}, // MemoryModel
  757. {0, 0, 0, 1}, // EntryPoint
  758. {0, 0, 0, 1}, // ExecutionMode
  759. {0, 0, 0, 1}, // Capability
  760. {1, 1, 0, 0}, // #18
  761. {1, 0, 0, 1}, // TypeVoid
  762. {1, 0, 0, 1}, // TypeBool
  763. {1, 0, 0, 1}, // TypeInt
  764. {1, 0, 0, 1}, // TypeFloat
  765. {1, 0, 0, 1}, // TypeVector
  766. {1, 0, 0, 1}, // TypeMatrix
  767. {1, 0, 0, 1}, // TypeImage
  768. {1, 0, 0, 1}, // TypeSampler
  769. {1, 0, 0, 1}, // TypeSampledImage
  770. {1, 0, 0, 1}, // TypeArray
  771. {1, 0, 0, 1}, // TypeRuntimeArray
  772. {1, 0, 0, 1}, // TypeStruct
  773. {1, 0, 0, 1}, // TypeOpaque
  774. {1, 0, 0, 1}, // TypePointer
  775. {1, 0, 0, 1}, // TypeFunction
  776. {1, 0, 0, 1}, // TypeEvent
  777. {1, 0, 0, 1}, // TypeDeviceEvent
  778. {1, 0, 0, 1}, // TypeReserveId
  779. {1, 0, 0, 1}, // TypeQueue
  780. {1, 0, 0, 1}, // TypePipe
  781. {0, 0, 0, 1}, // TypeForwardPointer
  782. {1, 1, 0, 0}, // #40
  783. {1, 1, 0, 0}, // ConstantTrue
  784. {1, 1, 0, 0}, // ConstantFalse
  785. {1, 1, 0, 0}, // Constant
  786. {1, 1, 9, 0}, // ConstantComposite
  787. {1, 1, 0, 1}, // ConstantSampler
  788. {1, 1, 0, 0}, // ConstantNull
  789. {1, 1, 0, 0}, // #47
  790. {1, 1, 0, 0}, // SpecConstantTrue
  791. {1, 1, 0, 0}, // SpecConstantFalse
  792. {1, 1, 0, 0}, // SpecConstant
  793. {1, 1, 9, 0}, // SpecConstantComposite
  794. {1, 1, 0, 0}, // SpecConstantOp
  795. {1, 1, 0, 0}, // #53
  796. {1, 1, 0, 1}, // Function
  797. {1, 1, 0, 0}, // FunctionParameter
  798. {0, 0, 0, 0}, // FunctionEnd
  799. {1, 1, 9, 0}, // FunctionCall
  800. {1, 1, 0, 0}, // #58
  801. {1, 1, 0, 1}, // Variable
  802. {1, 1, 0, 0}, // ImageTexelPointer
  803. {1, 1, 1, 1}, // Load
  804. {0, 0, 2, 1}, // Store
  805. {0, 0, 0, 0}, // CopyMemory
  806. {0, 0, 0, 0}, // CopyMemorySized
  807. {1, 1, 0, 1}, // AccessChain
  808. {1, 1, 0, 0}, // InBoundsAccessChain
  809. {1, 1, 0, 0}, // PtrAccessChain
  810. {1, 1, 0, 0}, // ArrayLength
  811. {1, 1, 0, 0}, // GenericPtrMemSemantics
  812. {1, 1, 0, 0}, // InBoundsPtrAccessChain
  813. {0, 0, 0, 1}, // Decorate
  814. {0, 0, 0, 1}, // MemberDecorate
  815. {1, 0, 0, 0}, // DecorationGroup
  816. {0, 0, 0, 0}, // GroupDecorate
  817. {0, 0, 0, 0}, // GroupMemberDecorate
  818. {1, 1, 0, 0}, // #76
  819. {1, 1, 1, 1}, // VectorExtractDynamic
  820. {1, 1, 2, 1}, // VectorInsertDynamic
  821. {1, 1, 2, 1}, // VectorShuffle
  822. {1, 1, 9, 0}, // CompositeConstruct
  823. {1, 1, 1, 1}, // CompositeExtract
  824. {1, 1, 2, 1}, // CompositeInsert
  825. {1, 1, 1, 0}, // CopyObject
  826. {1, 1, 0, 0}, // Transpose
  827. {1, 1, 0, 0}, // #85
  828. {1, 1, 0, 0}, // SampledImage
  829. {1, 1, 2, 1}, // ImageSampleImplicitLod
  830. {1, 1, 2, 1}, // ImageSampleExplicitLod
  831. {1, 1, 3, 1}, // ImageSampleDrefImplicitLod
  832. {1, 1, 3, 1}, // ImageSampleDrefExplicitLod
  833. {1, 1, 2, 1}, // ImageSampleProjImplicitLod
  834. {1, 1, 2, 1}, // ImageSampleProjExplicitLod
  835. {1, 1, 3, 1}, // ImageSampleProjDrefImplicitLod
  836. {1, 1, 3, 1}, // ImageSampleProjDrefExplicitLod
  837. {1, 1, 2, 1}, // ImageFetch
  838. {1, 1, 3, 1}, // ImageGather
  839. {1, 1, 3, 1}, // ImageDrefGather
  840. {1, 1, 2, 1}, // ImageRead
  841. {0, 0, 3, 1}, // ImageWrite
  842. {1, 1, 1, 0}, // Image
  843. {1, 1, 1, 0}, // ImageQueryFormat
  844. {1, 1, 1, 0}, // ImageQueryOrder
  845. {1, 1, 2, 0}, // ImageQuerySizeLod
  846. {1, 1, 1, 0}, // ImageQuerySize
  847. {1, 1, 2, 0}, // ImageQueryLod
  848. {1, 1, 1, 0}, // ImageQueryLevels
  849. {1, 1, 1, 0}, // ImageQuerySamples
  850. {1, 1, 0, 0}, // #108
  851. {1, 1, 1, 0}, // ConvertFToU
  852. {1, 1, 1, 0}, // ConvertFToS
  853. {1, 1, 1, 0}, // ConvertSToF
  854. {1, 1, 1, 0}, // ConvertUToF
  855. {1, 1, 1, 0}, // UConvert
  856. {1, 1, 1, 0}, // SConvert
  857. {1, 1, 1, 0}, // FConvert
  858. {1, 1, 1, 0}, // QuantizeToF16
  859. {1, 1, 1, 0}, // ConvertPtrToU
  860. {1, 1, 1, 0}, // SatConvertSToU
  861. {1, 1, 1, 0}, // SatConvertUToS
  862. {1, 1, 1, 0}, // ConvertUToPtr
  863. {1, 1, 1, 0}, // PtrCastToGeneric
  864. {1, 1, 1, 0}, // GenericCastToPtr
  865. {1, 1, 1, 1}, // GenericCastToPtrExplicit
  866. {1, 1, 1, 0}, // Bitcast
  867. {1, 1, 0, 0}, // #125
  868. {1, 1, 1, 0}, // SNegate
  869. {1, 1, 1, 0}, // FNegate
  870. {1, 1, 2, 0}, // IAdd
  871. {1, 1, 2, 0}, // FAdd
  872. {1, 1, 2, 0}, // ISub
  873. {1, 1, 2, 0}, // FSub
  874. {1, 1, 2, 0}, // IMul
  875. {1, 1, 2, 0}, // FMul
  876. {1, 1, 2, 0}, // UDiv
  877. {1, 1, 2, 0}, // SDiv
  878. {1, 1, 2, 0}, // FDiv
  879. {1, 1, 2, 0}, // UMod
  880. {1, 1, 2, 0}, // SRem
  881. {1, 1, 2, 0}, // SMod
  882. {1, 1, 2, 0}, // FRem
  883. {1, 1, 2, 0}, // FMod
  884. {1, 1, 2, 0}, // VectorTimesScalar
  885. {1, 1, 2, 0}, // MatrixTimesScalar
  886. {1, 1, 2, 0}, // VectorTimesMatrix
  887. {1, 1, 2, 0}, // MatrixTimesVector
  888. {1, 1, 2, 0}, // MatrixTimesMatrix
  889. {1, 1, 2, 0}, // OuterProduct
  890. {1, 1, 2, 0}, // Dot
  891. {1, 1, 2, 0}, // IAddCarry
  892. {1, 1, 2, 0}, // ISubBorrow
  893. {1, 1, 2, 0}, // UMulExtended
  894. {1, 1, 2, 0}, // SMulExtended
  895. {1, 1, 0, 0}, // #153
  896. {1, 1, 1, 0}, // Any
  897. {1, 1, 1, 0}, // All
  898. {1, 1, 1, 0}, // IsNan
  899. {1, 1, 1, 0}, // IsInf
  900. {1, 1, 1, 0}, // IsFinite
  901. {1, 1, 1, 0}, // IsNormal
  902. {1, 1, 1, 0}, // SignBitSet
  903. {1, 1, 2, 0}, // LessOrGreater
  904. {1, 1, 2, 0}, // Ordered
  905. {1, 1, 2, 0}, // Unordered
  906. {1, 1, 2, 0}, // LogicalEqual
  907. {1, 1, 2, 0}, // LogicalNotEqual
  908. {1, 1, 2, 0}, // LogicalOr
  909. {1, 1, 2, 0}, // LogicalAnd
  910. {1, 1, 1, 0}, // LogicalNot
  911. {1, 1, 3, 0}, // Select
  912. {1, 1, 2, 0}, // IEqual
  913. {1, 1, 2, 0}, // INotEqual
  914. {1, 1, 2, 0}, // UGreaterThan
  915. {1, 1, 2, 0}, // SGreaterThan
  916. {1, 1, 2, 0}, // UGreaterThanEqual
  917. {1, 1, 2, 0}, // SGreaterThanEqual
  918. {1, 1, 2, 0}, // ULessThan
  919. {1, 1, 2, 0}, // SLessThan
  920. {1, 1, 2, 0}, // ULessThanEqual
  921. {1, 1, 2, 0}, // SLessThanEqual
  922. {1, 1, 2, 0}, // FOrdEqual
  923. {1, 1, 2, 0}, // FUnordEqual
  924. {1, 1, 2, 0}, // FOrdNotEqual
  925. {1, 1, 2, 0}, // FUnordNotEqual
  926. {1, 1, 2, 0}, // FOrdLessThan
  927. {1, 1, 2, 0}, // FUnordLessThan
  928. {1, 1, 2, 0}, // FOrdGreaterThan
  929. {1, 1, 2, 0}, // FUnordGreaterThan
  930. {1, 1, 2, 0}, // FOrdLessThanEqual
  931. {1, 1, 2, 0}, // FUnordLessThanEqual
  932. {1, 1, 2, 0}, // FOrdGreaterThanEqual
  933. {1, 1, 2, 0}, // FUnordGreaterThanEqual
  934. {1, 1, 0, 0}, // #192
  935. {1, 1, 0, 0}, // #193
  936. {1, 1, 2, 0}, // ShiftRightLogical
  937. {1, 1, 2, 0}, // ShiftRightArithmetic
  938. {1, 1, 2, 0}, // ShiftLeftLogical
  939. {1, 1, 2, 0}, // BitwiseOr
  940. {1, 1, 2, 0}, // BitwiseXor
  941. {1, 1, 2, 0}, // BitwiseAnd
  942. {1, 1, 1, 0}, // Not
  943. {1, 1, 4, 0}, // BitFieldInsert
  944. {1, 1, 3, 0}, // BitFieldSExtract
  945. {1, 1, 3, 0}, // BitFieldUExtract
  946. {1, 1, 1, 0}, // BitReverse
  947. {1, 1, 1, 0}, // BitCount
  948. {1, 1, 0, 0}, // #206
  949. {1, 1, 0, 0}, // DPdx
  950. {1, 1, 0, 0}, // DPdy
  951. {1, 1, 0, 0}, // Fwidth
  952. {1, 1, 0, 0}, // DPdxFine
  953. {1, 1, 0, 0}, // DPdyFine
  954. {1, 1, 0, 0}, // FwidthFine
  955. {1, 1, 0, 0}, // DPdxCoarse
  956. {1, 1, 0, 0}, // DPdyCoarse
  957. {1, 1, 0, 0}, // FwidthCoarse
  958. {1, 1, 0, 0}, // #216
  959. {1, 1, 0, 0}, // #217
  960. {0, 0, 0, 0}, // EmitVertex
  961. {0, 0, 0, 0}, // EndPrimitive
  962. {0, 0, 0, 0}, // EmitStreamVertex
  963. {0, 0, 0, 0}, // EndStreamPrimitive
  964. {1, 1, 0, 0}, // #222
  965. {1, 1, 0, 0}, // #223
  966. {0, 0, 3, 0}, // ControlBarrier
  967. {0, 0, 2, 0}, // MemoryBarrier
  968. {1, 1, 0, 0}, // #226
  969. {1, 1, 0, 0}, // AtomicLoad
  970. {0, 0, 0, 0}, // AtomicStore
  971. {1, 1, 0, 0}, // AtomicExchange
  972. {1, 1, 0, 0}, // AtomicCompareExchange
  973. {1, 1, 0, 0}, // AtomicCompareExchangeWeak
  974. {1, 1, 0, 0}, // AtomicIIncrement
  975. {1, 1, 0, 0}, // AtomicIDecrement
  976. {1, 1, 0, 0}, // AtomicIAdd
  977. {1, 1, 0, 0}, // AtomicISub
  978. {1, 1, 0, 0}, // AtomicSMin
  979. {1, 1, 0, 0}, // AtomicUMin
  980. {1, 1, 0, 0}, // AtomicSMax
  981. {1, 1, 0, 0}, // AtomicUMax
  982. {1, 1, 0, 0}, // AtomicAnd
  983. {1, 1, 0, 0}, // AtomicOr
  984. {1, 1, 0, 0}, // AtomicXor
  985. {1, 1, 0, 0}, // #243
  986. {1, 1, 0, 0}, // #244
  987. {1, 1, 0, 0}, // Phi
  988. {0, 0, 2, 1}, // LoopMerge
  989. {0, 0, 1, 1}, // SelectionMerge
  990. {1, 0, 0, 0}, // Label
  991. {0, 0, 1, 0}, // Branch
  992. {0, 0, 3, 1}, // BranchConditional
  993. {0, 0, 0, 0}, // Switch
  994. {0, 0, 0, 0}, // Kill
  995. {0, 0, 0, 0}, // Return
  996. {0, 0, 0, 0}, // ReturnValue
  997. {0, 0, 0, 0}, // Unreachable
  998. {0, 0, 0, 0}, // LifetimeStart
  999. {0, 0, 0, 0}, // LifetimeStop
  1000. {1, 1, 0, 0}, // #258
  1001. {1, 1, 0, 0}, // GroupAsyncCopy
  1002. {0, 0, 0, 0}, // GroupWaitEvents
  1003. {1, 1, 0, 0}, // GroupAll
  1004. {1, 1, 0, 0}, // GroupAny
  1005. {1, 1, 0, 0}, // GroupBroadcast
  1006. {1, 1, 0, 0}, // GroupIAdd
  1007. {1, 1, 0, 0}, // GroupFAdd
  1008. {1, 1, 0, 0}, // GroupFMin
  1009. {1, 1, 0, 0}, // GroupUMin
  1010. {1, 1, 0, 0}, // GroupSMin
  1011. {1, 1, 0, 0}, // GroupFMax
  1012. {1, 1, 0, 0}, // GroupUMax
  1013. {1, 1, 0, 0}, // GroupSMax
  1014. {1, 1, 0, 0}, // #272
  1015. {1, 1, 0, 0}, // #273
  1016. {1, 1, 0, 0}, // ReadPipe
  1017. {1, 1, 0, 0}, // WritePipe
  1018. {1, 1, 0, 0}, // ReservedReadPipe
  1019. {1, 1, 0, 0}, // ReservedWritePipe
  1020. {1, 1, 0, 0}, // ReserveReadPipePackets
  1021. {1, 1, 0, 0}, // ReserveWritePipePackets
  1022. {0, 0, 0, 0}, // CommitReadPipe
  1023. {0, 0, 0, 0}, // CommitWritePipe
  1024. {1, 1, 0, 0}, // IsValidReserveId
  1025. {1, 1, 0, 0}, // GetNumPipePackets
  1026. {1, 1, 0, 0}, // GetMaxPipePackets
  1027. {1, 1, 0, 0}, // GroupReserveReadPipePackets
  1028. {1, 1, 0, 0}, // GroupReserveWritePipePackets
  1029. {0, 0, 0, 0}, // GroupCommitReadPipe
  1030. {0, 0, 0, 0}, // GroupCommitWritePipe
  1031. {1, 1, 0, 0}, // #289
  1032. {1, 1, 0, 0}, // #290
  1033. {1, 1, 0, 0}, // EnqueueMarker
  1034. {1, 1, 0, 0}, // EnqueueKernel
  1035. {1, 1, 0, 0}, // GetKernelNDrangeSubGroupCount
  1036. {1, 1, 0, 0}, // GetKernelNDrangeMaxSubGroupSize
  1037. {1, 1, 0, 0}, // GetKernelWorkGroupSize
  1038. {1, 1, 0, 0}, // GetKernelPreferredWorkGroupSizeMultiple
  1039. {0, 0, 0, 0}, // RetainEvent
  1040. {0, 0, 0, 0}, // ReleaseEvent
  1041. {1, 1, 0, 0}, // CreateUserEvent
  1042. {1, 1, 0, 0}, // IsValidEvent
  1043. {0, 0, 0, 0}, // SetUserEventStatus
  1044. {0, 0, 0, 0}, // CaptureEventProfilingInfo
  1045. {1, 1, 0, 0}, // GetDefaultQueue
  1046. {1, 1, 0, 0}, // BuildNDRange
  1047. {1, 1, 2, 1}, // ImageSparseSampleImplicitLod
  1048. {1, 1, 2, 1}, // ImageSparseSampleExplicitLod
  1049. {1, 1, 3, 1}, // ImageSparseSampleDrefImplicitLod
  1050. {1, 1, 3, 1}, // ImageSparseSampleDrefExplicitLod
  1051. {1, 1, 2, 1}, // ImageSparseSampleProjImplicitLod
  1052. {1, 1, 2, 1}, // ImageSparseSampleProjExplicitLod
  1053. {1, 1, 3, 1}, // ImageSparseSampleProjDrefImplicitLod
  1054. {1, 1, 3, 1}, // ImageSparseSampleProjDrefExplicitLod
  1055. {1, 1, 2, 1}, // ImageSparseFetch
  1056. {1, 1, 3, 1}, // ImageSparseGather
  1057. {1, 1, 3, 1}, // ImageSparseDrefGather
  1058. {1, 1, 1, 0}, // ImageSparseTexelsResident
  1059. {0, 0, 0, 0}, // NoLine
  1060. {1, 1, 0, 0}, // AtomicFlagTestAndSet
  1061. {0, 0, 0, 0}, // AtomicFlagClear
  1062. {1, 1, 0, 0}, // ImageSparseRead
  1063. {1, 1, 0, 0}, // SizeOf
  1064. {1, 1, 0, 0}, // TypePipeStorage
  1065. {1, 1, 0, 0}, // ConstantPipeStorage
  1066. {1, 1, 0, 0}, // CreatePipeFromPipeStorage
  1067. {1, 1, 0, 0}, // GetKernelLocalSizeForSubgroupCount
  1068. {1, 1, 0, 0}, // GetKernelMaxNumSubgroups
  1069. {1, 1, 0, 0}, // TypeNamedBarrier
  1070. {1, 1, 0, 1}, // NamedBarrierInitialize
  1071. {0, 0, 2, 1}, // MemoryNamedBarrier
  1072. {1, 1, 0, 0}, // ModuleProcessed
  1073. {0, 0, 0, 1}, // ExecutionModeId
  1074. {0, 0, 0, 1}, // DecorateId
  1075. {1, 1, 1, 1}, // GroupNonUniformElect
  1076. {1, 1, 1, 1}, // GroupNonUniformAll
  1077. {1, 1, 1, 1}, // GroupNonUniformAny
  1078. {1, 1, 1, 1}, // GroupNonUniformAllEqual
  1079. {1, 1, 1, 1}, // GroupNonUniformBroadcast
  1080. {1, 1, 1, 1}, // GroupNonUniformBroadcastFirst
  1081. {1, 1, 1, 1}, // GroupNonUniformBallot
  1082. {1, 1, 1, 1}, // GroupNonUniformInverseBallot
  1083. {1, 1, 1, 1}, // GroupNonUniformBallotBitExtract
  1084. {1, 1, 1, 1}, // GroupNonUniformBallotBitCount
  1085. {1, 1, 1, 1}, // GroupNonUniformBallotFindLSB
  1086. {1, 1, 1, 1}, // GroupNonUniformBallotFindMSB
  1087. {1, 1, 1, 1}, // GroupNonUniformShuffle
  1088. {1, 1, 1, 1}, // GroupNonUniformShuffleXor
  1089. {1, 1, 1, 1}, // GroupNonUniformShuffleUp
  1090. {1, 1, 1, 1}, // GroupNonUniformShuffleDown
  1091. {1, 1, 1, 1}, // GroupNonUniformIAdd
  1092. {1, 1, 1, 1}, // GroupNonUniformFAdd
  1093. {1, 1, 1, 1}, // GroupNonUniformIMul
  1094. {1, 1, 1, 1}, // GroupNonUniformFMul
  1095. {1, 1, 1, 1}, // GroupNonUniformSMin
  1096. {1, 1, 1, 1}, // GroupNonUniformUMin
  1097. {1, 1, 1, 1}, // GroupNonUniformFMin
  1098. {1, 1, 1, 1}, // GroupNonUniformSMax
  1099. {1, 1, 1, 1}, // GroupNonUniformUMax
  1100. {1, 1, 1, 1}, // GroupNonUniformFMax
  1101. {1, 1, 1, 1}, // GroupNonUniformBitwiseAnd
  1102. {1, 1, 1, 1}, // GroupNonUniformBitwiseOr
  1103. {1, 1, 1, 1}, // GroupNonUniformBitwiseXor
  1104. {1, 1, 1, 1}, // GroupNonUniformLogicalAnd
  1105. {1, 1, 1, 1}, // GroupNonUniformLogicalOr
  1106. {1, 1, 1, 1}, // GroupNonUniformLogicalXor
  1107. {1, 1, 1, 1}, // GroupNonUniformQuadBroadcast
  1108. {1, 1, 1, 1}, // GroupNonUniformQuadSwap
  1109. };
  1110. static_assert(_SMOLV_ARRAY_SIZE(kSpirvOpData) == kKnownOpsCount, "kSpirvOpData table mismatch with known SpvOps");
  1111. // Instruction encoding depends on the table that describes the various SPIR-V opcodes.
  1112. // Whenever we change or expand the table, we need to bump up the SMOL-V version, and make
  1113. // sure that we can still decode files encoded by an older version.
  1114. static int smolv_GetKnownOpsCount(int version)
  1115. {
  1116. if (version == 0)
  1117. return SpvOpModuleProcessed+1;
  1118. if (version == 1) // 2020 February, version 1 added ExecutionModeId..GroupNonUniformQuadSwap
  1119. return SpvOpGroupNonUniformQuadSwap+1;
  1120. return 0;
  1121. }
  1122. static bool smolv_OpHasResult(SpvOp op, int opsCount)
  1123. {
  1124. if (op < 0 || op >= opsCount)
  1125. return false;
  1126. return kSpirvOpData[op].hasResult != 0;
  1127. }
  1128. static bool smolv_OpHasType(SpvOp op, int opsCount)
  1129. {
  1130. if (op < 0 || op >= opsCount)
  1131. return false;
  1132. return kSpirvOpData[op].hasType != 0;
  1133. }
  1134. static int smolv_OpDeltaFromResult(SpvOp op, int opsCount)
  1135. {
  1136. if (op < 0 || op >= opsCount)
  1137. return 0;
  1138. return kSpirvOpData[op].deltaFromResult;
  1139. }
  1140. static bool smolv_OpVarRest(SpvOp op, int opsCount)
  1141. {
  1142. if (op < 0 || op >= opsCount)
  1143. return false;
  1144. return kSpirvOpData[op].varrest != 0;
  1145. }
  1146. static bool smolv_OpDebugInfo(SpvOp op, int opsCount)
  1147. {
  1148. return
  1149. op == SpvOpSourceContinued ||
  1150. op == SpvOpSource ||
  1151. op == SpvOpSourceExtension ||
  1152. op == SpvOpName ||
  1153. op == SpvOpMemberName ||
  1154. op == SpvOpString ||
  1155. op == SpvOpLine ||
  1156. op == SpvOpNoLine ||
  1157. op == SpvOpModuleProcessed;
  1158. }
  1159. static int smolv_DecorationExtraOps(int dec)
  1160. {
  1161. if (dec == 0 || (dec >= 2 && dec <= 5)) // RelaxedPrecision, Block..ColMajor
  1162. return 0;
  1163. if (dec >= 29 && dec <= 37) // Stream..XfbStride
  1164. return 1;
  1165. return -1; // unknown, encode length
  1166. }
  1167. // --------------------------------------------------------------------------------------------
  1168. static bool smolv_CheckGenericHeader(const uint32_t* words, size_t wordCount, uint32_t expectedMagic, uint32_t versionMask)
  1169. {
  1170. if (!words)
  1171. return false;
  1172. if (wordCount < 5)
  1173. return false;
  1174. uint32_t headerMagic = words[0];
  1175. if (headerMagic != expectedMagic)
  1176. return false;
  1177. uint32_t headerVersion = words[1] & versionMask;
  1178. if (headerVersion < 0x00010000 || headerVersion > 0x00010500)
  1179. return false; // only support 1.0 through 1.5
  1180. return true;
  1181. }
  1182. static const int kSpirVHeaderMagic = 0x07230203;
  1183. static const int kSmolHeaderMagic = 0x534D4F4C; // "SMOL"
  1184. static const int kSmolCurrEncodingVersion = 1;
  1185. static bool smolv_CheckSpirVHeader(const uint32_t* words, size_t wordCount)
  1186. {
  1187. //@TODO: if SPIR-V header magic was reversed, that means the file got written
  1188. // in a "big endian" order. Need to byteswap all words then.
  1189. return smolv_CheckGenericHeader(words, wordCount, kSpirVHeaderMagic, 0xFFFFFFFF);
  1190. }
  1191. static bool smolv_CheckSmolHeader(const uint8_t* bytes, size_t byteCount)
  1192. {
  1193. if (!smolv_CheckGenericHeader((const uint32_t*)bytes, byteCount/4, kSmolHeaderMagic, 0x00FFFFFF))
  1194. return false;
  1195. if (byteCount < 24) // one more word past header to store decoded length
  1196. return false;
  1197. // SMOL-V version
  1198. int smolVersion = ((const uint32_t*)bytes)[1] >> 24;
  1199. if (smolVersion < 0 || smolVersion > kSmolCurrEncodingVersion)
  1200. return false;
  1201. return true;
  1202. }
  1203. static void smolv_Write4(smolv::ByteArray& arr, uint32_t v)
  1204. {
  1205. arr.push_back(v & 0xFF);
  1206. arr.push_back((v >> 8) & 0xFF);
  1207. arr.push_back((v >> 16) & 0xFF);
  1208. arr.push_back(v >> 24);
  1209. }
  1210. static void smolv_Write4(uint8_t*& buf, uint32_t v)
  1211. {
  1212. memcpy(buf, &v, 4);
  1213. buf += 4;
  1214. }
  1215. static bool smolv_Read4(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outv)
  1216. {
  1217. if (data + 4 > dataEnd)
  1218. return false;
  1219. outv = (data[0]) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
  1220. data += 4;
  1221. return true;
  1222. }
  1223. // --------------------------------------------------------------------------------------------
  1224. // Variable-length integer encoding for unsigned integers. In each byte:
  1225. // - highest bit set if more bytes follow, cleared if this is last byte.
  1226. // - other 7 bits are the actual value payload.
  1227. // Takes 1-5 bytes to encode an integer (values between 0 and 127 take one byte, etc.).
  1228. static void smolv_WriteVarint(smolv::ByteArray& arr, uint32_t v)
  1229. {
  1230. while (v > 127)
  1231. {
  1232. arr.push_back((v & 127) | 128);
  1233. v >>= 7;
  1234. }
  1235. arr.push_back(v & 127);
  1236. }
  1237. static bool smolv_ReadVarint(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outVal)
  1238. {
  1239. uint32_t v = 0;
  1240. uint32_t shift = 0;
  1241. while (data < dataEnd)
  1242. {
  1243. uint8_t b = *data;
  1244. v |= (b & 127) << shift;
  1245. shift += 7;
  1246. data++;
  1247. if (!(b & 128))
  1248. break;
  1249. }
  1250. outVal = v;
  1251. return true; //@TODO: report failures
  1252. }
  1253. static uint32_t smolv_ZigEncode(int32_t i)
  1254. {
  1255. return (uint32_t(i) << 1) ^ (i >> 31);
  1256. }
  1257. static int32_t smolv_ZigDecode(uint32_t u)
  1258. {
  1259. return (u & 1) ? ((u >> 1) ^ ~0) : (u >> 1);
  1260. }
  1261. // Remap most common Op codes (Load, Store, Decorate, VectorShuffle etc.) to be in < 16 range, for
  1262. // more compact varint encoding. This basically swaps rarely used op values that are < 16 with the
  1263. // ones that are common.
  1264. static SpvOp smolv_RemapOp(SpvOp op)
  1265. {
  1266. # define _SMOLV_SWAP_OP(op1,op2) if (op==op1) return op2; if (op==op2) return op1
  1267. _SMOLV_SWAP_OP(SpvOpDecorate,SpvOpNop); // 0: 24%
  1268. _SMOLV_SWAP_OP(SpvOpLoad,SpvOpUndef); // 1: 17%
  1269. _SMOLV_SWAP_OP(SpvOpStore,SpvOpSourceContinued); // 2: 9%
  1270. _SMOLV_SWAP_OP(SpvOpAccessChain,SpvOpSource); // 3: 7.2%
  1271. _SMOLV_SWAP_OP(SpvOpVectorShuffle,SpvOpSourceExtension); // 4: 5.0%
  1272. // Name - already small enum value - 5: 4.4%
  1273. // MemberName - already small enum value - 6: 2.9%
  1274. _SMOLV_SWAP_OP(SpvOpMemberDecorate,SpvOpString); // 7: 4.0%
  1275. _SMOLV_SWAP_OP(SpvOpLabel,SpvOpLine); // 8: 0.9%
  1276. _SMOLV_SWAP_OP(SpvOpVariable,(SpvOp)9); // 9: 3.9%
  1277. _SMOLV_SWAP_OP(SpvOpFMul,SpvOpExtension); // 10: 3.9%
  1278. _SMOLV_SWAP_OP(SpvOpFAdd,SpvOpExtInstImport); // 11: 2.5%
  1279. // ExtInst - already small enum value - 12: 1.2%
  1280. // VectorShuffleCompact - already small enum value - used for compact shuffle encoding
  1281. _SMOLV_SWAP_OP(SpvOpTypePointer,SpvOpMemoryModel); // 14: 2.2%
  1282. _SMOLV_SWAP_OP(SpvOpFNegate,SpvOpEntryPoint); // 15: 1.1%
  1283. # undef _SMOLV_SWAP_OP
  1284. return op;
  1285. }
  1286. // For most compact varint encoding of common instructions, the instruction length should come out
  1287. // into 3 bits (be <8). SPIR-V instruction lengths are always at least 1, and for some other
  1288. // instructions they are guaranteed to be some other minimum length. Adjust the length before encoding,
  1289. // and after decoding accordingly.
  1290. static uint32_t smolv_EncodeLen(SpvOp op, uint32_t len)
  1291. {
  1292. len--;
  1293. if (op == SpvOpVectorShuffle) len -= 4;
  1294. if (op == SpvOpVectorShuffleCompact) len -= 4;
  1295. if (op == SpvOpDecorate) len -= 2;
  1296. if (op == SpvOpLoad) len -= 3;
  1297. if (op == SpvOpAccessChain) len -= 3;
  1298. return len;
  1299. }
  1300. static uint32_t smolv_DecodeLen(SpvOp op, uint32_t len)
  1301. {
  1302. len++;
  1303. if (op == SpvOpVectorShuffle) len += 4;
  1304. if (op == SpvOpVectorShuffleCompact) len += 4;
  1305. if (op == SpvOpDecorate) len += 2;
  1306. if (op == SpvOpLoad) len += 3;
  1307. if (op == SpvOpAccessChain) len += 3;
  1308. return len;
  1309. }
  1310. // Shuffling bits of length + opcode to be more compact in varint encoding in typical cases:
  1311. // 0x LLLL OOOO is how SPIR-V encodes it (L=length, O=op), we shuffle into:
  1312. // 0x LLLO OOLO, so that common case (op<16, len<8) is encoded into one byte.
  1313. static bool smolv_WriteLengthOp(smolv::ByteArray& arr, uint32_t len, SpvOp op)
  1314. {
  1315. len = smolv_EncodeLen(op, len);
  1316. // SPIR-V length field is 16 bits; if we get a larger value that means something
  1317. // was wrong, e.g. a vector shuffle instruction with less than 4 words (and our
  1318. // adjustment to common lengths in smolv_EncodeLen wrapped around)
  1319. if (len > 0xFFFF)
  1320. return false;
  1321. op = smolv_RemapOp(op);
  1322. uint32_t oplen = ((len >> 4) << 20) | ((op >> 4) << 8) | ((len & 0xF) << 4) | (op & 0xF);
  1323. smolv_WriteVarint(arr, oplen);
  1324. return true;
  1325. }
  1326. static bool smolv_ReadLengthOp(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outLen, SpvOp& outOp)
  1327. {
  1328. uint32_t val;
  1329. if (!smolv_ReadVarint(data, dataEnd, val))
  1330. return false;
  1331. outLen = ((val >> 20) << 4) | ((val >> 4) & 0xF);
  1332. outOp = (SpvOp)(((val >> 4) & 0xFFF0) | (val & 0xF));
  1333. outOp = smolv_RemapOp(outOp);
  1334. outLen = smolv_DecodeLen(outOp, outLen);
  1335. return true;
  1336. }
  1337. #define _SMOLV_READ_OP(len, words, op) \
  1338. uint32_t len = words[0] >> 16; \
  1339. if (len < 1) return false; /* malformed instruction, length needs to be at least 1 */ \
  1340. if (words + len > wordsEnd) return false; /* malformed instruction, goes past end of data */ \
  1341. SpvOp op = (SpvOp)(words[0] & 0xFFFF)
  1342. bool smolv::Encode(const void* spirvData, size_t spirvSize, ByteArray& outSmolv, uint32_t flags, StripOpNameFilterFunc stripFilter)
  1343. {
  1344. const size_t wordCount = spirvSize / 4;
  1345. if (wordCount * 4 != spirvSize)
  1346. return false;
  1347. const uint32_t* words = (const uint32_t*)spirvData;
  1348. const uint32_t* wordsEnd = words + wordCount;
  1349. if (!smolv_CheckSpirVHeader(words, wordCount))
  1350. return false;
  1351. // reserve space in output (typical compression is to about 30%; reserve half of input space)
  1352. outSmolv.reserve(outSmolv.size() + spirvSize/2);
  1353. // header (matches SPIR-V one, except different magic)
  1354. smolv_Write4(outSmolv, kSmolHeaderMagic);
  1355. smolv_Write4(outSmolv, (words[1] & 0x00FFFFFF) + (kSmolCurrEncodingVersion<<24)); // SPIR-V version (_XXX) + SMOL-V version (X___)
  1356. smolv_Write4(outSmolv, words[2]); // generator
  1357. smolv_Write4(outSmolv, words[3]); // bound
  1358. smolv_Write4(outSmolv, words[4]); // schema
  1359. const size_t headerSpirvSizeOffset = outSmolv.size(); // size field may get updated later if stripping is enabled
  1360. smolv_Write4(outSmolv, (uint32_t)spirvSize); // space needed to decode (i.e. original SPIR-V size)
  1361. size_t strippedSpirvWordCount = wordCount;
  1362. uint32_t prevResult = 0;
  1363. uint32_t prevDecorate = 0;
  1364. const int knownOpsCount = smolv_GetKnownOpsCount(kSmolCurrEncodingVersion);
  1365. words += 5;
  1366. while (words < wordsEnd)
  1367. {
  1368. _SMOLV_READ_OP(instrLen, words, op);
  1369. if ((flags & kEncodeFlagStripDebugInfo) && smolv_OpDebugInfo(op, knownOpsCount))
  1370. {
  1371. if (!stripFilter || op != SpvOpName || !stripFilter(reinterpret_cast<const char*>(&words[2])))
  1372. {
  1373. strippedSpirvWordCount -= instrLen;
  1374. words += instrLen;
  1375. continue;
  1376. }
  1377. }
  1378. // A usual case of vector shuffle, with less than 4 components, each with a value
  1379. // in [0..3] range: encode it in a more compact form, with the swizzle pattern in one byte.
  1380. // Turn this into a VectorShuffleCompact instruction, that takes up unused slot in Ops.
  1381. uint32_t swizzle = 0;
  1382. if (op == SpvOpVectorShuffle && instrLen <= 9)
  1383. {
  1384. uint32_t swz0 = instrLen > 5 ? words[5] : 0;
  1385. uint32_t swz1 = instrLen > 6 ? words[6] : 0;
  1386. uint32_t swz2 = instrLen > 7 ? words[7] : 0;
  1387. uint32_t swz3 = instrLen > 8 ? words[8] : 0;
  1388. if (swz0 < 4 && swz1 < 4 && swz2 < 4 && swz3 < 4)
  1389. {
  1390. op = SpvOpVectorShuffleCompact;
  1391. swizzle = (swz0 << 6) | (swz1 << 4) | (swz2 << 2) | (swz3);
  1392. }
  1393. }
  1394. // length + opcode
  1395. if (!smolv_WriteLengthOp(outSmolv, instrLen, op))
  1396. return false;
  1397. size_t ioffs = 1;
  1398. // write type as varint, if we have it
  1399. if (smolv_OpHasType(op, knownOpsCount))
  1400. {
  1401. if (ioffs >= instrLen)
  1402. return false;
  1403. smolv_WriteVarint(outSmolv, words[ioffs]);
  1404. ioffs++;
  1405. }
  1406. // write result as delta+zig+varint, if we have it
  1407. if (smolv_OpHasResult(op, knownOpsCount))
  1408. {
  1409. if (ioffs >= instrLen)
  1410. return false;
  1411. uint32_t v = words[ioffs];
  1412. smolv_WriteVarint(outSmolv, smolv_ZigEncode(v - prevResult)); // some deltas are negative, use zig
  1413. prevResult = v;
  1414. ioffs++;
  1415. }
  1416. // Decorate & MemberDecorate: IDs relative to previous decorate
  1417. if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
  1418. {
  1419. if (ioffs >= instrLen)
  1420. return false;
  1421. uint32_t v = words[ioffs];
  1422. smolv_WriteVarint(outSmolv, smolv_ZigEncode(v - prevDecorate)); // spirv-remapped deltas often negative, use zig
  1423. prevDecorate = v;
  1424. ioffs++;
  1425. }
  1426. // MemberDecorate special encoding: whole row of MemberDecorate instructions is often referring
  1427. // to the same type and linearly increasing member indices. Scan ahead to see how many we have,
  1428. // and encode whole bunch as one.
  1429. if (op == SpvOpMemberDecorate)
  1430. {
  1431. // scan ahead until we reach end, non-member-decoration or different type
  1432. const uint32_t decorationType = words[ioffs-1];
  1433. const uint32_t* memberWords = words;
  1434. uint32_t prevIndex = 0;
  1435. uint32_t prevOffset = 0;
  1436. // write a byte on how many we have encoded as a bunch
  1437. size_t countLocation = outSmolv.size();
  1438. outSmolv.push_back(0);
  1439. int count = 0;
  1440. while (memberWords < wordsEnd && count < 255)
  1441. {
  1442. _SMOLV_READ_OP(memberLen, memberWords, memberOp);
  1443. if (memberOp != SpvOpMemberDecorate)
  1444. break;
  1445. if (memberLen < 4)
  1446. return false; // invalid input
  1447. if (memberWords[1] != decorationType)
  1448. break;
  1449. // write member index as delta from previous
  1450. uint32_t memberIndex = memberWords[2];
  1451. smolv_WriteVarint(outSmolv, memberIndex - prevIndex);
  1452. prevIndex = memberIndex;
  1453. // decoration (and length if not common/known)
  1454. uint32_t memberDec = memberWords[3];
  1455. smolv_WriteVarint(outSmolv, memberDec);
  1456. const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
  1457. if (knownExtraOps == -1)
  1458. smolv_WriteVarint(outSmolv, memberLen-4);
  1459. else if (unsigned(knownExtraOps) + 4 != memberLen)
  1460. return false; // invalid input
  1461. // Offset decorations are most often linearly increasing, so encode as deltas
  1462. if (memberDec == 35) // Offset
  1463. {
  1464. if (memberLen != 5)
  1465. return false;
  1466. smolv_WriteVarint(outSmolv, memberWords[4]-prevOffset);
  1467. prevOffset = memberWords[4];
  1468. }
  1469. else
  1470. {
  1471. // write rest of decorations as varint
  1472. for (uint32_t i = 4; i < memberLen; ++i)
  1473. smolv_WriteVarint(outSmolv, memberWords[i]);
  1474. }
  1475. memberWords += memberLen;
  1476. ++count;
  1477. }
  1478. outSmolv[countLocation] = uint8_t(count);
  1479. words = memberWords;
  1480. continue;
  1481. }
  1482. // Write out this many IDs, encoding them relative+zigzag to result ID
  1483. int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
  1484. for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
  1485. {
  1486. if (ioffs >= instrLen)
  1487. return false;
  1488. uint32_t delta = prevResult - words[ioffs];
  1489. // some deltas are negative (often on branches, or if program was processed by spirv-remap),
  1490. // so use zig encoding
  1491. smolv_WriteVarint(outSmolv, smolv_ZigEncode(delta));
  1492. }
  1493. if (op == SpvOpVectorShuffleCompact)
  1494. {
  1495. // compact vector shuffle, just write out single swizzle byte
  1496. outSmolv.push_back(uint8_t(swizzle));
  1497. ioffs = instrLen;
  1498. }
  1499. else if (smolv_OpVarRest(op, knownOpsCount))
  1500. {
  1501. // write out rest of words with variable encoding (expected to be small integers)
  1502. for (; ioffs < instrLen; ++ioffs)
  1503. smolv_WriteVarint(outSmolv, words[ioffs]);
  1504. }
  1505. else
  1506. {
  1507. // write out rest of words without any encoding
  1508. for (; ioffs < instrLen; ++ioffs)
  1509. smolv_Write4(outSmolv, words[ioffs]);
  1510. }
  1511. words += instrLen;
  1512. }
  1513. if (strippedSpirvWordCount != wordCount)
  1514. {
  1515. uint8_t* headerSpirvSize = &outSmolv[headerSpirvSizeOffset];
  1516. smolv_Write4(headerSpirvSize, (uint32_t)strippedSpirvWordCount * 4);
  1517. }
  1518. return true;
  1519. }
  1520. size_t smolv::GetDecodedBufferSize(const void* smolvData, size_t smolvSize)
  1521. {
  1522. if (!smolv_CheckSmolHeader((const uint8_t*)smolvData, smolvSize))
  1523. return 0;
  1524. const uint32_t* words = (const uint32_t*)smolvData;
  1525. return words[5];
  1526. }
  1527. bool smolv::Decode(const void* smolvData, size_t smolvSize, void* spirvOutputBuffer, size_t spirvOutputBufferSize, uint32_t flags)
  1528. {
  1529. // check header, and whether we have enough output buffer space
  1530. const size_t neededBufferSize = GetDecodedBufferSize(smolvData, smolvSize);
  1531. if (neededBufferSize == 0)
  1532. return false; // invalid SMOL-V
  1533. if (spirvOutputBufferSize < neededBufferSize)
  1534. return false; // not enough space in output buffer
  1535. if (spirvOutputBuffer == NULL)
  1536. return false; // output buffer is null
  1537. const uint8_t* bytes = (const uint8_t*)smolvData;
  1538. const uint8_t* bytesEnd = bytes + smolvSize;
  1539. uint8_t* outSpirv = (uint8_t*)spirvOutputBuffer;
  1540. uint32_t val;
  1541. int smolVersion = 0;
  1542. // header
  1543. smolv_Write4(outSpirv, kSpirVHeaderMagic); bytes += 4;
  1544. smolv_Read4(bytes, bytesEnd, val); smolVersion = val >> 24; val &= 0x00FFFFFF; smolv_Write4(outSpirv, val); // version
  1545. smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // generator
  1546. smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // bound
  1547. smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // schema
  1548. bytes += 4; // decode buffer size
  1549. // there are two SMOL-V encoding versions, both not indicating anything in their header version field:
  1550. // one that is called "before zero" here (2016-08-31 code). Support decoding that one only by presence
  1551. // of this special flag.
  1552. const bool beforeZeroVersion = smolVersion == 0 && (flags & kDecodeFlagUse20160831AsZeroVersion) != 0;
  1553. const int knownOpsCount = smolv_GetKnownOpsCount(smolVersion);
  1554. uint32_t prevResult = 0;
  1555. uint32_t prevDecorate = 0;
  1556. while (bytes < bytesEnd)
  1557. {
  1558. // read length + opcode
  1559. uint32_t instrLen;
  1560. SpvOp op;
  1561. if (!smolv_ReadLengthOp(bytes, bytesEnd, instrLen, op))
  1562. return false;
  1563. const bool wasSwizzle = (op == SpvOpVectorShuffleCompact);
  1564. if (wasSwizzle)
  1565. op = SpvOpVectorShuffle;
  1566. smolv_Write4(outSpirv, (instrLen << 16) | op);
  1567. size_t ioffs = 1;
  1568. // read type as varint, if we have it
  1569. if (smolv_OpHasType(op, knownOpsCount))
  1570. {
  1571. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1572. smolv_Write4(outSpirv, val);
  1573. ioffs++;
  1574. }
  1575. // read result as delta+varint, if we have it
  1576. if (smolv_OpHasResult(op, knownOpsCount))
  1577. {
  1578. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1579. val = prevResult + smolv_ZigDecode(val);
  1580. smolv_Write4(outSpirv, val);
  1581. prevResult = val;
  1582. ioffs++;
  1583. }
  1584. // Decorate: IDs relative to previous decorate
  1585. if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
  1586. {
  1587. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1588. // "before zero" version did not use zig encoding for the value
  1589. val = prevDecorate + (beforeZeroVersion ? val : smolv_ZigDecode(val));
  1590. smolv_Write4(outSpirv, val);
  1591. prevDecorate = val;
  1592. ioffs++;
  1593. }
  1594. // MemberDecorate special decoding
  1595. if (op == SpvOpMemberDecorate && !beforeZeroVersion)
  1596. {
  1597. if (bytes >= bytesEnd)
  1598. return false; // broken input
  1599. int count = *bytes++;
  1600. int prevIndex = 0;
  1601. int prevOffset = 0;
  1602. for (int m = 0; m < count; ++m)
  1603. {
  1604. // read member index
  1605. uint32_t memberIndex;
  1606. if (!smolv_ReadVarint(bytes, bytesEnd, memberIndex)) return false;
  1607. memberIndex += prevIndex;
  1608. prevIndex = memberIndex;
  1609. // decoration (and length if not common/known)
  1610. uint32_t memberDec;
  1611. if (!smolv_ReadVarint(bytes, bytesEnd, memberDec)) return false;
  1612. const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
  1613. uint32_t memberLen;
  1614. if (knownExtraOps == -1)
  1615. {
  1616. if (!smolv_ReadVarint(bytes, bytesEnd, memberLen)) return false;
  1617. memberLen += 4;
  1618. }
  1619. else
  1620. memberLen = 4 + knownExtraOps;
  1621. // write SPIR-V op+length (unless it's first member decoration, in which case it was written before)
  1622. if (m != 0)
  1623. {
  1624. smolv_Write4(outSpirv, (memberLen << 16) | op);
  1625. smolv_Write4(outSpirv, prevDecorate);
  1626. }
  1627. smolv_Write4(outSpirv, memberIndex);
  1628. smolv_Write4(outSpirv, memberDec);
  1629. // Special case for Offset decorations
  1630. if (memberDec == 35) // Offset
  1631. {
  1632. if (memberLen != 5)
  1633. return false;
  1634. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1635. val += prevOffset;
  1636. smolv_Write4(outSpirv, val);
  1637. prevOffset = val;
  1638. }
  1639. else
  1640. {
  1641. for (uint32_t i = 4; i < memberLen; ++i)
  1642. {
  1643. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1644. smolv_Write4(outSpirv, val);
  1645. }
  1646. }
  1647. }
  1648. continue;
  1649. }
  1650. // Read this many IDs, that are relative to result ID
  1651. int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
  1652. // "before zero" version only used zig encoding for IDs of several ops; after
  1653. // that ops got zig encoding for their IDs
  1654. bool zigDecodeVals = true;
  1655. if (beforeZeroVersion)
  1656. {
  1657. if (op != SpvOpControlBarrier && op != SpvOpMemoryBarrier && op != SpvOpLoopMerge && op != SpvOpSelectionMerge && op != SpvOpBranch && op != SpvOpBranchConditional && op != SpvOpMemoryNamedBarrier)
  1658. zigDecodeVals = false;
  1659. }
  1660. for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
  1661. {
  1662. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1663. if (zigDecodeVals)
  1664. val = smolv_ZigDecode(val);
  1665. smolv_Write4(outSpirv, prevResult - val);
  1666. }
  1667. if (wasSwizzle && instrLen <= 9)
  1668. {
  1669. uint32_t swizzle = *bytes++;
  1670. if (instrLen > 5) smolv_Write4(outSpirv, (swizzle >> 6) & 3);
  1671. if (instrLen > 6) smolv_Write4(outSpirv, (swizzle >> 4) & 3);
  1672. if (instrLen > 7) smolv_Write4(outSpirv, (swizzle >> 2) & 3);
  1673. if (instrLen > 8) smolv_Write4(outSpirv, swizzle & 3);
  1674. }
  1675. else if (smolv_OpVarRest(op, knownOpsCount))
  1676. {
  1677. // read rest of words with variable encoding
  1678. for (; ioffs < instrLen; ++ioffs)
  1679. {
  1680. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1681. smolv_Write4(outSpirv, val);
  1682. }
  1683. }
  1684. else
  1685. {
  1686. // read rest of words without any encoding
  1687. for (; ioffs < instrLen; ++ioffs)
  1688. {
  1689. if (!smolv_Read4(bytes, bytesEnd, val)) return false;
  1690. smolv_Write4(outSpirv, val);
  1691. }
  1692. }
  1693. }
  1694. if ((uint8_t*)spirvOutputBuffer + neededBufferSize != outSpirv)
  1695. return false; // something went wrong during decoding? we should have decoded to exact output size
  1696. return true;
  1697. }
  1698. // --------------------------------------------------------------------------------------------
  1699. // Calculating instruction count / space stats on SPIR-V and SMOL-V
  1700. struct smolv::Stats
  1701. {
  1702. Stats() { memset(this, 0, sizeof(*this)); }
  1703. size_t opCounts[kKnownOpsCount];
  1704. size_t opSizes[kKnownOpsCount];
  1705. size_t smolOpSizes[kKnownOpsCount];
  1706. size_t varintCountsOp[6];
  1707. size_t varintCountsType[6];
  1708. size_t varintCountsRes[6];
  1709. size_t varintCountsOther[6];
  1710. size_t totalOps;
  1711. size_t totalSize;
  1712. size_t totalSizeSmol;
  1713. size_t inputCount;
  1714. };
  1715. smolv::Stats* smolv::StatsCreate()
  1716. {
  1717. return new Stats();
  1718. }
  1719. void smolv::StatsDelete(smolv::Stats *s)
  1720. {
  1721. delete s;
  1722. }
  1723. bool smolv::StatsCalculate(smolv::Stats* stats, const void* spirvData, size_t spirvSize)
  1724. {
  1725. if (!stats)
  1726. return false;
  1727. const size_t wordCount = spirvSize / 4;
  1728. if (wordCount * 4 != spirvSize)
  1729. return false;
  1730. const uint32_t* words = (const uint32_t*)spirvData;
  1731. const uint32_t* wordsEnd = words + wordCount;
  1732. if (!smolv_CheckSpirVHeader(words, wordCount))
  1733. return false;
  1734. words += 5;
  1735. stats->inputCount++;
  1736. stats->totalSize += wordCount;
  1737. while (words < wordsEnd)
  1738. {
  1739. _SMOLV_READ_OP(instrLen, words, op);
  1740. if (op < kKnownOpsCount)
  1741. {
  1742. stats->opCounts[op]++;
  1743. stats->opSizes[op] += instrLen;
  1744. }
  1745. words += instrLen;
  1746. stats->totalOps++;
  1747. }
  1748. return true;
  1749. }
  1750. bool smolv::StatsCalculateSmol(smolv::Stats* stats, const void* smolvData, size_t smolvSize)
  1751. {
  1752. if (!stats)
  1753. return false;
  1754. // debugging helper to dump all encoded bytes to stdout, keep at "if 0"
  1755. # if 0
  1756. # define _SMOLV_DEBUG_PRINT_ENCODED_BYTES() { \
  1757. printf("Op %-22s ", op < kKnownOpsCount ? kSpirvOpNames[op] : "???"); \
  1758. for (const uint8_t* b = instrBegin; b < bytes; ++b) \
  1759. printf("%02x ", *b); \
  1760. printf("\n"); \
  1761. }
  1762. # else
  1763. # define _SMOLV_DEBUG_PRINT_ENCODED_BYTES() {}
  1764. # endif
  1765. const uint8_t* bytes = (const uint8_t*)smolvData;
  1766. const uint8_t* bytesEnd = bytes + smolvSize;
  1767. if (!smolv_CheckSmolHeader(bytes, smolvSize))
  1768. return false;
  1769. uint32_t val;
  1770. int smolVersion;
  1771. bytes += 4;
  1772. smolv_Read4(bytes, bytesEnd, val); smolVersion = val >> 24;
  1773. const int knownOpsCount = smolv_GetKnownOpsCount(smolVersion);
  1774. bytes += 16;
  1775. stats->totalSizeSmol += smolvSize;
  1776. while (bytes < bytesEnd)
  1777. {
  1778. const uint8_t* instrBegin = bytes;
  1779. const uint8_t* varBegin;
  1780. // read length + opcode
  1781. uint32_t instrLen;
  1782. SpvOp op;
  1783. varBegin = bytes;
  1784. if (!smolv_ReadLengthOp(bytes, bytesEnd, instrLen, op))
  1785. return false;
  1786. const bool wasSwizzle = (op == SpvOpVectorShuffleCompact);
  1787. if (wasSwizzle)
  1788. op = SpvOpVectorShuffle;
  1789. stats->varintCountsOp[bytes-varBegin]++;
  1790. size_t ioffs = 1;
  1791. if (smolv_OpHasType(op, knownOpsCount))
  1792. {
  1793. varBegin = bytes;
  1794. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1795. stats->varintCountsType[bytes-varBegin]++;
  1796. ioffs++;
  1797. }
  1798. if (smolv_OpHasResult(op, knownOpsCount))
  1799. {
  1800. varBegin = bytes;
  1801. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1802. stats->varintCountsRes[bytes-varBegin]++;
  1803. ioffs++;
  1804. }
  1805. if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
  1806. {
  1807. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1808. ioffs++;
  1809. }
  1810. // MemberDecorate special decoding
  1811. if (op == SpvOpMemberDecorate)
  1812. {
  1813. if (bytes >= bytesEnd)
  1814. return false; // broken input
  1815. int count = *bytes++;
  1816. for (int m = 0; m < count; ++m)
  1817. {
  1818. uint32_t memberIndex;
  1819. if (!smolv_ReadVarint(bytes, bytesEnd, memberIndex)) return false;
  1820. uint32_t memberDec;
  1821. if (!smolv_ReadVarint(bytes, bytesEnd, memberDec)) return false;
  1822. const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
  1823. uint32_t memberLen;
  1824. if (knownExtraOps == -1)
  1825. {
  1826. if (!smolv_ReadVarint(bytes, bytesEnd, memberLen)) return false;
  1827. memberLen += 4;
  1828. }
  1829. else
  1830. memberLen = 4 + knownExtraOps;
  1831. for (uint32_t i = 4; i < memberLen; ++i)
  1832. {
  1833. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1834. }
  1835. }
  1836. stats->smolOpSizes[op] += bytes - instrBegin;
  1837. _SMOLV_DEBUG_PRINT_ENCODED_BYTES();
  1838. continue;
  1839. }
  1840. int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
  1841. for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
  1842. {
  1843. varBegin = bytes;
  1844. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1845. stats->varintCountsRes[bytes-varBegin]++;
  1846. }
  1847. if (wasSwizzle && instrLen <= 9)
  1848. {
  1849. bytes++;
  1850. }
  1851. else if (smolv_OpVarRest(op, knownOpsCount))
  1852. {
  1853. for (; ioffs < instrLen; ++ioffs)
  1854. {
  1855. varBegin = bytes;
  1856. if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
  1857. stats->varintCountsOther[bytes-varBegin]++;
  1858. }
  1859. }
  1860. else
  1861. {
  1862. for (; ioffs < instrLen; ++ioffs)
  1863. {
  1864. if (!smolv_Read4(bytes, bytesEnd, val)) return false;
  1865. }
  1866. }
  1867. if (op < kKnownOpsCount)
  1868. {
  1869. stats->smolOpSizes[op] += bytes - instrBegin;
  1870. }
  1871. _SMOLV_DEBUG_PRINT_ENCODED_BYTES();
  1872. }
  1873. return true;
  1874. }
  1875. static bool CompareOpCounters (std::pair<SpvOp,size_t> a, std::pair<SpvOp,size_t> b)
  1876. {
  1877. return a.second > b.second;
  1878. }
  1879. void smolv::StatsPrint(const Stats* stats)
  1880. {
  1881. if (!stats)
  1882. return;
  1883. typedef std::pair<SpvOp,size_t> OpCounter;
  1884. OpCounter counts[kKnownOpsCount];
  1885. OpCounter sizes[kKnownOpsCount];
  1886. OpCounter sizesSmol[kKnownOpsCount];
  1887. for (int i = 0; i < kKnownOpsCount; ++i)
  1888. {
  1889. counts[i].first = (SpvOp)i;
  1890. counts[i].second = stats->opCounts[i];
  1891. sizes[i].first = (SpvOp)i;
  1892. sizes[i].second = stats->opSizes[i];
  1893. sizesSmol[i].first = (SpvOp)i;
  1894. sizesSmol[i].second = stats->smolOpSizes[i];
  1895. }
  1896. std::sort(counts, counts + kKnownOpsCount, CompareOpCounters);
  1897. std::sort(sizes, sizes + kKnownOpsCount, CompareOpCounters);
  1898. std::sort(sizesSmol, sizesSmol + kKnownOpsCount, CompareOpCounters);
  1899. printf("Stats for %i SPIR-V inputs, total size %i words (%.1fKB):\n", (int)stats->inputCount, (int)stats->totalSize, stats->totalSize * 4.0f / 1024.0f);
  1900. printf("Most occuring ops:\n");
  1901. for (int i = 0; i < 30; ++i)
  1902. {
  1903. SpvOp op = counts[i].first;
  1904. printf(" #%2i: %4i %-20s %4i (%4.1f%%)\n", i, op, kSpirvOpNames[op], (int)counts[i].second, (float)counts[i].second / (float)stats->totalOps * 100.0f);
  1905. }
  1906. printf("Largest total size of ops:\n");
  1907. for (int i = 0; i < 30; ++i)
  1908. {
  1909. SpvOp op = sizes[i].first;
  1910. printf(" #%2i: %-22s %6i (%4.1f%%) avg len %.1f\n",
  1911. i,
  1912. kSpirvOpNames[op],
  1913. (int)sizes[i].second*4,
  1914. (float)sizes[i].second / (float)stats->totalSize * 100.0f,
  1915. (float)sizes[i].second*4 / (float)stats->opCounts[op]
  1916. );
  1917. }
  1918. printf("SMOL varint encoding counts per byte length:\n");
  1919. printf(" B: %6s %6s %6s %6s\n", "Op", "Type", "Result", "Other");
  1920. for (int i = 1; i < 6; ++i)
  1921. {
  1922. printf(" %i: %6i %6i %6i %6i\n", i, (int)stats->varintCountsOp[i], (int)stats->varintCountsType[i], (int)stats->varintCountsRes[i], (int)stats->varintCountsOther[i]);
  1923. }
  1924. printf("Largest total size of ops in SMOL:\n");
  1925. for (int i = 0; i < 30; ++i)
  1926. {
  1927. SpvOp op = sizesSmol[i].first;
  1928. printf(" #%2i: %-22s %6i (%4.1f%%) avg len %.1f\n",
  1929. i,
  1930. kSpirvOpNames[op],
  1931. (int)sizesSmol[i].second,
  1932. (float)sizesSmol[i].second / (float)stats->totalSizeSmol * 100.0f,
  1933. (float)sizesSmol[i].second / (float)stats->opCounts[op]
  1934. );
  1935. }
  1936. }
  1937. // ------------------------------------------------------------------------------
  1938. // This software is available under 2 licenses -- choose whichever you prefer.
  1939. // ------------------------------------------------------------------------------
  1940. // ALTERNATIVE A - MIT License
  1941. // Copyright (c) 2016-2020 Aras Pranckevicius
  1942. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  1943. // this software and associated documentation files (the "Software"), to deal in
  1944. // the Software without restriction, including without limitation the rights to
  1945. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  1946. // of the Software, and to permit persons to whom the Software is furnished to do
  1947. // so, subject to the following conditions:
  1948. // The above copyright notice and this permission notice shall be included in all
  1949. // copies or substantial portions of the Software.
  1950. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1951. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1952. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1953. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  1954. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  1955. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  1956. // SOFTWARE.
  1957. // ------------------------------------------------------------------------------
  1958. // ALTERNATIVE B - Public Domain (www.unlicense.org)
  1959. // This is free and unencumbered software released into the public domain.
  1960. // Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
  1961. // software, either in source code form or as a compiled binary, for any purpose,
  1962. // commercial or non-commercial, and by any means.
  1963. // In jurisdictions that recognize copyright laws, the author or authors of this
  1964. // software dedicate any and all copyright interest in the software to the public
  1965. // domain. We make this dedication for the benefit of the public at large and to
  1966. // the detriment of our heirs and successors. We intend this dedication to be an
  1967. // overt act of relinquishment in perpetuity of all present and future rights to
  1968. // this software under copyright law.
  1969. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1970. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1971. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1972. // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  1973. // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  1974. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  1975. // ------------------------------------------------------------------------------