SPIR-V: Move from Version .99 Rev 31 to Version 1.0, Rev 2.
diff --git a/SPIRV/GLSL.std.450.h b/SPIRV/GLSL.std.450.h
index 13bb8e3..d1c9b5c 100755
--- a/SPIRV/GLSL.std.450.h
+++ b/SPIRV/GLSL.std.450.h
@@ -28,7 +28,7 @@
 #define GLSLstd450_H
 
 const int GLSLstd450Version = 99;
-const int GLSLstd450Revision = 2;
+const int GLSLstd450Revision = 3;
 
 enum GLSLstd450 {
     GLSLstd450Bad = 0,              // Don't use
@@ -82,47 +82,44 @@
     GLSLstd450FClamp = 43,
     GLSLstd450UClamp = 44,
     GLSLstd450SClamp = 45,
-    GLSLstd450Mix = 46,
-    GLSLstd450Step = 47,
-    GLSLstd450SmoothStep = 48,
+    GLSLstd450FMix = 46,
+    GLSLstd450IMix = 47,
+    GLSLstd450Step = 48,
+    GLSLstd450SmoothStep = 49,
 
-    GLSLstd450Fma = 49,
-    GLSLstd450Frexp = 50,            // second operand needs an OpVariable to write to
-    GLSLstd450FrexpStruct = 51,      // no OpVariable operand
-    GLSLstd450Ldexp = 52,
+    GLSLstd450Fma = 50,
+    GLSLstd450Frexp = 51,            // second operand needs an OpVariable to write to
+    GLSLstd450FrexpStruct = 52,      // no OpVariable operand
+    GLSLstd450Ldexp = 53,
 
-    GLSLstd450PackSnorm4x8 = 53,
-    GLSLstd450PackUnorm4x8 = 54,
-    GLSLstd450PackSnorm2x16 = 55,
-    GLSLstd450PackUnorm2x16 = 56,
-    GLSLstd450PackHalf2x16 = 57,
-    GLSLstd450PackDouble2x32 = 58,
-    GLSLstd450UnpackSnorm2x16 = 59,
-    GLSLstd450UnpackUnorm2x16 = 60,
-    GLSLstd450UnpackHalf2x16 = 61,
-    GLSLstd450UnpackSnorm4x8 = 62,
-    GLSLstd450UnpackUnorm4x8 = 63,
-    GLSLstd450UnpackDouble2x32 = 64,
+    GLSLstd450PackSnorm4x8 = 54,
+    GLSLstd450PackUnorm4x8 = 55,
+    GLSLstd450PackSnorm2x16 = 56,
+    GLSLstd450PackUnorm2x16 = 57,
+    GLSLstd450PackHalf2x16 = 58,
+    GLSLstd450PackDouble2x32 = 59,
+    GLSLstd450UnpackSnorm2x16 = 60,
+    GLSLstd450UnpackUnorm2x16 = 61,
+    GLSLstd450UnpackHalf2x16 = 62,
+    GLSLstd450UnpackSnorm4x8 = 63,
+    GLSLstd450UnpackUnorm4x8 = 64,
+    GLSLstd450UnpackDouble2x32 = 65,
 
-    GLSLstd450Length = 65,
-    GLSLstd450Distance = 66,
-    GLSLstd450Cross = 67,
-    GLSLstd450Normalize = 68,
-    GLSLstd450FaceForward = 69,
-    GLSLstd450Reflect = 70,
-    GLSLstd450Refract = 71,
+    GLSLstd450Length = 66,
+    GLSLstd450Distance = 67,
+    GLSLstd450Cross = 68,
+    GLSLstd450Normalize = 69,
+    GLSLstd450FaceForward = 70,
+    GLSLstd450Reflect = 71,
+    GLSLstd450Refract = 72,
 
-    GLSLstd450FindILSB = 72,
-    GLSLstd450FindSMSB = 73,
-    GLSLstd450FindUMSB = 74,
+    GLSLstd450FindILsb = 73,
+    GLSLstd450FindSMsb = 74,
+    GLSLstd450FindUMsb = 75,
 
-    GLSLstd450InterpolateAtCentroid = 75,
-    GLSLstd450InterpolateAtSample = 76,
-    GLSLstd450InterpolateAtOffset = 77,
-
-    GLSLstd450AddCarry = 78,        // These three should move to the core instruction set
-    GLSLstd450SubBorrow = 79,
-    GLSLstd450MulExtended = 80,
+    GLSLstd450InterpolateAtCentroid = 76,
+    GLSLstd450InterpolateAtSample = 77,
+    GLSLstd450InterpolateAtOffset = 78,
 
     GLSLstd450Count
 };
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index c005197..c5342ac 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -60,7 +60,10 @@
 
 namespace {
 
-const int GlslangMagic = 0x51a;
+// For low-order part of the generator's magic number. Bump up
+// when there is a change in the style (e.g., if SSA form changes,
+// or a different instruction sequence to do something gets used).
+const int GeneratorVersion = 1;
 
 //
 // The main holder of information for translating glslang to SPIR-V.
@@ -113,13 +116,16 @@
     spv::Id createNoArgOperation(glslang::TOperator op);
     spv::Id getSymbolId(const glslang::TIntermSymbol* node);
     void addDecoration(spv::Id id, spv::Decoration dec);
+    void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
     void addMemberDecoration(spv::Id id, int member, spv::Decoration dec);
-    spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst);
+    spv::Id createSpvSpecConstant(const glslang::TIntermTyped&);
+    spv::Id createSpvConstant(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant);
     bool isTrivialLeaf(const glslang::TIntermTyped* node);
     bool isTrivial(const glslang::TIntermTyped* node);
     spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
 
     spv::Function* shaderEntry;
+    spv::Instruction* entryPoint;
     int sequenceDepth;
 
     // There is a 1:1 mapping between a spv builder and a module; this is thread safe
@@ -169,7 +175,7 @@
     case EShLangFragment:         return spv::ExecutionModelFragment;
     case EShLangCompute:          return spv::ExecutionModelGLCompute;
     default:
-        spv::MissingFunctionality("GLSL stage");
+        assert(0);
         return spv::ExecutionModelFragment;
     }
 }
@@ -191,12 +197,12 @@
         // TODO: how are we distuingishing between default and non-default non-writable uniforms?  Do default uniforms even exist?
     } else {
         switch (type.getQualifier().storage) {
-        case glslang::EvqShared:        return spv::StorageClassWorkgroupLocal;  break;
-        case glslang::EvqGlobal:        return spv::StorageClassPrivateGlobal;
+        case glslang::EvqShared:        return spv::StorageClassWorkgroup;  break;
+        case glslang::EvqGlobal:        return spv::StorageClassPrivate;
         case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
         case glslang::EvqTemporary:     return spv::StorageClassFunction;
         default: 
-            spv::MissingFunctionality("unknown glslang storage class");
+            assert(0);
             return spv::StorageClassFunction;
         }
     }
@@ -206,14 +212,14 @@
 spv::Dim TranslateDimensionality(const glslang::TSampler& sampler)
 {
     switch (sampler.dim) {
-    case glslang::Esd1D:     return spv::Dim1D;
-    case glslang::Esd2D:     return spv::Dim2D;
-    case glslang::Esd3D:     return spv::Dim3D;
-    case glslang::EsdCube:   return spv::DimCube;
-    case glslang::EsdRect:   return spv::DimRect;
-    case glslang::EsdBuffer: return spv::DimBuffer;
+    case glslang::Esd1D:      return spv::Dim1D;
+    case glslang::Esd2D:      return spv::Dim2D;
+    case glslang::Esd3D:      return spv::Dim3D;
+    case glslang::EsdCube:    return spv::DimCube;
+    case glslang::EsdRect:    return spv::DimRect;
+    case glslang::EsdBuffer:  return spv::DimBuffer;
     default:
-        spv::MissingFunctionality("unknown sampler dimension");
+        assert(0);
         return spv::Dim2D;
     }
 }
@@ -240,7 +246,7 @@
         case glslang::EvqVaryingIn:    return spv::DecorationBlock;
         case glslang::EvqVaryingOut:   return spv::DecorationBlock;
         default:
-            spv::MissingFunctionality("kind of block");
+            assert(0);
             break;
         }
     }
@@ -275,11 +281,10 @@
                 }
             case glslang::EvqVaryingIn:
             case glslang::EvqVaryingOut:
-                if (type.getQualifier().layoutPacking != glslang::ElpNone)
-                    spv::MissingFunctionality("in/out block layout");
+                assert(type.getQualifier().layoutPacking == glslang::ElpNone);
                 return (spv::Decoration)spv::BadValue;
             default:
-                spv::MissingFunctionality("block storage qualification");
+                assert(0);
                 return (spv::Decoration)spv::BadValue;
             }
         }
@@ -287,12 +292,16 @@
 }
 
 // Translate glslang type to SPIR-V interpolation decorations.
+// Returns spv::Decoration(spv::BadValue) when no decoration
+// should be applied.
 spv::Decoration TranslateInterpolationDecoration(const glslang::TType& type)
 {
-    if (type.getQualifier().smooth)
-        return spv::DecorationSmooth;
+    if (type.getQualifier().smooth) {
+        // Smooth decoration doesn't exist in SPIR-V 1.0
+        return (spv::Decoration)spv::BadValue;
+    }
     if (type.getQualifier().nopersp)
-        return spv::DecorationNoperspective;
+        return spv::DecorationNoPerspective;
     else if (type.getQualifier().patch)
         return spv::DecorationPatch;
     else if (type.getQualifier().flat)
@@ -344,8 +353,6 @@
     case glslang::EbvSampleId:             return spv::BuiltInSampleId;
     case glslang::EbvSamplePosition:       return spv::BuiltInSamplePosition;
     case glslang::EbvSampleMask:           return spv::BuiltInSampleMask;
-    case glslang::EbvFragColor:            return spv::BuiltInFragColor;
-    case glslang::EbvFragData:             return spv::BuiltInFragColor;
     case glslang::EbvFragDepth:            return spv::BuiltInFragDepth;
     case glslang::EbvHelperInvocation:     return spv::BuiltInHelperInvocation;
     case glslang::EbvNumWorkGroups:        return spv::BuiltInNumWorkgroups;
@@ -414,7 +421,7 @@
 
 TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* glslangIntermediate)
     : TIntermTraverser(true, false, true), shaderEntry(0), sequenceDepth(0),
-      builder(GlslangMagic),
+      builder((glslang::GetKhronosToolId() << 16) | GeneratorVersion),
       inMain(false), mainTerminated(false), linkageOnly(false),
       glslangIntermediate(glslangIntermediate)
 {
@@ -425,7 +432,7 @@
     stdBuiltins = builder.import("GLSL.std.450");
     builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
     shaderEntry = builder.makeMain();
-    builder.addEntryPoint(executionModel, shaderEntry, "main");
+    entryPoint = builder.addEntryPoint(executionModel, shaderEntry, "main");
 
     // Add the source extensions
     const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
@@ -451,9 +458,9 @@
     case EShLangTessEvaluation:
         builder.addCapability(spv::CapabilityTessellation);
         switch (glslangIntermediate->getInputPrimitive()) {
-        case glslang::ElgTriangles:           mode = spv::ExecutionModeInputTriangles;     break;
-        case glslang::ElgQuads:               mode = spv::ExecutionModeInputQuads;         break;
-        case glslang::ElgIsolines:            mode = spv::ExecutionModeInputIsolines;      break;
+        case glslang::ElgTriangles:           mode = spv::ExecutionModeTriangles;     break;
+        case glslang::ElgQuads:               mode = spv::ExecutionModeQuads;         break;
+        case glslang::ElgIsolines:            mode = spv::ExecutionModeIsolines;      break;
         default:                              mode = spv::BadValue;                        break;
         }
         if (mode != spv::BadValue)
@@ -486,7 +493,7 @@
         case glslang::ElgPoints:             mode = spv::ExecutionModeInputPoints;             break;
         case glslang::ElgLines:              mode = spv::ExecutionModeInputLines;              break;
         case glslang::ElgLinesAdjacency:     mode = spv::ExecutionModeInputLinesAdjacency;     break;
-        case glslang::ElgTriangles:          mode = spv::ExecutionModeInputTriangles;          break;
+        case glslang::ElgTriangles:          mode = spv::ExecutionModeTriangles;               break;
         case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break;
         default:                             mode = spv::BadValue;         break;
         }
@@ -520,7 +527,6 @@
             builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests);
 
         switch(glslangIntermediate->getDepth()) {
-        case glslang::EldAny:      mode = spv::ExecutionModeDepthAny;     break;
         case glslang::EldGreater:  mode = spv::ExecutionModeDepthGreater; break;
         case glslang::EldLess:     mode = spv::ExecutionModeDepthLess;    break;
         default:                   mode = spv::BadValue;                  break;
@@ -591,6 +597,11 @@
             builder.setAccessChainRValue(id);
         else
             builder.setAccessChainLValue(id);
+    } else {
+        // finish off the entry-point SPV instruction by adding the Input/Output <id>
+        spv::StorageClass sc = builder.getStorageClass(id);
+        if (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)
+            entryPoint->addIdOperand(id);
     }
 }
 
@@ -639,8 +650,7 @@
                                                node->getType().getBasicType());
 
                 // these all need their counterparts in createBinaryOperation()
-                if (rValue == 0)
-                    spv::MissingFunctionality("createBinaryOperation");
+                assert(rValue != spv::NoResult);
             }
 
             // store the result
@@ -660,20 +670,13 @@
 
             // Add the next element in the chain
 
-            int index = 0;
-            if (node->getRight()->getAsConstantUnion() == 0)
-                spv::MissingFunctionality("direct index without a constant node");
-            else 
-                index = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
-
+            int index = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
             if (node->getLeft()->getBasicType() == glslang::EbtBlock && node->getOp() == glslang::EOpIndexDirectStruct) {
                 // This may be, e.g., an anonymous block-member selection, which generally need
                 // index remapping due to hidden members in anonymous blocks.
                 std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()];
-                if (remapper.size() == 0)
-                    spv::MissingFunctionality("block without member remapping");
-                else
-                    index = remapper[index];
+                assert(remapper.size() > 0);
+                index = remapper[index];
             }
 
             if (! node->getLeft()->getType().isArray() &&
@@ -766,7 +769,7 @@
                                    node->getLeft()->getType().getBasicType());
 
     if (! result) {
-        spv::MissingFunctionality("glslang binary operation");
+        spv::MissingFunctionality("unknown glslang binary operation");
     } else {
         builder.clearAccessChain();
         builder.setAccessChainRValue(result);
@@ -832,7 +835,7 @@
 
     // if not, then possibly an operation
     if (! result)
-        result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand, node->getBasicType());
+        result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operand, node->getOperand()->getBasicType());
 
     if (result) {
         builder.clearAccessChain();
@@ -862,8 +865,7 @@
             spv::Id result = createBinaryOperation(op, TranslatePrecisionDecoration(node->getType()), 
                                                      convertGlslangToSpvType(node->getType()), operand, one, 
                                                      node->getType().getBasicType());
-            if (result == 0)
-                spv::MissingFunctionality("createBinaryOperation for unary");
+            assert(result != spv::NoResult);
 
             // The result of operation is always stored, but conditionally the
             // consumed result.  The consumed result is always an r-value.
@@ -886,7 +888,7 @@
         return false;
 
     default:
-        spv::MissingFunctionality("glslang unary");
+        spv::MissingFunctionality("unknown glslang unary");
         break;
     }
 
@@ -990,13 +992,7 @@
     {
         if (node->isUserDefined())
             result = handleUserFunctionCall(node);
-
-        if (! result) {
-            spv::MissingFunctionality("glslang function call");
-            glslang::TConstUnionArray emptyConsts;
-            int nextConst = 0;
-            result = createSpvConstant(node->getType(), emptyConsts, nextConst);
-        }
+        assert(result);
         builder.clearAccessChain();
         builder.setAccessChainRValue(result);
 
@@ -1053,12 +1049,10 @@
             for (int c = 0; c < (int)arguments.size(); ++c)
                 constituents.push_back(arguments[c]);
             constructed = builder.createCompositeConstruct(resultTypeId, constituents);
-        } else {
-            if (isMatrix)
-                constructed = builder.createMatrixConstructor(precision, arguments, resultTypeId);
-            else
-                constructed = builder.createConstructor(precision, arguments, resultTypeId);
-        }
+        } else if (isMatrix)
+            constructed = builder.createMatrixConstructor(precision, arguments, resultTypeId);
+        else
+            constructed = builder.createConstructor(precision, arguments, resultTypeId);
 
         builder.clearAccessChain();
         builder.setAccessChainRValue(constructed);
@@ -1131,21 +1125,6 @@
         atomic = true;
         break;
 
-    case glslang::EOpAddCarry:
-    case glslang::EOpSubBorrow:
-    case glslang::EOpUMulExtended:
-    case glslang::EOpIMulExtended:
-    case glslang::EOpBitfieldExtract:
-    case glslang::EOpBitfieldInsert:
-        spv::MissingFunctionality("integer aggregate");
-        break;
-
-    case glslang::EOpFma:
-    case glslang::EOpFrexp:
-    case glslang::EOpLdexp:
-        spv::MissingFunctionality("fma/frexp/ldexp aggregate");
-        break;
-
     default:
         break;
     }
@@ -1171,9 +1150,7 @@
                                        left->getType().getBasicType(), reduceComparison);
 
         // code above should only make binOp that exists in createBinaryOperation
-        if (result == 0)
-            spv::MissingFunctionality("createBinaryOperation for aggregate");
-
+        assert(result != spv::NoResult);
         builder.clearAccessChain();
         builder.setAccessChainRValue(result);
 
@@ -1192,7 +1169,7 @@
         // special case l-value operands; there are just a few
         bool lvalue = false;
         switch (node->getOp()) {
-        //case glslang::EOpFrexp:
+        case glslang::EOpFrexp:
         case glslang::EOpModf:
             if (arg == 1)
                 lvalue = true;
@@ -1208,9 +1185,16 @@
             if (arg == 0)
                 lvalue = true;
             break;
-        //case glslang::EOpUAddCarry:
-        //case glslang::EOpUSubBorrow:
-        //case glslang::EOpUMulExtended:
+        case glslang::EOpAddCarry:
+        case glslang::EOpSubBorrow:
+            if (arg == 2)
+                lvalue = true;
+            break;
+        case glslang::EOpUMulExtended:
+        case glslang::EOpIMulExtended:
+            if (arg >= 2)
+                lvalue = true;
+            break;
         default:
             break;
         }
