21 Sep

spirv-stats – a tool to output statistics of your SPIR-V shader modules

I’ve just released a small one C++ file tool called spirv-stats. It will take one or more SPIR-V input files, and calculate the composition of the SPIR-V shader modules like so:

Totals: 35 hits 564 bytes
               OpDecorate =      5 hits (14.29%) 80 bytes (14.18%)
            OpTypePointer =      4 hits (11.43%) 64 bytes (11.35%)
               OpVariable =      4 hits (11.43%) 64 bytes (11.35%)
                   OpLoad =      3 hits ( 8.57%) 48 bytes ( 8.51%)
             OpTypeVector =      2 hits ( 5.71%) 32 bytes ( 5.67%)
          OpExtInstImport =      1 hits ( 2.86%) 24 bytes ( 4.26%)
            OpMemoryModel =      1 hits ( 2.86%) 12 bytes ( 2.13%)
             OpEntryPoint =      1 hits ( 2.86%) 32 bytes ( 5.67%)
          OpExecutionMode =      1 hits ( 2.86%) 12 bytes ( 2.13%)
             OpCapability =      1 hits ( 2.86%)  8 bytes ( 1.42%)
               OpTypeVoid =      1 hits ( 2.86%)  8 bytes ( 1.42%)
              OpTypeFloat =      1 hits ( 2.86%) 12 bytes ( 2.13%)
              OpTypeImage =      1 hits ( 2.86%) 36 bytes ( 6.38%)
       OpTypeSampledImage =      1 hits ( 2.86%) 12 bytes ( 2.13%)
           OpTypeFunction =      1 hits ( 2.86%) 12 bytes ( 2.13%)
               OpFunction =      1 hits ( 2.86%) 20 bytes ( 3.55%)
            OpFunctionEnd =      1 hits ( 2.86%)  4 bytes ( 0.71%)
                  OpStore =      1 hits ( 2.86%) 12 bytes ( 2.13%)
 OpImageSampleImplicitLod =      1 hits ( 2.86%) 20 bytes ( 3.55%)
                   OpFMul =      1 hits ( 2.86%) 20 bytes ( 3.55%)
                  OpLabel =      1 hits ( 2.86%)  8 bytes ( 1.42%)
                 OpReturn =      1 hits ( 2.86%)  4 bytes ( 0.71%)

It firstly outputs the total number of hits in the SPIR-V shader module(s) – this is the total number of opcodes found within the module(s). Then it outputs the total byte size of the module(s), followed by a sorted breakdown of the module(s), with the most hit opcodes coming first.

I decided to run this across the various folders of SPIR-V that @aras_p is using in his smol-v tool, with the following results.

dota2

