123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109 |
- // smol-v - public domain - https://github.com/aras-p/smol-v
- // authored 2016-2020 by Aras Pranckevicius
- // no warranty implied; use at your own risk
- // See end of file for license information.
- #include "smolv.h"
- #include <stdint.h>
- #include <vector>
- #include <algorithm>
- #include <cstdio>
- #include <cstring>
- #if !defined(_MSC_VER) && __cplusplus < 201103L
- #define static_assert(x,y)
- #endif
- #define _SMOLV_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
- // --------------------------------------------------------------------------------------------
- // Metadata about known SPIR-V operations
- enum SpvOp
- {
- SpvOpNop = 0,
- SpvOpUndef = 1,
- SpvOpSourceContinued = 2,
- SpvOpSource = 3,
- SpvOpSourceExtension = 4,
- SpvOpName = 5,
- SpvOpMemberName = 6,
- SpvOpString = 7,
- SpvOpLine = 8,
- SpvOpExtension = 10,
- SpvOpExtInstImport = 11,
- SpvOpExtInst = 12,
- SpvOpVectorShuffleCompact = 13, // not in SPIR-V, added for SMOL-V!
- SpvOpMemoryModel = 14,
- SpvOpEntryPoint = 15,
- SpvOpExecutionMode = 16,
- SpvOpCapability = 17,
- SpvOpTypeVoid = 19,
- SpvOpTypeBool = 20,
- SpvOpTypeInt = 21,
- SpvOpTypeFloat = 22,
- SpvOpTypeVector = 23,
- SpvOpTypeMatrix = 24,
- SpvOpTypeImage = 25,
- SpvOpTypeSampler = 26,
- SpvOpTypeSampledImage = 27,
- SpvOpTypeArray = 28,
- SpvOpTypeRuntimeArray = 29,
- SpvOpTypeStruct = 30,
- SpvOpTypeOpaque = 31,
- SpvOpTypePointer = 32,
- SpvOpTypeFunction = 33,
- SpvOpTypeEvent = 34,
- SpvOpTypeDeviceEvent = 35,
- SpvOpTypeReserveId = 36,
- SpvOpTypeQueue = 37,
- SpvOpTypePipe = 38,
- SpvOpTypeForwardPointer = 39,
- SpvOpConstantTrue = 41,
- SpvOpConstantFalse = 42,
- SpvOpConstant = 43,
- SpvOpConstantComposite = 44,
- SpvOpConstantSampler = 45,
- SpvOpConstantNull = 46,
- SpvOpSpecConstantTrue = 48,
- SpvOpSpecConstantFalse = 49,
- SpvOpSpecConstant = 50,
- SpvOpSpecConstantComposite = 51,
- SpvOpSpecConstantOp = 52,
- SpvOpFunction = 54,
- SpvOpFunctionParameter = 55,
- SpvOpFunctionEnd = 56,
- SpvOpFunctionCall = 57,
- SpvOpVariable = 59,
- SpvOpImageTexelPointer = 60,
- SpvOpLoad = 61,
- SpvOpStore = 62,
- SpvOpCopyMemory = 63,
- SpvOpCopyMemorySized = 64,
- SpvOpAccessChain = 65,
- SpvOpInBoundsAccessChain = 66,
- SpvOpPtrAccessChain = 67,
- SpvOpArrayLength = 68,
- SpvOpGenericPtrMemSemantics = 69,
- SpvOpInBoundsPtrAccessChain = 70,
- SpvOpDecorate = 71,
- SpvOpMemberDecorate = 72,
- SpvOpDecorationGroup = 73,
- SpvOpGroupDecorate = 74,
- SpvOpGroupMemberDecorate = 75,
- SpvOpVectorExtractDynamic = 77,
- SpvOpVectorInsertDynamic = 78,
- SpvOpVectorShuffle = 79,
- SpvOpCompositeConstruct = 80,
- SpvOpCompositeExtract = 81,
- SpvOpCompositeInsert = 82,
- SpvOpCopyObject = 83,
- SpvOpTranspose = 84,
- SpvOpSampledImage = 86,
- SpvOpImageSampleImplicitLod = 87,
- SpvOpImageSampleExplicitLod = 88,
- SpvOpImageSampleDrefImplicitLod = 89,
- SpvOpImageSampleDrefExplicitLod = 90,
- SpvOpImageSampleProjImplicitLod = 91,
- SpvOpImageSampleProjExplicitLod = 92,
- SpvOpImageSampleProjDrefImplicitLod = 93,
- SpvOpImageSampleProjDrefExplicitLod = 94,
- SpvOpImageFetch = 95,
- SpvOpImageGather = 96,
- SpvOpImageDrefGather = 97,
- SpvOpImageRead = 98,
- SpvOpImageWrite = 99,
- SpvOpImage = 100,
- SpvOpImageQueryFormat = 101,
- SpvOpImageQueryOrder = 102,
- SpvOpImageQuerySizeLod = 103,
- SpvOpImageQuerySize = 104,
- SpvOpImageQueryLod = 105,
- SpvOpImageQueryLevels = 106,
- SpvOpImageQuerySamples = 107,
- SpvOpConvertFToU = 109,
- SpvOpConvertFToS = 110,
- SpvOpConvertSToF = 111,
- SpvOpConvertUToF = 112,
- SpvOpUConvert = 113,
- SpvOpSConvert = 114,
- SpvOpFConvert = 115,
- SpvOpQuantizeToF16 = 116,
- SpvOpConvertPtrToU = 117,
- SpvOpSatConvertSToU = 118,
- SpvOpSatConvertUToS = 119,
- SpvOpConvertUToPtr = 120,
- SpvOpPtrCastToGeneric = 121,
- SpvOpGenericCastToPtr = 122,
- SpvOpGenericCastToPtrExplicit = 123,
- SpvOpBitcast = 124,
- SpvOpSNegate = 126,
- SpvOpFNegate = 127,
- SpvOpIAdd = 128,
- SpvOpFAdd = 129,
- SpvOpISub = 130,
- SpvOpFSub = 131,
- SpvOpIMul = 132,
- SpvOpFMul = 133,
- SpvOpUDiv = 134,
- SpvOpSDiv = 135,
- SpvOpFDiv = 136,
- SpvOpUMod = 137,
- SpvOpSRem = 138,
- SpvOpSMod = 139,
- SpvOpFRem = 140,
- SpvOpFMod = 141,
- SpvOpVectorTimesScalar = 142,
- SpvOpMatrixTimesScalar = 143,
- SpvOpVectorTimesMatrix = 144,
- SpvOpMatrixTimesVector = 145,
- SpvOpMatrixTimesMatrix = 146,
- SpvOpOuterProduct = 147,
- SpvOpDot = 148,
- SpvOpIAddCarry = 149,
- SpvOpISubBorrow = 150,
- SpvOpUMulExtended = 151,
- SpvOpSMulExtended = 152,
- SpvOpAny = 154,
- SpvOpAll = 155,
- SpvOpIsNan = 156,
- SpvOpIsInf = 157,
- SpvOpIsFinite = 158,
- SpvOpIsNormal = 159,
- SpvOpSignBitSet = 160,
- SpvOpLessOrGreater = 161,
- SpvOpOrdered = 162,
- SpvOpUnordered = 163,
- SpvOpLogicalEqual = 164,
- SpvOpLogicalNotEqual = 165,
- SpvOpLogicalOr = 166,
- SpvOpLogicalAnd = 167,
- SpvOpLogicalNot = 168,
- SpvOpSelect = 169,
- SpvOpIEqual = 170,
- SpvOpINotEqual = 171,
- SpvOpUGreaterThan = 172,
- SpvOpSGreaterThan = 173,
- SpvOpUGreaterThanEqual = 174,
- SpvOpSGreaterThanEqual = 175,
- SpvOpULessThan = 176,
- SpvOpSLessThan = 177,
- SpvOpULessThanEqual = 178,
- SpvOpSLessThanEqual = 179,
- SpvOpFOrdEqual = 180,
- SpvOpFUnordEqual = 181,
- SpvOpFOrdNotEqual = 182,
- SpvOpFUnordNotEqual = 183,
- SpvOpFOrdLessThan = 184,
- SpvOpFUnordLessThan = 185,
- SpvOpFOrdGreaterThan = 186,
- SpvOpFUnordGreaterThan = 187,
- SpvOpFOrdLessThanEqual = 188,
- SpvOpFUnordLessThanEqual = 189,
- SpvOpFOrdGreaterThanEqual = 190,
- SpvOpFUnordGreaterThanEqual = 191,
- SpvOpShiftRightLogical = 194,
- SpvOpShiftRightArithmetic = 195,
- SpvOpShiftLeftLogical = 196,
- SpvOpBitwiseOr = 197,
- SpvOpBitwiseXor = 198,
- SpvOpBitwiseAnd = 199,
- SpvOpNot = 200,
- SpvOpBitFieldInsert = 201,
- SpvOpBitFieldSExtract = 202,
- SpvOpBitFieldUExtract = 203,
- SpvOpBitReverse = 204,
- SpvOpBitCount = 205,
- SpvOpDPdx = 207,
- SpvOpDPdy = 208,
- SpvOpFwidth = 209,
- SpvOpDPdxFine = 210,
- SpvOpDPdyFine = 211,
- SpvOpFwidthFine = 212,
- SpvOpDPdxCoarse = 213,
- SpvOpDPdyCoarse = 214,
- SpvOpFwidthCoarse = 215,
- SpvOpEmitVertex = 218,
- SpvOpEndPrimitive = 219,
- SpvOpEmitStreamVertex = 220,
- SpvOpEndStreamPrimitive = 221,
- SpvOpControlBarrier = 224,
- SpvOpMemoryBarrier = 225,
- SpvOpAtomicLoad = 227,
- SpvOpAtomicStore = 228,
- SpvOpAtomicExchange = 229,
- SpvOpAtomicCompareExchange = 230,
- SpvOpAtomicCompareExchangeWeak = 231,
- SpvOpAtomicIIncrement = 232,
- SpvOpAtomicIDecrement = 233,
- SpvOpAtomicIAdd = 234,
- SpvOpAtomicISub = 235,
- SpvOpAtomicSMin = 236,
- SpvOpAtomicUMin = 237,
- SpvOpAtomicSMax = 238,
- SpvOpAtomicUMax = 239,
- SpvOpAtomicAnd = 240,
- SpvOpAtomicOr = 241,
- SpvOpAtomicXor = 242,
- SpvOpPhi = 245,
- SpvOpLoopMerge = 246,
- SpvOpSelectionMerge = 247,
- SpvOpLabel = 248,
- SpvOpBranch = 249,
- SpvOpBranchConditional = 250,
- SpvOpSwitch = 251,
- SpvOpKill = 252,
- SpvOpReturn = 253,
- SpvOpReturnValue = 254,
- SpvOpUnreachable = 255,
- SpvOpLifetimeStart = 256,
- SpvOpLifetimeStop = 257,
- SpvOpGroupAsyncCopy = 259,
- SpvOpGroupWaitEvents = 260,
- SpvOpGroupAll = 261,
- SpvOpGroupAny = 262,
- SpvOpGroupBroadcast = 263,
- SpvOpGroupIAdd = 264,
- SpvOpGroupFAdd = 265,
- SpvOpGroupFMin = 266,
- SpvOpGroupUMin = 267,
- SpvOpGroupSMin = 268,
- SpvOpGroupFMax = 269,
- SpvOpGroupUMax = 270,
- SpvOpGroupSMax = 271,
- SpvOpReadPipe = 274,
- SpvOpWritePipe = 275,
- SpvOpReservedReadPipe = 276,
- SpvOpReservedWritePipe = 277,
- SpvOpReserveReadPipePackets = 278,
- SpvOpReserveWritePipePackets = 279,
- SpvOpCommitReadPipe = 280,
- SpvOpCommitWritePipe = 281,
- SpvOpIsValidReserveId = 282,
- SpvOpGetNumPipePackets = 283,
- SpvOpGetMaxPipePackets = 284,
- SpvOpGroupReserveReadPipePackets = 285,
- SpvOpGroupReserveWritePipePackets = 286,
- SpvOpGroupCommitReadPipe = 287,
- SpvOpGroupCommitWritePipe = 288,
- SpvOpEnqueueMarker = 291,
- SpvOpEnqueueKernel = 292,
- SpvOpGetKernelNDrangeSubGroupCount = 293,
- SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
- SpvOpGetKernelWorkGroupSize = 295,
- SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
- SpvOpRetainEvent = 297,
- SpvOpReleaseEvent = 298,
- SpvOpCreateUserEvent = 299,
- SpvOpIsValidEvent = 300,
- SpvOpSetUserEventStatus = 301,
- SpvOpCaptureEventProfilingInfo = 302,
- SpvOpGetDefaultQueue = 303,
- SpvOpBuildNDRange = 304,
- SpvOpImageSparseSampleImplicitLod = 305,
- SpvOpImageSparseSampleExplicitLod = 306,
- SpvOpImageSparseSampleDrefImplicitLod = 307,
- SpvOpImageSparseSampleDrefExplicitLod = 308,
- SpvOpImageSparseSampleProjImplicitLod = 309,
- SpvOpImageSparseSampleProjExplicitLod = 310,
- SpvOpImageSparseSampleProjDrefImplicitLod = 311,
- SpvOpImageSparseSampleProjDrefExplicitLod = 312,
- SpvOpImageSparseFetch = 313,
- SpvOpImageSparseGather = 314,
- SpvOpImageSparseDrefGather = 315,
- SpvOpImageSparseTexelsResident = 316,
- SpvOpNoLine = 317,
- SpvOpAtomicFlagTestAndSet = 318,
- SpvOpAtomicFlagClear = 319,
- SpvOpImageSparseRead = 320,
- SpvOpSizeOf = 321,
- SpvOpTypePipeStorage = 322,
- SpvOpConstantPipeStorage = 323,
- SpvOpCreatePipeFromPipeStorage = 324,
- SpvOpGetKernelLocalSizeForSubgroupCount = 325,
- SpvOpGetKernelMaxNumSubgroups = 326,
- SpvOpTypeNamedBarrier = 327,
- SpvOpNamedBarrierInitialize = 328,
- SpvOpMemoryNamedBarrier = 329,
- SpvOpModuleProcessed = 330,
- SpvOpExecutionModeId = 331,
- SpvOpDecorateId = 332,
- SpvOpGroupNonUniformElect = 333,
- SpvOpGroupNonUniformAll = 334,
- SpvOpGroupNonUniformAny = 335,
- SpvOpGroupNonUniformAllEqual = 336,
- SpvOpGroupNonUniformBroadcast = 337,
- SpvOpGroupNonUniformBroadcastFirst = 338,
- SpvOpGroupNonUniformBallot = 339,
- SpvOpGroupNonUniformInverseBallot = 340,
- SpvOpGroupNonUniformBallotBitExtract = 341,
- SpvOpGroupNonUniformBallotBitCount = 342,
- SpvOpGroupNonUniformBallotFindLSB = 343,
- SpvOpGroupNonUniformBallotFindMSB = 344,
- SpvOpGroupNonUniformShuffle = 345,
- SpvOpGroupNonUniformShuffleXor = 346,
- SpvOpGroupNonUniformShuffleUp = 347,
- SpvOpGroupNonUniformShuffleDown = 348,
- SpvOpGroupNonUniformIAdd = 349,
- SpvOpGroupNonUniformFAdd = 350,
- SpvOpGroupNonUniformIMul = 351,
- SpvOpGroupNonUniformFMul = 352,
- SpvOpGroupNonUniformSMin = 353,
- SpvOpGroupNonUniformUMin = 354,
- SpvOpGroupNonUniformFMin = 355,
- SpvOpGroupNonUniformSMax = 356,
- SpvOpGroupNonUniformUMax = 357,
- SpvOpGroupNonUniformFMax = 358,
- SpvOpGroupNonUniformBitwiseAnd = 359,
- SpvOpGroupNonUniformBitwiseOr = 360,
- SpvOpGroupNonUniformBitwiseXor = 361,
- SpvOpGroupNonUniformLogicalAnd = 362,
- SpvOpGroupNonUniformLogicalOr = 363,
- SpvOpGroupNonUniformLogicalXor = 364,
- SpvOpGroupNonUniformQuadBroadcast = 365,
- SpvOpGroupNonUniformQuadSwap = 366,
- };
- static const int kKnownOpsCount = SpvOpGroupNonUniformQuadSwap+1;
- static const char* kSpirvOpNames[] =
- {
- "Nop",
- "Undef",
- "SourceContinued",
- "Source",
- "SourceExtension",
- "Name",
- "MemberName",
- "String",
- "Line",
- "#9",
- "Extension",
- "ExtInstImport",
- "ExtInst",
- "VectorShuffleCompact",
- "MemoryModel",
- "EntryPoint",
- "ExecutionMode",
- "Capability",
- "#18",
- "TypeVoid",
- "TypeBool",
- "TypeInt",
- "TypeFloat",
- "TypeVector",
- "TypeMatrix",
- "TypeImage",
- "TypeSampler",
- "TypeSampledImage",
- "TypeArray",
- "TypeRuntimeArray",
- "TypeStruct",
- "TypeOpaque",
- "TypePointer",
- "TypeFunction",
- "TypeEvent",
- "TypeDeviceEvent",
- "TypeReserveId",
- "TypeQueue",
- "TypePipe",
- "TypeForwardPointer",
- "#40",
- "ConstantTrue",
- "ConstantFalse",
- "Constant",
- "ConstantComposite",
- "ConstantSampler",
- "ConstantNull",
- "#47",
- "SpecConstantTrue",
- "SpecConstantFalse",
- "SpecConstant",
- "SpecConstantComposite",
- "SpecConstantOp",
- "#53",
- "Function",
- "FunctionParameter",
- "FunctionEnd",
- "FunctionCall",
- "#58",
- "Variable",
- "ImageTexelPointer",
- "Load",
- "Store",
- "CopyMemory",
- "CopyMemorySized",
- "AccessChain",
- "InBoundsAccessChain",
- "PtrAccessChain",
- "ArrayLength",
- "GenericPtrMemSemantics",
- "InBoundsPtrAccessChain",
- "Decorate",
- "MemberDecorate",
- "DecorationGroup",
- "GroupDecorate",
- "GroupMemberDecorate",
- "#76",
- "VectorExtractDynamic",
- "VectorInsertDynamic",
- "VectorShuffle",
- "CompositeConstruct",
- "CompositeExtract",
- "CompositeInsert",
- "CopyObject",
- "Transpose",
- "#85",
- "SampledImage",
- "ImageSampleImplicitLod",
- "ImageSampleExplicitLod",
- "ImageSampleDrefImplicitLod",
- "ImageSampleDrefExplicitLod",
- "ImageSampleProjImplicitLod",
- "ImageSampleProjExplicitLod",
- "ImageSampleProjDrefImplicitLod",
- "ImageSampleProjDrefExplicitLod",
- "ImageFetch",
- "ImageGather",
- "ImageDrefGather",
- "ImageRead",
- "ImageWrite",
- "Image",
- "ImageQueryFormat",
- "ImageQueryOrder",
- "ImageQuerySizeLod",
- "ImageQuerySize",
- "ImageQueryLod",
- "ImageQueryLevels",
- "ImageQuerySamples",
- "#108",
- "ConvertFToU",
- "ConvertFToS",
- "ConvertSToF",
- "ConvertUToF",
- "UConvert",
- "SConvert",
- "FConvert",
- "QuantizeToF16",
- "ConvertPtrToU",
- "SatConvertSToU",
- "SatConvertUToS",
- "ConvertUToPtr",
- "PtrCastToGeneric",
- "GenericCastToPtr",
- "GenericCastToPtrExplicit",
- "Bitcast",
- "#125",
- "SNegate",
- "FNegate",
- "IAdd",
- "FAdd",
- "ISub",
- "FSub",
- "IMul",
- "FMul",
- "UDiv",
- "SDiv",
- "FDiv",
- "UMod",
- "SRem",
- "SMod",
- "FRem",
- "FMod",
- "VectorTimesScalar",
- "MatrixTimesScalar",
- "VectorTimesMatrix",
- "MatrixTimesVector",
- "MatrixTimesMatrix",
- "OuterProduct",
- "Dot",
- "IAddCarry",
- "ISubBorrow",
- "UMulExtended",
- "SMulExtended",
- "#153",
- "Any",
- "All",
- "IsNan",
- "IsInf",
- "IsFinite",
- "IsNormal",
- "SignBitSet",
- "LessOrGreater",
- "Ordered",
- "Unordered",
- "LogicalEqual",
- "LogicalNotEqual",
- "LogicalOr",
- "LogicalAnd",
- "LogicalNot",
- "Select",
- "IEqual",
- "INotEqual",
- "UGreaterThan",
- "SGreaterThan",
- "UGreaterThanEqual",
- "SGreaterThanEqual",
- "ULessThan",
- "SLessThan",
- "ULessThanEqual",
- "SLessThanEqual",
- "FOrdEqual",
- "FUnordEqual",
- "FOrdNotEqual",
- "FUnordNotEqual",
- "FOrdLessThan",
- "FUnordLessThan",
- "FOrdGreaterThan",
- "FUnordGreaterThan",
- "FOrdLessThanEqual",
- "FUnordLessThanEqual",
- "FOrdGreaterThanEqual",
- "FUnordGreaterThanEqual",
- "#192",
- "#193",
- "ShiftRightLogical",
- "ShiftRightArithmetic",
- "ShiftLeftLogical",
- "BitwiseOr",
- "BitwiseXor",
- "BitwiseAnd",
- "Not",
- "BitFieldInsert",
- "BitFieldSExtract",
- "BitFieldUExtract",
- "BitReverse",
- "BitCount",
- "#206",
- "DPdx",
- "DPdy",
- "Fwidth",
- "DPdxFine",
- "DPdyFine",
- "FwidthFine",
- "DPdxCoarse",
- "DPdyCoarse",
- "FwidthCoarse",
- "#216",
- "#217",
- "EmitVertex",
- "EndPrimitive",
- "EmitStreamVertex",
- "EndStreamPrimitive",
- "#222",
- "#223",
- "ControlBarrier",
- "MemoryBarrier",
- "#226",
- "AtomicLoad",
- "AtomicStore",
- "AtomicExchange",
- "AtomicCompareExchange",
- "AtomicCompareExchangeWeak",
- "AtomicIIncrement",
- "AtomicIDecrement",
- "AtomicIAdd",
- "AtomicISub",
- "AtomicSMin",
- "AtomicUMin",
- "AtomicSMax",
- "AtomicUMax",
- "AtomicAnd",
- "AtomicOr",
- "AtomicXor",
- "#243",
- "#244",
- "Phi",
- "LoopMerge",
- "SelectionMerge",
- "Label",
- "Branch",
- "BranchConditional",
- "Switch",
- "Kill",
- "Return",
- "ReturnValue",
- "Unreachable",
- "LifetimeStart",
- "LifetimeStop",
- "#258",
- "GroupAsyncCopy",
- "GroupWaitEvents",
- "GroupAll",
- "GroupAny",
- "GroupBroadcast",
- "GroupIAdd",
- "GroupFAdd",
- "GroupFMin",
- "GroupUMin",
- "GroupSMin",
- "GroupFMax",
- "GroupUMax",
- "GroupSMax",
- "#272",
- "#273",
- "ReadPipe",
- "WritePipe",
- "ReservedReadPipe",
- "ReservedWritePipe",
- "ReserveReadPipePackets",
- "ReserveWritePipePackets",
- "CommitReadPipe",
- "CommitWritePipe",
- "IsValidReserveId",
- "GetNumPipePackets",
- "GetMaxPipePackets",
- "GroupReserveReadPipePackets",
- "GroupReserveWritePipePackets",
- "GroupCommitReadPipe",
- "GroupCommitWritePipe",
- "#289",
- "#290",
- "EnqueueMarker",
- "EnqueueKernel",
- "GetKernelNDrangeSubGroupCount",
- "GetKernelNDrangeMaxSubGroupSize",
- "GetKernelWorkGroupSize",
- "GetKernelPreferredWorkGroupSizeMultiple",
- "RetainEvent",
- "ReleaseEvent",
- "CreateUserEvent",
- "IsValidEvent",
- "SetUserEventStatus",
- "CaptureEventProfilingInfo",
- "GetDefaultQueue",
- "BuildNDRange",
- "ImageSparseSampleImplicitLod",
- "ImageSparseSampleExplicitLod",
- "ImageSparseSampleDrefImplicitLod",
- "ImageSparseSampleDrefExplicitLod",
- "ImageSparseSampleProjImplicitLod",
- "ImageSparseSampleProjExplicitLod",
- "ImageSparseSampleProjDrefImplicitLod",
- "ImageSparseSampleProjDrefExplicitLod",
- "ImageSparseFetch",
- "ImageSparseGather",
- "ImageSparseDrefGather",
- "ImageSparseTexelsResident",
- "NoLine",
- "AtomicFlagTestAndSet",
- "AtomicFlagClear",
- "ImageSparseRead",
- "SizeOf",
- "TypePipeStorage",
- "ConstantPipeStorage",
- "CreatePipeFromPipeStorage",
- "GetKernelLocalSizeForSubgroupCount",
- "GetKernelMaxNumSubgroups",
- "TypeNamedBarrier",
- "NamedBarrierInitialize",
- "MemoryNamedBarrier",
- "ModuleProcessed",
- "ExecutionModeId",
- "DecorateId",
- "GroupNonUniformElect",
- "GroupNonUniformAll",
- "GroupNonUniformAny",
- "GroupNonUniformAllEqual",
- "GroupNonUniformBroadcast",
- "GroupNonUniformBroadcastFirst",
- "GroupNonUniformBallot",
- "GroupNonUniformInverseBallot",
- "GroupNonUniformBallotBitExtract",
- "GroupNonUniformBallotBitCount",
- "GroupNonUniformBallotFindLSB",
- "GroupNonUniformBallotFindMSB",
- "GroupNonUniformShuffle",
- "GroupNonUniformShuffleXor",
- "GroupNonUniformShuffleUp",
- "GroupNonUniformShuffleDown",
- "GroupNonUniformIAdd",
- "GroupNonUniformFAdd",
- "GroupNonUniformIMul",
- "GroupNonUniformFMul",
- "GroupNonUniformSMin",
- "GroupNonUniformUMin",
- "GroupNonUniformFMin",
- "GroupNonUniformSMax",
- "GroupNonUniformUMax",
- "GroupNonUniformFMax",
- "GroupNonUniformBitwiseAnd",
- "GroupNonUniformBitwiseOr",
- "GroupNonUniformBitwiseXor",
- "GroupNonUniformLogicalAnd",
- "GroupNonUniformLogicalOr",
- "GroupNonUniformLogicalXor",
- "GroupNonUniformQuadBroadcast",
- "GroupNonUniformQuadSwap",
- };
- static_assert(_SMOLV_ARRAY_SIZE(kSpirvOpNames) == kKnownOpsCount, "kSpirvOpNames table mismatch with known SpvOps");
- struct OpData
- {
- uint8_t hasResult; // does it have result ID?
- uint8_t hasType; // does it have type ID?
- uint8_t deltaFromResult; // How many words after (optional) type+result to write out as deltas from result?
- uint8_t varrest; // should the rest of words be written in varint encoding?
- };
- static const OpData kSpirvOpData[] =
- {
- {0, 0, 0, 0}, // Nop
- {1, 1, 0, 0}, // Undef
- {0, 0, 0, 0}, // SourceContinued
- {0, 0, 0, 1}, // Source
- {0, 0, 0, 0}, // SourceExtension
- {0, 0, 0, 0}, // Name
- {0, 0, 0, 0}, // MemberName
- {0, 0, 0, 0}, // String
- {0, 0, 0, 1}, // Line
- {1, 1, 0, 0}, // #9
- {0, 0, 0, 0}, // Extension
- {1, 0, 0, 0}, // ExtInstImport
- {1, 1, 0, 1}, // ExtInst
- {1, 1, 2, 1}, // VectorShuffleCompact - new in SMOLV
- {0, 0, 0, 1}, // MemoryModel
- {0, 0, 0, 1}, // EntryPoint
- {0, 0, 0, 1}, // ExecutionMode
- {0, 0, 0, 1}, // Capability
- {1, 1, 0, 0}, // #18
- {1, 0, 0, 1}, // TypeVoid
- {1, 0, 0, 1}, // TypeBool
- {1, 0, 0, 1}, // TypeInt
- {1, 0, 0, 1}, // TypeFloat
- {1, 0, 0, 1}, // TypeVector
- {1, 0, 0, 1}, // TypeMatrix
- {1, 0, 0, 1}, // TypeImage
- {1, 0, 0, 1}, // TypeSampler
- {1, 0, 0, 1}, // TypeSampledImage
- {1, 0, 0, 1}, // TypeArray
- {1, 0, 0, 1}, // TypeRuntimeArray
- {1, 0, 0, 1}, // TypeStruct
- {1, 0, 0, 1}, // TypeOpaque
- {1, 0, 0, 1}, // TypePointer
- {1, 0, 0, 1}, // TypeFunction
- {1, 0, 0, 1}, // TypeEvent
- {1, 0, 0, 1}, // TypeDeviceEvent
- {1, 0, 0, 1}, // TypeReserveId
- {1, 0, 0, 1}, // TypeQueue
- {1, 0, 0, 1}, // TypePipe
- {0, 0, 0, 1}, // TypeForwardPointer
- {1, 1, 0, 0}, // #40
- {1, 1, 0, 0}, // ConstantTrue
- {1, 1, 0, 0}, // ConstantFalse
- {1, 1, 0, 0}, // Constant
- {1, 1, 9, 0}, // ConstantComposite
- {1, 1, 0, 1}, // ConstantSampler
- {1, 1, 0, 0}, // ConstantNull
- {1, 1, 0, 0}, // #47
- {1, 1, 0, 0}, // SpecConstantTrue
- {1, 1, 0, 0}, // SpecConstantFalse
- {1, 1, 0, 0}, // SpecConstant
- {1, 1, 9, 0}, // SpecConstantComposite
- {1, 1, 0, 0}, // SpecConstantOp
- {1, 1, 0, 0}, // #53
- {1, 1, 0, 1}, // Function
- {1, 1, 0, 0}, // FunctionParameter
- {0, 0, 0, 0}, // FunctionEnd
- {1, 1, 9, 0}, // FunctionCall
- {1, 1, 0, 0}, // #58
- {1, 1, 0, 1}, // Variable
- {1, 1, 0, 0}, // ImageTexelPointer
- {1, 1, 1, 1}, // Load
- {0, 0, 2, 1}, // Store
- {0, 0, 0, 0}, // CopyMemory
- {0, 0, 0, 0}, // CopyMemorySized
- {1, 1, 0, 1}, // AccessChain
- {1, 1, 0, 0}, // InBoundsAccessChain
- {1, 1, 0, 0}, // PtrAccessChain
- {1, 1, 0, 0}, // ArrayLength
- {1, 1, 0, 0}, // GenericPtrMemSemantics
- {1, 1, 0, 0}, // InBoundsPtrAccessChain
- {0, 0, 0, 1}, // Decorate
- {0, 0, 0, 1}, // MemberDecorate
- {1, 0, 0, 0}, // DecorationGroup
- {0, 0, 0, 0}, // GroupDecorate
- {0, 0, 0, 0}, // GroupMemberDecorate
- {1, 1, 0, 0}, // #76
- {1, 1, 1, 1}, // VectorExtractDynamic
- {1, 1, 2, 1}, // VectorInsertDynamic
- {1, 1, 2, 1}, // VectorShuffle
- {1, 1, 9, 0}, // CompositeConstruct
- {1, 1, 1, 1}, // CompositeExtract
- {1, 1, 2, 1}, // CompositeInsert
- {1, 1, 1, 0}, // CopyObject
- {1, 1, 0, 0}, // Transpose
- {1, 1, 0, 0}, // #85
- {1, 1, 0, 0}, // SampledImage
- {1, 1, 2, 1}, // ImageSampleImplicitLod
- {1, 1, 2, 1}, // ImageSampleExplicitLod
- {1, 1, 3, 1}, // ImageSampleDrefImplicitLod
- {1, 1, 3, 1}, // ImageSampleDrefExplicitLod
- {1, 1, 2, 1}, // ImageSampleProjImplicitLod
- {1, 1, 2, 1}, // ImageSampleProjExplicitLod
- {1, 1, 3, 1}, // ImageSampleProjDrefImplicitLod
- {1, 1, 3, 1}, // ImageSampleProjDrefExplicitLod
- {1, 1, 2, 1}, // ImageFetch
- {1, 1, 3, 1}, // ImageGather
- {1, 1, 3, 1}, // ImageDrefGather
- {1, 1, 2, 1}, // ImageRead
- {0, 0, 3, 1}, // ImageWrite
- {1, 1, 1, 0}, // Image
- {1, 1, 1, 0}, // ImageQueryFormat
- {1, 1, 1, 0}, // ImageQueryOrder
- {1, 1, 2, 0}, // ImageQuerySizeLod
- {1, 1, 1, 0}, // ImageQuerySize
- {1, 1, 2, 0}, // ImageQueryLod
- {1, 1, 1, 0}, // ImageQueryLevels
- {1, 1, 1, 0}, // ImageQuerySamples
- {1, 1, 0, 0}, // #108
- {1, 1, 1, 0}, // ConvertFToU
- {1, 1, 1, 0}, // ConvertFToS
- {1, 1, 1, 0}, // ConvertSToF
- {1, 1, 1, 0}, // ConvertUToF
- {1, 1, 1, 0}, // UConvert
- {1, 1, 1, 0}, // SConvert
- {1, 1, 1, 0}, // FConvert
- {1, 1, 1, 0}, // QuantizeToF16
- {1, 1, 1, 0}, // ConvertPtrToU
- {1, 1, 1, 0}, // SatConvertSToU
- {1, 1, 1, 0}, // SatConvertUToS
- {1, 1, 1, 0}, // ConvertUToPtr
- {1, 1, 1, 0}, // PtrCastToGeneric
- {1, 1, 1, 0}, // GenericCastToPtr
- {1, 1, 1, 1}, // GenericCastToPtrExplicit
- {1, 1, 1, 0}, // Bitcast
- {1, 1, 0, 0}, // #125
- {1, 1, 1, 0}, // SNegate
- {1, 1, 1, 0}, // FNegate
- {1, 1, 2, 0}, // IAdd
- {1, 1, 2, 0}, // FAdd
- {1, 1, 2, 0}, // ISub
- {1, 1, 2, 0}, // FSub
- {1, 1, 2, 0}, // IMul
- {1, 1, 2, 0}, // FMul
- {1, 1, 2, 0}, // UDiv
- {1, 1, 2, 0}, // SDiv
- {1, 1, 2, 0}, // FDiv
- {1, 1, 2, 0}, // UMod
- {1, 1, 2, 0}, // SRem
- {1, 1, 2, 0}, // SMod
- {1, 1, 2, 0}, // FRem
- {1, 1, 2, 0}, // FMod
- {1, 1, 2, 0}, // VectorTimesScalar
- {1, 1, 2, 0}, // MatrixTimesScalar
- {1, 1, 2, 0}, // VectorTimesMatrix
- {1, 1, 2, 0}, // MatrixTimesVector
- {1, 1, 2, 0}, // MatrixTimesMatrix
- {1, 1, 2, 0}, // OuterProduct
- {1, 1, 2, 0}, // Dot
- {1, 1, 2, 0}, // IAddCarry
- {1, 1, 2, 0}, // ISubBorrow
- {1, 1, 2, 0}, // UMulExtended
- {1, 1, 2, 0}, // SMulExtended
- {1, 1, 0, 0}, // #153
- {1, 1, 1, 0}, // Any
- {1, 1, 1, 0}, // All
- {1, 1, 1, 0}, // IsNan
- {1, 1, 1, 0}, // IsInf
- {1, 1, 1, 0}, // IsFinite
- {1, 1, 1, 0}, // IsNormal
- {1, 1, 1, 0}, // SignBitSet
- {1, 1, 2, 0}, // LessOrGreater
- {1, 1, 2, 0}, // Ordered
- {1, 1, 2, 0}, // Unordered
- {1, 1, 2, 0}, // LogicalEqual
- {1, 1, 2, 0}, // LogicalNotEqual
- {1, 1, 2, 0}, // LogicalOr
- {1, 1, 2, 0}, // LogicalAnd
- {1, 1, 1, 0}, // LogicalNot
- {1, 1, 3, 0}, // Select
- {1, 1, 2, 0}, // IEqual
- {1, 1, 2, 0}, // INotEqual
- {1, 1, 2, 0}, // UGreaterThan
- {1, 1, 2, 0}, // SGreaterThan
- {1, 1, 2, 0}, // UGreaterThanEqual
- {1, 1, 2, 0}, // SGreaterThanEqual
- {1, 1, 2, 0}, // ULessThan
- {1, 1, 2, 0}, // SLessThan
- {1, 1, 2, 0}, // ULessThanEqual
- {1, 1, 2, 0}, // SLessThanEqual
- {1, 1, 2, 0}, // FOrdEqual
- {1, 1, 2, 0}, // FUnordEqual
- {1, 1, 2, 0}, // FOrdNotEqual
- {1, 1, 2, 0}, // FUnordNotEqual
- {1, 1, 2, 0}, // FOrdLessThan
- {1, 1, 2, 0}, // FUnordLessThan
- {1, 1, 2, 0}, // FOrdGreaterThan
- {1, 1, 2, 0}, // FUnordGreaterThan
- {1, 1, 2, 0}, // FOrdLessThanEqual
- {1, 1, 2, 0}, // FUnordLessThanEqual
- {1, 1, 2, 0}, // FOrdGreaterThanEqual
- {1, 1, 2, 0}, // FUnordGreaterThanEqual
- {1, 1, 0, 0}, // #192
- {1, 1, 0, 0}, // #193
- {1, 1, 2, 0}, // ShiftRightLogical
- {1, 1, 2, 0}, // ShiftRightArithmetic
- {1, 1, 2, 0}, // ShiftLeftLogical
- {1, 1, 2, 0}, // BitwiseOr
- {1, 1, 2, 0}, // BitwiseXor
- {1, 1, 2, 0}, // BitwiseAnd
- {1, 1, 1, 0}, // Not
- {1, 1, 4, 0}, // BitFieldInsert
- {1, 1, 3, 0}, // BitFieldSExtract
- {1, 1, 3, 0}, // BitFieldUExtract
- {1, 1, 1, 0}, // BitReverse
- {1, 1, 1, 0}, // BitCount
- {1, 1, 0, 0}, // #206
- {1, 1, 0, 0}, // DPdx
- {1, 1, 0, 0}, // DPdy
- {1, 1, 0, 0}, // Fwidth
- {1, 1, 0, 0}, // DPdxFine
- {1, 1, 0, 0}, // DPdyFine
- {1, 1, 0, 0}, // FwidthFine
- {1, 1, 0, 0}, // DPdxCoarse
- {1, 1, 0, 0}, // DPdyCoarse
- {1, 1, 0, 0}, // FwidthCoarse
- {1, 1, 0, 0}, // #216
- {1, 1, 0, 0}, // #217
- {0, 0, 0, 0}, // EmitVertex
- {0, 0, 0, 0}, // EndPrimitive
- {0, 0, 0, 0}, // EmitStreamVertex
- {0, 0, 0, 0}, // EndStreamPrimitive
- {1, 1, 0, 0}, // #222
- {1, 1, 0, 0}, // #223
- {0, 0, 3, 0}, // ControlBarrier
- {0, 0, 2, 0}, // MemoryBarrier
- {1, 1, 0, 0}, // #226
- {1, 1, 0, 0}, // AtomicLoad
- {0, 0, 0, 0}, // AtomicStore
- {1, 1, 0, 0}, // AtomicExchange
- {1, 1, 0, 0}, // AtomicCompareExchange
- {1, 1, 0, 0}, // AtomicCompareExchangeWeak
- {1, 1, 0, 0}, // AtomicIIncrement
- {1, 1, 0, 0}, // AtomicIDecrement
- {1, 1, 0, 0}, // AtomicIAdd
- {1, 1, 0, 0}, // AtomicISub
- {1, 1, 0, 0}, // AtomicSMin
- {1, 1, 0, 0}, // AtomicUMin
- {1, 1, 0, 0}, // AtomicSMax
- {1, 1, 0, 0}, // AtomicUMax
- {1, 1, 0, 0}, // AtomicAnd
- {1, 1, 0, 0}, // AtomicOr
- {1, 1, 0, 0}, // AtomicXor
- {1, 1, 0, 0}, // #243
- {1, 1, 0, 0}, // #244
- {1, 1, 0, 0}, // Phi
- {0, 0, 2, 1}, // LoopMerge
- {0, 0, 1, 1}, // SelectionMerge
- {1, 0, 0, 0}, // Label
- {0, 0, 1, 0}, // Branch
- {0, 0, 3, 1}, // BranchConditional
- {0, 0, 0, 0}, // Switch
- {0, 0, 0, 0}, // Kill
- {0, 0, 0, 0}, // Return
- {0, 0, 0, 0}, // ReturnValue
- {0, 0, 0, 0}, // Unreachable
- {0, 0, 0, 0}, // LifetimeStart
- {0, 0, 0, 0}, // LifetimeStop
- {1, 1, 0, 0}, // #258
- {1, 1, 0, 0}, // GroupAsyncCopy
- {0, 0, 0, 0}, // GroupWaitEvents
- {1, 1, 0, 0}, // GroupAll
- {1, 1, 0, 0}, // GroupAny
- {1, 1, 0, 0}, // GroupBroadcast
- {1, 1, 0, 0}, // GroupIAdd
- {1, 1, 0, 0}, // GroupFAdd
- {1, 1, 0, 0}, // GroupFMin
- {1, 1, 0, 0}, // GroupUMin
- {1, 1, 0, 0}, // GroupSMin
- {1, 1, 0, 0}, // GroupFMax
- {1, 1, 0, 0}, // GroupUMax
- {1, 1, 0, 0}, // GroupSMax
- {1, 1, 0, 0}, // #272
- {1, 1, 0, 0}, // #273
- {1, 1, 0, 0}, // ReadPipe
- {1, 1, 0, 0}, // WritePipe
- {1, 1, 0, 0}, // ReservedReadPipe
- {1, 1, 0, 0}, // ReservedWritePipe
- {1, 1, 0, 0}, // ReserveReadPipePackets
- {1, 1, 0, 0}, // ReserveWritePipePackets
- {0, 0, 0, 0}, // CommitReadPipe
- {0, 0, 0, 0}, // CommitWritePipe
- {1, 1, 0, 0}, // IsValidReserveId
- {1, 1, 0, 0}, // GetNumPipePackets
- {1, 1, 0, 0}, // GetMaxPipePackets
- {1, 1, 0, 0}, // GroupReserveReadPipePackets
- {1, 1, 0, 0}, // GroupReserveWritePipePackets
- {0, 0, 0, 0}, // GroupCommitReadPipe
- {0, 0, 0, 0}, // GroupCommitWritePipe
- {1, 1, 0, 0}, // #289
- {1, 1, 0, 0}, // #290
- {1, 1, 0, 0}, // EnqueueMarker
- {1, 1, 0, 0}, // EnqueueKernel
- {1, 1, 0, 0}, // GetKernelNDrangeSubGroupCount
- {1, 1, 0, 0}, // GetKernelNDrangeMaxSubGroupSize
- {1, 1, 0, 0}, // GetKernelWorkGroupSize
- {1, 1, 0, 0}, // GetKernelPreferredWorkGroupSizeMultiple
- {0, 0, 0, 0}, // RetainEvent
- {0, 0, 0, 0}, // ReleaseEvent
- {1, 1, 0, 0}, // CreateUserEvent
- {1, 1, 0, 0}, // IsValidEvent
- {0, 0, 0, 0}, // SetUserEventStatus
- {0, 0, 0, 0}, // CaptureEventProfilingInfo
- {1, 1, 0, 0}, // GetDefaultQueue
- {1, 1, 0, 0}, // BuildNDRange
- {1, 1, 2, 1}, // ImageSparseSampleImplicitLod
- {1, 1, 2, 1}, // ImageSparseSampleExplicitLod
- {1, 1, 3, 1}, // ImageSparseSampleDrefImplicitLod
- {1, 1, 3, 1}, // ImageSparseSampleDrefExplicitLod
- {1, 1, 2, 1}, // ImageSparseSampleProjImplicitLod
- {1, 1, 2, 1}, // ImageSparseSampleProjExplicitLod
- {1, 1, 3, 1}, // ImageSparseSampleProjDrefImplicitLod
- {1, 1, 3, 1}, // ImageSparseSampleProjDrefExplicitLod
- {1, 1, 2, 1}, // ImageSparseFetch
- {1, 1, 3, 1}, // ImageSparseGather
- {1, 1, 3, 1}, // ImageSparseDrefGather
- {1, 1, 1, 0}, // ImageSparseTexelsResident
- {0, 0, 0, 0}, // NoLine
- {1, 1, 0, 0}, // AtomicFlagTestAndSet
- {0, 0, 0, 0}, // AtomicFlagClear
- {1, 1, 0, 0}, // ImageSparseRead
- {1, 1, 0, 0}, // SizeOf
- {1, 1, 0, 0}, // TypePipeStorage
- {1, 1, 0, 0}, // ConstantPipeStorage
- {1, 1, 0, 0}, // CreatePipeFromPipeStorage
- {1, 1, 0, 0}, // GetKernelLocalSizeForSubgroupCount
- {1, 1, 0, 0}, // GetKernelMaxNumSubgroups
- {1, 1, 0, 0}, // TypeNamedBarrier
- {1, 1, 0, 1}, // NamedBarrierInitialize
- {0, 0, 2, 1}, // MemoryNamedBarrier
- {1, 1, 0, 0}, // ModuleProcessed
- {0, 0, 0, 1}, // ExecutionModeId
- {0, 0, 0, 1}, // DecorateId
- {1, 1, 1, 1}, // GroupNonUniformElect
- {1, 1, 1, 1}, // GroupNonUniformAll
- {1, 1, 1, 1}, // GroupNonUniformAny
- {1, 1, 1, 1}, // GroupNonUniformAllEqual
- {1, 1, 1, 1}, // GroupNonUniformBroadcast
- {1, 1, 1, 1}, // GroupNonUniformBroadcastFirst
- {1, 1, 1, 1}, // GroupNonUniformBallot
- {1, 1, 1, 1}, // GroupNonUniformInverseBallot
- {1, 1, 1, 1}, // GroupNonUniformBallotBitExtract
- {1, 1, 1, 1}, // GroupNonUniformBallotBitCount
- {1, 1, 1, 1}, // GroupNonUniformBallotFindLSB
- {1, 1, 1, 1}, // GroupNonUniformBallotFindMSB
- {1, 1, 1, 1}, // GroupNonUniformShuffle
- {1, 1, 1, 1}, // GroupNonUniformShuffleXor
- {1, 1, 1, 1}, // GroupNonUniformShuffleUp
- {1, 1, 1, 1}, // GroupNonUniformShuffleDown
- {1, 1, 1, 1}, // GroupNonUniformIAdd
- {1, 1, 1, 1}, // GroupNonUniformFAdd
- {1, 1, 1, 1}, // GroupNonUniformIMul
- {1, 1, 1, 1}, // GroupNonUniformFMul
- {1, 1, 1, 1}, // GroupNonUniformSMin
- {1, 1, 1, 1}, // GroupNonUniformUMin
- {1, 1, 1, 1}, // GroupNonUniformFMin
- {1, 1, 1, 1}, // GroupNonUniformSMax
- {1, 1, 1, 1}, // GroupNonUniformUMax
- {1, 1, 1, 1}, // GroupNonUniformFMax
- {1, 1, 1, 1}, // GroupNonUniformBitwiseAnd
- {1, 1, 1, 1}, // GroupNonUniformBitwiseOr
- {1, 1, 1, 1}, // GroupNonUniformBitwiseXor
- {1, 1, 1, 1}, // GroupNonUniformLogicalAnd
- {1, 1, 1, 1}, // GroupNonUniformLogicalOr
- {1, 1, 1, 1}, // GroupNonUniformLogicalXor
- {1, 1, 1, 1}, // GroupNonUniformQuadBroadcast
- {1, 1, 1, 1}, // GroupNonUniformQuadSwap
- };
- static_assert(_SMOLV_ARRAY_SIZE(kSpirvOpData) == kKnownOpsCount, "kSpirvOpData table mismatch with known SpvOps");
- // Instruction encoding depends on the table that describes the various SPIR-V opcodes.
- // Whenever we change or expand the table, we need to bump up the SMOL-V version, and make
- // sure that we can still decode files encoded by an older version.
- static int smolv_GetKnownOpsCount(int version)
- {
- if (version == 0)
- return SpvOpModuleProcessed+1;
- if (version == 1) // 2020 February, version 1 added ExecutionModeId..GroupNonUniformQuadSwap
- return SpvOpGroupNonUniformQuadSwap+1;
- return 0;
- }
- static bool smolv_OpHasResult(SpvOp op, int opsCount)
- {
- if (op < 0 || op >= opsCount)
- return false;
- return kSpirvOpData[op].hasResult != 0;
- }
- static bool smolv_OpHasType(SpvOp op, int opsCount)
- {
- if (op < 0 || op >= opsCount)
- return false;
- return kSpirvOpData[op].hasType != 0;
- }
- static int smolv_OpDeltaFromResult(SpvOp op, int opsCount)
- {
- if (op < 0 || op >= opsCount)
- return 0;
- return kSpirvOpData[op].deltaFromResult;
- }
- static bool smolv_OpVarRest(SpvOp op, int opsCount)
- {
- if (op < 0 || op >= opsCount)
- return false;
- return kSpirvOpData[op].varrest != 0;
- }
- static bool smolv_OpDebugInfo(SpvOp op, int opsCount)
- {
- return
- op == SpvOpSourceContinued ||
- op == SpvOpSource ||
- op == SpvOpSourceExtension ||
- op == SpvOpName ||
- op == SpvOpMemberName ||
- op == SpvOpString ||
- op == SpvOpLine ||
- op == SpvOpNoLine ||
- op == SpvOpModuleProcessed;
- }
- static int smolv_DecorationExtraOps(int dec)
- {
- if (dec == 0 || (dec >= 2 && dec <= 5)) // RelaxedPrecision, Block..ColMajor
- return 0;
- if (dec >= 29 && dec <= 37) // Stream..XfbStride
- return 1;
- return -1; // unknown, encode length
- }
- // --------------------------------------------------------------------------------------------
- static bool smolv_CheckGenericHeader(const uint32_t* words, size_t wordCount, uint32_t expectedMagic, uint32_t versionMask)
- {
- if (!words)
- return false;
- if (wordCount < 5)
- return false;
-
- uint32_t headerMagic = words[0];
- if (headerMagic != expectedMagic)
- return false;
- uint32_t headerVersion = words[1] & versionMask;
- if (headerVersion < 0x00010000 || headerVersion > 0x00010500)
- return false; // only support 1.0 through 1.5
-
- return true;
- }
- static const int kSpirVHeaderMagic = 0x07230203;
- static const int kSmolHeaderMagic = 0x534D4F4C; // "SMOL"
- static const int kSmolCurrEncodingVersion = 1;
- static bool smolv_CheckSpirVHeader(const uint32_t* words, size_t wordCount)
- {
- //@TODO: if SPIR-V header magic was reversed, that means the file got written
- // in a "big endian" order. Need to byteswap all words then.
- return smolv_CheckGenericHeader(words, wordCount, kSpirVHeaderMagic, 0xFFFFFFFF);
- }
- static bool smolv_CheckSmolHeader(const uint8_t* bytes, size_t byteCount)
- {
- if (!smolv_CheckGenericHeader((const uint32_t*)bytes, byteCount/4, kSmolHeaderMagic, 0x00FFFFFF))
- return false;
- if (byteCount < 24) // one more word past header to store decoded length
- return false;
- // SMOL-V version
- int smolVersion = ((const uint32_t*)bytes)[1] >> 24;
- if (smolVersion < 0 || smolVersion > kSmolCurrEncodingVersion)
- return false;
- return true;
- }
- static void smolv_Write4(smolv::ByteArray& arr, uint32_t v)
- {
- arr.push_back(v & 0xFF);
- arr.push_back((v >> 8) & 0xFF);
- arr.push_back((v >> 16) & 0xFF);
- arr.push_back(v >> 24);
- }
- static void smolv_Write4(uint8_t*& buf, uint32_t v)
- {
- memcpy(buf, &v, 4);
- buf += 4;
- }
- static bool smolv_Read4(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outv)
- {
- if (data + 4 > dataEnd)
- return false;
- outv = (data[0]) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
- data += 4;
- return true;
- }
- // --------------------------------------------------------------------------------------------
- // Variable-length integer encoding for unsigned integers. In each byte:
- // - highest bit set if more bytes follow, cleared if this is last byte.
- // - other 7 bits are the actual value payload.
- // Takes 1-5 bytes to encode an integer (values between 0 and 127 take one byte, etc.).
- static void smolv_WriteVarint(smolv::ByteArray& arr, uint32_t v)
- {
- while (v > 127)
- {
- arr.push_back((v & 127) | 128);
- v >>= 7;
- }
- arr.push_back(v & 127);
- }
- static bool smolv_ReadVarint(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outVal)
- {
- uint32_t v = 0;
- uint32_t shift = 0;
- while (data < dataEnd)
- {
- uint8_t b = *data;
- v |= (b & 127) << shift;
- shift += 7;
- data++;
- if (!(b & 128))
- break;
- }
- outVal = v;
- return true; //@TODO: report failures
- }
- static uint32_t smolv_ZigEncode(int32_t i)
- {
- return (uint32_t(i) << 1) ^ (i >> 31);
- }
- static int32_t smolv_ZigDecode(uint32_t u)
- {
- return (u & 1) ? ((u >> 1) ^ ~0) : (u >> 1);
- }
- // Remap most common Op codes (Load, Store, Decorate, VectorShuffle etc.) to be in < 16 range, for
- // more compact varint encoding. This basically swaps rarely used op values that are < 16 with the
- // ones that are common.
- static SpvOp smolv_RemapOp(SpvOp op)
- {
- # define _SMOLV_SWAP_OP(op1,op2) if (op==op1) return op2; if (op==op2) return op1
- _SMOLV_SWAP_OP(SpvOpDecorate,SpvOpNop); // 0: 24%
- _SMOLV_SWAP_OP(SpvOpLoad,SpvOpUndef); // 1: 17%
- _SMOLV_SWAP_OP(SpvOpStore,SpvOpSourceContinued); // 2: 9%
- _SMOLV_SWAP_OP(SpvOpAccessChain,SpvOpSource); // 3: 7.2%
- _SMOLV_SWAP_OP(SpvOpVectorShuffle,SpvOpSourceExtension); // 4: 5.0%
- // Name - already small enum value - 5: 4.4%
- // MemberName - already small enum value - 6: 2.9%
- _SMOLV_SWAP_OP(SpvOpMemberDecorate,SpvOpString); // 7: 4.0%
- _SMOLV_SWAP_OP(SpvOpLabel,SpvOpLine); // 8: 0.9%
- _SMOLV_SWAP_OP(SpvOpVariable,(SpvOp)9); // 9: 3.9%
- _SMOLV_SWAP_OP(SpvOpFMul,SpvOpExtension); // 10: 3.9%
- _SMOLV_SWAP_OP(SpvOpFAdd,SpvOpExtInstImport); // 11: 2.5%
- // ExtInst - already small enum value - 12: 1.2%
- // VectorShuffleCompact - already small enum value - used for compact shuffle encoding
- _SMOLV_SWAP_OP(SpvOpTypePointer,SpvOpMemoryModel); // 14: 2.2%
- _SMOLV_SWAP_OP(SpvOpFNegate,SpvOpEntryPoint); // 15: 1.1%
- # undef _SMOLV_SWAP_OP
- return op;
- }
- // For most compact varint encoding of common instructions, the instruction length should come out
- // into 3 bits (be <8). SPIR-V instruction lengths are always at least 1, and for some other
- // instructions they are guaranteed to be some other minimum length. Adjust the length before encoding,
- // and after decoding accordingly.
- static uint32_t smolv_EncodeLen(SpvOp op, uint32_t len)
- {
- len--;
- if (op == SpvOpVectorShuffle) len -= 4;
- if (op == SpvOpVectorShuffleCompact) len -= 4;
- if (op == SpvOpDecorate) len -= 2;
- if (op == SpvOpLoad) len -= 3;
- if (op == SpvOpAccessChain) len -= 3;
- return len;
- }
- static uint32_t smolv_DecodeLen(SpvOp op, uint32_t len)
- {
- len++;
- if (op == SpvOpVectorShuffle) len += 4;
- if (op == SpvOpVectorShuffleCompact) len += 4;
- if (op == SpvOpDecorate) len += 2;
- if (op == SpvOpLoad) len += 3;
- if (op == SpvOpAccessChain) len += 3;
- return len;
- }
- // Shuffling bits of length + opcode to be more compact in varint encoding in typical cases:
- // 0x LLLL OOOO is how SPIR-V encodes it (L=length, O=op), we shuffle into:
- // 0x LLLO OOLO, so that common case (op<16, len<8) is encoded into one byte.
- static bool smolv_WriteLengthOp(smolv::ByteArray& arr, uint32_t len, SpvOp op)
- {
- len = smolv_EncodeLen(op, len);
- // SPIR-V length field is 16 bits; if we get a larger value that means something
- // was wrong, e.g. a vector shuffle instruction with less than 4 words (and our
- // adjustment to common lengths in smolv_EncodeLen wrapped around)
- if (len > 0xFFFF)
- return false;
- op = smolv_RemapOp(op);
- uint32_t oplen = ((len >> 4) << 20) | ((op >> 4) << 8) | ((len & 0xF) << 4) | (op & 0xF);
- smolv_WriteVarint(arr, oplen);
- return true;
- }
- static bool smolv_ReadLengthOp(const uint8_t*& data, const uint8_t* dataEnd, uint32_t& outLen, SpvOp& outOp)
- {
- uint32_t val;
- if (!smolv_ReadVarint(data, dataEnd, val))
- return false;
- outLen = ((val >> 20) << 4) | ((val >> 4) & 0xF);
- outOp = (SpvOp)(((val >> 4) & 0xFFF0) | (val & 0xF));
- outOp = smolv_RemapOp(outOp);
- outLen = smolv_DecodeLen(outOp, outLen);
- return true;
- }
- #define _SMOLV_READ_OP(len, words, op) \
- uint32_t len = words[0] >> 16; \
- if (len < 1) return false; /* malformed instruction, length needs to be at least 1 */ \
- if (words + len > wordsEnd) return false; /* malformed instruction, goes past end of data */ \
- SpvOp op = (SpvOp)(words[0] & 0xFFFF)
- bool smolv::Encode(const void* spirvData, size_t spirvSize, ByteArray& outSmolv, uint32_t flags, StripOpNameFilterFunc stripFilter)
- {
- const size_t wordCount = spirvSize / 4;
- if (wordCount * 4 != spirvSize)
- return false;
- const uint32_t* words = (const uint32_t*)spirvData;
- const uint32_t* wordsEnd = words + wordCount;
- if (!smolv_CheckSpirVHeader(words, wordCount))
- return false;
- // reserve space in output (typical compression is to about 30%; reserve half of input space)
- outSmolv.reserve(outSmolv.size() + spirvSize/2);
- // header (matches SPIR-V one, except different magic)
- smolv_Write4(outSmolv, kSmolHeaderMagic);
- smolv_Write4(outSmolv, (words[1] & 0x00FFFFFF) + (kSmolCurrEncodingVersion<<24)); // SPIR-V version (_XXX) + SMOL-V version (X___)
- smolv_Write4(outSmolv, words[2]); // generator
- smolv_Write4(outSmolv, words[3]); // bound
- smolv_Write4(outSmolv, words[4]); // schema
- const size_t headerSpirvSizeOffset = outSmolv.size(); // size field may get updated later if stripping is enabled
- smolv_Write4(outSmolv, (uint32_t)spirvSize); // space needed to decode (i.e. original SPIR-V size)
- size_t strippedSpirvWordCount = wordCount;
- uint32_t prevResult = 0;
- uint32_t prevDecorate = 0;
-
- const int knownOpsCount = smolv_GetKnownOpsCount(kSmolCurrEncodingVersion);
- words += 5;
- while (words < wordsEnd)
- {
- _SMOLV_READ_OP(instrLen, words, op);
- if ((flags & kEncodeFlagStripDebugInfo) && smolv_OpDebugInfo(op, knownOpsCount))
- {
- if (!stripFilter || op != SpvOpName || !stripFilter(reinterpret_cast<const char*>(&words[2])))
- {
- strippedSpirvWordCount -= instrLen;
- words += instrLen;
- continue;
- }
- }
- // A usual case of vector shuffle, with less than 4 components, each with a value
- // in [0..3] range: encode it in a more compact form, with the swizzle pattern in one byte.
- // Turn this into a VectorShuffleCompact instruction, that takes up unused slot in Ops.
- uint32_t swizzle = 0;
- if (op == SpvOpVectorShuffle && instrLen <= 9)
- {
- uint32_t swz0 = instrLen > 5 ? words[5] : 0;
- uint32_t swz1 = instrLen > 6 ? words[6] : 0;
- uint32_t swz2 = instrLen > 7 ? words[7] : 0;
- uint32_t swz3 = instrLen > 8 ? words[8] : 0;
- if (swz0 < 4 && swz1 < 4 && swz2 < 4 && swz3 < 4)
- {
- op = SpvOpVectorShuffleCompact;
- swizzle = (swz0 << 6) | (swz1 << 4) | (swz2 << 2) | (swz3);
- }
- }
- // length + opcode
- if (!smolv_WriteLengthOp(outSmolv, instrLen, op))
- return false;
- size_t ioffs = 1;
- // write type as varint, if we have it
- if (smolv_OpHasType(op, knownOpsCount))
- {
- if (ioffs >= instrLen)
- return false;
- smolv_WriteVarint(outSmolv, words[ioffs]);
- ioffs++;
- }
- // write result as delta+zig+varint, if we have it
- if (smolv_OpHasResult(op, knownOpsCount))
- {
- if (ioffs >= instrLen)
- return false;
- uint32_t v = words[ioffs];
- smolv_WriteVarint(outSmolv, smolv_ZigEncode(v - prevResult)); // some deltas are negative, use zig
- prevResult = v;
- ioffs++;
- }
- // Decorate & MemberDecorate: IDs relative to previous decorate
- if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
- {
- if (ioffs >= instrLen)
- return false;
- uint32_t v = words[ioffs];
- smolv_WriteVarint(outSmolv, smolv_ZigEncode(v - prevDecorate)); // spirv-remapped deltas often negative, use zig
- prevDecorate = v;
- ioffs++;
- }
- // MemberDecorate special encoding: whole row of MemberDecorate instructions is often referring
- // to the same type and linearly increasing member indices. Scan ahead to see how many we have,
- // and encode whole bunch as one.
- if (op == SpvOpMemberDecorate)
- {
- // scan ahead until we reach end, non-member-decoration or different type
- const uint32_t decorationType = words[ioffs-1];
- const uint32_t* memberWords = words;
- uint32_t prevIndex = 0;
- uint32_t prevOffset = 0;
- // write a byte on how many we have encoded as a bunch
- size_t countLocation = outSmolv.size();
- outSmolv.push_back(0);
- int count = 0;
- while (memberWords < wordsEnd && count < 255)
- {
- _SMOLV_READ_OP(memberLen, memberWords, memberOp);
- if (memberOp != SpvOpMemberDecorate)
- break;
- if (memberLen < 4)
- return false; // invalid input
- if (memberWords[1] != decorationType)
- break;
- // write member index as delta from previous
- uint32_t memberIndex = memberWords[2];
- smolv_WriteVarint(outSmolv, memberIndex - prevIndex);
- prevIndex = memberIndex;
- // decoration (and length if not common/known)
- uint32_t memberDec = memberWords[3];
- smolv_WriteVarint(outSmolv, memberDec);
- const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
- if (knownExtraOps == -1)
- smolv_WriteVarint(outSmolv, memberLen-4);
- else if (unsigned(knownExtraOps) + 4 != memberLen)
- return false; // invalid input
- // Offset decorations are most often linearly increasing, so encode as deltas
- if (memberDec == 35) // Offset
- {
- if (memberLen != 5)
- return false;
- smolv_WriteVarint(outSmolv, memberWords[4]-prevOffset);
- prevOffset = memberWords[4];
- }
- else
- {
- // write rest of decorations as varint
- for (uint32_t i = 4; i < memberLen; ++i)
- smolv_WriteVarint(outSmolv, memberWords[i]);
- }
- memberWords += memberLen;
- ++count;
- }
- outSmolv[countLocation] = uint8_t(count);
- words = memberWords;
- continue;
- }
- // Write out this many IDs, encoding them relative+zigzag to result ID
- int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
- for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
- {
- if (ioffs >= instrLen)
- return false;
- uint32_t delta = prevResult - words[ioffs];
- // some deltas are negative (often on branches, or if program was processed by spirv-remap),
- // so use zig encoding
- smolv_WriteVarint(outSmolv, smolv_ZigEncode(delta));
- }
- if (op == SpvOpVectorShuffleCompact)
- {
- // compact vector shuffle, just write out single swizzle byte
- outSmolv.push_back(uint8_t(swizzle));
- ioffs = instrLen;
- }
- else if (smolv_OpVarRest(op, knownOpsCount))
- {
- // write out rest of words with variable encoding (expected to be small integers)
- for (; ioffs < instrLen; ++ioffs)
- smolv_WriteVarint(outSmolv, words[ioffs]);
- }
- else
- {
- // write out rest of words without any encoding
- for (; ioffs < instrLen; ++ioffs)
- smolv_Write4(outSmolv, words[ioffs]);
- }
-
- words += instrLen;
- }
- if (strippedSpirvWordCount != wordCount)
- {
- uint8_t* headerSpirvSize = &outSmolv[headerSpirvSizeOffset];
- smolv_Write4(headerSpirvSize, (uint32_t)strippedSpirvWordCount * 4);
- }
-
- return true;
- }
- size_t smolv::GetDecodedBufferSize(const void* smolvData, size_t smolvSize)
- {
- if (!smolv_CheckSmolHeader((const uint8_t*)smolvData, smolvSize))
- return 0;
- const uint32_t* words = (const uint32_t*)smolvData;
- return words[5];
- }
- bool smolv::Decode(const void* smolvData, size_t smolvSize, void* spirvOutputBuffer, size_t spirvOutputBufferSize, uint32_t flags)
- {
- // check header, and whether we have enough output buffer space
- const size_t neededBufferSize = GetDecodedBufferSize(smolvData, smolvSize);
- if (neededBufferSize == 0)
- return false; // invalid SMOL-V
- if (spirvOutputBufferSize < neededBufferSize)
- return false; // not enough space in output buffer
- if (spirvOutputBuffer == NULL)
- return false; // output buffer is null
- const uint8_t* bytes = (const uint8_t*)smolvData;
- const uint8_t* bytesEnd = bytes + smolvSize;
- uint8_t* outSpirv = (uint8_t*)spirvOutputBuffer;
-
- uint32_t val;
- int smolVersion = 0;
- // header
- smolv_Write4(outSpirv, kSpirVHeaderMagic); bytes += 4;
- smolv_Read4(bytes, bytesEnd, val); smolVersion = val >> 24; val &= 0x00FFFFFF; smolv_Write4(outSpirv, val); // version
- smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // generator
- smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // bound
- smolv_Read4(bytes, bytesEnd, val); smolv_Write4(outSpirv, val); // schema
- bytes += 4; // decode buffer size
-
- // there are two SMOL-V encoding versions, both not indicating anything in their header version field:
- // one that is called "before zero" here (2016-08-31 code). Support decoding that one only by presence
- // of this special flag.
- const bool beforeZeroVersion = smolVersion == 0 && (flags & kDecodeFlagUse20160831AsZeroVersion) != 0;
- const int knownOpsCount = smolv_GetKnownOpsCount(smolVersion);
- uint32_t prevResult = 0;
- uint32_t prevDecorate = 0;
- while (bytes < bytesEnd)
- {
- // read length + opcode
- uint32_t instrLen;
- SpvOp op;
- if (!smolv_ReadLengthOp(bytes, bytesEnd, instrLen, op))
- return false;
- const bool wasSwizzle = (op == SpvOpVectorShuffleCompact);
- if (wasSwizzle)
- op = SpvOpVectorShuffle;
- smolv_Write4(outSpirv, (instrLen << 16) | op);
- size_t ioffs = 1;
- // read type as varint, if we have it
- if (smolv_OpHasType(op, knownOpsCount))
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- smolv_Write4(outSpirv, val);
- ioffs++;
- }
- // read result as delta+varint, if we have it
- if (smolv_OpHasResult(op, knownOpsCount))
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- val = prevResult + smolv_ZigDecode(val);
- smolv_Write4(outSpirv, val);
- prevResult = val;
- ioffs++;
- }
-
- // Decorate: IDs relative to previous decorate
- if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- // "before zero" version did not use zig encoding for the value
- val = prevDecorate + (beforeZeroVersion ? val : smolv_ZigDecode(val));
- smolv_Write4(outSpirv, val);
- prevDecorate = val;
- ioffs++;
- }
- // MemberDecorate special decoding
- if (op == SpvOpMemberDecorate && !beforeZeroVersion)
- {
- if (bytes >= bytesEnd)
- return false; // broken input
- int count = *bytes++;
- int prevIndex = 0;
- int prevOffset = 0;
- for (int m = 0; m < count; ++m)
- {
- // read member index
- uint32_t memberIndex;
- if (!smolv_ReadVarint(bytes, bytesEnd, memberIndex)) return false;
- memberIndex += prevIndex;
- prevIndex = memberIndex;
-
- // decoration (and length if not common/known)
- uint32_t memberDec;
- if (!smolv_ReadVarint(bytes, bytesEnd, memberDec)) return false;
- const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
- uint32_t memberLen;
- if (knownExtraOps == -1)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, memberLen)) return false;
- memberLen += 4;
- }
- else
- memberLen = 4 + knownExtraOps;
- // write SPIR-V op+length (unless it's first member decoration, in which case it was written before)
- if (m != 0)
- {
- smolv_Write4(outSpirv, (memberLen << 16) | op);
- smolv_Write4(outSpirv, prevDecorate);
- }
- smolv_Write4(outSpirv, memberIndex);
- smolv_Write4(outSpirv, memberDec);
- // Special case for Offset decorations
- if (memberDec == 35) // Offset
- {
- if (memberLen != 5)
- return false;
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- val += prevOffset;
- smolv_Write4(outSpirv, val);
- prevOffset = val;
- }
- else
- {
- for (uint32_t i = 4; i < memberLen; ++i)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- smolv_Write4(outSpirv, val);
- }
- }
- }
- continue;
- }
- // Read this many IDs, that are relative to result ID
- int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
- // "before zero" version only used zig encoding for IDs of several ops; after
- // that ops got zig encoding for their IDs
- bool zigDecodeVals = true;
- if (beforeZeroVersion)
- {
- if (op != SpvOpControlBarrier && op != SpvOpMemoryBarrier && op != SpvOpLoopMerge && op != SpvOpSelectionMerge && op != SpvOpBranch && op != SpvOpBranchConditional && op != SpvOpMemoryNamedBarrier)
- zigDecodeVals = false;
- }
- for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- if (zigDecodeVals)
- val = smolv_ZigDecode(val);
- smolv_Write4(outSpirv, prevResult - val);
- }
- if (wasSwizzle && instrLen <= 9)
- {
- uint32_t swizzle = *bytes++;
- if (instrLen > 5) smolv_Write4(outSpirv, (swizzle >> 6) & 3);
- if (instrLen > 6) smolv_Write4(outSpirv, (swizzle >> 4) & 3);
- if (instrLen > 7) smolv_Write4(outSpirv, (swizzle >> 2) & 3);
- if (instrLen > 8) smolv_Write4(outSpirv, swizzle & 3);
- }
- else if (smolv_OpVarRest(op, knownOpsCount))
- {
- // read rest of words with variable encoding
- for (; ioffs < instrLen; ++ioffs)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- smolv_Write4(outSpirv, val);
- }
- }
- else
- {
- // read rest of words without any encoding
- for (; ioffs < instrLen; ++ioffs)
- {
- if (!smolv_Read4(bytes, bytesEnd, val)) return false;
- smolv_Write4(outSpirv, val);
- }
- }
- }
- if ((uint8_t*)spirvOutputBuffer + neededBufferSize != outSpirv)
- return false; // something went wrong during decoding? we should have decoded to exact output size
-
- return true;
- }
- // --------------------------------------------------------------------------------------------
- // Calculating instruction count / space stats on SPIR-V and SMOL-V
- struct smolv::Stats
- {
- Stats() { memset(this, 0, sizeof(*this)); }
- size_t opCounts[kKnownOpsCount];
- size_t opSizes[kKnownOpsCount];
- size_t smolOpSizes[kKnownOpsCount];
- size_t varintCountsOp[6];
- size_t varintCountsType[6];
- size_t varintCountsRes[6];
- size_t varintCountsOther[6];
- size_t totalOps;
- size_t totalSize;
- size_t totalSizeSmol;
- size_t inputCount;
- };
- smolv::Stats* smolv::StatsCreate()
- {
- return new Stats();
- }
- void smolv::StatsDelete(smolv::Stats *s)
- {
- delete s;
- }
- bool smolv::StatsCalculate(smolv::Stats* stats, const void* spirvData, size_t spirvSize)
- {
- if (!stats)
- return false;
- const size_t wordCount = spirvSize / 4;
- if (wordCount * 4 != spirvSize)
- return false;
- const uint32_t* words = (const uint32_t*)spirvData;
- const uint32_t* wordsEnd = words + wordCount;
- if (!smolv_CheckSpirVHeader(words, wordCount))
- return false;
- words += 5;
-
- stats->inputCount++;
- stats->totalSize += wordCount;
- while (words < wordsEnd)
- {
- _SMOLV_READ_OP(instrLen, words, op);
- if (op < kKnownOpsCount)
- {
- stats->opCounts[op]++;
- stats->opSizes[op] += instrLen;
- }
- words += instrLen;
- stats->totalOps++;
- }
-
- return true;
- }
- bool smolv::StatsCalculateSmol(smolv::Stats* stats, const void* smolvData, size_t smolvSize)
- {
- if (!stats)
- return false;
- // debugging helper to dump all encoded bytes to stdout, keep at "if 0"
- # if 0
- # define _SMOLV_DEBUG_PRINT_ENCODED_BYTES() { \
- printf("Op %-22s ", op < kKnownOpsCount ? kSpirvOpNames[op] : "???"); \
- for (const uint8_t* b = instrBegin; b < bytes; ++b) \
- printf("%02x ", *b); \
- printf("\n"); \
- }
- # else
- # define _SMOLV_DEBUG_PRINT_ENCODED_BYTES() {}
- # endif
-
- const uint8_t* bytes = (const uint8_t*)smolvData;
- const uint8_t* bytesEnd = bytes + smolvSize;
- if (!smolv_CheckSmolHeader(bytes, smolvSize))
- return false;
- uint32_t val;
- int smolVersion;
- bytes += 4;
- smolv_Read4(bytes, bytesEnd, val); smolVersion = val >> 24;
- const int knownOpsCount = smolv_GetKnownOpsCount(smolVersion);
- bytes += 16;
-
- stats->totalSizeSmol += smolvSize;
-
- while (bytes < bytesEnd)
- {
- const uint8_t* instrBegin = bytes;
- const uint8_t* varBegin;
- // read length + opcode
- uint32_t instrLen;
- SpvOp op;
- varBegin = bytes;
- if (!smolv_ReadLengthOp(bytes, bytesEnd, instrLen, op))
- return false;
- const bool wasSwizzle = (op == SpvOpVectorShuffleCompact);
- if (wasSwizzle)
- op = SpvOpVectorShuffle;
- stats->varintCountsOp[bytes-varBegin]++;
-
- size_t ioffs = 1;
- if (smolv_OpHasType(op, knownOpsCount))
- {
- varBegin = bytes;
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- stats->varintCountsType[bytes-varBegin]++;
- ioffs++;
- }
- if (smolv_OpHasResult(op, knownOpsCount))
- {
- varBegin = bytes;
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- stats->varintCountsRes[bytes-varBegin]++;
- ioffs++;
- }
-
- if (op == SpvOpDecorate || op == SpvOpMemberDecorate)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- ioffs++;
- }
- // MemberDecorate special decoding
- if (op == SpvOpMemberDecorate)
- {
- if (bytes >= bytesEnd)
- return false; // broken input
- int count = *bytes++;
- for (int m = 0; m < count; ++m)
- {
- uint32_t memberIndex;
- if (!smolv_ReadVarint(bytes, bytesEnd, memberIndex)) return false;
- uint32_t memberDec;
- if (!smolv_ReadVarint(bytes, bytesEnd, memberDec)) return false;
- const int knownExtraOps = smolv_DecorationExtraOps(memberDec);
- uint32_t memberLen;
- if (knownExtraOps == -1)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, memberLen)) return false;
- memberLen += 4;
- }
- else
- memberLen = 4 + knownExtraOps;
- for (uint32_t i = 4; i < memberLen; ++i)
- {
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- }
- }
- stats->smolOpSizes[op] += bytes - instrBegin;
- _SMOLV_DEBUG_PRINT_ENCODED_BYTES();
- continue;
- }
- int relativeCount = smolv_OpDeltaFromResult(op, knownOpsCount);
- for (int i = 0; i < relativeCount && ioffs < instrLen; ++i, ++ioffs)
- {
- varBegin = bytes;
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- stats->varintCountsRes[bytes-varBegin]++;
- }
- if (wasSwizzle && instrLen <= 9)
- {
- bytes++;
- }
- else if (smolv_OpVarRest(op, knownOpsCount))
- {
- for (; ioffs < instrLen; ++ioffs)
- {
- varBegin = bytes;
- if (!smolv_ReadVarint(bytes, bytesEnd, val)) return false;
- stats->varintCountsOther[bytes-varBegin]++;
- }
- }
- else
- {
- for (; ioffs < instrLen; ++ioffs)
- {
- if (!smolv_Read4(bytes, bytesEnd, val)) return false;
- }
- }
-
- if (op < kKnownOpsCount)
- {
- stats->smolOpSizes[op] += bytes - instrBegin;
- }
- _SMOLV_DEBUG_PRINT_ENCODED_BYTES();
- }
-
- return true;
- }
- static bool CompareOpCounters (std::pair<SpvOp,size_t> a, std::pair<SpvOp,size_t> b)
- {
- return a.second > b.second;
- }
- void smolv::StatsPrint(const Stats* stats)
- {
- if (!stats)
- return;
- typedef std::pair<SpvOp,size_t> OpCounter;
- OpCounter counts[kKnownOpsCount];
- OpCounter sizes[kKnownOpsCount];
- OpCounter sizesSmol[kKnownOpsCount];
- for (int i = 0; i < kKnownOpsCount; ++i)
- {
- counts[i].first = (SpvOp)i;
- counts[i].second = stats->opCounts[i];
- sizes[i].first = (SpvOp)i;
- sizes[i].second = stats->opSizes[i];
- sizesSmol[i].first = (SpvOp)i;
- sizesSmol[i].second = stats->smolOpSizes[i];
- }
- std::sort(counts, counts + kKnownOpsCount, CompareOpCounters);
- std::sort(sizes, sizes + kKnownOpsCount, CompareOpCounters);
- std::sort(sizesSmol, sizesSmol + kKnownOpsCount, CompareOpCounters);
-
- 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);
- printf("Most occuring ops:\n");
- for (int i = 0; i < 30; ++i)
- {
- SpvOp op = counts[i].first;
- 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);
- }
- printf("Largest total size of ops:\n");
- for (int i = 0; i < 30; ++i)
- {
- SpvOp op = sizes[i].first;
- printf(" #%2i: %-22s %6i (%4.1f%%) avg len %.1f\n",
- i,
- kSpirvOpNames[op],
- (int)sizes[i].second*4,
- (float)sizes[i].second / (float)stats->totalSize * 100.0f,
- (float)sizes[i].second*4 / (float)stats->opCounts[op]
- );
- }
- printf("SMOL varint encoding counts per byte length:\n");
- printf(" B: %6s %6s %6s %6s\n", "Op", "Type", "Result", "Other");
- for (int i = 1; i < 6; ++i)
- {
- printf(" %i: %6i %6i %6i %6i\n", i, (int)stats->varintCountsOp[i], (int)stats->varintCountsType[i], (int)stats->varintCountsRes[i], (int)stats->varintCountsOther[i]);
- }
- printf("Largest total size of ops in SMOL:\n");
- for (int i = 0; i < 30; ++i)
- {
- SpvOp op = sizesSmol[i].first;
- printf(" #%2i: %-22s %6i (%4.1f%%) avg len %.1f\n",
- i,
- kSpirvOpNames[op],
- (int)sizesSmol[i].second,
- (float)sizesSmol[i].second / (float)stats->totalSizeSmol * 100.0f,
- (float)sizesSmol[i].second / (float)stats->opCounts[op]
- );
- }
- }
- // ------------------------------------------------------------------------------
- // This software is available under 2 licenses -- choose whichever you prefer.
- // ------------------------------------------------------------------------------
- // ALTERNATIVE A - MIT License
- // Copyright (c) 2016-2020 Aras Pranckevicius
- // Permission is hereby granted, free of charge, to any person obtaining a copy of
- // this software and associated documentation files (the "Software"), to deal in
- // the Software without restriction, including without limitation the rights to
- // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- // of the Software, and to permit persons to whom the Software is furnished to do
- // so, subject to the following conditions:
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
- // ------------------------------------------------------------------------------
- // ALTERNATIVE B - Public Domain (www.unlicense.org)
- // This is free and unencumbered software released into the public domain.
- // Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
- // software, either in source code form or as a compiled binary, for any purpose,
- // commercial or non-commercial, and by any means.
- // In jurisdictions that recognize copyright laws, the author or authors of this
- // software dedicate any and all copyright interest in the software to the public
- // domain. We make this dedication for the benefit of the public at large and to
- // the detriment of our heirs and successors. We intend this dedication to be an
- // overt act of relinquishment in perpetuity of all present and future rights to
- // this software under copyright law.
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- // ------------------------------------------------------------------------------
|