@@ -1230,7 +1214,7 @@
             result = createNoArgOperation(node->getOp());
             break;
         case 1:
-            result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands.front(), node->getType().getBasicType());
+            result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands.front(), glslangOperands[0]->getAsTyped()->getBasicType());
             break;
         default:
             result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
@@ -1242,7 +1226,7 @@
         return false;
 
     if (! result) {
-        spv::MissingFunctionality("glslang aggregate");
+        spv::MissingFunctionality("unknown glslang aggregate");
         return true;
     } else {
         builder.clearAccessChain();
@@ -1350,7 +1334,7 @@
 void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node)
 {
     int nextConst = 0;
-    spv::Id constant = createSpvConstant(node->getType(), node->getConstArray(), nextConst);
+    spv::Id constant = createSpvConstant(node->getType(), node->getConstArray(), nextConst, false);
 
     builder.clearAccessChain();
     builder.setAccessChainRValue(constant);
@@ -1418,7 +1402,7 @@
         break;
 
     default:
-        spv::MissingFunctionality("branch type");
+        assert(0);
         break;
     }
 
@@ -1429,9 +1413,9 @@
 {
     // First, steer off constants, which are not SPIR-V variables, but 
     // can still have a mapping to a SPIR-V Id.
+    // This includes specialization constants.
     if (node->getQualifier().storage == glslang::EvqConst) {
-        int nextConst = 0;
-        return createSpvConstant(node->getType(), node->getConstArray(), nextConst);
+        return createSpvSpecConstant(*node);
     }
 
     // Now, handle actual variables
@@ -1453,7 +1437,7 @@
         case glslang::EbtInt:      return builder.makeIntType(32);
         case glslang::EbtUint:     return builder.makeUintType(32);
         default:
-            spv::MissingFunctionality("sampled type");
+            assert(0);
             return builder.makeFloatType(32);
     }
 }
@@ -1474,8 +1458,7 @@
     switch (type.getBasicType()) {
     case glslang::EbtVoid:
         spvType = builder.makeVoidType();
-        if (type.isArray())
-            spv::MissingFunctionality("array of void");
+        assert (! type.isArray());
         break;
     case glslang::EbtFloat:
         spvType = builder.makeFloatType(32);
@@ -1499,12 +1482,13 @@
     case glslang::EbtSampler:
         {
             const glslang::TSampler& sampler = type.getSampler();
-            spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
-                                            sampler.image ? 2 : 1, TranslateImageFormat(type));
-            // OpenGL "textures" need to be combined with a sampler
-            if (! sampler.image)
-                spvType = builder.makeSampledImageType(spvType);
-        }
+                // an image is present, make its type
+                spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
+                                                sampler.image ? 2 : 1, TranslateImageFormat(type));
+            if (! sampler.image) {
+                    spvType = builder.makeSampledImageType(spvType);
+                }
+            }
         break;
     case glslang::EbtStruct:
     case glslang::EbtBlock:
@@ -1593,7 +1577,7 @@
         }
         break;
     default:
-        spv::MissingFunctionality("basic type");
+        assert(0);
         break;
     }
 
@@ -1620,10 +1604,14 @@
             spvType = builder.makeArrayType(spvType, type.getOuterArraySize());
         }
 
-        // TODO: layout still needs to be done hierarchically for arrays of arrays, which 
+        // TODO: explicit layout still needs to be done hierarchically for arrays of arrays, which 
         // may still require additional "link time" support from the front-end 
         // for arrays of arrays
-        if (explicitLayout)
+
+        // We need to decorate array strides for types needing explicit layout,
+        // except for the very top if it is an array of blocks; that array is
+        // not laid out in memory in a way needing a stride.
+        if (explicitLayout && type.getBasicType() != glslang::EbtBlock)
             builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type));
     }
 
@@ -1883,8 +1871,11 @@
         operands.push_back(*(opIt++));
         if (node->getOp() == glslang::EOpImageStore)
             operands.push_back(*(opIt++));
-        // TODO: add 'sample' operand
         if (node->getOp() == glslang::EOpImageLoad) {
+            if (sampler.ms) {
+                operands.push_back(spv::ImageOperandsSampleMask);
+                operands.push_back(*(opIt++));
+            }
             return builder.createOp(spv::OpImageRead, convertGlslangToSpvType(node->getType()), operands);
         } else if (node->getOp() == glslang::EOpImageStore) {
             builder.createNoResultOp(spv::OpImageWrite, operands);
@@ -1909,8 +1900,6 @@
     }
 
     // Check for texture functions other than queries
-    if (cracked.gather)
-        spv::MissingFunctionality("texture gather");
 
     // check for bias argument
     bool bias = false;
@@ -1925,14 +1914,18 @@
             bias = true;
     }
 
-    bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow;
-
     // set the rest of the arguments
+
     params.coords = arguments[1];
     int extraArgs = 0;
-    if (cubeCompare)
+
+    // sort out where Dref is coming from
+    if (sampler.shadow && sampler.dim == glslang::EsdCube && sampler.arrayed)
         params.Dref = arguments[2];
-    else if (sampler.shadow) {
+    else if (sampler.shadow && cracked.gather) {
+        params.Dref = arguments[2];
+        ++extraArgs;
+    } else if (sampler.shadow) {
         std::vector<spv::Id> indexes;
         int comp;
         if (cracked.proj)
@@ -1954,20 +1947,28 @@
         params.gradY = arguments[3 + extraArgs];
         extraArgs += 2;
     }
-    //if (gather && compare) {
-    //    params.compare = arguments[2 + extraArgs];
-    //    ++extraArgs;
-    //}
-    if (cracked.offset || cracked.offsets) {
+    if (cracked.offset) {
         params.offset = arguments[2 + extraArgs];
         ++extraArgs;
+    } else if (cracked.offsets) {
+        params.offsets = arguments[2 + extraArgs];
+        ++extraArgs;
     }
     if (bias) {
         params.bias = arguments[2 + extraArgs];
         ++extraArgs;
     }
+    if (cracked.gather && ! sampler.shadow) {
+        // default component is 0, if missing, otherwise an argument
+        if (2 + extraArgs < (int)arguments.size()) {
+            params.comp = arguments[2 + extraArgs];
+            ++extraArgs;
+        } else {
+            params.comp = builder.makeIntConstant(0);
+        }
+    }
 
-    return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), cracked.fetch, cracked.proj, params);
+    return builder.createTextureCall(precision, convertGlslangToSpvType(node->getType()), cracked.fetch, cracked.proj, cracked.gather, params);
 }
 
 spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node)
@@ -2308,6 +2309,7 @@
 {
     spv::Op unaryOp = spv::OpNop;
     int libCall = -1;
+    bool isUnsigned = typeProxy == glslang::EbtUint;
     bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
 
     switch (op) {
@@ -2538,11 +2540,13 @@
         unaryOp = spv::OpBitCount;
         break;
     case glslang::EOpFindLSB:
-        libCall = spv::GLSLstd450FindILSB;
+        libCall = spv::GLSLstd450FindILsb;
         break;
     case glslang::EOpFindMSB:
-        spv::MissingFunctionality("signed vs. unsigned FindMSB");
-        libCall = spv::GLSLstd450FindSMSB;
+        if (isUnsigned)
+            libCall = spv::GLSLstd450FindUMsb;
+        else
+            libCall = spv::GLSLstd450FindSMsb;
         break;
 
     default:
@@ -2717,7 +2721,7 @@
         opCode = spv::OpAtomicLoad;
         break;
     default:
-        spv::MissingFunctionality("missing nested atomic");
+        assert(0);
         break;
     }
 
@@ -2754,6 +2758,11 @@
 
     spv::Op opCode = spv::OpNop;
     int libCall = -1;
+    int consumedOperands = operands.size();
+    spv::Id typeId0 = 0;
+    if (consumedOperands > 0)
+        typeId0 = builder.getTypeId(operands[0]);
+    spv::Id frexpIntType = 0;
 
     switch (op) {
     case glslang::EOpMin:
@@ -2794,7 +2803,10 @@
             libCall = spv::GLSLstd450SClamp;
         break;
     case glslang::EOpMix:
-        libCall = spv::GLSLstd450Mix;
+        if (isFloat)
+            libCall = spv::GLSLstd450FMix;
+        else
+            libCall = spv::GLSLstd450IMix;
         break;
     case glslang::EOpStep:
         libCall = spv::GLSLstd450Step;
@@ -2819,6 +2831,52 @@
         libCall = spv::GLSLstd450Refract;
         break;
 
+    case glslang::EOpAddCarry:
+        opCode = spv::OpIAddCarry;
+        typeId = builder.makeStructResultType(typeId0, typeId0);
+        consumedOperands = 2;
+        break;
+    case glslang::EOpSubBorrow:
+        opCode = spv::OpISubBorrow;
+        typeId = builder.makeStructResultType(typeId0, typeId0);
+        consumedOperands = 2;
+        break;
+    case glslang::EOpUMulExtended:
+        opCode = spv::OpUMulExtended;
+        typeId = builder.makeStructResultType(typeId0, typeId0);
+        consumedOperands = 2;
+        break;
+    case glslang::EOpIMulExtended:
+        opCode = spv::OpSMulExtended;
+        typeId = builder.makeStructResultType(typeId0, typeId0);
+        consumedOperands = 2;
+        break;
+    case glslang::EOpBitfieldExtract:
+        if (isUnsigned)
+            opCode = spv::OpBitFieldUExtract;
+        else
+            opCode = spv::OpBitFieldSExtract;
+        break;
+    case glslang::EOpBitfieldInsert:
+        opCode = spv::OpBitFieldInsert;
+        break;
+
+    case glslang::EOpFma:
+        libCall = spv::GLSLstd450Fma;
+        break;
+    case glslang::EOpFrexp:
+        libCall = spv::GLSLstd450FrexpStruct;
+        if (builder.getNumComponents(operands[0]) == 1)
+            frexpIntType = builder.makeIntegerType(32, true);
+        else
+            frexpIntType = builder.makeVectorType(builder.makeIntegerType(32, true), builder.getNumComponents(operands[0]));
+        typeId = builder.makeStructResultType(typeId0, frexpIntType);
+        consumedOperands = 1;
+        break;
+    case glslang::EOpLdexp:
+        libCall = spv::GLSLstd450Ldexp;
+        break;
+
     default:
         return 0;
     }
@@ -2827,7 +2885,7 @@
     if (libCall >= 0)
         id = builder.createBuiltinCall(precision, typeId, stdBuiltins, libCall, operands);
     else {
-        switch (operands.size()) {
+        switch (consumedOperands) {
         case 0:
             // should all be handled by visitAggregate and createNoArgOperation
             assert(0);
@@ -2839,16 +2897,34 @@
         case 2:
             id = builder.createBinOp(opCode, typeId, operands[0], operands[1]);
             break;
-        case 3:
-            id = builder.createTriOp(opCode, typeId, operands[0], operands[1], operands[2]);
-            break;
         default:
-            // These do not exist yet
-            assert(0 && "operation with more than 3 operands");
+            // anything 3 or over doesn't have l-value operands, so all should be consumed
+            assert(consumedOperands == operands.size());
+            id = builder.createOp(opCode, typeId, operands);
             break;
         }
     }
 
+    // Decode the return types that were structures
+    switch (op) {
+    case glslang::EOpAddCarry:
+    case glslang::EOpSubBorrow:
+        builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
+        id = builder.createCompositeExtract(id, typeId0, 0);
+        break;
+    case glslang::EOpUMulExtended:
+    case glslang::EOpIMulExtended:
+        builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]);
+        builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]);
+        break;
+    case glslang::EOpFrexp:
+        builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]);
+        id = builder.createCompositeExtract(id, typeId0, 0);
+        break;
+    default:
+        break;
+    }
+
     builder.setPrecision(id, precision);
 
     return id;
@@ -2883,13 +2959,13 @@
         builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsImageMemoryMask);
         return 0;
     case glslang::EOpMemoryBarrierShared:
-        builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupLocalMemoryMask);
+        builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupMemoryMask);
         return 0;
     case glslang::EOpGroupMemoryBarrier:
-        builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupGlobalMemoryMask);
+        builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsCrossWorkgroupMemoryMask);
         return 0;
     default:
-        spv::MissingFunctionality("operation with no arguments");
+        spv::MissingFunctionality("unknown operation with no arguments");
         return 0;
     }
 }
@@ -2945,31 +3021,57 @@
     if (builtIn != spv::BadValue)
         builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
 
-    if (linkageOnly)
-        builder.addDecoration(id, spv::DecorationNoStaticUse);
-
     return id;
 }
 
+// If 'dec' is valid, add no-operand decoration to an object
 void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec)
 {
     if (dec != spv::BadValue)
         builder.addDecoration(id, dec);
 }
 
+// If 'dec' is valid, add a one-operand decoration to an object
+void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec, unsigned value)
+{
+    if (dec != spv::BadValue)
+        builder.addDecoration(id, dec, value);
+}
+
+// If 'dec' is valid, add a no-operand decoration to a struct member
 void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec)
 {
     if (dec != spv::BadValue)
         builder.addMemberDecoration(id, (unsigned)member, dec);
 }
 
+// Make a full tree of instructions to build a SPIR-V specialization constant,
+// or regularly constant if possible.
+//
+// TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though
+//
+// Recursively walk the nodes.  The nodes form a tree whose leaves are
+// regular constants, which themselves are trees that createSpvConstant()
+// recursively walks.  So, this function walks the "top" of the tree:
+//  - emit specialization constant-building instructions for specConstant
+//  - when running into a non-spec-constant, switch to createSpvConstant()
+spv::Id TGlslangToSpvTraverser::createSpvSpecConstant(const glslang::TIntermTyped& node)
+{
+    assert(node.getQualifier().storage == glslang::EvqConst);
+
+    // hand off to the non-spec-constant path
+    assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
+    int nextConst = 0;
+    return createSpvConstant(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), nextConst, false);
+}
+
 // Use 'consts' as the flattened glslang source of scalar constants to recursively
 // build the aggregate SPIR-V constant.
 //
 // If there are not enough elements present in 'consts', 0 will be substituted;
 // an empty 'consts' can be used to create a fully zeroed SPIR-V constant.
 //
-spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst)
+spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant)
 {
     // vector of constants for SPIR-V
     std::vector<spv::Id> spvConsts;
@@ -2980,15 +3082,15 @@
     if (glslangType.isArray()) {
         glslang::TType elementType(glslangType, 0);
         for (int i = 0; i < glslangType.getOuterArraySize(); ++i)
-            spvConsts.push_back(createSpvConstant(elementType, consts, nextConst));
+            spvConsts.push_back(createSpvConstant(elementType, consts, nextConst, false));
     } else if (glslangType.isMatrix()) {
         glslang::TType vectorType(glslangType, 0);
         for (int col = 0; col < glslangType.getMatrixCols(); ++col)
-            spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst));
+            spvConsts.push_back(createSpvConstant(vectorType, consts, nextConst, false));
     } else if (glslangType.getStruct()) {
         glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
         for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
-            spvConsts.push_back(createSpvConstant(*iter->type, consts, nextConst));
+            spvConsts.push_back(createSpvConstant(*iter->type, consts, nextConst, false));
     } else if (glslangType.isVector()) {
         for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) {
             bool zero = nextConst >= consts.size();
@@ -3009,7 +3111,7 @@
                 spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst()));
                 break;
             default:
-                spv::MissingFunctionality("constant vector type");
+                assert(0);
                 break;
             }
             ++nextConst;
@@ -3020,22 +3122,22 @@
         spv::Id scalar = 0;
         switch (glslangType.getBasicType()) {
         case glslang::EbtInt:
-            scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst());
+            scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant);
             break;
         case glslang::EbtUint:
-            scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst());
+            scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant);
             break;
         case glslang::EbtFloat:
-            scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst());
+            scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant);
             break;
         case glslang::EbtDouble:
-            scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst());
+            scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant);
             break;
         case glslang::EbtBool:
-            scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst());
+            scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant);
             break;
         default:
-            spv::MissingFunctionality("constant scalar type");
+            assert(0);
             break;
         }
         ++nextConst;
@@ -3180,7 +3282,7 @@
 {
     const int bufSize = 100;
     char buf[bufSize];
-    snprintf(buf, bufSize, "%d, Revision %d", spv::Version, spv::Revision);
+    snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision);
     version = buf;
 }
 
diff --git a/SPIRV/SPVRemapper.cpp b/SPIRV/SPVRemapper.cpp
index 0f303e3..9beba21 100755
--- a/SPIRV/SPVRemapper.cpp
+++ b/SPIRV/SPVRemapper.cpp
@@ -446,7 +446,6 @@
                 idFn(asId(word++));
                 break;
 
-            case spv::OperandOptionalId:
             case spv::OperandVariableIds:
                 for (unsigned i = 0; i < numOperands; ++i)
                     idFn(asId(word++));
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index dba9c4c..a46c924 100755
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -55,14 +55,12 @@
 
 namespace spv {
 
-const int SpvBuilderMagic = 0xBB;
-
-Builder::Builder(unsigned int userNumber) :
+Builder::Builder(unsigned int magicNumber) :
     source(SourceLanguageUnknown),
     sourceVersion(0),
     addressModel(AddressingModelLogical),
     memoryModel(MemoryModelGLSL450),
-    builderNumber(userNumber << 16 | SpvBuilderMagic),
+    builderNumber(magicNumber),
     buildPoint(0),
     uniqueId(0),
     mainFunction(0)
@@ -112,6 +110,20 @@
     return type->getResultId();
 }
 
+Id Builder::makeSamplerType()
+{
+    Instruction* type;
+    if (groupedTypes[OpTypeSampler].size() == 0) {
+        type = new Instruction(getUniqueId(), NoType, OpTypeSampler);
+        groupedTypes[OpTypeSampler].push_back(type);
+        constantsTypesGlobals.push_back(type);
+        module.mapInstruction(type);
+    } else
+        type = groupedTypes[OpTypeSampler].back();
+
+    return type->getResultId();
+}
+
 Id Builder::makePointer(StorageClass storageClass, Id pointee)
 {
     // try to find it
@@ -176,8 +188,15 @@
     return type->getResultId();
 }
 