Totals: 57090 hits 1099348 bytes
              OpMemberDecorate =  10907 hits (19.10%) 215824 bytes (19.63%)
                        OpLoad =   9140 hits (16.01%) 146240 bytes (13.30%)
                 OpAccessChain =   6034 hits (10.57%) 127080 bytes (11.56%)
                    OpVariable =   3273 hits ( 5.73%)  52368 bytes ( 4.76%)
                    OpDecorate =   2923 hits ( 5.12%)  44556 bytes ( 4.05%)
                       OpStore =   2701 hits ( 4.73%)  32412 bytes ( 2.95%)
                    OpConstant =   2403 hits ( 4.21%)  38448 bytes ( 3.50%)
                        OpFMul =   2398 hits ( 4.20%)  47960 bytes ( 4.36%)
          OpCompositeConstruct =   2053 hits ( 3.60%)  49788 bytes ( 4.53%)
                 OpTypePointer =   1952 hits ( 3.42%)  31232 bytes ( 2.84%)
                        OpFAdd =   1669 hits ( 2.92%)  33380 bytes ( 3.04%)
               OpVectorShuffle =   1371 hits ( 2.40%)  41800 bytes ( 3.80%)
                     OpExtInst =   1259 hits ( 2.21%)  35060 bytes ( 3.19%)
                        OpFSub =    925 hits ( 1.62%)  18500 bytes ( 1.68%)
                         OpDot =    894 hits ( 1.57%)  17880 bytes ( 1.63%)
           OpConstantComposite =    736 hits ( 1.29%)  18096 bytes ( 1.65%)
                  OpTypeStruct =    573 hits ( 1.00%)  44184 bytes ( 4.02%)
                       OpLabel =    542 hits ( 0.95%)   4336 bytes ( 0.39%)
                  OpTypeVector =    406 hits ( 0.71%)   6496 bytes ( 0.59%)
                   OpTypeArray =    403 hits ( 0.71%)   6448 bytes ( 0.59%)
      OpImageSampleImplicitLod =    316 hits ( 0.55%)   6320 bytes ( 0.57%)
      OpImageSampleExplicitLod =    300 hits ( 0.53%)   9000 bytes ( 0.82%)
            OpCompositeExtract =    257 hits ( 0.45%)   5140 bytes ( 0.47%)
                      OpBranch =    249 hits ( 0.44%)   1992 bytes ( 0.18%)
            OpTypeSampledImage =    225 hits ( 0.39%)   2700 bytes ( 0.25%)
                   OpTypeImage =    225 hits ( 0.39%)   8100 bytes ( 0.74%)
                        OpFDiv =    212 hits ( 0.37%)   4240 bytes ( 0.39%)
                     OpTypeInt =    210 hits ( 0.37%)   3360 bytes ( 0.31%)
  OpImageSampleDrefExplicitLod =    207 hits ( 0.36%)   6624 bytes ( 0.60%)
           OpBranchConditional =    155 hits ( 0.27%)   2480 bytes ( 0.23%)
              OpSelectionMerge =    153 hits ( 0.27%)   1836 bytes ( 0.17%)
                  OpCapability =    131 hits ( 0.23%)   1048 bytes ( 0.10%)
                OpFOrdLessThan =    131 hits ( 0.23%)   2620 bytes ( 0.24%)
                   OpTypeFloat =    110 hits ( 0.19%)   1320 bytes ( 0.12%)
                    OpTypeVoid =    110 hits ( 0.19%)    880 bytes ( 0.08%)
                 OpFunctionEnd =    110 hits ( 0.19%)    440 bytes ( 0.04%)
                  OpEntryPoint =    110 hits ( 0.19%)   6240 bytes ( 0.57%)
                 OpMemoryModel =    110 hits ( 0.19%)   1320 bytes ( 0.12%)
               OpExtInstImport =    110 hits ( 0.19%)   2640 bytes ( 0.24%)
                      OpReturn =    110 hits ( 0.19%)    440 bytes ( 0.04%)
                    OpFunction =    110 hits ( 0.19%)   2200 bytes ( 0.20%)
                OpTypeFunction =    110 hits ( 0.19%)   1320 bytes ( 0.12%)
                  OpTypeMatrix =     92 hits ( 0.16%)   1472 bytes ( 0.13%)
                        OpName =     87 hits ( 0.15%)   1368 bytes ( 0.12%)
                    OpTypeBool =     67 hits ( 0.12%)    536 bytes ( 0.05%)
             OpFOrdGreaterThan =     67 hits ( 0.12%)   1340 bytes ( 0.12%)
               OpExecutionMode =     65 hits ( 0.11%)    780 bytes ( 0.07%)
                      OpSelect =     56 hits ( 0.10%)   1344 bytes ( 0.12%)
                 OpConvertSToF =     48 hits ( 0.08%)    768 bytes ( 0.07%)
                     OpBitcast =     44 hits ( 0.08%)    704 bytes ( 0.06%)
            OpShiftLeftLogical =     44 hits ( 0.08%)    880 bytes ( 0.08%)
                        OpIAdd =     44 hits ( 0.08%)    880 bytes ( 0.08%)
                  OpMemberName =     34 hits ( 0.06%)    832 bytes ( 0.08%)
                        OpKill =     28 hits ( 0.05%)    112 bytes ( 0.01%)
                        OpFMod =     17 hits ( 0.03%)    340 bytes ( 0.03%)
                 OpConvertFToS =     16 hits ( 0.03%)    256 bytes ( 0.02%)
                   OpFOrdEqual =     11 hits ( 0.02%)    220 bytes ( 0.02%)
             OpSourceExtension =     10 hits ( 0.02%)    360 bytes ( 0.03%)
                      OpSource =     10 hits ( 0.02%)    120 bytes ( 0.01%)
           OpVectorTimesScalar =      8 hits ( 0.01%)    160 bytes ( 0.01%)
                     OpFNegate =      7 hits ( 0.01%)    112 bytes ( 0.01%)
        OpVectorExtractDynamic =      3 hits ( 0.01%)     60 bytes ( 0.01%)
                  OpLogicalNot =      2 hits ( 0.00%)     32 bytes ( 0.00%)
                 OpConvertUToF =      2 hits ( 0.00%)     32 bytes ( 0.00%)
                   OpLoopMerge =      2 hits ( 0.00%)     32 bytes ( 0.00%)
           OpFOrdLessThanEqual =      2 hits ( 0.00%)     40 bytes ( 0.00%)
                   OpLogicalOr =      1 hits ( 0.00%)     20 bytes ( 0.00%)

OpMemberDecorate dominates the dota2 shaders – nearly 20% of the module is decorating members of structs! Next we have OpLoad at 16% of the hits, but with 13% of the size of the files, followed by OpAccessChain at 10% of the hits and 12% of the size. Most of the shader module(s) are taken up with decorating struct members, and then loading and storing to various variables.

shadertoy