+// Make a struct without checking for duplication.
+// See makeStructResultType() for non-decorated structs
+// needed as the result of some instructions, which does
+// check for duplicates.
 Id Builder::makeStructType(std::vector<Id>& members, const char* name)
 {
+    // Don't look for previous one, because in the general case,
+    // structs can be duplicated except for decorations.
+
     // not found, make it
     Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct);
     for (int op = 0; op < (int)members.size(); ++op)
@@ -190,6 +209,30 @@
     return type->getResultId();
 }
 
+// Make a struct for the simple results of several instructions,
+// checking for duplication.
+Id Builder::makeStructResultType(Id type0, Id type1)
+{
+    // try to find it
+    Instruction* type;
+    for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) {
+        type = groupedTypes[OpTypeStruct][t];
+        if (type->getNumOperands() != 2)
+            continue;
+        if (type->getIdOperand(0) != type0 || 
+            type->getIdOperand(1) != type1)
+            continue;
+        return type->getResultId();
+    }
+
+    // not found, make it
+    std::vector<spv::Id> members;
+    members.push_back(type0);
+    members.push_back(type1);
+
+    return makeStructType(members, "ResType");
+}
+
 Id Builder::makeVectorType(Id component, int size)
 {
     // try to find it
@@ -387,7 +430,7 @@
     case OpTypePointer:
         return getMostBasicTypeClass(instr->getIdOperand(1));
     default:
-        MissingFunctionality("getMostBasicTypeClass");
+        assert(0);
         return OpTypeFloat;
     }
 }
@@ -406,7 +449,7 @@
     case OpTypeMatrix:
         return instr->getImmediateOperand(1);
     default:
-        MissingFunctionality("getNumTypeComponents on non bool/int/float/vector/matrix");
+        assert(0);
         return 1;
     }
 }
@@ -434,7 +477,7 @@
     case OpTypePointer:
         return getScalarTypeId(getContainedTypeId(typeId));
     default:
-        MissingFunctionality("getScalarTypeId");
+        assert(0);
         return NoResult;
     }
 }
@@ -457,7 +500,7 @@
     case OpTypeStruct:
         return instr->getIdOperand(member);
     default:
-        MissingFunctionality("getContainedTypeId");
+        assert(0);
         return NoResult;
     }
 }
@@ -470,12 +513,12 @@
 
 // See if a scalar constant of this type has already been created, so it
 // can be reused rather than duplicated.  (Required by the specification).
-Id Builder::findScalarConstant(Op typeClass, Id typeId, unsigned value) const
+Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const
 {
     Instruction* constant;
     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
         constant = groupedConstants[typeClass][i];
-        if (constant->getNumOperands() == 1 &&
+        if (constant->getOpCode() == opcode &&
             constant->getTypeId() == typeId &&
             constant->getImmediateOperand(0) == value)
             return constant->getResultId();
@@ -485,12 +528,12 @@
 }
 
 // Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double').
-Id Builder::findScalarConstant(Op typeClass, Id typeId, unsigned v1, unsigned v2) const
+Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const
 {
     Instruction* constant;
     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
         constant = groupedConstants[typeClass][i];
-        if (constant->getNumOperands() == 2 &&
+        if (constant->getOpCode() == opcode &&
             constant->getTypeId() == typeId &&
             constant->getImmediateOperand(0) == v1 &&
             constant->getImmediateOperand(1) == v2)
@@ -524,18 +567,17 @@
     }
 }
 
-Id Builder::makeBoolConstant(bool b)
+Id Builder::makeBoolConstant(bool b, bool specConstant)
 {
     Id typeId = makeBoolType();
     Instruction* constant;
+    Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse);
 
     // See if we already made it
     Id existing = 0;
     for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) {
         constant = groupedConstants[OpTypeBool][i];
-        if (constant->getTypeId() == typeId &&
-            (b ? (constant->getOpCode() == OpConstantTrue) : 
-                 (constant->getOpCode() == OpConstantFalse)))
+        if (constant->getTypeId() == typeId && constant->getOpCode() == opcode)
             existing = constant->getResultId();
     }
 
@@ -543,7 +585,7 @@
         return existing;
 
     // Make it
-    Instruction* c = new Instruction(getUniqueId(), typeId, b ? OpConstantTrue : OpConstantFalse);
+    Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
     constantsTypesGlobals.push_back(c);
     groupedConstants[OpTypeBool].push_back(c);
     module.mapInstruction(c);
@@ -551,13 +593,14 @@
     return c->getResultId();
 }
 
-Id Builder::makeIntConstant(Id typeId, unsigned value)
+Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
 {
-    Id existing = findScalarConstant(OpTypeInt, typeId, value);
+    Op opcode = specConstant ? OpSpecConstant : OpConstant;
+    Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value);
     if (existing)
         return existing;
 
-    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstant);
+    Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
     c->addImmediateOperand(value);
     constantsTypesGlobals.push_back(c);
     groupedConstants[OpTypeInt].push_back(c);
@@ -566,15 +609,16 @@
     return c->getResultId();
 }
 
-Id Builder::makeFloatConstant(float f)
+Id Builder::makeFloatConstant(float f, bool specConstant)
 {
+    Op opcode = specConstant ? OpSpecConstant : OpConstant;
     Id typeId = makeFloatType(32);
     unsigned value = *(unsigned int*)&f;
-    Id existing = findScalarConstant(OpTypeFloat, typeId, value);
+    Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
     if (existing)
         return existing;
 
-    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstant);
+    Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
     c->addImmediateOperand(value);
     constantsTypesGlobals.push_back(c);
     groupedConstants[OpTypeFloat].push_back(c);
@@ -583,17 +627,18 @@
     return c->getResultId();
 }
 
-Id Builder::makeDoubleConstant(double d)
+Id Builder::makeDoubleConstant(double d, bool specConstant)
 {
+    Op opcode = specConstant ? OpSpecConstant : OpConstant;
     Id typeId = makeFloatType(64);
     unsigned long long value = *(unsigned long long*)&d;
     unsigned op1 = value & 0xFFFFFFFF;
     unsigned op2 = value >> 32;
-    Id existing = findScalarConstant(OpTypeFloat, typeId, op1, op2);
+    Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2);
     if (existing)
         return existing;
 
-    Instruction* c = new Instruction(getUniqueId(), typeId, OpConstant);
+    Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
     c->addImmediateOperand(op1);
     c->addImmediateOperand(op2);
     constantsTypesGlobals.push_back(c);
@@ -644,7 +689,7 @@
     case OpTypeMatrix:
         break;
     default:
-        MissingFunctionality("Constant composite type in Builder");
+        assert(0);
         return makeFloatConstant(0.0);
     }
 
@@ -662,7 +707,7 @@
     return c->getResultId();
 }
 
-void Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name)
+Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name)
 {
     Instruction* entryPoint = new Instruction(OpEntryPoint);
     entryPoint->addImmediateOperand(model);
@@ -670,6 +715,8 @@
     entryPoint->addStringOperand(name);
 
     entryPoints.push_back(entryPoint);
+
+    return entryPoint;
 }
 
 // Currently relying on the fact that all 'value' of interest are small non-negative values.
@@ -720,6 +767,8 @@
 
 void Builder::addDecoration(Id id, Decoration decoration, int num)
 {
+    if (decoration == (spv::Decoration)spv::BadValue)
+        return;
     Instruction* dec = new Instruction(OpDecorate);
     dec->addIdOperand(id);
     dec->addImmediateOperand(decoration);
@@ -833,25 +882,14 @@
     inst->addImmediateOperand(storageClass);
 
     switch (storageClass) {
-    case StorageClassUniformConstant:
-    case StorageClassUniform:
-    case StorageClassInput:
-    case StorageClassOutput:
-    case StorageClassWorkgroupLocal:
-    case StorageClassPrivateGlobal:
-    case StorageClassWorkgroupGlobal:
-    case StorageClassAtomicCounter:
-        constantsTypesGlobals.push_back(inst);
-        module.mapInstruction(inst);
-        break;
-
     case StorageClassFunction:
         // Validation rules require the declaration in the entry block
         buildPoint->getParent().addLocalVariable(inst);
         break;
 
     default:
-        MissingFunctionality("storage class in createVariable");
+        constantsTypesGlobals.push_back(inst);
+        module.mapInstruction(inst);
         break;
     }
 
@@ -1175,7 +1213,7 @@
 
 // Accept all parameters needed to create a texture instruction.
 // Create the correct instruction based on the inputs, and make the call.
-Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, const TextureParameters& parameters)
+Id Builder::createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
 {
     static const int maxTextureArgs = 10;
     Id texArgs[maxTextureArgs] = {};
@@ -1189,6 +1227,8 @@
     texArgs[numArgs++] = parameters.coords;
     if (parameters.Dref)
         texArgs[numArgs++] = parameters.Dref;
+    if (parameters.comp)
+        texArgs[numArgs++] = parameters.comp;
 
     //
     // Set up the optional arguments
@@ -1238,6 +1278,11 @@
     opCode = OpImageSampleImplicitLod;
     if (fetch) {
         opCode = OpImageFetch;
+    } else if (gather) {
+        if (parameters.Dref)
+            opCode = OpImageDrefGather;
+        else
+            opCode = OpImageGather;
     } else if (xplicit) {
         if (parameters.Dref) {
             if (proj)
@@ -1281,6 +1326,7 @@
         }
     }
 
+    // Build the SPIR-V instruction
     Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
     for (int op = 0; op < optArgNum; ++op)
         textureInst->addIdOperand(texArgs[op]);
@@ -1324,8 +1370,12 @@
         case Dim3D:
             numComponents = 3;
             break;
+        case DimSubpassData:
+            MissingFunctionality("input-attachment dim");
+            break;
+
         default:
-            MissingFunctionality("texture query dimensionality");
+            assert(0);
             break;
         }
         if (isArrayedImageType(getImageType(parameters.sampler)))
@@ -1345,7 +1395,8 @@
         resultType = makeIntType(32);
         break;
     default:
-        MissingFunctionality("Texture query op code");
+        assert(0);
+        break;
     }
 
     Instruction* query = new Instruction(getUniqueId(), resultType, opCode);
@@ -1360,57 +1411,6 @@
 }
 
 // Comments in header
-//Id Builder::createSamplePositionCall(Decoration precision, Id returnType, Id sampleIdx)
-//{
-//    // Return type is only flexible type
-//    Function* opCode = (fSamplePosition, returnType);
-//
-//    Instruction* instr = (opCode, sampleIdx);
-//    setPrecision(instr, precision);
-//
-//    return instr;
-//}
-
-// Comments in header
-//Id Builder::createBitFieldExtractCall(Decoration precision, Id id, Id offset, Id bits, bool isSigned)
-//{
-//    Op opCode = isSigned ? sBitFieldExtract
-//                                               : uBitFieldExtract;
-//
-//    if (isScalar(offset) == false || isScalar(bits) == false)
-//        MissingFunctionality("bitFieldExtract operand types");
-//
-//    // Dest and value are matching flexible types
-//    Function* opCode = (opCode, id->getType(), id->getType());
-//
-//    assert(opCode);
-//
-//    Instruction* instr = (opCode, id, offset, bits);
-//    setPrecision(instr, precision);
-//
-//    return instr;
-//}
-
-// Comments in header
-//Id Builder::createBitFieldInsertCall(Decoration precision, Id base, Id insert, Id offset, Id bits)
-//{
-//    Op opCode = bitFieldInsert;
-//
-//    if (isScalar(offset) == false || isScalar(bits) == false)
-//        MissingFunctionality("bitFieldInsert operand types");
-//
-//    // Dest, base, and insert are matching flexible types
-//    Function* opCode = (opCode, base->getType(), base->getType(), base->getType());
-//
-//    assert(opCode);
-//
-//    Instruction* instr = (opCode, base, insert, offset, bits);
-//    setPrecision(instr, precision);
-//
-//    return instr;
-//}
-
-// Comments in header
 Id Builder::createCompare(Decoration precision, Id value1, Id value2, bool equal)
 {
     Id boolType = makeBoolType();
@@ -1488,115 +1488,6 @@
     //return result;
 }
 