Totals: 75544 hits 1170540 bytes
                        OpLoad =  13486 hits (17.85%) 215776 bytes (18.43%)
                       OpStore =  10671 hits (14.13%) 128052 bytes (10.94%)
                       OpLabel =   7005 hits ( 9.27%)  56040 bytes ( 4.79%)
                        OpName =   5718 hits ( 7.57%)  93332 bytes ( 7.97%)
                    OpVariable =   5503 hits ( 7.28%)  88048 bytes ( 7.52%)
                      OpBranch =   4010 hits ( 5.31%)  32080 bytes ( 2.74%)
                    OpConstant =   3059 hits ( 4.05%)  48944 bytes ( 4.18%)
           OpBranchConditional =   2523 hits ( 3.34%)  40368 bytes ( 3.45%)
              OpSelectionMerge =   2469 hits ( 3.27%)  29628 bytes ( 2.53%)
                 OpAccessChain =   2171 hits ( 2.87%)  43696 bytes ( 3.73%)
                     OpExtInst =   1736 hits ( 2.30%)  47980 bytes ( 4.10%)
                        OpFMul =   1495 hits ( 1.98%)  29900 bytes ( 2.55%)
                OpFunctionCall =   1308 hits ( 1.73%)  38372 bytes ( 3.28%)
                        OpFAdd =   1230 hits ( 1.63%)  24600 bytes ( 2.10%)
                        OpFSub =   1027 hits ( 1.36%)  20540 bytes ( 1.75%)
           OpFunctionParameter =    960 hits ( 1.27%)  11520 bytes ( 0.98%)
           OpConstantComposite =    918 hits ( 1.22%)  20852 bytes ( 1.78%)
          OpCompositeConstruct =    869 hits ( 1.15%)  20120 bytes ( 1.72%)
                   OpFOrdEqual =    702 hits ( 0.93%)  14040 bytes ( 1.20%)
           OpVectorTimesScalar =    686 hits ( 0.91%)  13720 bytes ( 1.17%)
               OpVectorShuffle =    593 hits ( 0.78%)  17828 bytes ( 1.52%)
           OpFOrdLessThanEqual =    591 hits ( 0.78%)  11820 bytes ( 1.01%)
                      OpIEqual =    582 hits ( 0.77%)  11640 bytes ( 0.99%)
            OpCompositeExtract =    427 hits ( 0.57%)   8540 bytes ( 0.73%)
                    OpFunction =    415 hits ( 0.55%)   8300 bytes ( 0.71%)
                 OpFunctionEnd =    415 hits ( 0.55%)   1660 bytes ( 0.14%)
                        OpFDiv =    380 hits ( 0.50%)   7600 bytes ( 0.65%)
                 OpReturnValue =    342 hits ( 0.45%)   2736 bytes ( 0.23%)
                  OpLogicalAnd =    330 hits ( 0.44%)   6600 bytes ( 0.56%)
        OpFOrdGreaterThanEqual =    325 hits ( 0.43%)   6500 bytes ( 0.56%)
                OpFOrdLessThan =    289 hits ( 0.38%)   5780 bytes ( 0.49%)
                         OpPhi =    278 hits ( 0.37%)   7784 bytes ( 0.66%)
                OpTypeFunction =    268 hits ( 0.35%)   5808 bytes ( 0.50%)
             OpFOrdGreaterThan =    246 hits ( 0.33%)   4920 bytes ( 0.42%)
                        OpIAdd =    244 hits ( 0.32%)   4880 bytes ( 0.42%)
                 OpTypePointer =    244 hits ( 0.32%)   3904 bytes ( 0.33%)
              OpMemberDecorate =    180 hits ( 0.24%)   3600 bytes ( 0.31%)
                  OpMemberName =    180 hits ( 0.24%)   4320 bytes ( 0.37%)
                    OpDecorate =    162 hits ( 0.21%)   2520 bytes ( 0.22%)
                      OpReturn =    127 hits ( 0.17%)    508 bytes ( 0.04%)
                  OpLogicalNot =    122 hits ( 0.16%)   1952 bytes ( 0.17%)
                         OpDot =    103 hits ( 0.14%)   2060 bytes ( 0.18%)
                        OpFMod =     97 hits ( 0.13%)   1940 bytes ( 0.17%)
      OpImageSampleImplicitLod =     96 hits ( 0.13%)   2200 bytes ( 0.19%)
                   OpLogicalOr =     88 hits ( 0.12%)   1760 bytes ( 0.15%)
                     OpFNegate =     83 hits ( 0.11%)   1328 bytes ( 0.11%)
                   OpSLessThan =     74 hits ( 0.10%)   1480 bytes ( 0.13%)
                 OpConvertSToF =     67 hits ( 0.09%)   1072 bytes ( 0.09%)
                  OpTypeVector =     58 hits ( 0.08%)    928 bytes ( 0.08%)
                   OpLoopMerge =     54 hits ( 0.07%)    864 bytes ( 0.07%)
                 OpConvertFToS =     43 hits ( 0.06%)    688 bytes ( 0.06%)
           OpSGreaterThanEqual =     39 hits ( 0.05%)    780 bytes ( 0.07%)
                   OpTypeArray =     38 hits ( 0.05%)    608 bytes ( 0.05%)
                     OpTypeInt =     36 hits ( 0.05%)    576 bytes ( 0.05%)
           OpMatrixTimesVector =     32 hits ( 0.04%)    640 bytes ( 0.05%)
              OpSLessThanEqual =     21 hits ( 0.03%)    420 bytes ( 0.04%)
                        OpISub =     21 hits ( 0.03%)    420 bytes ( 0.04%)
            OpTypeSampledImage =     19 hits ( 0.03%)    228 bytes ( 0.02%)
                   OpTypeImage =     19 hits ( 0.03%)    684 bytes ( 0.06%)
                    OpTypeBool =     18 hits ( 0.02%)    144 bytes ( 0.01%)
                   OpTypeFloat =     18 hits ( 0.02%)    216 bytes ( 0.02%)
                  OpTypeStruct =     18 hits ( 0.02%)    864 bytes ( 0.07%)
                    OpTypeVoid =     18 hits ( 0.02%)    144 bytes ( 0.01%)
                      OpSource =     18 hits ( 0.02%)    216 bytes ( 0.02%)
               OpExtInstImport =     18 hits ( 0.02%)    432 bytes ( 0.04%)
                 OpMemoryModel =     18 hits ( 0.02%)    216 bytes ( 0.02%)
                  OpEntryPoint =     18 hits ( 0.02%)    504 bytes ( 0.04%)
               OpExecutionMode =     18 hits ( 0.02%)    216 bytes ( 0.02%)
                  OpCapability =     18 hits ( 0.02%)    144 bytes ( 0.01%)
                OpFOrdNotEqual =     16 hits ( 0.02%)    320 bytes ( 0.03%)
                  OpTypeMatrix =     13 hits ( 0.02%)    208 bytes ( 0.02%)
                        OpIMul =     13 hits ( 0.02%)    260 bytes ( 0.02%)
                        OpSDiv =     12 hits ( 0.02%)    240 bytes ( 0.02%)
                      OpSelect =      7 hits ( 0.01%)    168 bytes ( 0.01%)
                OpConstantTrue =      5 hits ( 0.01%)     60 bytes ( 0.01%)
               OpConstantFalse =      5 hits ( 0.01%)     60 bytes ( 0.01%)
                         OpAny =      4 hits ( 0.01%)     64 bytes ( 0.01%)
           OpVectorTimesMatrix =      3 hits ( 0.00%)     60 bytes ( 0.01%)
                        OpKill =      3 hits ( 0.00%)     12 bytes ( 0.00%)
                        OpDPdx =      2 hits ( 0.00%)     32 bytes ( 0.00%)
                        OpDPdy =      2 hits ( 0.00%)     32 bytes ( 0.00%)
                     OpSNegate =      2 hits ( 0.00%)     32 bytes ( 0.00%)
             OpLogicalNotEqual =      1 hits ( 0.00%)     20 bytes ( 0.00%)
                       OpUndef =      1 hits ( 0.00%)     12 bytes ( 0.00%)
                OpSGreaterThan =      1 hits ( 0.00%)     20 bytes ( 0.00%)