-// Comments in header
-//Id Builder::createOperation(Decoration precision, Op opCode, Id operand)
-//{
-//    Op* opCode = 0;
-//
-//    // Handle special return types here.  Things that don't have same result type as parameter
-//    switch (opCode) {
-//    case fIsNan:
-//    case fIsInf:
-//        break;
-//    case fFloatBitsToInt:
-//        break;
-//    case fIntBitsTofloat:
-//        break;
-//    case fPackSnorm2x16:
-//    case fPackUnorm2x16:
-//    case fPackHalf2x16:
-//        break;
-//    case fUnpackUnorm2x16:
-//    case fUnpackSnorm2x16:
-//    case fUnpackHalf2x16:
-//        break;
-//
-//    case fFrexp:
-//    case fLdexp:
-//    case fPackUnorm4x8:
-//    case fPackSnorm4x8:
-//    case fUnpackUnorm4x8:
-//    case fUnpackSnorm4x8:
-//    case fPackDouble2x32:
-//    case fUnpackDouble2x32:
-//        break;
-//    case fLength:
-//       // scalar result type
-//       break;
-//    case any:
-//    case all:
-//        // fixed result type
-//        break;
-//    case fModF:
-//        // modf() will return a struct that the caller must decode
-//        break;
-//    default:
-//        // Unary operations that have operand and dest with same flexible type
-//        break;
-//    }
-//
-//    assert(opCode);
-//
-//    Instruction* instr = (opCode, operand);
-//    setPrecision(instr, precision);
-//
-//    return instr;
-//}
-//
-//// Comments in header
-//Id Builder::createOperation(Decoration precision, Op opCode, Id operand0, Id operand1)
-//{
-//    Function* opCode = 0;
-//
-//    // Handle special return types here.  Things that don't have same result type as parameter
-//    switch (opCode) {
-//    case fDistance:
-//    case fDot2:
-//    case fDot3:
-//    case fDot4:
-//        // scalar result type
-//        break;
-//    case fStep:
-//        // first argument can be scalar, return and second argument match
-//        break;
-//    case fSmoothStep:
-//        // first argument can be scalar, return and second argument match
-//        break;
-//    default:
-//        // Binary operations that have operand and dest with same flexible type
-//        break;
-//    }
-//
-//    assert(opCode);
-//
-//    Instruction* instr = (opCode, operand0, operand1);
-//    setPrecision(instr, precision);
-//
-//    return instr;
-//}
-//
-//Id Builder::createOperation(Decoration precision, Op opCode, Id operand0, Id operand1, Id operand2)
-//{
-//    Function* opCode;
-//
-//    // Handle special return types here.  Things that don't have same result type as parameter
-//    switch (opCode) {
-//    case fSmoothStep:
-//        // first argument can be scalar, return and second argument match
-//        break;
-//    default:
-//        // Use operand0 type as result type
-//        break;
-//    }
-//
-//    assert(opCode);
-//
-//    Instruction* instr = (opCode, operand0, operand1, operand2);
-//    setPrecision(instr, precision);
-//
-//    return instr;
-//}
-
 // OpCompositeConstruct
 Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
 {
@@ -1625,11 +1516,8 @@
     Id scalarTypeId = getScalarTypeId(resultTypeId);
     std::vector<Id> constituents;  // accumulate the arguments for OpCompositeConstruct
     for (unsigned int i = 0; i < sources.size(); ++i) {
-        if (isAggregate(sources[i]))
-            MissingFunctionality("aggregate in vector constructor");
-
+        assert(! isAggregate(sources[i]));
         unsigned int sourceSize = getNumComponents(sources[i]);
-
         unsigned int sourcesToUse = sourceSize;
         if (sourcesToUse + targetComponent > numTargetComponents)
             sourcesToUse = numTargetComponents - targetComponent;
@@ -1790,7 +1678,7 @@
 
     // Go back to the headerBlock and make the flow control split
     builder.setBuildPoint(headerBlock);
-    builder.createMerge(OpSelectionMerge, mergeBlock, SelectionControlMaskNone);
+    builder.createSelectionMerge(mergeBlock, SelectionControlMaskNone);
     if (elseBlock)
         builder.createConditionalBranch(condition, thenBlock, elseBlock);
     else
@@ -1814,7 +1702,7 @@
     Block* mergeBlock = new Block(getUniqueId(), function);
 
     // make and insert the switch's selection-merge instruction
-    createMerge(OpSelectionMerge, mergeBlock, SelectionControlMaskNone);
+    createSelectionMerge(mergeBlock, SelectionControlMaskNone);
 
     // make the switch instruction
     Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
@@ -1898,7 +1786,7 @@
         getBuildPoint()->addInstruction(loop.isFirstIteration);
 
         // Mark the end of the structured loop. This must exist in the loop header block.
-        createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);
+        createLoopMerge(loop.merge, loop.header, LoopControlMaskNone);
 
         // Generate code to see if this is the first iteration of the loop.
         // It needs to be in its own block, since the loop merge and
@@ -1912,7 +1800,7 @@
         // Control flow after this "if" normally reconverges at the loop body.
         // However, the loop test has a "break branch" out of this selection
         // construct because it can transfer control to the loop merge block.
-        createMerge(OpSelectionMerge, loop.body, SelectionControlMaskNone);
+        createSelectionMerge(loop.body, SelectionControlMaskNone);
 
         Block* loopTest = new Block(getUniqueId(), *loop.function);
         createConditionalBranch(loop.isFirstIteration->getResultId(), loop.body, loopTest);
@@ -1930,7 +1818,7 @@
     // the body, then this is a loop merge.  Otherwise the loop merge
     // has already been generated and this is a conditional merge.
     if (loop.testFirst) {
-        createMerge(OpLoopMerge, loop.merge, LoopControlMaskNone);
+        createLoopMerge(loop.merge, loop.header, LoopControlMaskNone);
         // Branching to the "body" block will keep control inside
         // the loop.
         createConditionalBranch(condition, loop.body, loop.merge);
@@ -1943,7 +1831,7 @@
         // of a merge instruction, and a block can't be the target of more
         // than one merge instruction, we need to make an intermediate block.
         Block* stayInLoopBlock = new Block(getUniqueId(), *loop.function);
-        createMerge(OpSelectionMerge, stayInLoopBlock, SelectionControlMaskNone);
+        createSelectionMerge(stayInLoopBlock, SelectionControlMaskNone);
 
         // This is the loop test.
         createConditionalBranch(condition, stayInLoopBlock, loop.merge);
@@ -2047,12 +1935,13 @@
 {
     assert(accessChain.isRValue == false);
 
+    transferAccessChainSwizzle(true);
     Id base = collapseAccessChain();
 
     if (accessChain.swizzle.size() && accessChain.component != NoResult)
         MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");
 
-    // If swizzle exists, it is out-of-order or not full, we must load the target vector,
+    // If swizzle still exists, it is out-of-order or not full, we must load the target vector,
     // extract and insert elements to perform writeMask and/or swizzle.
     Id source = NoResult;
     if (accessChain.swizzle.size()) {
@@ -2078,8 +1967,9 @@
     Id id;
 
     if (accessChain.isRValue) {
+        // transfer access chain, but keep it static, so we can stay in registers
+        transferAccessChainSwizzle(false);
         if (accessChain.indexChain.size() > 0) {
-            mergeAccessChainSwizzle();  // TODO: optimization: look at applying this optimization more widely
             Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
         
             // if all the accesses are constants, we can use OpCompositeExtract
@@ -2113,6 +2003,7 @@
         } else
             id = accessChain.base;
     } else {
+        transferAccessChainSwizzle(true);
         // load through the access chain
         id = createLoad(collapseAccessChain());
     }
@@ -2142,6 +2033,7 @@
 {
     assert(accessChain.isRValue == false);
 
+    transferAccessChainSwizzle(true);
     Id lvalue = collapseAccessChain();
 
     // If swizzle exists, it is out-of-order or not full, we must load the target vector,
@@ -2162,7 +2054,26 @@
     out.push_back(uniqueId + 1);
     out.push_back(0);
 
-    // First instructions, some created on the spot here:
+    // Capabilities
+    for (auto cap : capabilities) {
+        Instruction capInst(0, 0, OpCapability);
+        capInst.addImmediateOperand(cap);
+        capInst.dump(out);
+    }
+
+    // TBD: OpExtension ...
+
+    dumpInstructions(out, imports);
+    Instruction memInst(0, 0, OpMemoryModel);
+    memInst.addImmediateOperand(addressModel);
+    memInst.addImmediateOperand(memoryModel);
+    memInst.dump(out);
+
+    // Instructions saved up while building:
+    dumpInstructions(out, entryPoints);
+    dumpInstructions(out, executionModes);
+
+    // Debug instructions
     if (source != SourceLanguageUnknown) {
         Instruction sourceInst(0, 0, OpSource);
         sourceInst.addImmediateOperand(source);
@@ -2174,28 +2085,12 @@
         extInst.addStringOperand(extensions[e]);
         extInst.dump(out);
     }
-
-    // TBD: OpExtension ...
-
-    // Capabilities
-    for (auto cap : capabilities) {
-        Instruction capInst(0, 0, OpCapability);
-        capInst.addImmediateOperand(cap);
-        capInst.dump(out);
-    }
-
-    dumpInstructions(out, imports);
-    Instruction memInst(0, 0, OpMemoryModel);
-    memInst.addImmediateOperand(addressModel);
-    memInst.addImmediateOperand(memoryModel);
-    memInst.dump(out);
-
-    // Instructions saved up while building:
-    dumpInstructions(out, entryPoints);
-    dumpInstructions(out, executionModes);
     dumpInstructions(out, names);
     dumpInstructions(out, lines);
+
+    // Annotation instructions
     dumpInstructions(out, decorations);
+
     dumpInstructions(out, constantsTypesGlobals);
     dumpInstructions(out, externals);
 
@@ -2207,10 +2102,13 @@
 // Protected methods.
 //
 
+// Turn the described access chain in 'accessChain' into an instruction
+// computing its address.  This *cannot* include complex swizzles, which must
+// be handled after this is called, but it does include swizzles that select
+// an individual element, as a single address of a scalar type can be
+// computed by an OpAccessChain instruction.
 Id Builder::collapseAccessChain()
 {
-    // TODO: bring in an individual component swizzle here, so that a pointer 
-    // all the way to the component level can be created.
     assert(accessChain.isRValue == false);
 
     if (accessChain.indexChain.size() > 0) {
@@ -2222,9 +2120,12 @@
         return accessChain.instr;
     } else
         return accessChain.base;
+
+    // note that non-trivial swizzling is left pending...
 }
 
-// clear out swizzle if it is redundant
+// clear out swizzle if it is redundant, that is reselecting the same components
+// that would be present without the swizzle.
 void Builder::simplifyAccessChainSwizzle()
 {
     // If the swizzle has fewer components than the vector, it is subsetting, and must stay
@@ -2244,29 +2145,45 @@
         accessChain.preSwizzleBaseType = NoType;
 }
 
-// clear out swizzle if it can become part of the indexes
-void Builder::mergeAccessChainSwizzle()
+// To the extent any swizzling can become part of the chain
+// of accesses instead of a post operation, make it so.
+// If 'dynamic' is true, include transfering a non-static component index,
+// otherwise, only transfer static indexes.
+//
+// Also, Boolean vectors are likely to be special.  While
+// for external storage, they should only be integer types,
+// function-local bool vectors could use sub-word indexing,
+// so keep that as a separate Insert/Extract on a loaded vector.
+void Builder::transferAccessChainSwizzle(bool dynamic)
 {
-    // is there even a chance of doing something?  Need a single-component swizzle
-    if ((accessChain.swizzle.size() > 1) ||
-        (accessChain.swizzle.size() == 0 && accessChain.component == NoResult))
+    // too complex?
+    if (accessChain.swizzle.size() > 1)
         return;
 
-    // TODO: optimization: remove this, but for now confine this to non-dynamic accesses
-    // (the above test is correct when this is removed.)
-    if (accessChain.component != NoResult)
+    // non existent?
+    if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
         return;
 
-    // move the swizzle over to the indexes
-    if (accessChain.swizzle.size() == 1)
+    // single component...
+
+    // skip doing it for Boolean vectors
+    if (isBoolType(getContainedTypeId(accessChain.preSwizzleBaseType)))
+        return;
+
+    if (accessChain.swizzle.size() == 1) {
+        // handle static component
         accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
-    else
+        accessChain.swizzle.clear();
+        // note, the only valid remaining dynamic access would be to this one
+        // component, so don't bother even looking at accessChain.component
+        accessChain.preSwizzleBaseType = NoType;
+        accessChain.component = NoResult;
+    } else if (dynamic && accessChain.component != NoResult) {
+        // handle dynamic component
         accessChain.indexChain.push_back(accessChain.component);
-
-    // now there is no need to track this swizzle
-    accessChain.component = NoResult;
-    accessChain.preSwizzleBaseType = NoType;
-    accessChain.swizzle.clear();
+        accessChain.preSwizzleBaseType = NoType;
+        accessChain.component = NoResult;
+    }
 }
 
 // Utility method for creating a new block and setting the insert point to
@@ -2292,14 +2209,23 @@
     block->addPredecessor(buildPoint);
 }
 
-void Builder::createMerge(Op mergeCode, Block* mergeBlock, unsigned int control)
+void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
 {
-    Instruction* merge = new Instruction(mergeCode);
+    Instruction* merge = new Instruction(OpSelectionMerge);
     merge->addIdOperand(mergeBlock->getId());
     merge->addImmediateOperand(control);
     buildPoint->addInstruction(merge);
 }
 
+void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control)
+{
+    Instruction* merge = new Instruction(OpLoopMerge);
+    merge->addIdOperand(mergeBlock->getId());
+    merge->addIdOperand(continueBlock->getId());
+    merge->addImmediateOperand(control);
+    buildPoint->addInstruction(merge);
+}
+
 void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
 {
     Instruction* branch = new Instruction(OpBranchConditional);
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 3bc8db2..5750b00 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -99,12 +99,14 @@
     Id makeUintType(int width) { return makeIntegerType(width, false); }
     Id makeFloatType(int width);
     Id makeStructType(std::vector<Id>& members, const char*);
+    Id makeStructResultType(Id type0, Id type1);
     Id makeVectorType(Id component, int size);
     Id makeMatrixType(Id component, int cols, int rows);
     Id makeArrayType(Id element, unsigned size);
     Id makeRuntimeArray(Id element);
     Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
     Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
+    Id makeSamplerType();
     Id makeSampledImageType(Id imageType);
 
     // For querying about types.
@@ -118,12 +120,14 @@
     Id getScalarTypeId(Id typeId) const;
     Id getContainedTypeId(Id typeId) const;
     Id getContainedTypeId(Id typeId, int) const;
+    StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
 
     bool isPointer(Id resultId)     const { return isPointerType(getTypeId(resultId)); }
     bool isScalar(Id resultId)      const { return isScalarType(getTypeId(resultId)); }
     bool isVector(Id resultId)      const { return isVectorType(getTypeId(resultId)); }
     bool isMatrix(Id resultId)      const { return isMatrixType(getTypeId(resultId)); }
     bool isAggregate(Id resultId)   const { return isAggregateType(getTypeId(resultId)); }
+    bool isBoolType(Id typeId)      const { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
 
     bool isPointerType(Id typeId)   const { return getTypeClass(typeId) == OpTypePointer; }
     bool isScalarType(Id typeId)    const { return getTypeClass(typeId) == OpTypeFloat  || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
@@ -140,6 +144,7 @@
     bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
     bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
     unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
+    StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
 
     int getTypeNumColumns(Id typeId) const
     {
@@ -172,18 +177,17 @@
     }
 
     // For making new constants (will return old constant if the requested one was already made).
-    Id makeBoolConstant(bool b);
-    Id makeIntConstant(Id typeId, unsigned value);
-    Id makeIntConstant(int i)         { return makeIntConstant(makeIntType(32),  (unsigned)i); }
-    Id makeUintConstant(unsigned u)   { return makeIntConstant(makeUintType(32),           u); }
-    Id makeFloatConstant(float f);
-    Id makeDoubleConstant(double d);
+    Id makeBoolConstant(bool b, bool specConstant = false);
+    Id makeIntConstant(int i, bool specConstant = false)         { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
+    Id makeUintConstant(unsigned u, bool specConstant = false)   { return makeIntConstant(makeUintType(32),           u, specConstant); }
+    Id makeFloatConstant(float f, bool specConstant = false);
+    Id makeDoubleConstant(double d, bool specConstant = false);
 
     // Turn the array of constants into a proper spv constant of the requested type.
     Id makeCompositeConstant(Id type, std::vector<Id>& comps);
 
     // Methods for adding information outside the CFG.
-    void addEntryPoint(ExecutionModel, Function*, const char* name);
+    Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
     void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
     void addName(Id, const char* name);
     void addMemberName(Id, int member, const char* name);
@@ -296,10 +300,11 @@
         Id gradX;
         Id gradY;
         Id sample;
+        Id comp;
     };
 
     // Select the correct texture operation based on all inputs, and emit the correct instruction
-    Id createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, const TextureParameters&);
+    Id createTextureCall(Decoration precision, Id resultType, bool fetch, bool proj, bool gather, const TextureParameters&);
 
     // Emit the OpTextureQuery* instruction that was passed in.
     // Figure out the right return value and type, and return it.
@@ -426,13 +431,13 @@
     //
 
     struct AccessChain {
-        Id base;                     // for l-values, pointer to the base object, for r-values, the base object
+        Id base;                       // for l-values, pointer to the base object, for r-values, the base object
         std::vector<Id> indexChain;
-        Id instr;                    // the instruction that generates this access chain
-        std::vector<unsigned> swizzle;
-        Id component;                // a dynamic component index, can coexist with a swizzle, done after the swizzle
-        Id preSwizzleBaseType;       // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
-        bool isRValue;
+        Id instr;                      // cache the instruction that generates this access chain
+        std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
+        Id component;                  // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
+        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
+        bool isRValue;                 // true if 'base' is an r-value, otherwise, base is an l-value
     };
 
     //
@@ -490,15 +495,17 @@
     void dump(std::vector<unsigned int>&) const;
 
 protected:
-    Id findScalarConstant(Op typeClass, Id typeId, unsigned value) const;
-    Id findScalarConstant(Op typeClass, Id typeId, unsigned v1, unsigned v2) const;
+    Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
+    Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const;
+    Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const;
     Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
     Id collapseAccessChain();
+    void transferAccessChainSwizzle(bool dynamic);
     void simplifyAccessChainSwizzle();
-    void mergeAccessChainSwizzle();
     void createAndSetNoPredecessorBlock(const char*);
     void createBranch(Block* block);
-    void createMerge(Op, Block*, unsigned int control);
+    void createSelectionMerge(Block* mergeBlock, unsigned int control);
+    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
     void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
     void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const;
 
diff --git a/SPIRV/disassemble.cpp b/SPIRV/disassemble.cpp
index 9df69e9..8662f03 100755
--- a/SPIRV/disassemble.cpp
+++ b/SPIRV/disassemble.cpp
@@ -48,15 +48,17 @@
 #include <sstream>
 #include <cstring>
 
+namespace spv {
+    // Include C-based headers that don't have a namespace
+    #include "SPIRV/GLSL.std.450.h"
+}
+const char* GlslStd450DebugNames[spv::GLSLstd450Count];
+
 #include "disassemble.h"
 #include "doc.h"
 
 namespace spv {
 
-#include "GLSL.std.450.h"
-
-const char* GlslStd450DebugNames[spv::GLSLstd450Count];
-
 void Kill(std::ostream& out, const char* message)
 {
     out << std::endl << "Disassembly failed: " << message << std::endl;
@@ -92,7 +94,7 @@
     void outputMask(OperandClass operandClass, unsigned mask);
     void disassembleImmediates(int numOperands);
     void disassembleIds(int numOperands);
-    void disassembleString();
+    int disassembleString();
     void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
 
     // Data
@@ -128,10 +130,10 @@
     }
 
     // Version
-    out << "// Module Version " << stream[word++] << std::endl;
+    out << "// Module Version " << std::hex << stream[word++] << std::endl;
 
     // Generator's magic number
-    out << "// Generated by (magic number): " << std::setbase(16) << stream[word++] << std::setbase(10) << std::endl;
+    out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;
 
     // Result <id> bound
     bound = stream[word++];
@@ -280,15 +282,18 @@
     }
 }
 
-void SpirvStream::disassembleString()
+// return the number of operands consumed by the string
+int SpirvStream::disassembleString()
 {
+    int startWord = word;
+
     out << " \"";
 
-    char* wordString;
+    const char* wordString;
     bool done = false;
     do {
         unsigned int content = stream[word];
-        wordString = (char*)&content;
+        wordString = (const char*)&content;
         for (int charCount = 0; charCount < 4; ++charCount) {
             if (*wordString == 0) {
                 done = true;
@@ -300,6 +305,8 @@
     } while (! done);
 
     out << "\"";
+
+    return word - startWord;
 }
 
 void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
@@ -389,15 +396,15 @@
         case OperandScope:
         case OperandMemorySemantics:
             disassembleIds(1);
+            --numOperands;
             // Get names for printing "(XXX)" for readability, *after* this id
             if (opCode == OpName)
                 idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
             break;
-        case OperandOptionalId:
         case OperandVariableIds:
             disassembleIds(numOperands);
             return;
-        case OperandOptionalImage:
+        case OperandImageOperands:
             outputMask(OperandImageOperands, stream[word++]);
             --numOperands;
             disassembleIds(numOperands);
@@ -440,6 +447,7 @@
             return;
         case OperandLiteralNumber:
             disassembleImmediates(1);
+            --numOperands;
             if (opCode == OpExtInst) {
                 ExtInstSet extInstSet = GLSL450Inst;
                 if (0 == memcmp("OpenCL", (const char*)(idDescriptor[stream[word-2]].c_str()), 6)) {
@@ -447,15 +455,16 @@
                 }
                 unsigned entrypoint = stream[word - 1];
                 if (extInstSet == GLSL450Inst) {
-                    if (entrypoint < spv::GLSLstd450Count) {
+                    if (entrypoint < GLSLstd450Count) {
                         out << "(" << GlslStd450DebugNames[entrypoint] << ")";
                     }
                 }
             }
             break;
+        case OperandOptionalLiteralString:
         case OperandLiteralString:
-            disassembleString();
-            return;
+            numOperands -= disassembleString();
+            break;
         default:
             assert(operandClass >= OperandSource && operandClass < OperandOpcode);
 
@@ -463,10 +472,9 @@
                 outputMask(operandClass, stream[word++]);
             else
                 out << OperandClassParams[operandClass].getName(stream[word++]);
-
+            --numOperands;
             break;
         }
-        --numOperands;
     }
 
     return;
@@ -508,9 +516,9 @@
     names[GLSLstd450Exp2]                    = "Exp2";
     names[GLSLstd450Log2]                    = "Log2";
     names[GLSLstd450Sqrt]                    = "Sqrt";
-    names[GLSLstd450InverseSqrt]             = "Inversesqrt";
+    names[GLSLstd450InverseSqrt]             = "InverseSqrt";
     names[GLSLstd450Determinant]             = "Determinant";
-    names[GLSLstd450MatrixInverse]           = "Inverse";
+    names[GLSLstd450MatrixInverse]           = "MatrixInverse";
     names[GLSLstd450Modf]                    = "Modf";
     names[GLSLstd450ModfStruct]              = "ModfStruct";
     names[GLSLstd450FMin]                    = "FMin";
@@ -522,9 +530,10 @@
     names[GLSLstd450FClamp]                  = "FClamp";
     names[GLSLstd450SClamp]                  = "SClamp";
     names[GLSLstd450UClamp]                  = "UClamp";
-    names[GLSLstd450Mix]                     = "Mix";
+    names[GLSLstd450FMix]                    = "FMix";
+    names[GLSLstd450IMix]                    = "IMix";
     names[GLSLstd450Step]                    = "Step";
-    names[GLSLstd450SmoothStep]              = "Smoothstep";
+    names[GLSLstd450SmoothStep]              = "SmoothStep";
     names[GLSLstd450Fma]                     = "Fma";
     names[GLSLstd450Frexp]                   = "Frexp";
     names[GLSLstd450FrexpStruct]             = "FrexpStruct";
@@ -545,15 +554,12 @@
     names[GLSLstd450Distance]                = "Distance";
     names[GLSLstd450Cross]                   = "Cross";
     names[GLSLstd450Normalize]               = "Normalize";
-    names[GLSLstd450FaceForward]             = "Faceforward";
+    names[GLSLstd450FaceForward]             = "FaceForward";
     names[GLSLstd450Reflect]                 = "Reflect";
     names[GLSLstd450Refract]                 = "Refract";
-    names[GLSLstd450AddCarry]                = "UaddCarry";
-    names[GLSLstd450SubBorrow]               = "UsubBorrow";
-    names[GLSLstd450MulExtended]             = "UmulExtended";
-    names[GLSLstd450FindILSB]                = "FindILsb";
-    names[GLSLstd450FindSMSB]                = "FindSMsb";
-    names[GLSLstd450FindUMSB]                = "FindUMsb";
+    names[GLSLstd450FindILsb]                = "FindILsb";
+    names[GLSLstd450FindSMsb]                = "FindSMsb";
+    names[GLSLstd450FindUMsb]                = "FindUMsb";
     names[GLSLstd450InterpolateAtCentroid]   = "InterpolateAtCentroid";
     names[GLSLstd450InterpolateAtSample]     = "InterpolateAtSample";
     names[GLSLstd450InterpolateAtOffset]     = "InterpolateAtOffset";
diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp
index ff0d780..64a55f9 100755
--- a/SPIRV/doc.cpp
+++ b/SPIRV/doc.cpp
@@ -64,7 +64,7 @@
 //    (for non-sparse mask enums, this is the number of enumurants)
 //
 
-const int SourceLanguageCeiling = 4;
+const int SourceLanguageCeiling = 5;
 
 const char* SourceString(int source)
 {
@@ -72,7 +72,8 @@
     case 0:  return "Unknown";
     case 1:  return "ESSL";
     case 2:  return "GLSL";
-    case 3:  return "OpenCL";
+    case 3:  return "OpenCL_C";
+    case 4:  return "OpenCL_CPP";
 
     case SourceLanguageCeiling:
     default: return "Bad";
@@ -125,7 +126,7 @@
     }
 }
 
-const int ExecutionModeCeiling = 32;
+const int ExecutionModeCeiling = 33;
 
 const char* ExecutionModeString(int mode)
 {
@@ -143,7 +144,7 @@
     case 10: return "PointMode";
     case 11: return "Xfb";
     case 12: return "DepthReplacing";
-    case 13: return "DepthAny";
+    case 13: return "Bad";
     case 14: return "DepthGreater";
     case 15: return "DepthLess";
     case 16: return "DepthUnchanged";
@@ -152,16 +153,17 @@
     case 19: return "InputPoints";
     case 20: return "InputLines";
     case 21: return "InputLinesAdjacency";
-    case 22: return "InputTriangles";
+    case 22: return "Triangles";
     case 23: return "InputTrianglesAdjacency";
-    case 24: return "InputQuads";
-    case 25: return "InputIsolines";
+    case 24: return "Quads";
+    case 25: return "Isolines";
     case 26: return "OutputVertices";
     case 27: return "OutputPoints";
     case 28: return "OutputLineStrip";
     case 29: return "OutputTriangleStrip";
     case 30: return "VecTypeHint";
     case 31: return "ContractionOff";
+    case 32: return "Bad";
 
     case ExecutionModeCeiling:
     default: return "Bad";
@@ -177,12 +179,12 @@
     case 1:  return "Input";
     case 2:  return "Uniform";
     case 3:  return "Output";
-    case 4:  return "WorkgroupLocal";
-    case 5:  return "WorkgroupGlobal";
-    case 6:  return "PrivateGlobal";
+    case 4:  return "Workgroup";
+    case 5:  return "CrossWorkgroup";
+    case 6:  return "Private";
     case 7:  return "Function";
     case 8:  return "Generic";
-    case 9:  return "Bad";
+    case 9:  return "PushConstant";
     case 10: return "AtomicCounter";
     case 11: return "Image";
 
@@ -191,7 +193,7 @@
     }
 }
 
-const int DecorationCeiling = 42;
+const int DecorationCeiling = 45;
 
 const char* DecorationString(int decoration)
 {
@@ -208,8 +210,8 @@
     case 9:  return "GLSLPacked";
     case 10: return "CPacked";
     case 11: return "BuiltIn";
-    case 12: return "Smooth";
-    case 13: return "Noperspective";
+    case 12: return "Bad";
+    case 13: return "NoPerspective";
     case 14: return "Flat";
     case 15: return "Patch";
     case 16: return "Centroid";
@@ -220,10 +222,10 @@
     case 21: return "Volatile";
     case 22: return "Constant";
     case 23: return "Coherent";
-    case 24: return "Nonwritable";
-    case 25: return "Nonreadable";
+    case 24: return "NonWritable";
+    case 25: return "NonReadable";
     case 26: return "Uniform";
-    case 27: return "NoStaticUse";
+    case 27: return "Bad";
     case 28: return "SaturatedConversion";
     case 29: return "Stream";
     case 30: return "Location";
@@ -238,13 +240,16 @@
     case 39: return "FP Rounding Mode";
     case 40: return "FP Fast Math Mode";
     case 41: return "Linkage Attributes";
+    case 42: return "NoContraction";
+    case 43: return "InputAttachmentIndex";
+    case 44: return "Alignment";
 
     case DecorationCeiling:
     default:  return "Bad";
     }
 }
 
-const int BuiltInCeiling = 42;
+const int BuiltInCeiling = 44;
 
 const char* BuiltInString(int builtIn)
 {
@@ -270,7 +275,7 @@
     case 18: return "SampleId";
     case 19: return "SamplePosition";
     case 20: return "SampleMask";
-    case 21: return "FragColor";
+    case 21: return "Bad";
     case 22: return "FragDepth";
     case 23: return "HelperInvocation";
     case 24: return "NumWorkgroups";
@@ -284,20 +289,22 @@
     case 32: return "EnqueuedWorkgroupSize";
     case 33: return "GlobalOffset";
     case 34: return "GlobalLinearId";
-    case 35: return "WorkgroupLinearId";
+    case 35: return "Bad";
     case 36: return "SubgroupSize";
     case 37: return "SubgroupMaxSize";
     case 38: return "NumSubgroups";
     case 39: return "NumEnqueuedSubgroups";
     case 40: return "SubgroupId";
     case 41: return "SubgroupLocalInvocationId";
+    case 42: return "VertexIndex";                 // TBD: put next to VertexId?
+    case 43: return "InstanceIndex";               // TBD: put next to InstanceId?
 
     case BuiltInCeiling:
     default: return "Bad";
     }
 }
 
-const int DimensionCeiling = 6;
+const int DimensionCeiling = 7;
 
 const char* DimensionString(int dim)
 {
@@ -308,6 +315,7 @@
     case 3:  return "Cube";
     case 4:  return "Rect";
     case 5:  return "Buffer";
+    case 6:  return "SubpassData";
 
     case DimensionCeiling:
     default: return "Bad";
@@ -438,7 +446,7 @@
     }
 }
 
-const int ImageChannelDataTypeCeiling = 16;
+const int ImageChannelDataTypeCeiling = 17;
 
 const char* ImageChannelDataTypeString(int type)
 {
@@ -460,6 +468,7 @@
     case 13: return "HalfFloat";
     case 14: return "Float";
     case 15: return "UnormInt24";
+    case 16: return "UnormInt101010_2";
 
     case ImageChannelDataTypeCeiling:
     default:
@@ -467,7 +476,7 @@
     }
 }
 
-const int ImageOperandsCeiling = 7;
+const int ImageOperandsCeiling = 8;
 
 const char* ImageOperandsString(int format)
 {
@@ -479,6 +488,7 @@
     case 4: return "Offset";
     case 5: return "ConstOffsets";
     case 6: return "Sample";
+    case 7: return "MinLod";
 
     case ImageOperandsCeiling:
     default:
@@ -604,35 +614,38 @@
     }
 }
 
-const int MemorySemanticsCeiling = 10;
+const int MemorySemanticsCeiling = 12;
 
 const char* MemorySemanticsString(int mem)
 {
+    // Note: No bits set (None) means "Relaxed"
     switch (mem) {
-    case 0: return "Relaxed";
-    case 1: return "SequentiallyConsistent";
-    case 2: return "Acquire";
-    case 3: return "Release";
-
-    case 4: return "UniformMemory";
-    case 5: return "SubgroupMemory";
-    case 6: return "WorkgroupLocalMemory";
-    case 7: return "WorkgroupGlobalMemory";
-    case 8: return "AtomicCounterMemory";
-    case 9: return "ImageMemory";
+    case 0: return "Bad"; // Note: this is a placeholder for 'Consume'
+    case 1: return "Acquire";
+    case 2: return "Release";
+    case 3: return "AcquireRelease";
+    case 4: return "SequentiallyConsistent";
+    case 5: return "Bad"; // Note: reserved for future expansion
+    case 6: return "UniformMemory";
+    case 7: return "SubgroupMemory";
+    case 8: return "WorkgroupMemory";
+    case 9: return "CrossWorkgroupMemory";
+    case 10: return "AtomicCounterMemory";
+    case 11: return "ImageMemory";
 
     case MemorySemanticsCeiling:
     default:     return "Bad";
     }
 }
 
-const int MemoryAccessCeiling = 2;
+const int MemoryAccessCeiling = 3;
 
 const char* MemoryAccessString(int mem)
 {
     switch (mem) {
     case 0:  return "Volatile";
     case 1:  return "Aligned";
+    case 2:  return "Nontemporal";
 
     case MemoryAccessCeiling:
     default: return "Bad";
@@ -699,7 +712,7 @@
     }
 }
 
-const int CapabilityCeiling = 36;
+const int CapabilityCeiling = 57;
 
 const char* CapabilityString(int info)
 {
@@ -721,7 +734,7 @@
     case 13: return "ImageBasic";
     case 14: return "ImageReadWrite";
     case 15: return "ImageMipmap";
-    case 16: return "ImageSRGBWrite";
+    case 16: return "Bad";
     case 17: return "Pipes";
     case 18: return "Groups";
     case 19: return "DeviceEnqueue";
@@ -731,7 +744,7 @@
     case 23: return "TessellationPointSize";
     case 24: return "GeometryPointSize";
     case 25: return "ImageGatherExtended"; 
-    case 26: return "StorageImageExtendedFormats";
+    case 26: return "Bad";
     case 27: return "StorageImageMultisample";
     case 28: return "UniformBufferArrayDynamicIndexing";
     case 29: return "SampledImageArrayDynamicIndexing";
@@ -741,6 +754,27 @@
     case 33: return "CullDistance";
     case 34: return "ImageCubeArray";
     case 35: return "SampleRateShading";
+    case 36: return "ImageRect";
+    case 37: return "SampledRect";
+    case 38: return "GenericPointer";
+    case 39: return "Int8";
+    case 40: return "InputAttachment";
+    case 41: return "SparseResidency";
+    case 42: return "MinLod";
+    case 43: return "Sampled1D";
+    case 44: return "Image1D";
+    case 45: return "SampledCubeArray";
+    case 46: return "SampledBuffer";
+    case 47: return "ImageBuffer";
+    case 48: return "ImageMSArray";
+    case 49: return "StorageImageExtendedFormats";
+    case 50: return "ImageQuery";
+    case 51: return "DerivativeControl";
+    case 52: return "InterpolationFunction";
+    case 53: return "TransformFeedback";
+    case 54: return "GeometryStreams";
+    case 55: return "StorageImageReadWithoutFormat";
+    case 56: return "StorageImageWriteWithoutFormat";
 
     case CapabilityCeiling:
     default: return "Bad";
@@ -752,7 +786,7 @@
     switch (op) {
     case 0:   return "OpNop";
     case 1:   return "OpUndef";
-    case 2:   return "Bad";
+    case 2:   return "OpSourceContinued";
     case 3:   return "OpSource";
     case 4:   return "OpSourceExtension";
     case 5:   return "OpName";
@@ -789,7 +823,7 @@
     case 36:  return "OpTypeReserveId";
     case 37:  return "OpTypeQueue";
     case 38:  return "OpTypePipe";
-    case 39:  return "Bad";
+    case 39:  return "OpTypeForwardPointer";
     case 40:  return "Bad";
     case 41:  return "OpConstantTrue";
     case 42:  return "OpConstantFalse";
@@ -820,7 +854,7 @@
     case 67:  return "OpPtrAccessChain";
     case 68:  return "OpArrayLength";
     case 69:  return "OpGenericPtrMemSemantics";
-    case 70:  return "Bad";
+    case 70:  return "OpInBoundsPtrAccessChain";
     case 71:  return "OpDecorate";
     case 72:  return "OpMemberDecorate";
     case 73:  return "OpDecorationGroup";
@@ -850,7 +884,7 @@
     case 97:  return "OpImageDrefGather";
     case 98:  return "OpImageRead";
     case 99:  return "OpImageWrite";
-    case 100: return "OpImageQueryDim";
+    case 100: return "OpImage";
     case 101: return "OpImageQueryFormat";
     case 102: return "OpImageQueryOrder";
     case 103: return "OpImageQuerySizeLod";
@@ -901,8 +935,8 @@
     case 148: return "OpDot";
     case 149: return "OpIAddCarry";
     case 150: return "OpISubBorrow";
-    case 151: return "OpIMulExtended";
-    case 152: return "Bad";
+    case 151: return "OpUMulExtended";
+    case 152: return "OpSMulExtended";
     case 153: return "Bad";
     case 154: return "OpAny";
     case 155: return "OpAll";
@@ -1009,8 +1043,8 @@
     case 256: return "OpLifetimeStart";
     case 257: return "OpLifetimeStop";
     case 258: return "Bad";
-    case 259: return "OpAsyncGroupCopy";
-    case 260: return "OpWaitGroupEvents";
+    case 259: return "OpGroupAsyncCopy";
+    case 260: return "OpGroupWaitEvents";
     case 261: return "OpGroupAll";
     case 262: return "OpGroupAny";
     case 263: return "OpGroupBroadcast";
@@ -1055,6 +1089,21 @@
     case 302: return "OpCaptureEventProfilingInfo";
     case 303: return "OpGetDefaultQueue";
     case 304: return "OpBuildNDRange";
+    case 305: return "OpImageSparseSampleImplicitLod";
+    case 306: return "OpImageSparseSampleExplicitLod";
+    case 307: return "OpImageSparseSampleDrefImplicitLod";
+    case 308: return "OpImageSparseSampleDrefExplicitLod";
+    case 309: return "OpImageSparseSampleProjImplicitLod";
+    case 310: return "OpImageSparseSampleProjExplicitLod";
+    case 311: return "OpImageSparseSampleProjDrefImplicitLod";
+    case 312: return "OpImageSparseSampleProjDrefExplicitLod";
+    case 313: return "OpImageSparseFetch";
+    case 314: return "OpImageSparseGather";
+    case 315: return "OpImageSparseDrefGather";
+    case 316: return "OpImageSparseTexelsResident";
+    case 317: return "OpNoLine";
+    case 318: return "OpAtomicFlagTestAndSet";
+    case 319: return "OpAtomicFlagClear";
 
     case OpcodeCeiling:
     default:
@@ -1113,6 +1162,7 @@
 
     InstructionDesc[OpNop].setResultAndType(false, false);
     InstructionDesc[OpSource].setResultAndType(false, false);
+    InstructionDesc[OpSourceContinued].setResultAndType(false, false);
     InstructionDesc[OpSourceExtension].setResultAndType(false, false);
     InstructionDesc[OpExtension].setResultAndType(false, false);
     InstructionDesc[OpExtInstImport].setResultAndType(true, false);
@@ -1134,6 +1184,7 @@
     InstructionDesc[OpTypeStruct].setResultAndType(true, false);
     InstructionDesc[OpTypeOpaque].setResultAndType(true, false);
     InstructionDesc[OpTypePointer].setResultAndType(true, false);
+    InstructionDesc[OpTypeForwardPointer].setResultAndType(false, false);
     InstructionDesc[OpTypeFunction].setResultAndType(true, false);
     InstructionDesc[OpTypeEvent].setResultAndType(true, false);
     InstructionDesc[OpTypeDeviceEvent].setResultAndType(true, false);
@@ -1152,6 +1203,7 @@
     InstructionDesc[OpMemberName].setResultAndType(false, false);
     InstructionDesc[OpString].setResultAndType(true, false);
     InstructionDesc[OpLine].setResultAndType(false, false);
+    InstructionDesc[OpNoLine].setResultAndType(false, false);
     InstructionDesc[OpCopyMemory].setResultAndType(false, false);
     InstructionDesc[OpCopyMemorySized].setResultAndType(false, false);
     InstructionDesc[OpEmitVertex].setResultAndType(false, false);
@@ -1181,11 +1233,12 @@
     InstructionDesc[OpSetUserEventStatus].setResultAndType(false, false);
     InstructionDesc[OpRetainEvent].setResultAndType(false, false);
     InstructionDesc[OpReleaseEvent].setResultAndType(false, false);
-    InstructionDesc[OpWaitGroupEvents].setResultAndType(false, false);
+    InstructionDesc[OpGroupWaitEvents].setResultAndType(false, false);
+    InstructionDesc[OpAtomicFlagClear].setResultAndType(false, false);
 
     // Specific additional context-dependent operands
 
-    ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "Number of <<Invocation,invocations>>");
+    ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <<Invocation,invocations>>'");
 
     ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'x size'");
     ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'y size'");
@@ -1198,24 +1251,26 @@
     ExecutionModeOperands[ExecutionModeOutputVertices].push(OperandLiteralNumber, "'Vertex count'");
     ExecutionModeOperands[ExecutionModeVecTypeHint].push(OperandLiteralNumber, "'Vector type'");
 
-    DecorationOperands[DecorationStream].push(OperandLiteralNumber, "Stream number");
-    DecorationOperands[DecorationLocation].push(OperandLiteralNumber, "Location");
-    DecorationOperands[DecorationComponent].push(OperandLiteralNumber, "Component within a vector");
-    DecorationOperands[DecorationIndex].push(OperandLiteralNumber, "Index");
-    DecorationOperands[DecorationBinding].push(OperandLiteralNumber, "Binding point");
-    DecorationOperands[DecorationDescriptorSet].push(OperandLiteralNumber, "Descriptor set");
-    DecorationOperands[DecorationOffset].push(OperandLiteralNumber, "Byte offset");
-    DecorationOperands[DecorationXfbBuffer].push(OperandLiteralNumber, "XFB buffer number");
-    DecorationOperands[DecorationXfbStride].push(OperandLiteralNumber, "XFB stride");
-    DecorationOperands[DecorationArrayStride].push(OperandLiteralNumber, "Array stride");
-    DecorationOperands[DecorationMatrixStride].push(OperandLiteralNumber, "Matrix stride");
+    DecorationOperands[DecorationStream].push(OperandLiteralNumber, "'Stream Number'");
+    DecorationOperands[DecorationLocation].push(OperandLiteralNumber, "'Location'");
+    DecorationOperands[DecorationComponent].push(OperandLiteralNumber, "'Component'");
+    DecorationOperands[DecorationIndex].push(OperandLiteralNumber, "'Index'");
+    DecorationOperands[DecorationBinding].push(OperandLiteralNumber, "'Binding Point'");
+    DecorationOperands[DecorationDescriptorSet].push(OperandLiteralNumber, "'Descriptor Set'");
+    DecorationOperands[DecorationOffset].push(OperandLiteralNumber, "'Byte Offset'");
+    DecorationOperands[DecorationXfbBuffer].push(OperandLiteralNumber, "'XFB Buffer Number'");
+    DecorationOperands[DecorationXfbStride].push(OperandLiteralNumber, "'XFB Stride'");
+    DecorationOperands[DecorationArrayStride].push(OperandLiteralNumber, "'Array Stride'");
+    DecorationOperands[DecorationMatrixStride].push(OperandLiteralNumber, "'Matrix Stride'");
     DecorationOperands[DecorationBuiltIn].push(OperandLiteralNumber, "See <<BuiltIn,*BuiltIn*>>");
-    DecorationOperands[DecorationFPRoundingMode].push(OperandFPRoundingMode, "floating-point rounding mode");
-    DecorationOperands[DecorationFPFastMathMode].push(OperandFPFastMath, "fast-math mode");
-    DecorationOperands[DecorationLinkageAttributes].push(OperandLiteralString, "name");
-    DecorationOperands[DecorationLinkageAttributes].push(OperandLinkageType, "linkage type");
-    DecorationOperands[DecorationFuncParamAttr].push(OperandFuncParamAttr, "function parameter attribute");
-    DecorationOperands[DecorationSpecId].push(OperandLiteralNumber, "Specialization Constant ID");
+    DecorationOperands[DecorationFPRoundingMode].push(OperandFPRoundingMode, "'Floating-Point Rounding Mode'");
+    DecorationOperands[DecorationFPFastMathMode].push(OperandFPFastMath, "'Fast-Math Mode'");
+    DecorationOperands[DecorationLinkageAttributes].push(OperandLiteralString, "'Name'");
+    DecorationOperands[DecorationLinkageAttributes].push(OperandLinkageType, "'Linkage Type'");
+    DecorationOperands[DecorationFuncParamAttr].push(OperandFuncParamAttr, "'Function Parameter Attribute'");
+    DecorationOperands[DecorationSpecId].push(OperandLiteralNumber, "'Specialization Constant ID'");
+    DecorationOperands[DecorationInputAttachmentIndex].push(OperandLiteralNumber, "'Attachment Index'");
+    DecorationOperands[DecorationAlignment].push(OperandLiteralNumber, "'Alignment'");
 
     OperandClassParams[OperandSource].set(SourceLanguageCeiling, SourceString, 0);
     OperandClassParams[OperandExecutionModel].set(ExecutionModelCeiling, ExecutionModelString, ExecutionModelParams);
@@ -1251,6 +1306,54 @@
     OperandClassParams[OperandCapability].set(CapabilityCeiling, CapabilityString, CapabilityParams);
     OperandClassParams[OperandOpcode].set(OpcodeCeiling, OpcodeString, 0);
 
+    CapabilityParams[CapabilityShader].caps.push_back(CapabilityMatrix);
+    CapabilityParams[CapabilityGeometry].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityTessellation].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityVector16].caps.push_back(CapabilityKernel);
+    CapabilityParams[CapabilityFloat16Buffer].caps.push_back(CapabilityKernel);
+    CapabilityParams[CapabilityFloat16].caps.push_back(CapabilityFloat16Buffer);
+    CapabilityParams[CapabilityInt64Atomics].caps.push_back(CapabilityInt64);
+    CapabilityParams[CapabilityImageBasic].caps.push_back(CapabilityKernel);
+    CapabilityParams[CapabilityImageReadWrite].caps.push_back(CapabilityImageBasic);
+    CapabilityParams[CapabilityImageMipmap].caps.push_back(CapabilityImageBasic);
+    CapabilityParams[CapabilityPipes].caps.push_back(CapabilityKernel);
+    CapabilityParams[CapabilityDeviceEnqueue].caps.push_back(CapabilityKernel);
+    CapabilityParams[CapabilityLiteralSampler].caps.push_back(CapabilityKernel);
+    CapabilityParams[CapabilityAtomicStorage].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilitySampleRateShading].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityTessellationPointSize].caps.push_back(CapabilityTessellation);
+    CapabilityParams[CapabilityGeometryPointSize].caps.push_back(CapabilityGeometry);
+    CapabilityParams[CapabilityImageGatherExtended].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityStorageImageExtendedFormats].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityStorageImageMultisample].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityUniformBufferArrayDynamicIndexing].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilitySampledImageArrayDynamicIndexing].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityStorageBufferArrayDynamicIndexing].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityStorageImageArrayDynamicIndexing].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityClipDistance].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityCullDistance].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityGenericPointer].caps.push_back(CapabilityAddresses);
+    CapabilityParams[CapabilityInt8].caps.push_back(CapabilityKernel);
+    CapabilityParams[CapabilityInputAttachment].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityMinLod].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilitySparseResidency].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilitySampled1D].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilitySampledRect].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilitySampledBuffer].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilitySampledCubeArray].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityImageMSArray].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityImage1D].caps.push_back(CapabilitySampled1D);
+    CapabilityParams[CapabilityImageRect].caps.push_back(CapabilitySampledRect);
+    CapabilityParams[CapabilityImageBuffer].caps.push_back(CapabilitySampledBuffer);
+    CapabilityParams[CapabilityImageCubeArray].caps.push_back(CapabilitySampledCubeArray);
+    CapabilityParams[CapabilityImageQuery].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityDerivativeControl].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityInterpolationFunction].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityTransformFeedback].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityGeometryStreams].caps.push_back(CapabilityGeometry);
+    CapabilityParams[CapabilityStorageImageReadWithoutFormat].caps.push_back(CapabilityShader);
+    CapabilityParams[CapabilityStorageImageWriteWithoutFormat].caps.push_back(CapabilityShader);
+
     AddressingParams[AddressingModelPhysical32].caps.push_back(CapabilityAddresses);
     AddressingParams[AddressingModelPhysical64].caps.push_back(CapabilityAddresses);
 