The shadertoy folder is dominated by loads and stores. Then curiously OpLabel – this indicates that there is a heavy amount of branching/looping occurring in the source shaders, as an OpLabel signifies a new basic block has been declared. OpBranch is the sixth most used opcode, which also backs up the view that these shaders make heavy use of branching/looping.

talos

Totals: 76515 hits 1369056 bytes
                        OpLoad =  14158 hits (18.50%) 226528 bytes (16.55%)
                       OpStore =   8912 hits (11.65%) 106944 bytes ( 7.81%)
            OpCompositeExtract =   8642 hits (11.29%) 174160 bytes (12.72%)
                    OpVariable =   7203 hits ( 9.41%) 115248 bytes ( 8.42%)
                 OpAccessChain =   6349 hits ( 8.30%) 135404 bytes ( 9.89%)
               OpVectorShuffle =   3885 hits ( 5.08%) 122764 bytes ( 8.97%)
                    OpConstant =   3577 hits ( 4.67%)  57232 bytes ( 4.18%)
          OpCompositeConstruct =   3158 hits ( 4.13%)  82616 bytes ( 6.03%)
                    OpDecorate =   1921 hits ( 2.51%)  30188 bytes ( 2.21%)
                       OpLabel =   1642 hits ( 2.15%)  13136 bytes ( 0.96%)
                        OpFMul =   1622 hits ( 2.12%)  32440 bytes ( 2.37%)
                 OpTypePointer =   1548 hits ( 2.02%)  24768 bytes ( 1.81%)
                     OpExtInst =   1346 hits ( 1.76%)  38388 bytes ( 2.80%)
           OpFunctionParameter =   1142 hits ( 1.49%)  13704 bytes ( 1.00%)
                        OpFAdd =   1046 hits ( 1.37%)  20920 bytes ( 1.53%)
                OpFunctionCall =    863 hits ( 1.13%)  19616 bytes ( 1.43%)
           OpVectorTimesScalar =    794 hits ( 1.04%)  15880 bytes ( 1.16%)
                    OpFunction =    743 hits ( 0.97%)  14860 bytes ( 1.09%)
                 OpFunctionEnd =    743 hits ( 0.97%)   2972 bytes ( 0.22%)
                        OpFSub =    716 hits ( 0.94%)  14320 bytes ( 1.05%)
                OpTypeFunction =    680 hits ( 0.89%)  12528 bytes ( 0.92%)
                      OpBranch =    589 hits ( 0.77%)   4712 bytes ( 0.34%)
                 OpReturnValue =    586 hits ( 0.77%)   4688 bytes ( 0.34%)
      OpImageSampleImplicitLod =    316 hits ( 0.41%)   6320 bytes ( 0.46%)
           OpBranchConditional =    305 hits ( 0.40%)   4880 bytes ( 0.36%)
                  OpTypeVector =    299 hits ( 0.39%)   4784 bytes ( 0.35%)
              OpSelectionMerge =    281 hits ( 0.37%)   3372 bytes ( 0.25%)
           OpConstantComposite =    269 hits ( 0.35%)   6432 bytes ( 0.47%)
                         OpDot =    228 hits ( 0.30%)   4560 bytes ( 0.33%)
                     OpTypeInt =    200 hits ( 0.26%)   3200 bytes ( 0.23%)
           OpVectorTimesMatrix =    191 hits ( 0.25%)   3820 bytes ( 0.28%)
                      OpReturn =    158 hits ( 0.21%)    632 bytes ( 0.05%)
                        OpIAdd =    154 hits ( 0.20%)   3080 bytes ( 0.22%)
                        OpFDiv =    152 hits ( 0.20%)   3040 bytes ( 0.22%)
                  OpTypeMatrix =    150 hits ( 0.20%)   2400 bytes ( 0.18%)
                        OpIMul =    117 hits ( 0.15%)   2340 bytes ( 0.17%)
                     OpFNegate =    117 hits ( 0.15%)   1872 bytes ( 0.14%)
                  OpTypeStruct =    107 hits ( 0.14%)   1340 bytes ( 0.10%)
            OpTypeSampledImage =    102 hits ( 0.13%)   1224 bytes ( 0.09%)
                   OpTypeImage =    102 hits ( 0.13%)   3672 bytes ( 0.27%)
                   OpTypeArray =    101 hits ( 0.13%)   1616 bytes ( 0.12%)
                  OpEntryPoint =    100 hits ( 0.13%)   5352 bytes ( 0.39%)
              OpMemberDecorate =    100 hits ( 0.13%)   2000 bytes ( 0.15%)
                  OpCapability =    100 hits ( 0.13%)    800 bytes ( 0.06%)
                    OpTypeVoid =    100 hits ( 0.13%)    800 bytes ( 0.06%)
               OpExtInstImport =    100 hits ( 0.13%)   2400 bytes ( 0.18%)
                 OpMemoryModel =    100 hits ( 0.13%)   1200 bytes ( 0.09%)
                   OpTypeFloat =    100 hits ( 0.13%)   1200 bytes ( 0.09%)
        OpFOrdGreaterThanEqual =     84 hits ( 0.11%)   1680 bytes ( 0.12%)
             OpFOrdGreaterThan =     78 hits ( 0.10%)   1560 bytes ( 0.11%)
                    OpTypeBool =     75 hits ( 0.10%)    600 bytes ( 0.04%)
                OpFOrdLessThan =     73 hits ( 0.10%)   1460 bytes ( 0.11%)
               OpExecutionMode =     63 hits ( 0.08%)    756 bytes ( 0.06%)
                  OpLogicalNot =     36 hits ( 0.05%)    576 bytes ( 0.04%)
      OpImageSampleExplicitLod =     36 hits ( 0.05%)   1008 bytes ( 0.07%)
           OpMatrixTimesScalar =     32 hits ( 0.04%)    640 bytes ( 0.05%)
                   OpLoopMerge =     24 hits ( 0.03%)    384 bytes ( 0.03%)
           OpMatrixTimesVector =     16 hits ( 0.02%)    320 bytes ( 0.02%)
           OpMatrixTimesMatrix =     15 hits ( 0.02%)    300 bytes ( 0.02%)
  OpImageSampleDrefExplicitLod =     14 hits ( 0.02%)    448 bytes ( 0.03%)
                   OpSLessThan =     14 hits ( 0.02%)    280 bytes ( 0.02%)
                 OpConvertFToS =      8 hits ( 0.01%)    128 bytes ( 0.01%)
                      OpFwidth =      8 hits ( 0.01%)    128 bytes ( 0.01%)
                   OpTranspose =      6 hits ( 0.01%)     96 bytes ( 0.01%)
                   OpLogicalOr =      4 hits ( 0.01%)     80 bytes ( 0.01%)
                OpFOrdNotEqual =      4 hits ( 0.01%)     80 bytes ( 0.01%)
                        OpKill =      4 hits ( 0.01%)     16 bytes ( 0.00%)
                         OpPhi =      3 hits ( 0.00%)     84 bytes ( 0.01%)
           OpFOrdLessThanEqual =      2 hits ( 0.00%)     40 bytes ( 0.00%)
             OpLogicalNotEqual =      2 hits ( 0.00%)     40 bytes ( 0.00%)