@@ -1258,6 +1361,9 @@
     MemoryParams[MemoryModelGLSL450].caps.push_back(CapabilityShader);
     MemoryParams[MemoryModelOpenCL].caps.push_back(CapabilityKernel);
 
+    MemorySemanticsParams[MemorySemanticsUniformMemoryShift].caps.push_back(CapabilityShader);
+    MemorySemanticsParams[MemorySemanticsAtomicCounterMemoryShift].caps.push_back(CapabilityShader);
+
     ExecutionModelParams[ExecutionModelVertex].caps.push_back(CapabilityShader);
     ExecutionModelParams[ExecutionModelTessellationControl].caps.push_back(CapabilityTessellation);
     ExecutionModelParams[ExecutionModelTessellationEvaluation].caps.push_back(CapabilityTessellation);
@@ -1270,10 +1376,10 @@
     StorageParams[StorageClassInput].caps.push_back(CapabilityShader);
     StorageParams[StorageClassUniform].caps.push_back(CapabilityShader);
     StorageParams[StorageClassOutput].caps.push_back(CapabilityShader);
-    StorageParams[StorageClassPrivateGlobal].caps.push_back(CapabilityShader);
+    StorageParams[StorageClassPrivate].caps.push_back(CapabilityShader);
     StorageParams[StorageClassGeneric].caps.push_back(CapabilityKernel);
     StorageParams[StorageClassAtomicCounter].caps.push_back(CapabilityAtomicStorage);
-
+    StorageParams[StorageClassPushConstant].caps.push_back(CapabilityShader);
 
     // Sampler Filter & Addressing mode capabilities
     SamplerAddressingModeParams[SamplerAddressingModeNone].caps.push_back(CapabilityKernel);
@@ -1286,9 +1392,57 @@
     SamplerFilterModeParams[SamplerFilterModeLinear].caps.push_back(CapabilityKernel);
 
     // image format capabilities
-    for (int i = 0; i < ImageFormatCeiling; ++i) {
-        ImageFormatParams[i].caps.push_back(CapabilityShader);
-    }
+
+    // ES/Desktop float
+    ImageFormatParams[ImageFormatRgba32f].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatRgba16f].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatR32f].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatRgba8].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatRgba8Snorm].caps.push_back(CapabilityShader);
+
+    // Desktop float
+    ImageFormatParams[ImageFormatRg32f].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg16f].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR11fG11fB10f].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR16f].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRgba16].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRgb10A2].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg16].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg8].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR16].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR8].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRgba16Snorm].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg16Snorm].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg8Snorm].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR16Snorm].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR8Snorm].caps.push_back(CapabilityStorageImageExtendedFormats);
+
+    // ES/Desktop int
+    ImageFormatParams[ImageFormatRgba32i].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatRgba16i].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatRgba8i].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatR32i].caps.push_back(CapabilityShader);
+
+    // Desktop int
+    ImageFormatParams[ImageFormatRg32i].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg16i].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg8i].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR16i].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR8i].caps.push_back(CapabilityStorageImageExtendedFormats);
+
+    // ES/Desktop uint
+    ImageFormatParams[ImageFormatRgba32ui].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatRgba16ui].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatRgba8ui].caps.push_back(CapabilityShader);
+    ImageFormatParams[ImageFormatR32ui].caps.push_back(CapabilityShader);
+
+    // Desktop uint
+    ImageFormatParams[ImageFormatRgb10a2ui].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg32ui].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg16ui].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatRg8ui].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR16ui].caps.push_back(CapabilityStorageImageExtendedFormats);
+    ImageFormatParams[ImageFormatR8ui].caps.push_back(CapabilityStorageImageExtendedFormats);
 
     // image channel order capabilities
     for (int i = 0; i < ImageChannelOrderCeiling; ++i) {
@@ -1303,6 +1457,7 @@
     // image lookup operands
     ImageOperandsParams[ImageOperandsBiasShift].caps.push_back(CapabilityShader);
     ImageOperandsParams[ImageOperandsOffsetShift].caps.push_back(CapabilityImageGatherExtended);
+    ImageOperandsParams[ImageOperandsMinLodShift].caps.push_back(CapabilityMinLod);
 
     // fast math flags capabilities
     for (int i = 0; i < FPFastMathCeiling; ++i) {
@@ -1340,9 +1495,8 @@
     ExecutionModeParams[ExecutionModeOriginLowerLeft].caps.push_back(CapabilityShader);
     ExecutionModeParams[ExecutionModeEarlyFragmentTests].caps.push_back(CapabilityShader);
     ExecutionModeParams[ExecutionModePointMode].caps.push_back(CapabilityTessellation);
-    ExecutionModeParams[ExecutionModeXfb].caps.push_back(CapabilityShader);
+    ExecutionModeParams[ExecutionModeXfb].caps.push_back(CapabilityTransformFeedback);
     ExecutionModeParams[ExecutionModeDepthReplacing].caps.push_back(CapabilityShader);
-    ExecutionModeParams[ExecutionModeDepthAny].caps.push_back(CapabilityShader);
     ExecutionModeParams[ExecutionModeDepthGreater].caps.push_back(CapabilityShader);
     ExecutionModeParams[ExecutionModeDepthLess].caps.push_back(CapabilityShader);
     ExecutionModeParams[ExecutionModeDepthUnchanged].caps.push_back(CapabilityShader);
@@ -1350,11 +1504,11 @@
     ExecutionModeParams[ExecutionModeInputPoints].caps.push_back(CapabilityGeometry);
     ExecutionModeParams[ExecutionModeInputLines].caps.push_back(CapabilityGeometry);
     ExecutionModeParams[ExecutionModeInputLinesAdjacency].caps.push_back(CapabilityGeometry);
-    ExecutionModeParams[ExecutionModeInputTriangles].caps.push_back(CapabilityGeometry);
-    ExecutionModeParams[ExecutionModeInputTriangles].caps.push_back(CapabilityTessellation);
+    ExecutionModeParams[ExecutionModeTriangles].caps.push_back(CapabilityGeometry);
+    ExecutionModeParams[ExecutionModeTriangles].caps.push_back(CapabilityTessellation);
     ExecutionModeParams[ExecutionModeInputTrianglesAdjacency].caps.push_back(CapabilityGeometry);
-    ExecutionModeParams[ExecutionModeInputQuads].caps.push_back(CapabilityTessellation);
-    ExecutionModeParams[ExecutionModeInputIsolines].caps.push_back(CapabilityTessellation);
+    ExecutionModeParams[ExecutionModeQuads].caps.push_back(CapabilityTessellation);
+    ExecutionModeParams[ExecutionModeIsolines].caps.push_back(CapabilityTessellation);
     ExecutionModeParams[ExecutionModeOutputVertices].caps.push_back(CapabilityGeometry);
     ExecutionModeParams[ExecutionModeOutputVertices].caps.push_back(CapabilityTessellation);
     ExecutionModeParams[ExecutionModeOutputPoints].caps.push_back(CapabilityGeometry);
@@ -1370,8 +1524,7 @@
     DecorationParams[DecorationColMajor].caps.push_back(CapabilityMatrix);
     DecorationParams[DecorationGLSLShared].caps.push_back(CapabilityShader);
     DecorationParams[DecorationGLSLPacked].caps.push_back(CapabilityShader);
-    DecorationParams[DecorationSmooth].caps.push_back(CapabilityShader);
-    DecorationParams[DecorationNoperspective].caps.push_back(CapabilityShader);
+    DecorationParams[DecorationNoPerspective].caps.push_back(CapabilityShader);
     DecorationParams[DecorationFlat].caps.push_back(CapabilityShader);
     DecorationParams[DecorationPatch].caps.push_back(CapabilityTessellation);
     DecorationParams[DecorationCentroid].caps.push_back(CapabilityShader);
@@ -1381,14 +1534,14 @@
     DecorationParams[DecorationUniform].caps.push_back(CapabilityShader);
     DecorationParams[DecorationCPacked].caps.push_back(CapabilityKernel);
     DecorationParams[DecorationSaturatedConversion].caps.push_back(CapabilityKernel);
-    DecorationParams[DecorationStream].caps.push_back(CapabilityGeometry);
+    DecorationParams[DecorationStream].caps.push_back(CapabilityGeometryStreams);
     DecorationParams[DecorationLocation].caps.push_back(CapabilityShader);
     DecorationParams[DecorationComponent].caps.push_back(CapabilityShader);
     DecorationParams[DecorationIndex].caps.push_back(CapabilityShader);
     DecorationParams[DecorationBinding].caps.push_back(CapabilityShader);
     DecorationParams[DecorationDescriptorSet].caps.push_back(CapabilityShader);
-    DecorationParams[DecorationXfbBuffer].caps.push_back(CapabilityShader);
-    DecorationParams[DecorationXfbStride].caps.push_back(CapabilityShader);
+    DecorationParams[DecorationXfbBuffer].caps.push_back(CapabilityTransformFeedback);
+    DecorationParams[DecorationXfbStride].caps.push_back(CapabilityTransformFeedback);
     DecorationParams[DecorationArrayStride].caps.push_back(CapabilityShader);
     DecorationParams[DecorationMatrixStride].caps.push_back(CapabilityShader);
     DecorationParams[DecorationBuiltIn].caps.push_back(CapabilityShader);
@@ -1397,13 +1550,27 @@
     DecorationParams[DecorationFPFastMathMode].caps.push_back(CapabilityKernel);
     DecorationParams[DecorationLinkageAttributes].caps.push_back(CapabilityLinkage);
     DecorationParams[DecorationSpecId].caps.push_back(CapabilityShader);
+    DecorationParams[DecorationNoContraction].caps.push_back(CapabilityShader);
+    DecorationParams[DecorationInputAttachmentIndex].caps.push_back(CapabilityInputAttachment);
+    DecorationParams[DecorationAlignment].caps.push_back(CapabilityKernel);
 
     BuiltInParams[BuiltInPosition].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInPointSize].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInClipDistance].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInCullDistance].caps.push_back(CapabilityShader);
+
     BuiltInParams[BuiltInVertexId].caps.push_back(CapabilityShader);
+    BuiltInParams[BuiltInVertexId].desc = "Vertex ID, which takes on values 0, 1, 2, . . . .";
+
     BuiltInParams[BuiltInInstanceId].caps.push_back(CapabilityShader);
+    BuiltInParams[BuiltInInstanceId].desc = "Instance ID, which takes on values 0, 1, 2, . . . .";
+
+    BuiltInParams[BuiltInVertexIndex].caps.push_back(CapabilityShader);
+    BuiltInParams[BuiltInVertexIndex].desc = "Vertex index, which takes on values base, base+1, base+2, . . . .";
+
+    BuiltInParams[BuiltInInstanceIndex].caps.push_back(CapabilityShader);
+    BuiltInParams[BuiltInInstanceIndex].desc = "Instance index, which takes on values base, base+1, base+2, . . . .";
+
     BuiltInParams[BuiltInPrimitiveId].caps.push_back(CapabilityGeometry);
     BuiltInParams[BuiltInPrimitiveId].caps.push_back(CapabilityTessellation);
     BuiltInParams[BuiltInInvocationId].caps.push_back(CapabilityGeometry);
@@ -1420,16 +1587,13 @@
     BuiltInParams[BuiltInSampleId].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInSamplePosition].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInSampleMask].caps.push_back(CapabilityShader);
-    BuiltInParams[BuiltInFragColor].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInFragDepth].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInHelperInvocation].caps.push_back(CapabilityShader);
-    BuiltInParams[BuiltInLocalInvocationIndex].caps.push_back(CapabilityShader);
     BuiltInParams[BuiltInWorkDim].caps.push_back(CapabilityKernel);
     BuiltInParams[BuiltInGlobalSize].caps.push_back(CapabilityKernel);
     BuiltInParams[BuiltInEnqueuedWorkgroupSize].caps.push_back(CapabilityKernel);
     BuiltInParams[BuiltInGlobalOffset].caps.push_back(CapabilityKernel);
     BuiltInParams[BuiltInGlobalLinearId].caps.push_back(CapabilityKernel);
-    BuiltInParams[BuiltInWorkgroupLinearId].caps.push_back(CapabilityKernel);
 
     BuiltInParams[BuiltInSubgroupSize].caps.push_back(CapabilityKernel);
     BuiltInParams[BuiltInSubgroupMaxSize].caps.push_back(CapabilityKernel);
@@ -1438,8 +1602,11 @@
     BuiltInParams[BuiltInSubgroupId].caps.push_back(CapabilityKernel);
     BuiltInParams[BuiltInSubgroupLocalInvocationId].caps.push_back(CapabilityKernel);
 
+    DimensionalityParams[Dim1D].caps.push_back(CapabilitySampled1D);
     DimensionalityParams[DimCube].caps.push_back(CapabilityShader);
-    DimensionalityParams[DimRect].caps.push_back(CapabilityShader);
+    DimensionalityParams[DimRect].caps.push_back(CapabilitySampledRect);
+    DimensionalityParams[DimBuffer].caps.push_back(CapabilitySampledBuffer);
+    DimensionalityParams[DimSubpassData].caps.push_back(CapabilityInputAttachment);
 
     // Group Operations
     for (int i = 0; i < GroupOperationCeiling; ++i) {
@@ -1458,6 +1625,10 @@
 
     InstructionDesc[OpSource].operands.push(OperandSource, "");
     InstructionDesc[OpSource].operands.push(OperandLiteralNumber, "'Version'");
+    InstructionDesc[OpSource].operands.push(OperandId, "'File'", true);
+    InstructionDesc[OpSource].operands.push(OperandLiteralString, "'Source'", true);
+
+    InstructionDesc[OpSourceContinued].operands.push(OperandLiteralString, "'Continued Source'");
 
     InstructionDesc[OpSourceExtension].operands.push(OperandLiteralString, "'Extension'");
 
@@ -1470,7 +1641,6 @@
 
     InstructionDesc[OpString].operands.push(OperandLiteralString, "'String'");
 
-    InstructionDesc[OpLine].operands.push(OperandId, "'Target'");
     InstructionDesc[OpLine].operands.push(OperandId, "'File'");
     InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Line'");
     InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Column'");
@@ -1487,10 +1657,11 @@
     InstructionDesc[OpEntryPoint].operands.push(OperandExecutionModel, "");
     InstructionDesc[OpEntryPoint].operands.push(OperandId, "'Entry Point'");
     InstructionDesc[OpEntryPoint].operands.push(OperandLiteralString, "'Name'");
+    InstructionDesc[OpEntryPoint].operands.push(OperandVariableIds, "'Interface'");
 
     InstructionDesc[OpExecutionMode].operands.push(OperandId, "'Entry Point'");
     InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'");
-    InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution Mode,Execution Mode>>");
+    InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution_Mode,Execution Mode>>");
 
     InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'");
     InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'");
@@ -1511,7 +1682,7 @@
     InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'MS'");
     InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Sampled'");
     InstructionDesc[OpTypeImage].operands.push(OperandSamplerImageFormat, "");
-    InstructionDesc[OpTypeImage].operands.push(OperandOptionalLiteral, "'Access Qualifier'");
+    InstructionDesc[OpTypeImage].operands.push(OperandAccessQualifier, "", true);
 
     InstructionDesc[OpTypeSampledImage].operands.push(OperandId, "'Image Type'");
 
@@ -1529,15 +1700,18 @@
     InstructionDesc[OpTypePointer].operands.push(OperandStorage, "");
     InstructionDesc[OpTypePointer].operands.push(OperandId, "'Type'");
 
+    InstructionDesc[OpTypeForwardPointer].capabilities.push_back(CapabilityAddresses);
+    InstructionDesc[OpTypeForwardPointer].operands.push(OperandId, "'Pointer Type'");
+    InstructionDesc[OpTypeForwardPointer].operands.push(OperandStorage, "");
+
     InstructionDesc[OpTypeEvent].capabilities.push_back(CapabilityKernel);
 
-    InstructionDesc[OpTypeDeviceEvent].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpTypeDeviceEvent].capabilities.push_back(CapabilityDeviceEnqueue);
 
     InstructionDesc[OpTypeReserveId].capabilities.push_back(CapabilityPipes);
 
-    InstructionDesc[OpTypeQueue].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpTypeQueue].capabilities.push_back(CapabilityDeviceEnqueue);
 
-    InstructionDesc[OpTypePipe].operands.push(OperandId, "'Type'");
     InstructionDesc[OpTypePipe].operands.push(OperandAccessQualifier, "'Qualifier'");
     InstructionDesc[OpTypePipe].capabilities.push_back(CapabilityPipes);
 
@@ -1561,7 +1735,7 @@
     InstructionDesc[OpSpecConstantOp].operands.push(OperandVariableIds, "'Operands'");
 
     InstructionDesc[OpVariable].operands.push(OperandStorage, "");
-    InstructionDesc[OpVariable].operands.push(OperandOptionalId, "'Initializer'");
+    InstructionDesc[OpVariable].operands.push(OperandId, "'Initializer'", true);
 
     InstructionDesc[OpFunction].operands.push(OperandFunction, "");
     InstructionDesc[OpFunction].operands.push(OperandId, "'Function Type'");
@@ -1574,11 +1748,11 @@
     InstructionDesc[OpExtInst].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n...");
 
     InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'");
-    InstructionDesc[OpLoad].operands.push(OperandOptionalLiteral, "'Memory Access'");
+    InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true);
 
     InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'");
     InstructionDesc[OpStore].operands.push(OperandId, "'Object'");
-    InstructionDesc[OpStore].operands.push(OperandOptionalLiteral, "'Memory Access'");
+    InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true);
 
     InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'");
 
@@ -1621,101 +1795,196 @@
 
     InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Target'");
     InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Source'");
-    InstructionDesc[OpCopyMemory].operands.push(OperandOptionalLiteral, "'Memory Access'");
+    InstructionDesc[OpCopyMemory].operands.push(OperandMemoryAccess, "", true);
 
     InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Target'");
     InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Source'");
     InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Size'");
-    InstructionDesc[OpCopyMemorySized].operands.push(OperandOptionalLiteral, "'Memory Access'");
+    InstructionDesc[OpCopyMemorySized].operands.push(OperandMemoryAccess, "", true);
 
     InstructionDesc[OpCopyMemorySized].capabilities.push_back(CapabilityAddresses);
 
     InstructionDesc[OpSampledImage].operands.push(OperandId, "'Image'");
     InstructionDesc[OpSampledImage].operands.push(OperandId, "'Sampler'");
 
+    InstructionDesc[OpImage].operands.push(OperandId, "'Sampled Image'");
+
     InstructionDesc[OpImageRead].operands.push(OperandId, "'Image'");
     InstructionDesc[OpImageRead].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageRead].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageRead].operands.push(OperandVariableIds, "", true);
 
     InstructionDesc[OpImageWrite].operands.push(OperandId, "'Image'");
     InstructionDesc[OpImageWrite].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpImageWrite].operands.push(OperandId, "'Texel'");
+    InstructionDesc[OpImageWrite].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageWrite].operands.push(OperandVariableIds, "", true);
 
     InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Coordinate'");
-    InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageSampleImplicitLod].capabilities.push_back(CapabilityShader);
 
     InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Coordinate'");
-    InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandVariableIds, "", true);
 
     InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
-    InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageSampleDrefImplicitLod].capabilities.push_back(CapabilityShader);
 
     InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
-    InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageSampleDrefExplicitLod].capabilities.push_back(CapabilityShader);
 
     InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'");
-    InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageSampleProjImplicitLod].capabilities.push_back(CapabilityShader);
 
     InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'");
-    InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageSampleProjExplicitLod].capabilities.push_back(CapabilityShader);
 
     InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
-    InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageSampleProjDrefImplicitLod].capabilities.push_back(CapabilityShader);
 
     InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
-    InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageSampleProjDrefExplicitLod].capabilities.push_back(CapabilityShader);
 
-    InstructionDesc[OpImageFetch].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageFetch].operands.push(OperandId, "'Image'");
     InstructionDesc[OpImageFetch].operands.push(OperandId, "'Coordinate'");
-    InstructionDesc[OpImageFetch].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageFetch].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageFetch].operands.push(OperandVariableIds, "", true);
 
     InstructionDesc[OpImageGather].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageGather].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpImageGather].operands.push(OperandId, "'Component'");
-    InstructionDesc[OpImageGather].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageGather].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageGather].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageGather].capabilities.push_back(CapabilityShader);
 
     InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Sampled Image'");
     InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Coordinate'");
     InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'D~ref~'");
-    InstructionDesc[OpImageDrefGather].operands.push(OperandOptionalImage, "");
+    InstructionDesc[OpImageDrefGather].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageDrefGather].operands.push(OperandVariableIds, "", true);
     InstructionDesc[OpImageDrefGather].capabilities.push_back(CapabilityShader);
 
+    InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleImplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleExplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
+    InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleDrefImplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
+    InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleDrefExplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleProjImplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleProjExplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'");
+    InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'");
+    InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Image'");
+    InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseFetch].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseFetch].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseFetch].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Component'");
+    InstructionDesc[OpImageSparseGather].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseGather].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseGather].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Sampled Image'");
+    InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Coordinate'");
+    InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'D~ref~'");
+    InstructionDesc[OpImageSparseDrefGather].operands.push(OperandImageOperands, "", true);
+    InstructionDesc[OpImageSparseDrefGather].operands.push(OperandVariableIds, "", true);
+    InstructionDesc[OpImageSparseDrefGather].capabilities.push_back(CapabilitySparseResidency);
+
+    InstructionDesc[OpImageSparseTexelsResident].operands.push(OperandId, "'Resident Code'");
+    InstructionDesc[OpImageSparseTexelsResident].capabilities.push_back(CapabilitySparseResidency);
+
     InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Image'");
     InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Level of Detail'");
+    InstructionDesc[OpImageQuerySizeLod].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpImageQuerySizeLod].capabilities.push_back(CapabilityImageQuery);
 
     InstructionDesc[OpImageQuerySize].operands.push(OperandId, "'Image'");
+    InstructionDesc[OpImageQuerySize].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpImageQuerySize].capabilities.push_back(CapabilityImageQuery);
 
     InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Image'");
     InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Coordinate'");
-    InstructionDesc[OpImageQueryLod].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpImageQueryLod].capabilities.push_back(CapabilityImageQuery);
 
     InstructionDesc[OpImageQueryLevels].operands.push(OperandId, "'Image'");
-    InstructionDesc[OpImageQueryLevels].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpImageQueryLevels].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpImageQueryLevels].capabilities.push_back(CapabilityImageQuery);
 
     InstructionDesc[OpImageQuerySamples].operands.push(OperandId, "'Image'");
-    InstructionDesc[OpImageQuerySamples].capabilities.push_back(CapabilityShader);
-
-    InstructionDesc[OpImageQueryDim].operands.push(OperandId, "'Image'");
-    InstructionDesc[OpImageQueryDim].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpImageQuerySamples].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpImageQuerySamples].capabilities.push_back(CapabilityImageQuery);
 
     InstructionDesc[OpImageQueryFormat].operands.push(OperandId, "'Image'");
     InstructionDesc[OpImageQueryFormat].capabilities.push_back(CapabilityKernel);
@@ -1734,6 +2003,11 @@
     InstructionDesc[OpPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'");
     InstructionDesc[OpPtrAccessChain].capabilities.push_back(CapabilityAddresses);
 
+    InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Base'");
+    InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Element'");
+    InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'");
+    InstructionDesc[OpInBoundsPtrAccessChain].capabilities.push_back(CapabilityAddresses);
+
     InstructionDesc[OpSNegate].operands.push(OperandId, "'Operand'");
 
     InstructionDesc[OpFNegate].operands.push(OperandId, "'Operand'");
@@ -1887,6 +2161,18 @@
     InstructionDesc[OpDot].operands.push(OperandId, "'Vector 1'");
     InstructionDesc[OpDot].operands.push(OperandId, "'Vector 2'");
 
+    InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 1'");
+    InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 2'");
+
+    InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 1'");
+    InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 2'");
+
+    InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 1'");
+    InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 2'");
+
+    InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 1'");
+    InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 2'");
+
     InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Base'");
     InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Shift'");
 
@@ -2019,22 +2305,22 @@
     InstructionDesc[OpFwidth].capabilities.push_back(CapabilityShader);
     InstructionDesc[OpFwidth].operands.push(OperandId, "'P'");
 
-    InstructionDesc[OpDPdxFine].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpDPdxFine].capabilities.push_back(CapabilityDerivativeControl);
     InstructionDesc[OpDPdxFine].operands.push(OperandId, "'P'");
 
-    InstructionDesc[OpDPdyFine].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpDPdyFine].capabilities.push_back(CapabilityDerivativeControl);
     InstructionDesc[OpDPdyFine].operands.push(OperandId, "'P'");
 
-    InstructionDesc[OpFwidthFine].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpFwidthFine].capabilities.push_back(CapabilityDerivativeControl);
     InstructionDesc[OpFwidthFine].operands.push(OperandId, "'P'");
 
-    InstructionDesc[OpDPdxCoarse].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpDPdxCoarse].capabilities.push_back(CapabilityDerivativeControl);
     InstructionDesc[OpDPdxCoarse].operands.push(OperandId, "'P'");
 
-    InstructionDesc[OpDPdyCoarse].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpDPdyCoarse].capabilities.push_back(CapabilityDerivativeControl);
     InstructionDesc[OpDPdyCoarse].operands.push(OperandId, "'P'");
 
-    InstructionDesc[OpFwidthCoarse].capabilities.push_back(CapabilityShader);
+    InstructionDesc[OpFwidthCoarse].capabilities.push_back(CapabilityDerivativeControl);
     InstructionDesc[OpFwidthCoarse].operands.push(OperandId, "'P'");
 
     InstructionDesc[OpEmitVertex].capabilities.push_back(CapabilityGeometry);
@@ -2042,10 +2328,10 @@
     InstructionDesc[OpEndPrimitive].capabilities.push_back(CapabilityGeometry);
 
     InstructionDesc[OpEmitStreamVertex].operands.push(OperandId, "'Stream'");
-    InstructionDesc[OpEmitStreamVertex].capabilities.push_back(CapabilityGeometry);
+    InstructionDesc[OpEmitStreamVertex].capabilities.push_back(CapabilityGeometryStreams);
 
     InstructionDesc[OpEndStreamPrimitive].operands.push(OperandId, "'Stream'");
-    InstructionDesc[OpEndStreamPrimitive].capabilities.push_back(CapabilityGeometry);
+    InstructionDesc[OpEndStreamPrimitive].capabilities.push_back(CapabilityGeometryStreams);
 
     InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Memory'");
@@ -2140,7 +2426,18 @@
     InstructionDesc[OpAtomicXor].operands.push(OperandMemorySemantics, "'Semantics'");
     InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Value'");
 
+    InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandScope, "'Scope'");
+    InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandMemorySemantics, "'Semantics'");
+    InstructionDesc[OpAtomicFlagTestAndSet].capabilities.push_back(CapabilityKernel);
+
+    InstructionDesc[OpAtomicFlagClear].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpAtomicFlagClear].operands.push(OperandScope, "'Scope'");
+    InstructionDesc[OpAtomicFlagClear].operands.push(OperandMemorySemantics, "'Semantics'");
+    InstructionDesc[OpAtomicFlagClear].capabilities.push_back(CapabilityKernel);
+
     InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'");
+    InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'");
     InstructionDesc[OpLoopMerge].operands.push(OperandLoop, "");
 
     InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'");
@@ -2163,22 +2460,24 @@
 
     InstructionDesc[OpLifetimeStart].operands.push(OperandId, "'Pointer'");
     InstructionDesc[OpLifetimeStart].operands.push(OperandLiteralNumber, "'Size'");
+    InstructionDesc[OpLifetimeStart].capabilities.push_back(CapabilityKernel);
 
     InstructionDesc[OpLifetimeStop].operands.push(OperandId, "'Pointer'");
     InstructionDesc[OpLifetimeStop].operands.push(OperandLiteralNumber, "'Size'");
+    InstructionDesc[OpLifetimeStop].capabilities.push_back(CapabilityKernel);
 
-    InstructionDesc[OpAsyncGroupCopy].capabilities.push_back(CapabilityKernel);
-    InstructionDesc[OpAsyncGroupCopy].operands.push(OperandScope, "'Execution'");
-    InstructionDesc[OpAsyncGroupCopy].operands.push(OperandId, "'Destination'");
-    InstructionDesc[OpAsyncGroupCopy].operands.push(OperandId, "'Source'");
-    InstructionDesc[OpAsyncGroupCopy].operands.push(OperandId, "'Num Elements'");
-    InstructionDesc[OpAsyncGroupCopy].operands.push(OperandId, "'Stride'");
-    InstructionDesc[OpAsyncGroupCopy].operands.push(OperandId, "'Event'");
+    InstructionDesc[OpGroupAsyncCopy].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpGroupAsyncCopy].operands.push(OperandScope, "'Execution'");
+    InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Destination'");
+    InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Source'");
+    InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Num Elements'");
+    InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Stride'");
+    InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Event'");
 
-    InstructionDesc[OpWaitGroupEvents].capabilities.push_back(CapabilityKernel);
-    InstructionDesc[OpWaitGroupEvents].operands.push(OperandScope, "'Execution'");
-    InstructionDesc[OpWaitGroupEvents].operands.push(OperandId, "'Num Events'");
-    InstructionDesc[OpWaitGroupEvents].operands.push(OperandId, "'Events List'");
+    InstructionDesc[OpGroupWaitEvents].capabilities.push_back(CapabilityKernel);
+    InstructionDesc[OpGroupWaitEvents].operands.push(OperandScope, "'Execution'");
+    InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Num Events'");
+    InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Events List'");
 
     InstructionDesc[OpGroupAll].capabilities.push_back(CapabilityGroups);
     InstructionDesc[OpGroupAll].operands.push(OperandScope, "'Execution'");
@@ -2236,67 +2535,95 @@
     InstructionDesc[OpReadPipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpWritePipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpReservedReadPipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Reserve Id'");
     InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Index'");
     InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpReservedWritePipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Reserve Id'");
     InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Index'");
     InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pointer'");
+    InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpReserveReadPipePackets].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Num Packets'");
+    InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpReserveWritePipePackets].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Num Packets'");
+    InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpCommitReadPipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Reserve Id'");
+    InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpCommitWritePipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Reserve Id'");
+    InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpIsValidReserveId].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpIsValidReserveId].operands.push(OperandId, "'Reserve Id'");
 
     InstructionDesc[OpGetNumPipePackets].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Pipe'");