The talos folder is dominated once again by loads and stores. Next is OpCompositeExtract – which is extracting an element from a composite (aggregate, matrix or vector). I’d take a guess that there is a lot of vector math going on in these shaders, as the sixth most used opcode is OpVectorShuffle.

unity

Totals: 77783 hits 1346368 bytes
                    OpDecorate =  18764 hits (24.12%) 235700 bytes (17.51%)
                        OpLoad =  13131 hits (16.88%) 210096 bytes (15.60%)
                       OpStore =   6949 hits ( 8.93%)  83388 bytes ( 6.19%)
                 OpAccessChain =   5562 hits ( 7.15%) 115316 bytes ( 8.56%)
               OpVectorShuffle =   3883 hits ( 4.99%) 125980 bytes ( 9.36%)
                        OpName =   3428 hits ( 4.41%)  69392 bytes ( 5.15%)
              OpMemberDecorate =   3145 hits ( 4.04%)  59492 bytes ( 4.42%)
                    OpVariable =   3062 hits ( 3.94%)  48992 bytes ( 3.64%)
                        OpFMul =   3017 hits ( 3.88%)  60340 bytes ( 4.48%)
                  OpMemberName =   2293 hits ( 2.95%)  72892 bytes ( 5.41%)
                        OpFAdd =   1977 hits ( 2.54%)  39540 bytes ( 2.94%)
                    OpConstant =   1784 hits ( 2.29%)  28544 bytes ( 2.12%)
                 OpTypePointer =   1742 hits ( 2.24%)  27872 bytes ( 2.07%)
                     OpExtInst =    916 hits ( 1.18%)  24552 bytes ( 1.82%)
                     OpFNegate =    831 hits ( 1.07%)  13296 bytes ( 0.99%)
                       OpLabel =    726 hits ( 0.93%)   5808 bytes ( 0.43%)
                         OpDot =    686 hits ( 0.88%)  13720 bytes ( 1.02%)
          OpCompositeConstruct =    598 hits ( 0.77%)  14156 bytes ( 1.05%)
                   OpTypeArray =    496 hits ( 0.64%)   7936 bytes ( 0.59%)
                      OpBranch =    381 hits ( 0.49%)   3048 bytes ( 0.23%)
                  OpTypeStruct =    367 hits ( 0.47%)  12108 bytes ( 0.90%)
                  OpTypeVector =    347 hits ( 0.45%)   5552 bytes ( 0.41%)
            OpCompositeExtract =    269 hits ( 0.35%)   5380 bytes ( 0.40%)
      OpImageSampleImplicitLod =    241 hits ( 0.31%)   4820 bytes ( 0.36%)
           OpConstantComposite =    232 hits ( 0.30%)   5548 bytes ( 0.41%)
                        OpFDiv =    217 hits ( 0.28%)   4340 bytes ( 0.32%)
                     OpTypeInt =    215 hits ( 0.28%)   3440 bytes ( 0.26%)
           OpBranchConditional =    210 hits ( 0.27%)   3360 bytes ( 0.25%)
              OpSelectionMerge =    206 hits ( 0.26%)   2472 bytes ( 0.18%)
             OpSourceExtension =    157 hits ( 0.20%)   5372 bytes ( 0.40%)
                 OpFunctionEnd =    130 hits ( 0.17%)    520 bytes ( 0.04%)
                      OpReturn =    130 hits ( 0.17%)    520 bytes ( 0.04%)
                    OpFunction =    130 hits ( 0.17%)   2600 bytes ( 0.19%)
                  OpCapability =    123 hits ( 0.16%)    984 bytes ( 0.07%)
                OpTypeFunction =    117 hits ( 0.15%)   1420 bytes ( 0.11%)
                    OpTypeVoid =    113 hits ( 0.15%)    904 bytes ( 0.07%)
                      OpSource =    113 hits ( 0.15%)   1356 bytes ( 0.10%)
                  OpEntryPoint =    113 hits ( 0.15%)   5712 bytes ( 0.42%)
               OpExtInstImport =    113 hits ( 0.15%)   2712 bytes ( 0.20%)
                   OpTypeFloat =    113 hits ( 0.15%)   1356 bytes ( 0.10%)
                 OpMemoryModel =    113 hits ( 0.15%)   1356 bytes ( 0.10%)
                OpFOrdLessThan =     95 hits ( 0.12%)   1900 bytes ( 0.14%)
            OpTypeSampledImage =     91 hits ( 0.12%)   1092 bytes ( 0.08%)
                   OpTypeImage =     91 hits ( 0.12%)   3276 bytes ( 0.24%)
               OpExecutionMode =     89 hits ( 0.11%)   1100 bytes ( 0.08%)
                    OpTypeBool =     52 hits ( 0.07%)    416 bytes ( 0.03%)
      OpImageSampleExplicitLod =     40 hits ( 0.05%)   1120 bytes ( 0.08%)
                OpFunctionCall =     27 hits ( 0.03%)    532 bytes ( 0.04%)
                OpFOrdNotEqual =     23 hits ( 0.03%)    460 bytes ( 0.03%)
                        OpIAdd =     23 hits ( 0.03%)    460 bytes ( 0.03%)
                     OpBitcast =     22 hits ( 0.03%)    352 bytes ( 0.03%)
           OpFunctionParameter =     15 hits ( 0.02%)    180 bytes ( 0.01%)
                   OpFOrdEqual =      9 hits ( 0.01%)    180 bytes ( 0.01%)
                      OpSelect =      5 hits ( 0.01%)    120 bytes ( 0.01%)
                   OpINotEqual =      5 hits ( 0.01%)    100 bytes ( 0.01%)
                  OpEmitVertex =      5 hits ( 0.01%)     20 bytes ( 0.00%)
                        OpIMul =      5 hits ( 0.01%)    100 bytes ( 0.01%)
  OpImageSampleDrefExplicitLod =      5 hits ( 0.01%)    160 bytes ( 0.01%)
                        OpKill =      5 hits ( 0.01%)     20 bytes ( 0.00%)
                 OpConvertUToF =      4 hits ( 0.01%)     64 bytes ( 0.00%)
                   OpSLessThan =      4 hits ( 0.01%)     80 bytes ( 0.01%)
              OpControlBarrier =      4 hits ( 0.01%)     64 bytes ( 0.00%)
                   OpLoopMerge =      4 hits ( 0.01%)     64 bytes ( 0.00%)
                      OpIEqual =      4 hits ( 0.01%)     80 bytes ( 0.01%)
        OpFOrdGreaterThanEqual =      3 hits ( 0.00%)     60 bytes ( 0.00%)
                        OpUMod =      2 hits ( 0.00%)     40 bytes ( 0.00%)
                   OpULessThan =      2 hits ( 0.00%)     40 bytes ( 0.00%)
            OpShiftLeftLogical =      2 hits ( 0.00%)     40 bytes ( 0.00%)
                OpEndPrimitive =      2 hits ( 0.00%)      8 bytes ( 0.00%)
                 OpConvertSToF =      1 hits ( 0.00%)     16 bytes ( 0.00%)
                  OpLogicalAnd =      1 hits ( 0.00%)     20 bytes ( 0.00%)
                     OpSNegate =      1 hits ( 0.00%)     16 bytes ( 0.00%)
             OpCompositeInsert =      1 hits ( 0.00%)     24 bytes ( 0.00%)
            OpTypeRuntimeArray =      1 hits ( 0.00%)     12 bytes ( 0.00%)

And lastly the unity folder. These shader modules are dominated by OpDecorate. The next three most used opcodes are OpLoad, OpStore and OpAccessChain – so loading and storing to variables is taking up a sizeable amount of the shader modules.

All Together

If we look at all the folders above as one output from  spirv-stats instead:

Totals: 286932 hits 4985312 bytes
                        OpLoad =  49915 hits (17.40%) 798640 bytes (16.02%)
                       OpStore =  29233 hits (10.19%) 350796 bytes ( 7.04%)
                    OpDecorate =  23770 hits ( 8.28%) 312964 bytes ( 6.28%)
                 OpAccessChain =  20116 hits ( 7.01%) 421496 bytes ( 8.45%)
                    OpVariable =  19041 hits ( 6.64%) 304656 bytes ( 6.11%)
              OpMemberDecorate =  14332 hits ( 4.99%) 280916 bytes ( 5.63%)
                    OpConstant =  10823 hits ( 3.77%) 173168 bytes ( 3.47%)
                       OpLabel =   9915 hits ( 3.46%)  79320 bytes ( 1.59%)
               OpVectorShuffle =   9732 hits ( 3.39%) 308372 bytes ( 6.19%)
            OpCompositeExtract =   9595 hits ( 3.34%) 193220 bytes ( 3.88%)
                        OpName =   9233 hits ( 3.22%) 164092 bytes ( 3.29%)
                        OpFMul =   8532 hits ( 2.97%) 170640 bytes ( 3.42%)
          OpCompositeConstruct =   6678 hits ( 2.33%) 166680 bytes ( 3.34%)
                        OpFAdd =   5922 hits ( 2.06%) 118440 bytes ( 2.38%)
                 OpTypePointer =   5486 hits ( 1.91%)  87776 bytes ( 1.76%)
                     OpExtInst =   5257 hits ( 1.83%) 145980 bytes ( 2.93%)
                      OpBranch =   5229 hits ( 1.82%)  41832 bytes ( 0.84%)
           OpBranchConditional =   3193 hits ( 1.11%)  51088 bytes ( 1.02%)
              OpSelectionMerge =   3109 hits ( 1.08%)  37308 bytes ( 0.75%)
                        OpFSub =   2668 hits ( 0.93%)  53360 bytes ( 1.07%)
                  OpMemberName =   2507 hits ( 0.87%)  78044 bytes ( 1.57%)
                OpFunctionCall =   2198 hits ( 0.77%)  58520 bytes ( 1.17%)
           OpConstantComposite =   2155 hits ( 0.75%)  50928 bytes ( 1.02%)
           OpFunctionParameter =   2117 hits ( 0.74%)  25404 bytes ( 0.51%)
                         OpDot =   1911 hits ( 0.67%)  38220 bytes ( 0.77%)
           OpVectorTimesScalar =   1488 hits ( 0.52%)  29760 bytes ( 0.60%)
                    OpFunction =   1398 hits ( 0.49%)  27960 bytes ( 0.56%)
                 OpFunctionEnd =   1398 hits ( 0.49%)   5592 bytes ( 0.11%)
                OpTypeFunction =   1175 hits ( 0.41%)  21076 bytes ( 0.42%)
                  OpTypeVector =   1110 hits ( 0.39%)  17760 bytes ( 0.36%)
                  OpTypeStruct =   1065 hits ( 0.37%)  58496 bytes ( 1.17%)
                     OpFNegate =   1038 hits ( 0.36%)  16608 bytes ( 0.33%)
                   OpTypeArray =   1038 hits ( 0.36%)  16608 bytes ( 0.33%)
      OpImageSampleImplicitLod =    969 hits ( 0.34%)  19660 bytes ( 0.39%)
                        OpFDiv =    961 hits ( 0.33%)  19220 bytes ( 0.39%)
                 OpReturnValue =    928 hits ( 0.32%)   7424 bytes ( 0.15%)
                   OpFOrdEqual =    722 hits ( 0.25%)  14440 bytes ( 0.29%)
                     OpTypeInt =    661 hits ( 0.23%)  10576 bytes ( 0.21%)
           OpFOrdLessThanEqual =    595 hits ( 0.21%)  11900 bytes ( 0.24%)
                OpFOrdLessThan =    588 hits ( 0.20%)  11760 bytes ( 0.24%)
                      OpIEqual =    586 hits ( 0.20%)  11720 bytes ( 0.24%)
                      OpReturn =    525 hits ( 0.18%)   2100 bytes ( 0.04%)
                        OpIAdd =    465 hits ( 0.16%)   9300 bytes ( 0.19%)
                   OpTypeImage =    437 hits ( 0.15%)  15732 bytes ( 0.32%)
            OpTypeSampledImage =    437 hits ( 0.15%)   5244 bytes ( 0.11%)
        OpFOrdGreaterThanEqual =    412 hits ( 0.14%)   8240 bytes ( 0.17%)
             OpFOrdGreaterThan =    391 hits ( 0.14%)   7820 bytes ( 0.16%)
      OpImageSampleExplicitLod =    376 hits ( 0.13%)  11128 bytes ( 0.22%)
                  OpCapability =    372 hits ( 0.13%)   2976 bytes ( 0.06%)
               OpExtInstImport =    341 hits ( 0.12%)   8184 bytes ( 0.16%)
                 OpMemoryModel =    341 hits ( 0.12%)   4092 bytes ( 0.08%)
                  OpEntryPoint =    341 hits ( 0.12%)  17808 bytes ( 0.36%)
                    OpTypeVoid =    341 hits ( 0.12%)   2728 bytes ( 0.05%)
                   OpTypeFloat =    341 hits ( 0.12%)   4092 bytes ( 0.08%)
                  OpLogicalAnd =    331 hits ( 0.12%)   6620 bytes ( 0.13%)
                         OpPhi =    281 hits ( 0.10%)   7868 bytes ( 0.16%)
                  OpTypeMatrix =    255 hits ( 0.09%)   4080 bytes ( 0.08%)
               OpExecutionMode =    235 hits ( 0.08%)   2852 bytes ( 0.06%)
  OpImageSampleDrefExplicitLod =    226 hits ( 0.08%)   7232 bytes ( 0.15%)
                    OpTypeBool =    212 hits ( 0.07%)   1696 bytes ( 0.03%)
           OpVectorTimesMatrix =    194 hits ( 0.07%)   3880 bytes ( 0.08%)
             OpSourceExtension =    167 hits ( 0.06%)   5732 bytes ( 0.11%)
                  OpLogicalNot =    160 hits ( 0.06%)   2560 bytes ( 0.05%)
                      OpSource =    141 hits ( 0.05%)   1692 bytes ( 0.03%)
                        OpIMul =    135 hits ( 0.05%)   2700 bytes ( 0.05%)
                 OpConvertSToF =    116 hits ( 0.04%)   1856 bytes ( 0.04%)
                        OpFMod =    114 hits ( 0.04%)   2280 bytes ( 0.05%)
                   OpLogicalOr =     93 hits ( 0.03%)   1860 bytes ( 0.04%)
                   OpSLessThan =     92 hits ( 0.03%)   1840 bytes ( 0.04%)
                   OpLoopMerge =     84 hits ( 0.03%)   1344 bytes ( 0.03%)
                      OpSelect =     68 hits ( 0.02%)   1632 bytes ( 0.03%)
                 OpConvertFToS =     67 hits ( 0.02%)   1072 bytes ( 0.02%)
                     OpBitcast =     66 hits ( 0.02%)   1056 bytes ( 0.02%)
           OpMatrixTimesVector =     48 hits ( 0.02%)    960 bytes ( 0.02%)
            OpShiftLeftLogical =     46 hits ( 0.02%)    920 bytes ( 0.02%)
                OpFOrdNotEqual =     43 hits ( 0.01%)    860 bytes ( 0.02%)
                        OpKill =     40 hits ( 0.01%)    160 bytes ( 0.00%)
           OpSGreaterThanEqual =     39 hits ( 0.01%)    780 bytes ( 0.02%)
           OpMatrixTimesScalar =     32 hits ( 0.01%)    640 bytes ( 0.01%)
                        OpISub =     21 hits ( 0.01%)    420 bytes ( 0.01%)
              OpSLessThanEqual =     21 hits ( 0.01%)    420 bytes ( 0.01%)
           OpMatrixTimesMatrix =     15 hits ( 0.01%)    300 bytes ( 0.01%)
                        OpSDiv =     12 hits ( 0.00%)    240 bytes ( 0.00%)
                      OpFwidth =      8 hits ( 0.00%)    128 bytes ( 0.00%)
                 OpConvertUToF =      6 hits ( 0.00%)     96 bytes ( 0.00%)
                   OpTranspose =      6 hits ( 0.00%)     96 bytes ( 0.00%)
                OpConstantTrue =      5 hits ( 0.00%)     60 bytes ( 0.00%)
                   OpINotEqual =      5 hits ( 0.00%)    100 bytes ( 0.00%)
                  OpEmitVertex =      5 hits ( 0.00%)     20 bytes ( 0.00%)
               OpConstantFalse =      5 hits ( 0.00%)     60 bytes ( 0.00%)
              OpControlBarrier =      4 hits ( 0.00%)     64 bytes ( 0.00%)
                         OpAny =      4 hits ( 0.00%)     64 bytes ( 0.00%)
                     OpSNegate =      3 hits ( 0.00%)     48 bytes ( 0.00%)
             OpLogicalNotEqual =      3 hits ( 0.00%)     60 bytes ( 0.00%)
        OpVectorExtractDynamic =      3 hits ( 0.00%)     60 bytes ( 0.00%)
                   OpULessThan =      2 hits ( 0.00%)     40 bytes ( 0.00%)
                        OpUMod =      2 hits ( 0.00%)     40 bytes ( 0.00%)
                        OpDPdx =      2 hits ( 0.00%)     32 bytes ( 0.00%)
                        OpDPdy =      2 hits ( 0.00%)     32 bytes ( 0.00%)
                OpEndPrimitive =      2 hits ( 0.00%)      8 bytes ( 0.00%)
             OpCompositeInsert =      1 hits ( 0.00%)     24 bytes ( 0.00%)
            OpTypeRuntimeArray =      1 hits ( 0.00%)     12 bytes ( 0.00%)
                       OpUndef =      1 hits ( 0.00%)     12 bytes ( 0.00%)
                OpSGreaterThan =      1 hits ( 0.00%)     20 bytes ( 0.00%)

We can see that loading and storing dominates our shader modules at 28% of the opcodes and 25% of the binary size.

Summary

The tool showed us some interesting divergent trends across each of the providers of the SPIR-V shader modules. Thanks to Valve, Shadertoy, Croteam and Unity for allowing @aras_p to use their SPIR-V shaders when he wrote his smol-v tool. I wouldn’t have had such interesting source material otherwise to run my tool against!

The  spirv-stats tool can be got via its GitHub repository – hope it is useful to someone!

One thought on “spirv-stats – a tool to output statistics of your SPIR-V shader modules

  1. Pingback: spirv-stats update – exposing more information | Duskborn

Leave a Reply

Your email address will not be published. Required fields are marked *