+    InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpGetMaxPipePackets].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Pipe'");
+    InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpGroupReserveReadPipePackets].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Num Packets'");
+    InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpGroupReserveWritePipePackets].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Num Packets'");
+    InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpGroupCommitReadPipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Reserve Id'");
+    InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpGroupCommitWritePipe].capabilities.push_back(CapabilityPipes);
     InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandScope, "'Execution'");
     InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Pipe'");
     InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Reserve Id'");
+    InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Size'");
+    InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Alignment'");
 
     InstructionDesc[OpBuildNDRange].capabilities.push_back(CapabilityDeviceEnqueue);
     InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkSize'");
diff --git a/SPIRV/doc.h b/SPIRV/doc.h
index c97ca85..accdd65 100755
--- a/SPIRV/doc.h
+++ b/SPIRV/doc.h
@@ -116,10 +116,9 @@
 enum OperandClass {
     OperandNone,
     OperandId,
-    OperandOptionalId,
-    OperandOptionalImage,
     OperandVariableIds,
     OperandOptionalLiteral,
+    OperandOptionalLiteralString,
     OperandVariableLiterals,
     OperandVariableIdLiteral,
     OperandVariableLiteralId,
@@ -168,18 +167,22 @@
 class OperandParameters {
 public:
     OperandParameters() { }
-    void push(OperandClass oc, const char* d)
+    void push(OperandClass oc, const char* d, bool opt = false)
     {
         opClass.push_back(oc);
         desc.push_back(d);
+        optional.push_back(opt);
     }
+    void setOptional();
     OperandClass getClass(int op) const { return opClass[op]; }
     const char* getDesc(int op) const { return desc[op]; }
+    bool isOptional(int op) const { return optional[op]; }
     int getNum() const { return (int)opClass.size(); }
 
 protected:
     std::vector<OperandClass> opClass;
     std::vector<const char*> desc;
+    std::vector<bool> optional;
 };
 
 // Parameterize an enumerant
@@ -240,7 +243,7 @@
     int resultPresent : 1;
 };
 
-const int OpcodeCeiling = 305;
+const int OpcodeCeiling = 320;
 
 // The set of objects that hold all the instruction/operand
 // parameterization information.
diff --git a/SPIRV/spirv.hpp b/SPIRV/spirv.hpp
index 829722e..f3d42a9 100755
--- a/SPIRV/spirv.hpp
+++ b/SPIRV/spirv.hpp
@@ -25,7 +25,6 @@
 // This header is automatically generated by the same tool that creates

 // the Binary Section of the SPIR-V specification.

 

-// Specification revision 31.

 // Enumeration tokens for SPIR-V, in various styles:

 //   C, C++, C++11, JSON, Lua, Python

 // 

@@ -47,9 +46,12 @@
 

 typedef unsigned int Id;

 

+#define SPV_VERSION 10000

+#define SPV_REVISION 2

+

 static const unsigned int MagicNumber = 0x07230203;

-static const unsigned int Version = 99;

-static const unsigned int Revision = 31;

+static const unsigned int Version = 0x00010000;

+static const unsigned int Revision = 2;

 static const unsigned int OpCodeMask = 0xffff;

 static const unsigned int WordCountShift = 16;

 

@@ -57,7 +59,8 @@
     SourceLanguageUnknown = 0,

     SourceLanguageESSL = 1,

     SourceLanguageGLSL = 2,

-    SourceLanguageOpenCL = 3,

+    SourceLanguageOpenCL_C = 3,

+    SourceLanguageOpenCL_CPP = 4,

 };

 

 enum ExecutionModel {

@@ -96,7 +99,6 @@
     ExecutionModePointMode = 10,

     ExecutionModeXfb = 11,

     ExecutionModeDepthReplacing = 12,

-    ExecutionModeDepthAny = 13,

     ExecutionModeDepthGreater = 14,

     ExecutionModeDepthLess = 15,

     ExecutionModeDepthUnchanged = 16,

@@ -105,10 +107,10 @@
     ExecutionModeInputPoints = 19,

     ExecutionModeInputLines = 20,

     ExecutionModeInputLinesAdjacency = 21,

-    ExecutionModeInputTriangles = 22,

+    ExecutionModeTriangles = 22,

     ExecutionModeInputTrianglesAdjacency = 23,

-    ExecutionModeInputQuads = 24,

-    ExecutionModeInputIsolines = 25,

+    ExecutionModeQuads = 24,

+    ExecutionModeIsolines = 25,

     ExecutionModeOutputVertices = 26,

     ExecutionModeOutputPoints = 27,

     ExecutionModeOutputLineStrip = 28,

@@ -122,11 +124,12 @@
     StorageClassInput = 1,

     StorageClassUniform = 2,

     StorageClassOutput = 3,

-    StorageClassWorkgroupLocal = 4,

-    StorageClassWorkgroupGlobal = 5,

-    StorageClassPrivateGlobal = 6,

+    StorageClassWorkgroup = 4,

+    StorageClassCrossWorkgroup = 5,

+    StorageClassPrivate = 6,

     StorageClassFunction = 7,

     StorageClassGeneric = 8,

+    StorageClassPushConstant = 9,

     StorageClassAtomicCounter = 10,

     StorageClassImage = 11,

 };

@@ -138,6 +141,7 @@
     DimCube = 3,

     DimRect = 4,

     DimBuffer = 5,

+    DimSubpassData = 6,

 };

 

 enum SamplerAddressingMode {

@@ -235,6 +239,7 @@
     ImageChannelDataTypeHalfFloat = 13,

     ImageChannelDataTypeFloat = 14,

     ImageChannelDataTypeUnormInt24 = 15,

+    ImageChannelDataTypeUnormInt101010_2 = 16,

 };

 

 enum ImageOperandsShift {

@@ -245,6 +250,7 @@
     ImageOperandsOffsetShift = 4,

     ImageOperandsConstOffsetsShift = 5,

     ImageOperandsSampleShift = 6,

+    ImageOperandsMinLodShift = 7,

 };

 

 enum ImageOperandsMask {

@@ -256,6 +262,7 @@
     ImageOperandsOffsetMask = 0x00000010,

     ImageOperandsConstOffsetsMask = 0x00000020,

     ImageOperandsSampleMask = 0x00000040,

+    ImageOperandsMinLodMask = 0x00000080,

 };

 

 enum FPFastMathModeShift {

@@ -317,8 +324,7 @@
     DecorationGLSLPacked = 9,

     DecorationCPacked = 10,

     DecorationBuiltIn = 11,

-    DecorationSmooth = 12,

-    DecorationNoperspective = 13,

+    DecorationNoPerspective = 13,

     DecorationFlat = 14,

     DecorationPatch = 15,

     DecorationCentroid = 16,

@@ -329,10 +335,9 @@
     DecorationVolatile = 21,

     DecorationConstant = 22,

     DecorationCoherent = 23,

-    DecorationNonwritable = 24,

-    DecorationNonreadable = 25,

+    DecorationNonWritable = 24,

+    DecorationNonReadable = 25,

     DecorationUniform = 26,

-    DecorationNoStaticUse = 27,

     DecorationSaturatedConversion = 28,

     DecorationStream = 29,

     DecorationLocation = 30,

@@ -347,6 +352,9 @@
     DecorationFPRoundingMode = 39,

     DecorationFPFastMathMode = 40,

     DecorationLinkageAttributes = 41,

+    DecorationNoContraction = 42,

+    DecorationInputAttachmentIndex = 43,

+    DecorationAlignment = 44,

 };

 

 enum BuiltIn {

@@ -370,7 +378,6 @@
     BuiltInSampleId = 18,

     BuiltInSamplePosition = 19,

     BuiltInSampleMask = 20,

-    BuiltInFragColor = 21,

     BuiltInFragDepth = 22,

     BuiltInHelperInvocation = 23,

     BuiltInNumWorkgroups = 24,

@@ -384,13 +391,14 @@
     BuiltInEnqueuedWorkgroupSize = 32,

     BuiltInGlobalOffset = 33,

     BuiltInGlobalLinearId = 34,

-    BuiltInWorkgroupLinearId = 35,

     BuiltInSubgroupSize = 36,

     BuiltInSubgroupMaxSize = 37,

     BuiltInNumSubgroups = 38,

     BuiltInNumEnqueuedSubgroups = 39,

     BuiltInSubgroupId = 40,

     BuiltInSubgroupLocalInvocationId = 41,

+    BuiltInVertexIndex = 42,

+    BuiltInInstanceIndex = 43,

 };

 

 enum SelectionControlShift {

@@ -431,41 +439,43 @@
 };

 

 enum MemorySemanticsShift {

-    MemorySemanticsRelaxedShift = 0,

-    MemorySemanticsSequentiallyConsistentShift = 1,

-    MemorySemanticsAcquireShift = 2,

-    MemorySemanticsReleaseShift = 3,

-    MemorySemanticsUniformMemoryShift = 4,

-    MemorySemanticsSubgroupMemoryShift = 5,

-    MemorySemanticsWorkgroupLocalMemoryShift = 6,

-    MemorySemanticsWorkgroupGlobalMemoryShift = 7,

-    MemorySemanticsAtomicCounterMemoryShift = 8,

-    MemorySemanticsImageMemoryShift = 9,

+    MemorySemanticsAcquireShift = 1,

+    MemorySemanticsReleaseShift = 2,

+    MemorySemanticsAcquireReleaseShift = 3,

+    MemorySemanticsSequentiallyConsistentShift = 4,

+    MemorySemanticsUniformMemoryShift = 6,

+    MemorySemanticsSubgroupMemoryShift = 7,

+    MemorySemanticsWorkgroupMemoryShift = 8,

+    MemorySemanticsCrossWorkgroupMemoryShift = 9,

+    MemorySemanticsAtomicCounterMemoryShift = 10,

+    MemorySemanticsImageMemoryShift = 11,

 };

 

 enum MemorySemanticsMask {

     MemorySemanticsMaskNone = 0,

-    MemorySemanticsRelaxedMask = 0x00000001,

-    MemorySemanticsSequentiallyConsistentMask = 0x00000002,

-    MemorySemanticsAcquireMask = 0x00000004,

-    MemorySemanticsReleaseMask = 0x00000008,

-    MemorySemanticsUniformMemoryMask = 0x00000010,

-    MemorySemanticsSubgroupMemoryMask = 0x00000020,

-    MemorySemanticsWorkgroupLocalMemoryMask = 0x00000040,

-    MemorySemanticsWorkgroupGlobalMemoryMask = 0x00000080,

-    MemorySemanticsAtomicCounterMemoryMask = 0x00000100,

-    MemorySemanticsImageMemoryMask = 0x00000200,

+    MemorySemanticsAcquireMask = 0x00000002,

+    MemorySemanticsReleaseMask = 0x00000004,

+    MemorySemanticsAcquireReleaseMask = 0x00000008,

+    MemorySemanticsSequentiallyConsistentMask = 0x00000010,

+    MemorySemanticsUniformMemoryMask = 0x00000040,

+    MemorySemanticsSubgroupMemoryMask = 0x00000080,

+    MemorySemanticsWorkgroupMemoryMask = 0x00000100,

+    MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,

+    MemorySemanticsAtomicCounterMemoryMask = 0x00000400,

+    MemorySemanticsImageMemoryMask = 0x00000800,

 };

 

 enum MemoryAccessShift {

     MemoryAccessVolatileShift = 0,

     MemoryAccessAlignedShift = 1,

+    MemoryAccessNontemporalShift = 2,

 };

 

 enum MemoryAccessMask {

     MemoryAccessMaskNone = 0,

     MemoryAccessVolatileMask = 0x00000001,

     MemoryAccessAlignedMask = 0x00000002,

+    MemoryAccessNontemporalMask = 0x00000004,

 };

 

 enum Scope {

@@ -514,7 +524,6 @@
     CapabilityImageBasic = 13,

     CapabilityImageReadWrite = 14,

     CapabilityImageMipmap = 15,

-    CapabilityImageSRGBWrite = 16,

     CapabilityPipes = 17,

     CapabilityGroups = 18,

     CapabilityDeviceEnqueue = 19,

@@ -524,7 +533,6 @@
     CapabilityTessellationPointSize = 23,

     CapabilityGeometryPointSize = 24,

     CapabilityImageGatherExtended = 25,

-    CapabilityStorageImageExtendedFormats = 26,

     CapabilityStorageImageMultisample = 27,

     CapabilityUniformBufferArrayDynamicIndexing = 28,

     CapabilitySampledImageArrayDynamicIndexing = 29,

@@ -534,11 +542,33 @@
     CapabilityCullDistance = 33,

     CapabilityImageCubeArray = 34,

     CapabilitySampleRateShading = 35,

+    CapabilityImageRect = 36,

+    CapabilitySampledRect = 37,

+    CapabilityGenericPointer = 38,

+    CapabilityInt8 = 39,

+    CapabilityInputAttachment = 40,

+    CapabilitySparseResidency = 41,

+    CapabilityMinLod = 42,

+    CapabilitySampled1D = 43,

+    CapabilityImage1D = 44,

+    CapabilitySampledCubeArray = 45,

+    CapabilitySampledBuffer = 46,

+    CapabilityImageBuffer = 47,

+    CapabilityImageMSArray = 48,

+    CapabilityStorageImageExtendedFormats = 49,

+    CapabilityImageQuery = 50,

+    CapabilityDerivativeControl = 51,

+    CapabilityInterpolationFunction = 52,

+    CapabilityTransformFeedback = 53,

+    CapabilityGeometryStreams = 54,

+    CapabilityStorageImageReadWithoutFormat = 55,

+    CapabilityStorageImageWriteWithoutFormat = 56,

 };

 

 enum Op {

     OpNop = 0,

     OpUndef = 1,

+    OpSourceContinued = 2,

     OpSource = 3,

     OpSourceExtension = 4,

     OpName = 5,

@@ -572,6 +602,7 @@
     OpTypeReserveId = 36,

     OpTypeQueue = 37,

     OpTypePipe = 38,

+    OpTypeForwardPointer = 39,

     OpConstantTrue = 41,

     OpConstantFalse = 42,

     OpConstant = 43,

@@ -598,6 +629,7 @@
     OpPtrAccessChain = 67,

     OpArrayLength = 68,

     OpGenericPtrMemSemantics = 69,

+    OpInBoundsPtrAccessChain = 70,

     OpDecorate = 71,

     OpMemberDecorate = 72,

     OpDecorationGroup = 73,

@@ -625,7 +657,7 @@
     OpImageDrefGather = 97,

     OpImageRead = 98,

     OpImageWrite = 99,

-    OpImageQueryDim = 100,

+    OpImage = 100,

     OpImageQueryFormat = 101,

     OpImageQueryOrder = 102,

     OpImageQuerySizeLod = 103,

@@ -674,7 +706,8 @@
     OpDot = 148,

     OpIAddCarry = 149,

     OpISubBorrow = 150,

-    OpIMulExtended = 151,

+    OpUMulExtended = 151,

+    OpSMulExtended = 152,

     OpAny = 154,

     OpAll = 155,

     OpIsNan = 156,

@@ -769,8 +802,8 @@
     OpUnreachable = 255,

     OpLifetimeStart = 256,

     OpLifetimeStop = 257,

-    OpAsyncGroupCopy = 259,

-    OpWaitGroupEvents = 260,

+    OpGroupAsyncCopy = 259,

+    OpGroupWaitEvents = 260,

     OpGroupAll = 261,

     OpGroupAny = 262,

     OpGroupBroadcast = 263,

@@ -811,6 +844,21 @@
     OpCaptureEventProfilingInfo = 302,

     OpGetDefaultQueue = 303,

     OpBuildNDRange = 304,

+    OpImageSparseSampleImplicitLod = 305,

+    OpImageSparseSampleExplicitLod = 306,

+    OpImageSparseSampleDrefImplicitLod = 307,

+    OpImageSparseSampleDrefExplicitLod = 308,

+    OpImageSparseSampleProjImplicitLod = 309,

+    OpImageSparseSampleProjExplicitLod = 310,

+    OpImageSparseSampleProjDrefImplicitLod = 311,

+    OpImageSparseSampleProjDrefExplicitLod = 312,

+    OpImageSparseFetch = 313,

+    OpImageSparseGather = 314,

+    OpImageSparseDrefGather = 315,

+    OpImageSparseTexelsResident = 316,

+    OpNoLine = 317,

+    OpAtomicFlagTestAndSet = 318,

+    OpAtomicFlagClear = 319,

 };

 

 // Overload operator| for mask bit combining

diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h
index 8bf369c..6736a13 100755
--- a/SPIRV/spvIR.h
+++ b/SPIRV/spvIR.h
@@ -74,18 +74,14 @@
 
 class Instruction {
 public:
-    Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), string(0) { }
-    explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), string(0) { }
-    virtual ~Instruction()
-    {
-        delete string;
-    }
+    Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode) { }
+    explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode) { }
+    virtual ~Instruction() {}
     void addIdOperand(Id id) { operands.push_back(id); }
     void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
     void addStringOperand(const char* str)
     {
         originalString = str;
-        string = new std::vector<unsigned int>;
         unsigned int word;
         char* wordString = (char*)&word;
         char* wordPtr = wordString;
@@ -96,7 +92,7 @@
             *(wordPtr++) = c;
             ++charCount;
             if (charCount == 4) {
-                string->push_back(word);
+                addImmediateOperand(word);
                 wordPtr = wordString;
                 charCount = 0;
             }
@@ -107,7 +103,7 @@
             // pad with 0s
             for (; charCount < 4; ++charCount)
                 *(wordPtr++) = 0;
-            string->push_back(word);
+            addImmediateOperand(word);
         }
     }
     Op getOpCode() const { return opCode; }
@@ -128,8 +124,6 @@
         if (resultId)
             ++wordCount;
         wordCount += (unsigned int)operands.size();
-        if (string)
-            wordCount += (unsigned int)string->size();
 
         // Write out the beginning of the instruction
         out.push_back(((wordCount) << WordCountShift) | opCode);
@@ -141,9 +135,6 @@
         // Write out the operands
         for (int op = 0; op < (int)operands.size(); ++op)
             out.push_back(operands[op]);
-        if (string)
-            for (int op = 0; op < (int)string->size(); ++op)
-                out.push_back((*string)[op]);
     }
 
 protected:
@@ -152,7 +143,6 @@
     Id typeId;
     Op opCode;
     std::vector<Id> operands;
-    std::vector<unsigned int>* string; // usually non-existent
     std::string originalString;        // could be optimized away; convenience for getting string operand
 };