Browse Source

Update glslang

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
ad399cab39
47 changed files with 3824 additions and 1775 deletions
  1. 0 2
      CMakeLists.txt
  2. 0 12
      platform/xcode/liblove.xcodeproj/project.pbxproj
  3. 23 0
      src/libraries/glslang/glslang/Include/BaseTypes.h
  4. 177 170
      src/libraries/glslang/glslang/Include/Types.h
  5. 14 12
      src/libraries/glslang/glslang/Include/arrays.h
  6. 158 5
      src/libraries/glslang/glslang/Include/intermediate.h
  7. 2 2
      src/libraries/glslang/glslang/Include/revision.h
  8. 36 2
      src/libraries/glslang/glslang/MachineIndependent/Constant.cpp
  9. 417 32
      src/libraries/glslang/glslang/MachineIndependent/Initialize.cpp
  10. 5 5
      src/libraries/glslang/glslang/MachineIndependent/Initialize.h
  11. 586 57
      src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp
  12. 2 0
      src/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h
  13. 15 31
      src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp
  14. 179 36
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp
  15. 32 21
      src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h
  16. 2 0
      src/libraries/glslang/glslang/MachineIndependent/RemoveTree.h
  17. 33 1
      src/libraries/glslang/glslang/MachineIndependent/Scan.cpp
  18. 2 0
      src/libraries/glslang/glslang/MachineIndependent/ScanContext.h
  19. 32 46
      src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp
  20. 21 2
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp
  21. 91 15
      src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h
  22. 41 1
      src/libraries/glslang/glslang/MachineIndependent/Versions.cpp
  23. 7 0
      src/libraries/glslang/glslang/MachineIndependent/Versions.h
  24. 2 0
      src/libraries/glslang/glslang/MachineIndependent/gl_types.h
  25. 480 625
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp
  26. 318 321
      src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h
  27. 185 8
      src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp
  28. 410 92
      src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp
  29. 21 7
      src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp
  30. 64 7
      src/libraries/glslang/glslang/MachineIndependent/localintermediate.h
  31. 0 6
      src/libraries/glslang/glslang/MachineIndependent/parseConst.cpp
  32. 2 0
      src/libraries/glslang/glslang/MachineIndependent/parseVersions.h
  33. 29 8
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp
  34. 4 0
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp
  35. 14 6
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h
  36. 0 81
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpMemory.cpp
  37. 261 24
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
  38. 0 77
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpSymbols.cpp
  39. 20 4
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
  40. 6 2
      src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h
  41. 2 0
      src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.h
  42. 39 1
      src/libraries/glslang/glslang/MachineIndependent/reflection.cpp
  43. 25 3
      src/libraries/glslang/glslang/MachineIndependent/reflection.h
  44. 0 14
      src/libraries/glslang/glslang/OSDependent/Unix/ossource.cpp
  45. 0 15
      src/libraries/glslang/glslang/OSDependent/Windows/ossource.cpp
  46. 0 3
      src/libraries/glslang/glslang/OSDependent/osinclude.h
  47. 67 19
      src/libraries/glslang/glslang/Public/ShaderLang.h

+ 0 - 2
CMakeLists.txt

@@ -1297,9 +1297,7 @@ set(LOVE_SRC_3P_GLSLANG_GLSLANG_MACHINEINDEPENDENT_PREPROCESSOR
 	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp
 	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp
 	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h
-	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpMemory.cpp
 	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp
-	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpSymbols.cpp
 	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp
 	src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h
 )

+ 0 - 12
platform/xcode/liblove.xcodeproj/project.pbxproj

@@ -1095,12 +1095,8 @@
 		FAF1408E1E20934C00F898D2 /* PpContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FED1E20934C00F898D2 /* PpContext.cpp */; };
 		FAF1408F1E20934C00F898D2 /* PpContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FED1E20934C00F898D2 /* PpContext.cpp */; };
 		FAF140901E20934C00F898D2 /* PpContext.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF13FEE1E20934C00F898D2 /* PpContext.h */; };
-		FAF140911E20934C00F898D2 /* PpMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FEF1E20934C00F898D2 /* PpMemory.cpp */; };
-		FAF140921E20934C00F898D2 /* PpMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FEF1E20934C00F898D2 /* PpMemory.cpp */; };
 		FAF140931E20934C00F898D2 /* PpScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FF01E20934C00F898D2 /* PpScanner.cpp */; };
 		FAF140941E20934C00F898D2 /* PpScanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FF01E20934C00F898D2 /* PpScanner.cpp */; };
-		FAF140951E20934C00F898D2 /* PpSymbols.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FF11E20934C00F898D2 /* PpSymbols.cpp */; };
-		FAF140961E20934C00F898D2 /* PpSymbols.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FF11E20934C00F898D2 /* PpSymbols.cpp */; };
 		FAF140971E20934C00F898D2 /* PpTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FF21E20934C00F898D2 /* PpTokens.cpp */; };
 		FAF140981E20934C00F898D2 /* PpTokens.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF13FF21E20934C00F898D2 /* PpTokens.cpp */; };
 		FAF140991E20934C00F898D2 /* PpTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF13FF31E20934C00F898D2 /* PpTokens.h */; };
@@ -1914,9 +1910,7 @@
 		FAF13FEC1E20934C00F898D2 /* PpAtom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PpAtom.cpp; sourceTree = "<group>"; };
 		FAF13FED1E20934C00F898D2 /* PpContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PpContext.cpp; sourceTree = "<group>"; };
 		FAF13FEE1E20934C00F898D2 /* PpContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PpContext.h; sourceTree = "<group>"; };
-		FAF13FEF1E20934C00F898D2 /* PpMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PpMemory.cpp; sourceTree = "<group>"; };
 		FAF13FF01E20934C00F898D2 /* PpScanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PpScanner.cpp; sourceTree = "<group>"; };
-		FAF13FF11E20934C00F898D2 /* PpSymbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PpSymbols.cpp; sourceTree = "<group>"; };
 		FAF13FF21E20934C00F898D2 /* PpTokens.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PpTokens.cpp; sourceTree = "<group>"; };
 		FAF13FF31E20934C00F898D2 /* PpTokens.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PpTokens.h; sourceTree = "<group>"; };
 		FAF13FF41E20934C00F898D2 /* propagateNoContraction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = propagateNoContraction.cpp; sourceTree = "<group>"; };
@@ -3471,9 +3465,7 @@
 				FAF13FEC1E20934C00F898D2 /* PpAtom.cpp */,
 				FAF13FED1E20934C00F898D2 /* PpContext.cpp */,
 				FAF13FEE1E20934C00F898D2 /* PpContext.h */,
-				FAF13FEF1E20934C00F898D2 /* PpMemory.cpp */,
 				FAF13FF01E20934C00F898D2 /* PpScanner.cpp */,
-				FAF13FF11E20934C00F898D2 /* PpSymbols.cpp */,
 				FAF13FF21E20934C00F898D2 /* PpTokens.cpp */,
 				FAF13FF31E20934C00F898D2 /* PpTokens.h */,
 			);
@@ -4079,7 +4071,6 @@
 				FAF140AA1E20934C00F898D2 /* SymbolTable.cpp in Sources */,
 				FA0B7A8D1A958EA3000E1D17 /* b2DistanceJoint.cpp in Sources */,
 				FA0B7A841A958EA3000E1D17 /* b2EdgeAndPolygonContact.cpp in Sources */,
-				FAF140921E20934C00F898D2 /* PpMemory.cpp in Sources */,
 				FA0B7E191A95902C000E1D17 /* MotorJoint.cpp in Sources */,
 				FAF1406F1E20934C00F898D2 /* Initialize.cpp in Sources */,
 				FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
@@ -4256,7 +4247,6 @@
 				FA0B7CE31A95902C000E1D17 /* wrap_Audio.cpp in Sources */,
 				FA0B7B381A958EA3000E1D17 /* wuff_internal.c in Sources */,
 				FA0B7DF81A95902C000E1D17 /* Body.cpp in Sources */,
-				FAF140961E20934C00F898D2 /* PpSymbols.cpp in Sources */,
 				FA4F2BB41DE1E4BD00CA37D7 /* RecordingDevice.cpp in Sources */,
 				FA0B7DF51A95902C000E1D17 /* wrap_Mouse.cpp in Sources */,
 				FA0B7E861A95902C000E1D17 /* CoreAudioDecoder.cpp in Sources */,
@@ -4440,7 +4430,6 @@
 				FAF140A91E20934C00F898D2 /* SymbolTable.cpp in Sources */,
 				FA0B7E181A95902C000E1D17 /* MotorJoint.cpp in Sources */,
 				FA0B7E4E1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
-				FAF140911E20934C00F898D2 /* PpMemory.cpp in Sources */,
 				FA0B7EBE1A95902C000E1D17 /* Thread.cpp in Sources */,
 				FAF1406E1E20934C00F898D2 /* Initialize.cpp in Sources */,
 				FA0B7EB81A95902C000E1D17 /* Channel.cpp in Sources */,
@@ -4617,7 +4606,6 @@
 				FA0B7DF41A95902C000E1D17 /* wrap_Mouse.cpp in Sources */,
 				FA0B7E851A95902C000E1D17 /* CoreAudioDecoder.cpp in Sources */,
 				FA0B7E751A95902C000E1D17 /* wrap_WeldJoint.cpp in Sources */,
-				FAF140951E20934C00F898D2 /* PpSymbols.cpp in Sources */,
 				FA0B7D551A95902C000E1D17 /* Buffer.cpp in Sources */,
 				FA57FB981AE1993600F2AD6D /* noise1234.cpp in Sources */,
 				FA0B7E211A95902C000E1D17 /* PolygonShape.cpp in Sources */,

+ 23 - 0
src/libraries/glslang/glslang/Include/BaseTypes.h

@@ -53,6 +53,10 @@ enum TBasicType {
     EbtUint,
     EbtInt64,
     EbtUint64,
+#ifdef AMD_EXTENSIONS
+    EbtInt16,
+    EbtUint16,
+#endif
     EbtBool,
     EbtAtomicUint,
     EbtSampler,
@@ -203,6 +207,9 @@ enum TBuiltInVariable {
     EbvBaryCoordPullModel,
 #endif
 
+    EbvViewIndex,
+    EbvDeviceIndex,
+
 #ifdef NV_EXTENSIONS
     EbvViewportMaskNV,
     EbvSecondaryPositionNV,
@@ -210,10 +217,22 @@ enum TBuiltInVariable {
     EbvPositionPerViewNV,
     EbvViewportMaskPerViewNV,
 #endif 
+
     // HLSL built-ins that live only temporarily, until they get remapped
     // to one of the above.
     EbvFragDepthGreater,
     EbvFragDepthLesser,
+    EbvStencilRef,
+    EbvGsOutputStream,
+    EbvOutputPatch,
+    EbvInputPatch,
+
+    // structbuffer types
+    EbvAppendConsume, // no need to differentiate append and consume
+    EbvRWStructuredBuffer,
+    EbvStructuredBuffer,
+    EbvByteAddressBuffer,
+    EbvRWByteAddressBuffer,
 
     EbvLast
 };
@@ -323,6 +342,10 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
     case EbvBaryCoordSmoothSample:      return "BaryCoordSmoothSample";
     case EbvBaryCoordPullModel:         return "BaryCoordPullModel";
 #endif
+
+    case EbvViewIndex:                  return "ViewIndex";
+    case EbvDeviceIndex:                return "DeviceIndex";
+
 #ifdef NV_EXTENSIONS
     case EbvViewportMaskNV:             return "ViewportMaskNV";
     case EbvSecondaryPositionNV:        return "SecondaryPositionNV";

+ 177 - 170
src/libraries/glslang/glslang/Include/Types.h

@@ -43,6 +43,8 @@
 #include "../Public/ShaderLang.h"
 #include "arrays.h"
 
+#include <algorithm>
+
 namespace glslang {
 
 const int GlslangMaxTypeLength = 200;  // TODO: need to print block/struct one member per line, so this can stay bounded
@@ -396,11 +398,13 @@ public:
         invariant = false;
         noContraction = false;
         makeTemporary();
+        declaredBuiltIn = EbvNone;
     }
 
     // drop qualifiers that don't belong in a temporary variable
     void makeTemporary()
     {
+        semanticName = nullptr;
         storage = EvqTemporary;
         builtIn = EbvNone;
         clearInterstage();
@@ -449,8 +453,10 @@ public:
         specConstant = false;
     }
 
+    const char*         semanticName;
     TStorageQualifier   storage   : 6;
     TBuiltInVariable    builtIn   : 8;
+    TBuiltInVariable    declaredBuiltIn : 8;
     TPrecisionQualifier precision : 3;
     bool invariant    : 1; // require canonical treatment for cross-shader invariance
     bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects
@@ -1302,6 +1308,7 @@ public:
 
     virtual TBasicType getBasicType() const { return basicType; }
     virtual const TSampler& getSampler() const { return sampler; }
+    virtual TSampler& getSampler() { return sampler; }
 
     virtual       TQualifier& getQualifier()       { return qualifier; }
     virtual const TQualifier& getQualifier() const { return qualifier; }
@@ -1378,127 +1385,84 @@ public:
         return !isPerVertexAndBuiltIn(language);
     }
     
+    // return true if this type contains any subtype which satisfies the given predicate.
+    template <typename P> 
+    bool contains(P predicate) const
+    {
+        if (predicate(this))
+            return true;
+
+        const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
+
+        return structure && std::any_of(structure->begin(), structure->end(), hasa);
+    }
+
     // Recursively checks if the type contains the given basic type
     virtual bool containsBasicType(TBasicType checkType) const
     {
-        if (basicType == checkType)
-            return true;
-        if (! structure)
-            return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->containsBasicType(checkType))
-                return true;
-        }
-        return false;
+        return contains([checkType](const TType* t) { return t->basicType == checkType; } );
     }
 
     // Recursively check the structure for any arrays, needed for some error checks
     virtual bool containsArray() const
     {
-        if (isArray())
-            return true;
-        if (structure == nullptr)
-            return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->containsArray())
-                return true;
-        }
-        return false;
+        return contains([](const TType* t) { return t->isArray(); } );
     }
 
     // Check the structure for any structures, needed for some error checks
     virtual bool containsStructure() const
     {
-        if (structure == nullptr)
-            return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->structure)
-                return true;
-        }
-        return false;
+        return contains([this](const TType* t) { return t != this && t->isStruct(); } );
     }
 
     // Recursively check the structure for any implicitly-sized arrays, needed for triggering a copyUp().
     virtual bool containsImplicitlySizedArray() const
     {
-        if (isImplicitlySizedArray())
-            return true;
-        if (structure == nullptr)
-            return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->containsImplicitlySizedArray())
-                return true;
-        }
-        return false;
+        return contains([](const TType* t) { return t->isImplicitlySizedArray(); } );
     }
 
     virtual bool containsOpaque() const
     {
-        if (isOpaque())
-            return true;
-        if (! structure)
-            return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->containsOpaque())
-                return true;
-        }
-        return false;
+        return contains([](const TType* t) { return t->isOpaque(); } );
     }
 
     // Recursively checks if the type contains an interstage IO builtin
     virtual bool containsBuiltInInterstageIO(EShLanguage language) const
     {
-        if (isBuiltInInterstageIO(language))
-            return true;
-
-        if (! structure)
-            return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->containsBuiltInInterstageIO(language))
-                return true;
-        }
-        return false;
+        return contains([language](const TType* t) { return t->isBuiltInInterstageIO(language); } );
     }
 
     virtual bool containsNonOpaque() const
     {
-        // list all non-opaque types
-        switch (basicType) {
-        case EbtVoid:
-        case EbtFloat:
-        case EbtDouble:
+        const auto nonOpaque = [](const TType* t) {
+            switch (t->basicType) {
+            case EbtVoid:
+            case EbtFloat:
+            case EbtDouble:
+#ifdef AMD_EXTENSIONS
+            case EbtFloat16:
+#endif
+            case EbtInt:
+            case EbtUint:
+            case EbtInt64:
+            case EbtUint64:
 #ifdef AMD_EXTENSIONS
-        case EbtFloat16:
+            case EbtInt16:
+            case EbtUint16:
 #endif
-        case EbtInt:
-        case EbtUint:
-        case EbtInt64:
-        case EbtUint64:
-        case EbtBool:
+            case EbtBool:
             return true;
-        default:
-            break;
-        }
-        if (! structure)
+            default:
             return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->containsNonOpaque())
-                return true;
-        }
-        return false;
+            }
+        };
+
+        return contains(nonOpaque);
     }
 
     virtual bool containsSpecializationSize() const
     {
-        if (isArray() && arraySizes->containsNode())
-            return true;
-        if (! structure)
-            return false;
-        for (unsigned int i = 0; i < structure->size(); ++i) {
-            if ((*structure)[i].type->containsSpecializationSize())
-                return true;
-        }
-        return false;
+        return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } );
     }
 
     // Array editing methods.  Array descriptors can be shared across
@@ -1569,6 +1533,10 @@ public:
         case EbtUint:              return "uint";
         case EbtInt64:             return "int64_t";
         case EbtUint64:            return "uint64_t";
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:             return "int16_t";
+        case EbtUint16:            return "uint16_t";
+#endif
         case EbtBool:              return "bool";
         case EbtAtomicUint:        return "atomic_uint";
         case EbtSampler:           return "sampler/image";
@@ -1580,10 +1548,11 @@ public:
 
     TString getCompleteString() const
     {
-        const int maxSize = GlslangMaxTypeLength;
-        char buf[maxSize];
-        char* p = &buf[0];
-        char* end = &buf[maxSize];
+        TString typeString;
+
+        const auto appendStr  = [&](const char* s)  { typeString.append(s); };
+        const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); };
+        const auto appendInt  = [&](int i)          { typeString.append(std::to_string(i).c_str()); };
 
         if (qualifier.hasLayout()) {
             // To reduce noise, skip this if the only layout is an xfb_buffer
@@ -1591,137 +1560,175 @@ public:
             TQualifier noXfbBuffer = qualifier;
             noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd;
             if (noXfbBuffer.hasLayout()) {
-                p += snprintf(p, end - p, "layout(");
+                appendStr("layout(");
                 if (qualifier.hasAnyLocation()) {
-                    p += snprintf(p, end - p, "location=%d ", qualifier.layoutLocation);
-                    if (qualifier.hasComponent())
-                        p += snprintf(p, end - p, "component=%d ", qualifier.layoutComponent);
-                    if (qualifier.hasIndex())
-                        p += snprintf(p, end - p, "index=%d ", qualifier.layoutIndex);
+                    appendStr(" location=");
+                    appendUint(qualifier.layoutLocation);
+                    if (qualifier.hasComponent()) {
+                        appendStr(" component=");
+                        appendUint(qualifier.layoutComponent);
+                    }
+                    if (qualifier.hasIndex()) {
+                        appendStr(" index=");
+                        appendUint(qualifier.layoutIndex);
+                    }
+                }
+                if (qualifier.hasSet()) {
+                    appendStr(" set=");
+                    appendUint(qualifier.layoutSet);
+                }
+                if (qualifier.hasBinding()) {
+                    appendStr(" binding=");
+                    appendUint(qualifier.layoutBinding);
+                }
+                if (qualifier.hasStream()) {
+                    appendStr(" stream=");
+                    appendUint(qualifier.layoutStream);
+                }
+                if (qualifier.hasMatrix()) {
+                    appendStr(" ");
+                    appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
+                }
+                if (qualifier.hasPacking()) {
+                    appendStr(" ");
+                    appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking));
+                }
+                if (qualifier.hasOffset()) {
+                    appendStr(" offset=");
+                    appendInt(qualifier.layoutOffset);
+                }
+                if (qualifier.hasAlign()) {
+                    appendStr(" align=");
+                    appendInt(qualifier.layoutAlign);
+                }
+                if (qualifier.hasFormat()) {
+                    appendStr(" ");
+                    appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat));
+                }
+                if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) {
+                    appendStr(" xfb_buffer=");
+                    appendUint(qualifier.layoutXfbBuffer);
+                }
+                if (qualifier.hasXfbOffset()) {
+                    appendStr(" xfb_offset=");
+                    appendUint(qualifier.layoutXfbOffset);
+                }
+                if (qualifier.hasXfbStride()) {
+                    appendStr(" xfb_stride=");
+                    appendUint(qualifier.layoutXfbStride);
+                }
+                if (qualifier.hasAttachment()) {
+                    appendStr(" input_attachment_index=");
+                    appendUint(qualifier.layoutAttachment);
+                }
+                if (qualifier.hasSpecConstantId()) {
+                    appendStr(" constant_id=");
+                    appendUint(qualifier.layoutSpecConstantId);
                 }
-                if (qualifier.hasSet())
-                    p += snprintf(p, end - p, "set=%d ", qualifier.layoutSet);
-                if (qualifier.hasBinding())
-                    p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding);
-                if (qualifier.hasStream())
-                    p += snprintf(p, end - p, "stream=%d ", qualifier.layoutStream);
-                if (qualifier.hasMatrix())
-                    p += snprintf(p, end - p, "%s ", TQualifier::getLayoutMatrixString(qualifier.layoutMatrix));
-                if (qualifier.hasPacking())
-                    p += snprintf(p, end - p, "%s ", TQualifier::getLayoutPackingString(qualifier.layoutPacking));
-                if (qualifier.hasOffset())
-                    p += snprintf(p, end - p, "offset=%d ", qualifier.layoutOffset);
-                if (qualifier.hasAlign())
-                    p += snprintf(p, end - p, "align=%d ", qualifier.layoutAlign);
-                if (qualifier.hasFormat())
-                    p += snprintf(p, end - p, "%s ", TQualifier::getLayoutFormatString(qualifier.layoutFormat));
-                if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset())
-                    p += snprintf(p, end - p, "xfb_buffer=%d ", qualifier.layoutXfbBuffer);
-                if (qualifier.hasXfbOffset())
-                    p += snprintf(p, end - p, "xfb_offset=%d ", qualifier.layoutXfbOffset);
-                if (qualifier.hasXfbStride())
-                    p += snprintf(p, end - p, "xfb_stride=%d ", qualifier.layoutXfbStride);
-                if (qualifier.hasAttachment())
-                    p += snprintf(p, end - p, "input_attachment_index=%d ", qualifier.layoutAttachment);
-                if (qualifier.hasSpecConstantId())
-                    p += snprintf(p, end - p, "constant_id=%d ", qualifier.layoutSpecConstantId);
                 if (qualifier.layoutPushConstant)
-                    p += snprintf(p, end - p, "push_constant ");
+                    appendStr(" push_constant");
 
 #ifdef NV_EXTENSIONS
                 if (qualifier.layoutPassthrough)
-                    p += snprintf(p, end - p, "passthrough ");
+                    appendStr(" passthrough");
                 if (qualifier.layoutViewportRelative)
-                    p += snprintf(p, end - p, "layoutViewportRelative ");
-                if (qualifier.layoutSecondaryViewportRelativeOffset != -2048)
-                    p += snprintf(p, end - p, "layoutSecondaryViewportRelativeOffset=%d ", qualifier.layoutSecondaryViewportRelativeOffset);
+                    appendStr(" layoutViewportRelative");
+                if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) {
+                    appendStr(" layoutSecondaryViewportRelativeOffset=");
+                    appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
+                }
 #endif
 
-                p += snprintf(p, end - p, ") ");
+                appendStr(")");
             }
         }
 
         if (qualifier.invariant)
-            p += snprintf(p, end - p, "invariant ");
+            appendStr(" invariant");
         if (qualifier.noContraction)
-            p += snprintf(p, end - p, "noContraction ");
+            appendStr(" noContraction");
         if (qualifier.centroid)
-            p += snprintf(p, end - p, "centroid ");
+            appendStr(" centroid");
         if (qualifier.smooth)
-            p += snprintf(p, end - p, "smooth ");
+            appendStr(" smooth");
         if (qualifier.flat)
-            p += snprintf(p, end - p, "flat ");
+            appendStr(" flat");
         if (qualifier.nopersp)
-            p += snprintf(p, end - p, "noperspective ");
+            appendStr(" noperspective");
 #ifdef AMD_EXTENSIONS
         if (qualifier.explicitInterp)
-            p += snprintf(p, end - p, "__explicitInterpAMD ");
+            appendStr(" __explicitInterpAMD");
 #endif
         if (qualifier.patch)
-            p += snprintf(p, end - p, "patch ");
+            appendStr(" patch");
         if (qualifier.sample)
-            p += snprintf(p, end - p, "sample ");
+            appendStr(" sample");
         if (qualifier.coherent)
-            p += snprintf(p, end - p, "coherent ");
+            appendStr(" coherent");
         if (qualifier.volatil)
-            p += snprintf(p, end - p, "volatile ");
+            appendStr(" volatile");
         if (qualifier.restrict)
-            p += snprintf(p, end - p, "restrict ");
+            appendStr(" restrict");
         if (qualifier.readonly)
-            p += snprintf(p, end - p, "readonly ");
+            appendStr(" readonly");
         if (qualifier.writeonly)
-            p += snprintf(p, end - p, "writeonly ");
+            appendStr(" writeonly");
         if (qualifier.specConstant)
-            p += snprintf(p, end - p, "specialization-constant ");
-        p += snprintf(p, end - p, "%s ", getStorageQualifierString());
+            appendStr(" specialization-constant");
+        appendStr(" ");
+        appendStr(getStorageQualifierString());
         if (isArray()) {
             for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) {
                 int size = arraySizes->getDimSize(i);
                 if (size == 0)
-                    p += snprintf(p, end - p, "implicitly-sized array of ");
-                else
-                    p += snprintf(p, end - p, "%d-element array of ", arraySizes->getDimSize(i));
+                    appendStr(" implicitly-sized array of");
+                else {
+                    appendStr(" ");
+                    appendInt(arraySizes->getDimSize(i));
+                    appendStr("-element array of");
+                }
             }
         }
-        if (qualifier.precision != EpqNone)
-            p += snprintf(p, end - p, "%s ", getPrecisionQualifierString());
-        if (isMatrix())
-            p += snprintf(p, end - p, "%dX%d matrix of ", matrixCols, matrixRows);
-        else if (isVector())
-            p += snprintf(p, end - p, "%d-component vector of ", vectorSize);
+        if (qualifier.precision != EpqNone) {
+            appendStr(" ");
+            appendStr(getPrecisionQualifierString());
+        }
+        if (isMatrix()) {
+            appendStr(" ");
+            appendInt(matrixCols);
+            appendStr("X");
+            appendInt(matrixRows);
+            appendStr(" matrix of");
+        } else if (isVector()) {
+            appendStr(" ");
+            appendInt(vectorSize);
+            appendStr("-component vector of");
+        }
 
-        *p = 0;
-        TString s(buf);
-        s.append(getBasicTypeString());
+        appendStr(" ");
+        typeString.append(getBasicTypeString());
 
         if (qualifier.builtIn != EbvNone) {
-            s.append(" ");
-            s.append(getBuiltInVariableString());
+            appendStr(" ");
+            appendStr(getBuiltInVariableString());
         }
 
         // Add struct/block members
         if (structure) {
-            s.append("{");
+            appendStr("{");
             for (size_t i = 0; i < structure->size(); ++i) {
-                if (s.size() > 3 * GlslangMaxTypeLength) {
-                    // If we are getting too long, cut it short,
-                    // just need to draw the line somewhere, as there is no limit to
-                    // how large a struct/block type can get.
-                    s.append("...");
-                    break;
-                }
                 if (! (*structure)[i].type->hiddenMember()) {
-                    s.append((*structure)[i].type->getCompleteString());
-                    s.append(" ");
-                    s.append((*structure)[i].type->getFieldName());
+                    typeString.append((*structure)[i].type->getCompleteString());
+                    typeString.append(" ");
+                    typeString.append((*structure)[i].type->getFieldName());
                     if (i < structure->size() - 1)
-                        s.append(", ");
+                        appendStr(", ");
                 }
             }
-            s.append("}");
+            appendStr("}");
         }
 
-        return s;
+        return typeString;
     }
 
     TString getBasicTypeString() const
@@ -1759,7 +1766,7 @@ public:
     }
 
     // append this type's mangled name to the passed in 'name'
-    void appendMangledName(TString& name)
+    void appendMangledName(TString& name) const
     {
         buildMangledName(name);
         name += ';' ;
@@ -1883,7 +1890,7 @@ protected:
     }
 
 
-    void buildMangledName(TString&);
+    void buildMangledName(TString&) const;
 
     TBasicType basicType : 8;
     int vectorSize       : 4;  // 1 means either scalar or 1-component vector; see vector1 to disambiguate.

+ 14 - 12
src/libraries/glslang/glslang/Include/arrays.h

@@ -264,6 +264,20 @@ struct TArraySizes {
 
         return false;
     }
+    bool isInnerSpecialization() const
+    {
+        for (int d = 1; d < sizes.size(); ++d) {
+            if (sizes.getDimNode(d) != nullptr)
+                return true;
+        }
+
+        return false;
+    }
+    bool isOuterSpecialization()
+    {
+        return sizes.getDimNode(0) != nullptr;
+    }
+
     bool isImplicit() const { return getOuterSize() == UnsizedArraySize || isInnerImplicit(); }
     void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); }
     void dereference() { sizes.pop_front(); }
@@ -288,18 +302,6 @@ struct TArraySizes {
         return true;
     }
 
-    // Returns true if any of the dimensions of the array is sized with a node
-    // instead of a front-end compile-time constant.
-    bool containsNode()
-    {
-        for (int d = 0; d < sizes.size(); ++d) {
-            if (sizes.getDimNode(d) != nullptr)
-                return true;
-        }
-
-        return false;
-    }
-
     bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
     bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
 

+ 158 - 5
src/libraries/glslang/glslang/Include/intermediate.h

@@ -141,6 +141,42 @@ enum TOperator {
     EOpConvFloat16ToDouble,
     EOpConvFloat16ToInt64,
     EOpConvFloat16ToUint64,
+
+    EOpConvBoolToInt16,
+    EOpConvIntToInt16,
+    EOpConvUintToInt16,
+    EOpConvFloatToInt16,
+    EOpConvDoubleToInt16,
+    EOpConvFloat16ToInt16,
+    EOpConvInt64ToInt16,
+    EOpConvUint64ToInt16,
+    EOpConvUint16ToInt16,
+    EOpConvInt16ToBool,
+    EOpConvInt16ToInt,
+    EOpConvInt16ToUint,
+    EOpConvInt16ToFloat,
+    EOpConvInt16ToDouble,
+    EOpConvInt16ToFloat16,
+    EOpConvInt16ToInt64,
+    EOpConvInt16ToUint64,
+
+    EOpConvBoolToUint16,
+    EOpConvIntToUint16,
+    EOpConvUintToUint16,
+    EOpConvFloatToUint16,
+    EOpConvDoubleToUint16,
+    EOpConvFloat16ToUint16,
+    EOpConvInt64ToUint16,
+    EOpConvUint64ToUint16,
+    EOpConvInt16ToUint16,
+    EOpConvUint16ToBool,
+    EOpConvUint16ToInt,
+    EOpConvUint16ToUint,
+    EOpConvUint16ToFloat,
+    EOpConvUint16ToDouble,
+    EOpConvUint16ToFloat16,
+    EOpConvUint16ToInt64,
+    EOpConvUint16ToUint64,
 #endif
 
     //
@@ -183,6 +219,7 @@ enum TOperator {
     EOpVectorSwizzle,
 
     EOpMethod,
+    EOpScoping,
 
     //
     // Built-in functions mapped to operators
@@ -243,6 +280,12 @@ enum TOperator {
     EOpDoubleBitsToUint64,
     EOpInt64BitsToDouble,
     EOpUint64BitsToDouble,
+#ifdef AMD_EXTENSIONS
+    EOpFloat16BitsToInt16,
+    EOpFloat16BitsToUint16,
+    EOpInt16BitsToFloat16,
+    EOpUint16BitsToFloat16,
+#endif
     EOpPackSnorm2x16,
     EOpUnpackSnorm2x16,
     EOpPackUnorm2x16,
@@ -262,6 +305,14 @@ enum TOperator {
 #ifdef AMD_EXTENSIONS
     EOpPackFloat2x16,
     EOpUnpackFloat2x16,
+    EOpPackInt2x16,
+    EOpUnpackInt2x16,
+    EOpPackUint2x16,
+    EOpUnpackUint2x16,
+    EOpPackInt4x16,
+    EOpUnpackInt4x16,
+    EOpPackUint4x16,
+    EOpUnpackUint4x16,
 #endif
 
     EOpLength,
@@ -393,15 +444,27 @@ enum TOperator {
     EOpConstructUint,
     EOpConstructInt64,
     EOpConstructUint64,
+#ifdef AMD_EXTENSIONS
+    EOpConstructInt16,
+    EOpConstructUint16,
+#endif
     EOpConstructBool,
     EOpConstructFloat,
     EOpConstructDouble,
+#ifdef AMD_EXTENSIONS
+    EOpConstructFloat16,
+#endif
     EOpConstructVec2,
     EOpConstructVec3,
     EOpConstructVec4,
     EOpConstructDVec2,
     EOpConstructDVec3,
     EOpConstructDVec4,
+#ifdef AMD_EXTENSIONS
+    EOpConstructF16Vec2,
+    EOpConstructF16Vec3,
+    EOpConstructF16Vec4,
+#endif
     EOpConstructBVec2,
     EOpConstructBVec3,
     EOpConstructBVec4,
@@ -417,6 +480,14 @@ enum TOperator {
     EOpConstructU64Vec2,
     EOpConstructU64Vec3,
     EOpConstructU64Vec4,
+#ifdef AMD_EXTENSIONS
+    EOpConstructI16Vec2,
+    EOpConstructI16Vec3,
+    EOpConstructI16Vec4,
+    EOpConstructU16Vec2,
+    EOpConstructU16Vec3,
+    EOpConstructU16Vec4,
+#endif
     EOpConstructMat2x2,
     EOpConstructMat2x3,
     EOpConstructMat2x4,
@@ -435,11 +506,34 @@ enum TOperator {
     EOpConstructDMat4x2,
     EOpConstructDMat4x3,
     EOpConstructDMat4x4,
+    EOpConstructIMat2x2,
+    EOpConstructIMat2x3,
+    EOpConstructIMat2x4,
+    EOpConstructIMat3x2,
+    EOpConstructIMat3x3,
+    EOpConstructIMat3x4,
+    EOpConstructIMat4x2,
+    EOpConstructIMat4x3,
+    EOpConstructIMat4x4,
+    EOpConstructUMat2x2,
+    EOpConstructUMat2x3,
+    EOpConstructUMat2x4,
+    EOpConstructUMat3x2,
+    EOpConstructUMat3x3,
+    EOpConstructUMat3x4,
+    EOpConstructUMat4x2,
+    EOpConstructUMat4x3,
+    EOpConstructUMat4x4,
+    EOpConstructBMat2x2,
+    EOpConstructBMat2x3,
+    EOpConstructBMat2x4,
+    EOpConstructBMat3x2,
+    EOpConstructBMat3x3,
+    EOpConstructBMat3x4,
+    EOpConstructBMat4x2,
+    EOpConstructBMat4x3,
+    EOpConstructBMat4x4,
 #ifdef AMD_EXTENSIONS
-    EOpConstructFloat16,
-    EOpConstructF16Vec2,
-    EOpConstructF16Vec3,
-    EOpConstructF16Vec4,
     EOpConstructF16Mat2x2,
     EOpConstructF16Mat2x3,
     EOpConstructF16Mat2x4,
@@ -539,6 +633,11 @@ enum TOperator {
     EOpTextureOffsetClamp,
     EOpTextureGradClamp,
     EOpTextureGradOffsetClamp,
+#ifdef AMD_EXTENSIONS
+    EOpTextureGatherLod,
+    EOpTextureGatherLodOffset,
+    EOpTextureGatherLodOffsets,
+#endif
 
     EOpSparseTextureGuardBegin,
 
@@ -558,6 +657,11 @@ enum TOperator {
     EOpSparseTextureOffsetClamp,
     EOpSparseTextureGradClamp,
     EOpSparseTextureGradOffsetClamp,
+#ifdef AMD_EXTENSIONS
+    EOpSparseTextureGatherLod,
+    EOpSparseTextureGatherLodOffset,
+    EOpSparseTextureGatherLodOffsets,
+#endif
 
     EOpSparseTextureGuardEnd,
     EOpSamplingGuardEnd,
@@ -624,6 +728,19 @@ enum TOperator {
     EOpMethodCalculateLevelOfDetail,     // ...
     EOpMethodCalculateLevelOfDetailUnclamped,     // ...
 
+    // Load already defined above for textures
+    EOpMethodLoad2,                      // Structure buffer object methods.  These are translated to existing
+    EOpMethodLoad3,                      // AST methods, and exist to represent HLSL semantics until that
+    EOpMethodLoad4,                      // translation is performed.  See HlslParseContext::decomposeSampleMethods().
+    EOpMethodStore,                      // ...
+    EOpMethodStore2,                     // ...
+    EOpMethodStore3,                     // ...
+    EOpMethodStore4,                     // ...
+    EOpMethodIncrementCounter,           // ...
+    EOpMethodDecrementCounter,           // ...
+    // EOpMethodAppend is defined for geo shaders below
+    EOpMethodConsume,
+
     // SM5 texture methods
     EOpMethodGatherRed,                  // These are covered under the above EOpMethodSample comment about
     EOpMethodGatherGreen,                // translation to existing AST opcodes.  They exist temporarily
@@ -744,6 +861,15 @@ protected:
     TType type;
 };
 
+//
+// Loop control hints
+//
+enum TLoopControl {
+    ELoopControlNone,
+    ELoopControlUnroll,
+    ELoopControlDontUnroll,
+};
+
 //
 // Handle for, do-while, and while loops.
 //
@@ -753,17 +879,25 @@ public:
         body(aBody),
         test(aTest),
         terminal(aTerminal),
-        first(testFirst) { }
+        first(testFirst),
+        control(ELoopControlNone)
+    { }
+
     virtual void traverse(TIntermTraverser*);
     TIntermNode*  getBody() const { return body; }
     TIntermTyped* getTest() const { return test; }
     TIntermTyped* getTerminal() const { return terminal; }
     bool testFirst() const { return first; }
+
+    void setLoopControl(TLoopControl c) { control = c; }
+    TLoopControl getLoopControl() const { return control; }
+
 protected:
     TIntermNode* body;       // code to loop over
     TIntermTyped* test;      // exit condition associated with loop, could be 0 for 'for' loops
     TIntermTyped* terminal;  // exists for for-loops
     bool first;              // true for while and for, not for do-while
+    TLoopControl control;    // loop control hint
 };
 
 //
@@ -1017,6 +1151,25 @@ public:
             cracked.gather = true;
             cracked.offsets = true;
             break;
+#ifdef AMD_EXTENSIONS
+        case EOpTextureGatherLod:
+        case EOpSparseTextureGatherLod:
+            cracked.gather = true;
+            cracked.lod    = true;
+            break;
+        case EOpTextureGatherLodOffset:
+        case EOpSparseTextureGatherLodOffset:
+            cracked.gather = true;
+            cracked.offset = true;
+            cracked.lod    = true;
+            break;
+        case EOpTextureGatherLodOffsets:
+        case EOpSparseTextureGatherLodOffsets:
+            cracked.gather  = true;
+            cracked.offsets = true;
+            cracked.lod     = true;
+            break;
+#endif
         case EOpSubpassLoad:
         case EOpSubpassLoadMS:
             cracked.subpass = true;

+ 2 - 2
src/libraries/glslang/glslang/Include/revision.h

@@ -2,5 +2,5 @@
 // For the version, it uses the latest git tag followed by the number of commits.
 // For the date, it uses the current date (when then script is run).
 
-#define GLSLANG_REVISION "Overload400-PrecQual.1843"
-#define GLSLANG_DATE "18-Feb-2017"
+#define GLSLANG_REVISION "Overload400-PrecQual.2000"
+#define GLSLANG_DATE "12-Apr-2017"

+ 36 - 2
src/libraries/glslang/glslang/MachineIndependent/Constant.cpp

@@ -193,7 +193,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
 
             case EbtUint:
                 if (rightUnionArray[i] == 0) {
-                    newConstArray[i].setUConst(0xFFFFFFFF);
+                    newConstArray[i].setUConst(0xFFFFFFFFu);
                 } else
                     newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
                 break;
@@ -213,6 +213,23 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
                 } else
                     newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
                 break;
+#ifdef AMD_EXTENSIONS
+            case EbtInt16:
+                if (rightUnionArray[i] == 0)
+                    newConstArray[i].setIConst(0x7FFF);
+                else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)0x8000)
+                    newConstArray[i].setIConst(0x8000);
+                else
+                    newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
+                break;
+
+            case EbtUint16:
+                if (rightUnionArray[i] == 0) {
+                    newConstArray[i].setUConst(0xFFFFu);
+                } else
+                    newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
+                break;
+#endif
             default:
                 return 0;
             }
@@ -457,10 +474,16 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
             case EbtFloat16:
 #endif
             case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
+#ifdef AMD_EXTENSIONS
+            case EbtInt16:
+#endif
             case EbtInt:   newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
+#ifdef AMD_EXTENSIONS
+            case EbtUint16:
+#endif
             case EbtUint:  newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst())));  break;
             case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
-            case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getU64Const())));  break;
+            case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const())));  break;
             default:
                 return 0;
             }
@@ -610,6 +633,14 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
         case EOpUintBitsToFloat:
         case EOpDoubleBitsToInt64:
         case EOpDoubleBitsToUint64:
+        case EOpInt64BitsToDouble:
+        case EOpUint64BitsToDouble:
+#ifdef AMD_EXTENSIONS
+        case EOpFloat16BitsToInt16:
+        case EOpFloat16BitsToUint16:
+        case EOpInt16BitsToFloat16:
+        case EOpUint16BitsToFloat16:
+#endif
 
         default:
             return 0;
@@ -702,6 +733,9 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
 #endif
                            children[0]->getAsTyped()->getBasicType() == EbtDouble;
     bool isSigned = children[0]->getAsTyped()->getBasicType() == EbtInt ||
+#ifdef AMD_EXTENSIONS
+                    children[0]->getAsTyped()->getBasicType() == EbtInt16 ||
+#endif
                     children[0]->getAsTyped()->getBasicType() == EbtInt64;
     bool isInt64 = children[0]->getAsTyped()->getBasicType() == EbtInt64 ||
                    children[0]->getAsTyped()->getBasicType() == EbtUint64;

+ 417 - 32
src/libraries/glslang/glslang/MachineIndependent/Initialize.cpp

@@ -103,6 +103,7 @@ TBuiltIns::~TBuiltIns()
 {
 }
 
+
 //
 // Add all context-independent built-in functions and variables that are present
 // for the given version and profile.  Share common ones across stages, otherwise
@@ -2615,6 +2616,157 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
 
             "\n");
     }
+
+    // GL_AMD_gpu_shader_int16
+    if (profile != EEsProfile && version >= 450) {
+        commonBuiltins.append(
+            "int16_t abs(int16_t);"
+            "i16vec2 abs(i16vec2);"
+            "i16vec3 abs(i16vec3);"
+            "i16vec4 abs(i16vec4);"
+
+            "int16_t sign(int16_t);"
+            "i16vec2 sign(i16vec2);"
+            "i16vec3 sign(i16vec3);"
+            "i16vec4 sign(i16vec4);"
+
+            "int16_t  min(int16_t,  int16_t);"
+            "i16vec2  min(i16vec2,  int16_t);"
+            "i16vec3  min(i16vec3,  int16_t);"
+            "i16vec4  min(i16vec4,  int16_t);"
+            "i16vec2  min(i16vec2,  i16vec2);"
+            "i16vec3  min(i16vec3,  i16vec3);"
+            "i16vec4  min(i16vec4,  i16vec4);"
+            "uint16_t min(uint16_t, uint16_t);"
+            "u16vec2  min(u16vec2,  uint16_t);"
+            "u16vec3  min(u16vec3,  uint16_t);"
+            "u16vec4  min(u16vec4,  uint16_t);"
+            "u16vec2  min(u16vec2,  u16vec2);"
+            "u16vec3  min(u16vec3,  u16vec3);"
+            "u16vec4  min(u16vec4,  u16vec4);"
+
+            "int16_t  max(int16_t,  int16_t);"
+            "i16vec2  max(i16vec2,  int16_t);"
+            "i16vec3  max(i16vec3,  int16_t);"
+            "i16vec4  max(i16vec4,  int16_t);"
+            "i16vec2  max(i16vec2,  i16vec2);"
+            "i16vec3  max(i16vec3,  i16vec3);"
+            "i16vec4  max(i16vec4,  i16vec4);"
+            "uint16_t max(uint16_t, uint16_t);"
+            "u16vec2  max(u16vec2,  uint16_t);"
+            "u16vec3  max(u16vec3,  uint16_t);"
+            "u16vec4  max(u16vec4,  uint16_t);"
+            "u16vec2  max(u16vec2,  u16vec2);"
+            "u16vec3  max(u16vec3,  u16vec3);"
+            "u16vec4  max(u16vec4,  u16vec4);"
+
+            "int16_t  clamp(int16_t,  int16_t,  int16_t);"
+            "i16vec2  clamp(i16vec2,  int16_t,  int16_t);"
+            "i16vec3  clamp(i16vec3,  int16_t,  int16_t);"
+            "i16vec4  clamp(i16vec4,  int16_t,  int16_t);"
+            "i16vec2  clamp(i16vec2,  i16vec2,  i16vec2);"
+            "i16vec3  clamp(i16vec3,  i16vec3,  i16vec3);"
+            "i16vec4  clamp(i16vec4,  i16vec4,  i16vec4);"
+            "uint16_t clamp(uint16_t, uint16_t, uint16_t);"
+            "u16vec2  clamp(u16vec2,  uint16_t, uint16_t);"
+            "u16vec3  clamp(u16vec3,  uint16_t, uint16_t);"
+            "u16vec4  clamp(u16vec4,  uint16_t, uint16_t);"
+            "u16vec2  clamp(u16vec2,  u16vec2,  u16vec2);"
+            "u16vec3  clamp(u16vec3,  u16vec3,  u16vec3);"
+            "u16vec4  clamp(u16vec4,  u16vec4,  u16vec4);"
+
+            "int16_t  mix(int16_t,  int16_t,  bool);"
+            "i16vec2  mix(i16vec2,  i16vec2,  bvec2);"
+            "i16vec3  mix(i16vec3,  i16vec3,  bvec3);"
+            "i16vec4  mix(i16vec4,  i16vec4,  bvec4);"
+            "uint16_t mix(uint16_t, uint16_t, bool);"
+            "u16vec2  mix(u16vec2,  u16vec2,  bvec2);"
+            "u16vec3  mix(u16vec3,  u16vec3,  bvec3);"
+            "u16vec4  mix(u16vec4,  u16vec4,  bvec4);"
+
+            "float16_t frexp(float16_t, out int16_t);"
+            "f16vec2   frexp(f16vec2,   out i16vec2);"
+            "f16vec3   frexp(f16vec3,   out i16vec3);"
+            "f16vec4   frexp(f16vec4,   out i16vec4);"
+
+            "float16_t ldexp(float16_t, int16_t);"
+            "f16vec2   ldexp(f16vec2,   i16vec2);"
+            "f16vec3   ldexp(f16vec3,   i16vec3);"
+            "f16vec4   ldexp(f16vec4,   i16vec4);"
+
+            "int16_t float16BitsToInt16(float16_t);"
+            "i16vec2 float16BitsToInt16(f16vec2);"
+            "i16vec3 float16BitsToInt16(f16vec3);"
+            "i16vec4 float16BitsToInt16(f16vec4);"
+
+            "uint16_t float16BitsToUint16(float16_t);"
+            "u16vec2  float16BitsToUint16(f16vec2);"
+            "u16vec3  float16BitsToUint16(f16vec3);"
+            "u16vec4  float16BitsToUint16(f16vec4);"
+
+            "float16_t int16BitsToFloat16(int16_t);"
+            "f16vec2   int16BitsToFloat16(i16vec2);"
+            "f16vec3   int16BitsToFloat16(i16vec3);"
+            "f16vec4   int16BitsToFloat16(i16vec4);"
+
+            "float16_t uint16BitsToFloat16(uint16_t);"
+            "f16vec2   uint16BitsToFloat16(u16vec2);"
+            "f16vec3   uint16BitsToFloat16(u16vec3);"
+            "f16vec4   uint16BitsToFloat16(u16vec4);"
+
+            "int      packInt2x16(i16vec2);"
+            "uint     packUint2x16(u16vec2);"
+            "int64_t  packInt4x16(i16vec4);"
+            "uint64_t packUint4x16(u16vec4);"
+            "i16vec2  unpackInt2x16(int);"
+            "u16vec2  unpackUint2x16(uint);"
+            "i16vec4  unpackInt4x16(int64_t);"
+            "u16vec4  unpackUint4x16(uint64_t);"
+
+            "bvec2 lessThan(i16vec2, i16vec2);"
+            "bvec3 lessThan(i16vec3, i16vec3);"
+            "bvec4 lessThan(i16vec4, i16vec4);"
+            "bvec2 lessThan(u16vec2, u16vec2);"
+            "bvec3 lessThan(u16vec3, u16vec3);"
+            "bvec4 lessThan(u16vec4, u16vec4);"
+
+            "bvec2 lessThanEqual(i16vec2, i16vec2);"
+            "bvec3 lessThanEqual(i16vec3, i16vec3);"
+            "bvec4 lessThanEqual(i16vec4, i16vec4);"
+            "bvec2 lessThanEqual(u16vec2, u16vec2);"
+            "bvec3 lessThanEqual(u16vec3, u16vec3);"
+            "bvec4 lessThanEqual(u16vec4, u16vec4);"
+
+            "bvec2 greaterThan(i16vec2, i16vec2);"
+            "bvec3 greaterThan(i16vec3, i16vec3);"
+            "bvec4 greaterThan(i16vec4, i16vec4);"
+            "bvec2 greaterThan(u16vec2, u16vec2);"
+            "bvec3 greaterThan(u16vec3, u16vec3);"
+            "bvec4 greaterThan(u16vec4, u16vec4);"
+
+            "bvec2 greaterThanEqual(i16vec2, i16vec2);"
+            "bvec3 greaterThanEqual(i16vec3, i16vec3);"
+            "bvec4 greaterThanEqual(i16vec4, i16vec4);"
+            "bvec2 greaterThanEqual(u16vec2, u16vec2);"
+            "bvec3 greaterThanEqual(u16vec3, u16vec3);"
+            "bvec4 greaterThanEqual(u16vec4, u16vec4);"
+
+            "bvec2 equal(i16vec2, i16vec2);"
+            "bvec3 equal(i16vec3, i16vec3);"
+            "bvec4 equal(i16vec4, i16vec4);"
+            "bvec2 equal(u16vec2, u16vec2);"
+            "bvec3 equal(u16vec3, u16vec3);"
+            "bvec4 equal(u16vec4, u16vec4);"
+
+            "bvec2 notEqual(i16vec2, i16vec2);"
+            "bvec3 notEqual(i16vec3, i16vec3);"
+            "bvec4 notEqual(i16vec4, i16vec4);"
+            "bvec2 notEqual(u16vec2, u16vec2);"
+            "bvec3 notEqual(u16vec3, u16vec3);"
+            "bvec4 notEqual(u16vec4, u16vec4);"
+
+            "\n");
+    }
 #endif
 
     //============================================================================
@@ -3137,6 +3289,13 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
     }
 
+    if ((profile != EEsProfile && version >= 140) ||
+        (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangCompute].append(
+            "in highp int gl_DeviceIndex;"     // GL_EXT_device_group
+            "\n");
+    }
+
     //============================================================================
     //
     // Define the interface to the vertex shader.
@@ -3261,11 +3420,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             stageBuiltins[EShLangVertex].append(
                 "out int gl_ViewportIndex;"
                 "out int gl_Layer;"
-                "out int gl_ViewportMask[];"
-                "out int gl_SecondaryViewportMaskNV[];"
-                "out vec4 gl_SecondaryPositionNV;"
-                "out vec4 gl_PositionPerViewNV[];"
-                "out int  gl_ViewportMaskPerViewNV[];"
+                "out int gl_ViewportMask[];"             // GL_NV_viewport_array2
+                "out int gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
+                "out vec4 gl_SecondaryPositionNV;"       // GL_NV_stereo_view_rendering
+                "out vec4 gl_PositionPerViewNV[];"       // GL_NVX_multiview_per_view_attributes
+                "out int  gl_ViewportMaskPerViewNV[];"   // GL_NVX_multiview_per_view_attributes
                 );
 #endif
 
@@ -3302,6 +3461,15 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
         }
     }
 
+    if ((profile != EEsProfile && version >= 140) ||
+        (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangVertex].append(
+            "in highp int gl_DeviceIndex;"     // GL_EXT_device_group
+            "in highp int gl_ViewIndex;"       // GL_EXT_multiview
+            "\n");
+    }
+
+
     //============================================================================
     //
     // Define the interface to the geometry shader.
@@ -3329,8 +3497,8 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             stageBuiltins[EShLangGeometry].append(
                 "float gl_CullDistance[];"
 #ifdef NV_EXTENSIONS
-                "vec4 gl_SecondaryPositionNV;"
-                "vec4 gl_PositionPerViewNV[];"
+                "vec4 gl_SecondaryPositionNV;"   // GL_NV_stereo_view_rendering
+                "vec4 gl_PositionPerViewNV[];"   // GL_NVX_multiview_per_view_attributes
 #endif
                 );
         stageBuiltins[EShLangGeometry].append(
@@ -3380,11 +3548,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
 #ifdef NV_EXTENSIONS
         if (version >= 450)
             stageBuiltins[EShLangGeometry].append(
-                "out int gl_ViewportMask[];"
-                "out int gl_SecondaryViewportMaskNV[];"
-                "out vec4 gl_SecondaryPositionNV;"
-                "out vec4 gl_PositionPerViewNV[];"
-                "out int  gl_ViewportMaskPerViewNV[];"
+                "out int gl_ViewportMask[];"               // GL_NV_viewport_array2
+                "out int gl_SecondaryViewportMaskNV[];"    // GL_NV_stereo_view_rendering
+                "out vec4 gl_SecondaryPositionNV;"         // GL_NV_stereo_view_rendering
+                "out vec4 gl_PositionPerViewNV[];"         // GL_NVX_multiview_per_view_attributes
+                "out int  gl_ViewportMaskPerViewNV[];"     // GL_NVX_multiview_per_view_attributes
             );
 #endif
 
@@ -3410,6 +3578,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             );
     }
 
+    if ((profile != EEsProfile && version >= 140) ||
+        (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangGeometry].append(
+            "in highp int gl_DeviceIndex;"     // GL_EXT_device_group
+            "in highp int gl_ViewIndex;"       // GL_EXT_multiview
+            "\n");
+    }
+
     //============================================================================
     //
     // Define the interface to the tessellation control shader.
@@ -3446,11 +3622,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
 #ifdef NV_EXTENSIONS
                 "int  gl_ViewportIndex;"
                 "int  gl_Layer;"
-                "int  gl_ViewportMask[];"
-                "vec4 gl_SecondaryPositionNV;"
-                "int  gl_SecondaryViewportMaskNV[];"
-                "vec4 gl_PositionPerViewNV[];"
-                "int  gl_ViewportMaskPerViewNV[];"
+                "int  gl_ViewportMask[];"             // GL_NV_viewport_array2
+                "vec4 gl_SecondaryPositionNV;"        // GL_NV_stereo_view_rendering
+                "int  gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
+                "vec4 gl_PositionPerViewNV[];"        // GL_NVX_multiview_per_view_attributes
+                "int  gl_ViewportMaskPerViewNV[];"    // GL_NVX_multiview_per_view_attributes
 #endif
                 );
         stageBuiltins[EShLangTessControl].append(
@@ -3481,6 +3657,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
     }
 
+    if ((profile != EEsProfile && version >= 140) ||
+        (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangTessControl].append(
+            "in highp int gl_DeviceIndex;"     // GL_EXT_device_group
+            "in highp int gl_ViewIndex;"       // GL_EXT_multiview
+            "\n");
+    }
+
     //============================================================================
     //
     // Define the interface to the tessellation evaluation shader.
@@ -3527,11 +3711,11 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             stageBuiltins[EShLangTessEvaluation].append(
                 "out int  gl_ViewportIndex;"
                 "out int  gl_Layer;"
-                "out int  gl_ViewportMask[];"
-                "out vec4 gl_SecondaryPositionNV;"
-                "out int  gl_SecondaryViewportMaskNV[];"
-                "out vec4 gl_PositionPerViewNV[];"
-                "out int  gl_ViewportMaskPerViewNV[];"
+                "out int  gl_ViewportMask[];"             // GL_NV_viewport_array2
+                "out vec4 gl_SecondaryPositionNV;"        // GL_NV_stereo_view_rendering
+                "out int  gl_SecondaryViewportMaskNV[];"  // GL_NV_stereo_view_rendering
+                "out vec4 gl_PositionPerViewNV[];"        // GL_NVX_multiview_per_view_attributes
+                "out int  gl_ViewportMaskPerViewNV[];"    // GL_NVX_multiview_per_view_attributes
                 );
 #endif
 
@@ -3556,6 +3740,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
     }
 
+    if ((profile != EEsProfile && version >= 140) ||
+        (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangTessEvaluation].append(
+            "in highp int gl_DeviceIndex;"     // GL_EXT_device_group
+            "in highp int gl_ViewIndex;"       // GL_EXT_multiview
+            "\n");
+    }
+
     //============================================================================
     //
     // Define the interface to the fragment shader.
@@ -3713,6 +3905,14 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
             "\n");
     }
 
+    if ((profile != EEsProfile && version >= 140) ||
+        (profile == EEsProfile && version >= 310)) {
+        stageBuiltins[EShLangFragment].append(
+            "flat in highp int gl_DeviceIndex;"     // GL_EXT_device_group
+            "flat in highp int gl_ViewIndex;"       // GL_EXT_multiview
+            "\n");
+    }
+
     // printf("%s\n", commonBuiltins.c_str());
     // printf("%s\n", stageBuiltins[EShLangFragment].c_str());
 }
@@ -3808,6 +4008,17 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c
                             else {
                                 addSamplingFunctions(sampler, typeName, version, profile);
                                 addGatherFunctions(sampler, typeName, version, profile);
+
+                                if (spvVersion.vulkan > 0 && sampler.dim == EsdBuffer && sampler.isCombined()) {
+                                    // Vulkan wants a textureBuffer to allow texelFetch() --
+                                    // a sampled image with no sampler.
+                                    // So, add sampling functions for both the
+                                    // samplerBuffer and textureBuffer types.
+                                    sampler.setTexture(sampler.type, sampler.dim, sampler.arrayed, sampler.shadow,
+                                                       sampler.ms);
+                                    TString textureTypeName = sampler.getString();
+                                    addSamplingFunctions(sampler, textureTypeName, version, profile);
+                                }
                             }
                         }
                     }
@@ -3831,7 +4042,7 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, c
 //
 // Add all the query functions for the given type.
 //
-void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
 {
     if (sampler.image && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430)))
         return;
@@ -3908,7 +4119,7 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int versi
 //
 // Add all the image access functions for the given type.
 //
-void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
 {
     int dims = dimMap[sampler.dim];
     // most things with an array add a dimension, except for cubemaps
@@ -4001,7 +4212,7 @@ void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int versi
 //
 // Add all the subpass access functions for the given type.
 //
-void TBuiltIns::addSubpassSampling(TSampler sampler, TString& typeName, int /*version*/, EProfile /*profile*/)
+void TBuiltIns::addSubpassSampling(TSampler sampler, const TString& typeName, int /*version*/, EProfile /*profile*/)
 {
     stageBuiltins[EShLangFragment].append(prefixes[sampler.type]);
     stageBuiltins[EShLangFragment].append("vec4 subpassLoad");
@@ -4018,7 +4229,7 @@ void TBuiltIns::addSubpassSampling(TSampler sampler, TString& typeName, int /*ve
 //
 // Add all the texture lookup functions for the given type.
 //
-void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
 {
     //
     // texturing
@@ -4248,7 +4459,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int ve
 //
 // Add all the texture gather functions for the given type.
 //
-void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
+void TBuiltIns::addGatherFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile)
 {
     switch (sampler.dim) {
     case Esd2D:
@@ -4303,6 +4514,7 @@ void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int vers
                 default:
                     break;
                 }
+
                 if (sparse)
                     s.append("ARB");
                 s.append("(");
@@ -4342,6 +4554,116 @@ void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int vers
             }
         }
     }
+
+#ifdef AMD_EXTENSIONS
+    if (sampler.dim == EsdRect || sampler.shadow)
+        return;
+
+    if (profile == EEsProfile || version < 450)
+        return;
+
+    for (int bias = 0; bias < 2; ++bias) { // loop over presence of bias argument
+
+        for (int lod = 0; lod < 2; ++lod) { // loop over presence of lod argument
+
+            if ((lod && bias) || (lod == 0 && bias == 0))
+                continue;
+
+            for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name:  none, Offset, and Offsets
+
+                for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument
+
+                    if (comp == 0 && bias)
+                        continue;
+
+                    if (offset > 0 && sampler.dim == EsdCube)
+                        continue;
+
+                    for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not
+                        if (sparse && (profile == EEsProfile || version < 450))
+                            continue;
+
+                        TString s;
+
+                        // return type
+                        if (sparse)
+                            s.append("int ");
+                        else {
+                            s.append(prefixes[sampler.type]);
+                            s.append("vec4 ");
+                        }
+
+                        // name
+                        if (sparse)
+                            s.append("sparseTextureGather");
+                        else
+                            s.append("textureGather");
+
+                        if (lod)
+                            s.append("Lod");
+
+                        switch (offset) {
+                        case 1:
+                            s.append("Offset");
+                            break;
+                        case 2:
+                            s.append("Offsets");
+                        default:
+                            break;
+                        }
+
+                        if (lod)
+                            s.append("AMD");
+                        else if (sparse)
+                            s.append("ARB");
+
+                        s.append("(");
+
+                        // sampler type argument
+                        s.append(typeName);
+
+                        // P coordinate argument
+                        s.append(",vec");
+                        int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0);
+                        s.append(postfixes[totalDims]);
+
+                        // lod argument
+                        if (lod)
+                            s.append(",float");
+
+                        // offset argument
+                        if (offset > 0) {
+                            s.append(",ivec2");
+                            if (offset == 2)
+                                s.append("[4]");
+                        }
+
+                        // texel out (for sparse texture)
+                        if (sparse) {
+                            s.append(",out ");
+                            s.append(prefixes[sampler.type]);
+                            s.append("vec4 ");
+                        }
+
+                        // comp argument
+                        if (comp)
+                            s.append(",int");
+
+                        // bias argument
+                        if (bias)
+                            s.append(",float");
+
+                        s.append(");\n");
+                        if (bias)
+                            stageBuiltins[EShLangFragment].append(s);
+                        else
+                            commonBuiltins.append(s);
+                    }
+                }
+            }
+        }
+    }
+#endif
 }
 
 //
@@ -4469,8 +4791,8 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
                         "highp vec4 gl_Position;"
                         "highp float gl_PointSize;"
 #ifdef NV_EXTENSIONS
-                        "highp vec4 gl_SecondaryPositionNV;"
-                        "highp vec4 gl_PositionPerViewNV[];"
+                        "highp vec4 gl_SecondaryPositionNV;"  // GL_NV_stereo_view_rendering
+                        "highp vec4 gl_PositionPerViewNV[];"  // GL_NVX_multiview_per_view_attributes
 #endif
                     "} gl_in[gl_MaxPatchVertices];"
                     "\n");
@@ -4659,8 +4981,8 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
                     s.append(
                         "float gl_CullDistance[];"
 #ifdef NV_EXTENSIONS
-                        "vec4 gl_SecondaryPositionNV;"
-                        "vec4 gl_PositionPerViewNV[];"
+                        "vec4 gl_SecondaryPositionNV;"  // GL_NV_stereo_view_rendering
+                        "vec4 gl_PositionPerViewNV[];"  // GL_NVX_multiview_per_view_attributes
 #endif
                        );
                 s.append(
@@ -5127,13 +5449,29 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
         //        symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size);
         //}
 
+        if ((profile != EEsProfile && version >= 140) ||
+            (profile == EEsProfile && version >= 310)) {
+            symbolTable.setVariableExtensions("gl_DeviceIndex",  1, &E_GL_EXT_device_group);
+            BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+            symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
+            BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
+        }
+
         break;
 
     case EShLangFragment:
         SpecialQualifier("gl_FrontFacing",      EvqFace,       EbvFace,             symbolTable);
         SpecialQualifier("gl_FragCoord",        EvqFragCoord,  EbvFragCoord,        symbolTable);
         SpecialQualifier("gl_PointCoord",       EvqPointCoord, EbvPointCoord,       symbolTable);
-        SpecialQualifier("gl_FragColor",        EvqFragColor,  EbvFragColor,        symbolTable);
+        if (spvVersion.spv == 0)
+            SpecialQualifier("gl_FragColor",    EvqFragColor,  EbvFragColor,        symbolTable);
+        else {
+            TSymbol* symbol = symbolTable.find("gl_FragColor");
+            if (symbol) {
+                symbol->getWritableType().getQualifier().storage = EvqVaryingOut;
+                symbol->getWritableType().getQualifier().layoutLocation = 0;
+            }
+        }
         SpecialQualifier("gl_FragDepth",        EvqFragDepth,  EbvFragDepth,        symbolTable);
         SpecialQualifier("gl_FragDepthEXT",     EvqFragDepth,  EbvFragDepth,        symbolTable);
         SpecialQualifier("gl_HelperInvocation", EvqVaryingIn,  EbvHelperInvocation, symbolTable);
@@ -5325,6 +5663,16 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             BuiltInVariable("gl_BaryCoordSmoothSampleAMD",      EbvBaryCoordSmoothSample,    symbolTable);
             BuiltInVariable("gl_BaryCoordPullModelAMD",         EbvBaryCoordPullModel,       symbolTable);
         }
+
+        // E_GL_AMD_texture_gather_bias_lod
+        if (profile != EEsProfile) {
+            symbolTable.setFunctionExtensions("textureGatherLodAMD",                1, &E_GL_AMD_texture_gather_bias_lod);
+            symbolTable.setFunctionExtensions("textureGatherLodOffsetAMD",          1, &E_GL_AMD_texture_gather_bias_lod);
+            symbolTable.setFunctionExtensions("textureGatherLodOffsetsAMD",         1, &E_GL_AMD_texture_gather_bias_lod);
+            symbolTable.setFunctionExtensions("sparseTextureGatherLodAMD",          1, &E_GL_AMD_texture_gather_bias_lod);
+            symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetAMD",    1, &E_GL_AMD_texture_gather_bias_lod);
+            symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetsAMD",   1, &E_GL_AMD_texture_gather_bias_lod);
+        }
 #endif
 
         symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth);
@@ -5344,6 +5692,11 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic);
             symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic);
         }
+
+        symbolTable.setVariableExtensions("gl_DeviceIndex",  1, &E_GL_EXT_device_group);
+        BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+        symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
+        BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
         break;
 
     case EShLangCompute:
@@ -5377,6 +5730,15 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.setFunctionExtensions("memoryBarrierShared",        1, &E_GL_ARB_compute_shader);
             symbolTable.setFunctionExtensions("groupMemoryBarrier",         1, &E_GL_ARB_compute_shader);
         }
+
+        if ((profile != EEsProfile && version >= 140) ||
+            (profile == EEsProfile && version >= 310)) {
+            symbolTable.setVariableExtensions("gl_DeviceIndex",  1, &E_GL_EXT_device_group);
+            BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable);
+            symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview);
+            BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable);
+        }
+
         break;
 
     default:
@@ -5462,6 +5824,12 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("doubleBitsToUint64", EOpDoubleBitsToUint64);
     symbolTable.relateToOperator("int64BitsToDouble",  EOpInt64BitsToDouble);
     symbolTable.relateToOperator("uint64BitsToDouble", EOpUint64BitsToDouble);
+#ifdef AMD_EXTENSIONS
+    symbolTable.relateToOperator("float16BitsToInt16",  EOpFloat16BitsToInt16);
+    symbolTable.relateToOperator("float16BitsToUint16", EOpFloat16BitsToUint16);
+    symbolTable.relateToOperator("int16BitsToFloat16",  EOpInt16BitsToFloat16);
+    symbolTable.relateToOperator("uint16BitsToFloat16", EOpUint16BitsToFloat16);
+#endif
 
     symbolTable.relateToOperator("packSnorm2x16",   EOpPackSnorm2x16);
     symbolTable.relateToOperator("unpackSnorm2x16", EOpUnpackSnorm2x16);
@@ -5485,6 +5853,16 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
     symbolTable.relateToOperator("unpackUint2x32",  EOpUnpackUint2x32);
 
 #ifdef AMD_EXTENSIONS
+    symbolTable.relateToOperator("packInt2x16",     EOpPackInt2x16);
+    symbolTable.relateToOperator("unpackInt2x16",   EOpUnpackInt2x16);
+    symbolTable.relateToOperator("packUint2x16",    EOpPackUint2x16);
+    symbolTable.relateToOperator("unpackUint2x16",  EOpUnpackUint2x16);
+
+    symbolTable.relateToOperator("packInt4x16",     EOpPackInt4x16);
+    symbolTable.relateToOperator("unpackInt4x16",   EOpUnpackInt4x16);
+    symbolTable.relateToOperator("packUint4x16",    EOpPackUint4x16);
+    symbolTable.relateToOperator("unpackUint4x16",  EOpUnpackUint4x16);
+
     symbolTable.relateToOperator("packFloat2x16",   EOpPackFloat2x16);
     symbolTable.relateToOperator("unpackFloat2x16", EOpUnpackFloat2x16);
 #endif
@@ -5706,6 +6084,13 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
             symbolTable.relateToOperator("cubeFaceIndexAMD",    EOpCubeFaceIndex);
             symbolTable.relateToOperator("cubeFaceCoordAMD",    EOpCubeFaceCoord);
             symbolTable.relateToOperator("timeAMD",             EOpTime);
+
+            symbolTable.relateToOperator("textureGatherLodAMD",                 EOpTextureGatherLod);
+            symbolTable.relateToOperator("textureGatherLodOffsetAMD",           EOpTextureGatherLodOffset);
+            symbolTable.relateToOperator("textureGatherLodOffsetsAMD",          EOpTextureGatherLodOffsets);
+            symbolTable.relateToOperator("sparseTextureGatherLodAMD",           EOpSparseTextureGatherLod);
+            symbolTable.relateToOperator("sparseTextureGatherLodOffsetAMD",     EOpSparseTextureGatherLodOffset);
+            symbolTable.relateToOperator("sparseTextureGatherLodOffsetsAMD",    EOpSparseTextureGatherLodOffsets);
 #endif
         }
     }

+ 5 - 5
src/libraries/glslang/glslang/MachineIndependent/Initialize.h

@@ -94,11 +94,11 @@ public:
 
 protected:
     void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion);
-    void addSubpassSampling(TSampler, TString& typeName, int version, EProfile profile);
-    void addQueryFunctions(TSampler, TString& typeName, int version, EProfile profile);
-    void addImageFunctions(TSampler, TString& typeName, int version, EProfile profile);
-    void addSamplingFunctions(TSampler, TString& typeName, int version, EProfile profile);
-    void addGatherFunctions(TSampler, TString& typeName, int version, EProfile profile);
+    void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile);
+    void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile);
+    void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile);
+    void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile);
+    void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile);
 
     // Helpers for making textual representations of the permutations
     // of texturing/imaging functions.

+ 586 - 57
src/libraries/glslang/glslang/MachineIndependent/Intermediate.cpp

@@ -130,8 +130,9 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
     }
 
     // Convert the children's type shape to be compatible.
-    right = addShapeConversion(op,  left->getType(), right);
-    left  = addShapeConversion(op, right->getType(),  left);
+    addBiShapeConversion(op, left, right);
+    if (left == nullptr || right == nullptr)
+        return nullptr;
 
     //
     // Need a new node holding things together.  Make
@@ -147,8 +148,8 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
     // If they are both (non-specialization) constants, they must be folded.
     // (Unless it's the sequence (comma) operator, but that's handled in addComma().)
     //
-    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
-    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+    TIntermConstantUnion *leftTempConstant = node->getLeft()->getAsConstantUnion();
+    TIntermConstantUnion *rightTempConstant = node->getRight()->getAsConstantUnion();
     if (leftTempConstant && rightTempConstant) {
         TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant);
         if (folded)
@@ -157,7 +158,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
 
     // If can propagate spec-constantness and if the operation is an allowed
     // specialization-constant operation, make a spec-constant.
-    if (specConstantPropagates(*left, *right) && isSpecializationOperation(*node))
+    if (specConstantPropagates(*node->getLeft(), *node->getRight()) && isSpecializationOperation(*node))
         node->getWritableType().getQualifier().makeSpecConstant();
 
     return node;
@@ -238,7 +239,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
         return nullptr;
 
     // convert shape
-    right = addShapeConversion(op, left->getType(), right);
+    right = addUniShapeConversion(op, left->getType(), right);
 
     // build the node
     TIntermBinary* node = addBinaryNode(op, left, right, loc);
@@ -307,6 +308,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
     case EOpConstructUint:   newType = EbtUint;   break;
     case EOpConstructInt64:  newType = EbtInt64;  break;
     case EOpConstructUint64: newType = EbtUint64; break;
+#ifdef AMD_EXTENSIONS
+    case EOpConstructInt16:  newType = EbtInt16;  break;
+    case EOpConstructUint16: newType = EbtUint16; break;
+#endif
     case EOpConstructBool:   newType = EbtBool;   break;
     case EOpConstructFloat:  newType = EbtFloat;  break;
     case EOpConstructDouble: newType = EbtDouble; break;
@@ -335,6 +340,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
     case EOpConstructUint:
     case EOpConstructInt64:
     case EOpConstructUint64:
+#ifdef AMD_EXTENSIONS
+    case EOpConstructInt16:
+    case EOpConstructUint16:
+#endif
     case EOpConstructBool:
     case EOpConstructFloat:
     case EOpConstructDouble:
@@ -356,12 +365,12 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
     node->updatePrecision();
 
     // If it's a (non-specialization) constant, it must be folded.
-    if (child->getAsConstantUnion())
-        return child->getAsConstantUnion()->fold(op, node->getType());
+    if (node->getOperand()->getAsConstantUnion())
+        return node->getOperand()->getAsConstantUnion()->fold(op, node->getType());
 
     // If it's a specialization constant, the result is too,
     // if the operation is allowed for specialization constants.
-    if (child->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node))
+    if (node->getOperand()->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node))
         node->getWritableType().getQualifier().makeSpecConstant();
 
     return node;
@@ -527,6 +536,14 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
     case EOpConstructUint64:
         promoteTo = EbtUint64;
         break;
+#ifdef AMD_EXTENSIONS
+    case EOpConstructInt16:
+        promoteTo = EbtInt16;
+        break;
+    case EOpConstructUint16:
+        promoteTo = EbtUint16;
+        break;
+#endif
 
     //
     // List all the binary ops that can implicitly convert one operand to the other's type;
@@ -615,15 +632,26 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
     case EOpRightShiftAssign:
         if ((type.getBasicType() == EbtInt ||
              type.getBasicType() == EbtUint ||
+#ifdef AMD_EXTENSIONS
+             type.getBasicType() == EbtInt16 ||
+             type.getBasicType() == EbtUint16 ||
+#endif
              type.getBasicType() == EbtInt64 ||
              type.getBasicType() == EbtUint64) &&
             (node->getType().getBasicType() == EbtInt ||
              node->getType().getBasicType() == EbtUint ||
+#ifdef AMD_EXTENSIONS
+             node->getType().getBasicType() == EbtInt16 ||
+             node->getType().getBasicType() == EbtUint16 ||
+#endif
              node->getType().getBasicType() == EbtInt64 ||
              node->getType().getBasicType() == EbtUint64))
 
             return node;
-        else
+        else if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool) {
+            promoteTo = type.getBasicType();
+            break;
+        } else
             return nullptr;
 
     default:
@@ -659,6 +687,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
 #endif
         case EbtInt64: newOp = EOpConvInt64ToDouble; break;
         case EbtUint64: newOp = EOpConvUint64ToDouble; break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:  newOp = EOpConvInt16ToDouble;  break;
+        case EbtUint16: newOp = EOpConvUint16ToDouble; break;
+#endif
         default:
             return nullptr;
         }
@@ -674,6 +706,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
 #endif
         case EbtInt64:  newOp = EOpConvInt64ToFloat;  break;
         case EbtUint64: newOp = EOpConvUint64ToFloat; break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:  newOp = EOpConvInt16ToFloat;  break;
+        case EbtUint16: newOp = EOpConvUint16ToFloat; break;
+#endif
         default:
             return nullptr;
         }
@@ -688,6 +724,8 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
         case EbtDouble: newOp = EOpConvDoubleToFloat16; break;
         case EbtInt64:  newOp = EOpConvInt64ToFloat16;  break;
         case EbtUint64: newOp = EOpConvUint64ToFloat16; break;
+        case EbtInt16:  newOp = EOpConvInt16ToFloat16;  break;
+        case EbtUint16: newOp = EOpConvUint16ToFloat16; break;
         default:
             return nullptr;
         }
@@ -704,6 +742,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
 #endif
         case EbtInt64:  newOp = EOpConvInt64ToBool;  break;
         case EbtUint64: newOp = EOpConvUint64ToBool; break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:  newOp = EOpConvInt16ToBool;  break;
+        case EbtUint16: newOp = EOpConvUint16ToBool; break;
+#endif
         default:
             return nullptr;
         }
@@ -719,6 +761,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
 #endif
         case EbtInt64:  newOp = EOpConvInt64ToInt;  break;
         case EbtUint64: newOp = EOpConvUint64ToInt; break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:  newOp = EOpConvInt16ToInt;  break;
+        case EbtUint16: newOp = EOpConvUint16ToInt; break;
+#endif
         default:
             return nullptr;
         }
@@ -734,6 +780,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
 #endif
         case EbtInt64:  newOp = EOpConvInt64ToUint;  break;
         case EbtUint64: newOp = EOpConvUint64ToUint; break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:  newOp = EOpConvInt16ToUint;  break;
+        case EbtUint16: newOp = EOpConvUint16ToUint; break;
+#endif
         default:
             return nullptr;
         }
@@ -749,6 +799,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
         case EbtFloat16: newOp = EOpConvFloat16ToInt64; break;
 #endif
         case EbtUint64: newOp = EOpConvUint64ToInt64; break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:  newOp = EOpConvInt16ToInt64;  break;
+        case EbtUint16: newOp = EOpConvUint16ToInt64; break;
+#endif
         default:
             return nullptr;
         }
@@ -764,10 +818,46 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
         case EbtFloat16: newOp = EOpConvFloat16ToUint64; break;
 #endif
         case EbtInt64:  newOp = EOpConvInt64ToUint64;  break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:  newOp = EOpConvInt16ToUint64;  break;
+        case EbtUint16: newOp = EOpConvUint16ToUint64; break;
+#endif
+        default:
+            return nullptr;
+        }
+        break;
+#ifdef AMD_EXTENSIONS
+    case EbtInt16:
+        switch (node->getBasicType()) {
+        case EbtInt:     newOp = EOpConvIntToInt16;     break;
+        case EbtUint:    newOp = EOpConvUintToInt16;    break;
+        case EbtBool:    newOp = EOpConvBoolToInt16;    break;
+        case EbtFloat:   newOp = EOpConvFloatToInt16;   break;
+        case EbtDouble:  newOp = EOpConvDoubleToInt16;  break;
+        case EbtFloat16: newOp = EOpConvFloat16ToInt16; break;
+        case EbtInt64:   newOp = EOpConvInt64ToInt16;   break;
+        case EbtUint64:  newOp = EOpConvUint64ToInt16;  break;
+        case EbtUint16:  newOp = EOpConvUint16ToInt16;  break;
+        default:
+            return nullptr;
+        }
+        break;
+    case EbtUint16:
+        switch (node->getBasicType()) {
+        case EbtInt:     newOp = EOpConvIntToUint16;     break;
+        case EbtUint:    newOp = EOpConvUintToUint16;    break;
+        case EbtBool:    newOp = EOpConvBoolToUint16;    break;
+        case EbtFloat:   newOp = EOpConvFloatToUint16;   break;
+        case EbtDouble:  newOp = EOpConvDoubleToUint16;  break;
+        case EbtFloat16: newOp = EOpConvFloat16ToUint16; break;
+        case EbtInt64:   newOp = EOpConvInt64ToUint16;   break;
+        case EbtUint64:  newOp = EOpConvUint64ToUint16;  break;
+        case EbtInt16:   newOp = EOpConvInt16ToUint16;   break;
         default:
             return nullptr;
         }
         break;
+#endif
     default:
         return nullptr;
     }
@@ -785,7 +875,10 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
 }
 
 // Convert the node's shape of type for the given type, as allowed by the
-// operation involved: 'op'.
+// operation involved: 'op'.  This is for situations where there is only one
+// direction to consider doing the shape conversion.
+//
+// This implements policy, it call addShapeConversion() for the mechanism.
 //
 // Generally, the AST represents allowed GLSL shapes, so this isn't needed
 // for GLSL.  Bad shapes are caught in conversion or promotion.
@@ -793,7 +886,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
 // Return 'node' if no conversion was done. Promotion handles final shape
 // checking.
 //
-TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type, TIntermTyped* node)
+TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node)
 {
     // some source languages don't do this
     switch (source) {
@@ -806,23 +899,142 @@ TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type,
 
     // some operations don't do this
     switch (op) {
+    case EOpFunctionCall:
+    case EOpReturn:
+        break;
+
+    case EOpMulAssign:
+        // want to support vector *= scalar native ops in AST and lower, not smear, similarly for
+        // matrix *= scalar, etc.
+
+    case EOpAddAssign:
+    case EOpSubAssign:
+    case EOpDivAssign:
+    case EOpAndAssign:
+    case EOpInclusiveOrAssign:
+    case EOpExclusiveOrAssign:
+    case EOpRightShiftAssign:
+    case EOpLeftShiftAssign:
+        if (node->getVectorSize() == 1)
+            return node;
+        break;
+
     case EOpAssign:
+        break;
+
+    case EOpMix:
+        break;
+
+    default:
+        return node;
+    }
+
+    return addShapeConversion(type, node);
+}
+
+// Convert the nodes' shapes to be compatible for the operation 'op'.
+//
+// This implements policy, it call addShapeConversion() for the mechanism.
+//
+// Generally, the AST represents allowed GLSL shapes, so this isn't needed
+// for GLSL.  Bad shapes are caught in conversion or promotion.
+//
+void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode)
+{
+    // some source languages don't do this
+    switch (source) {
+    case EShSourceHlsl:
+        break;
+    case EShSourceGlsl:
+    default:
+        return;
+    }
+
+    // some operations don't do this
+    // 'break' will mean attempt bidirectional conversion
+    switch (op) {
+    case EOpMulAssign:
+    case EOpAssign:
+    case EOpAddAssign:
+    case EOpSubAssign:
+    case EOpDivAssign:
+    case EOpAndAssign:
+    case EOpInclusiveOrAssign:
+    case EOpExclusiveOrAssign:
+    case EOpRightShiftAssign:
+    case EOpLeftShiftAssign:
+        // switch to unidirectional conversion (the lhs can't change)
+        rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode);
+        return;
+
+    case EOpAdd:
+    case EOpSub:
+    case EOpMul:
+    case EOpDiv:
+        // want to support vector * scalar native ops in AST and lower, not smear, similarly for
+        // matrix * vector, etc.
+        if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1)
+            return;
+        break;
+
+    case EOpRightShift:
+    case EOpLeftShift:
+        // can natively support the right operand being a scalar and the left a vector,
+        // but not the reverse
+        if (rhsNode->getVectorSize() == 1)
+            return;
+        break;
+
     case EOpLessThan:
     case EOpGreaterThan:
     case EOpLessThanEqual:
     case EOpGreaterThanEqual:
+
     case EOpEqual:
     case EOpNotEqual:
-    case EOpFunctionCall:
-    case EOpReturn:
+
     case EOpLogicalAnd:
     case EOpLogicalOr:
     case EOpLogicalXor:
+
+    case EOpAnd:
+    case EOpInclusiveOr:
+    case EOpExclusiveOr:
+
+    case EOpMix:
         break;
+
     default:
-        return node;
+        return;
     }
 
+    // Do bidirectional conversions
+    if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) {
+        if (lhsNode->getType().isScalarOrVec1())
+            lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
+        else
+            rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
+    }
+    lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
+    rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
+}
+
+// Convert the node's shape of type for the given type. It's not necessarily
+// an error if they are different and not converted, as some operations accept
+// mixed types.  Promotion will do final shape checking.
+//
+// If there is a chance of two nodes, with conversions possible in each direction,
+// the policy for what to ask for must be in the caller; this will do what is asked.
+//
+// Return 'node' if no conversion was done. Promotion handles final shape
+// checking.
+//
+TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node)
+{
+    // no conversion needed
+    if (node->getType() == type)
+        return node;
+
     // structures and arrays don't change shape, either to or from
     if (node->getType().isStruct() || node->getType().isArray() ||
         type.isStruct() || type.isArray())
@@ -831,12 +1043,12 @@ TIntermTyped* TIntermediate::addShapeConversion(TOperator op, const TType& type,
     // The new node that handles the conversion
     TOperator constructorOp = mapTypeToConstructorOp(type);
 
-    // scalar -> smeared -> vector, or
-    // vec1 -> scalar, or
-    // bigger vector -> smaller vector or scalar
-    if ((type.isVector() && node->getType().isScalar()) ||
-        (node->getType().isVector() && node->getVectorSize() == 1 && type.isScalar()) ||
-        (node->getVectorSize() > type.getVectorSize() && type.isVector()))
+    // scalar -> vector or vec1 -> vector or
+    // vector -> scalar or
+    // bigger vector -> smaller vector
+    if ((node->getType().isScalarOrVec1() && type.isVector()) ||
+        (node->getType().isVector() && type.isScalar()) ||
+        (node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize()))
         return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
 
     return node;
@@ -894,6 +1106,10 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
         case EbtUint:
         case EbtInt64:
         case EbtUint64:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+        case EbtUint16:
+#endif
         case EbtFloat:
         case EbtDouble:
 #ifdef AMD_EXTENSIONS
@@ -907,6 +1123,10 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
         switch (from) {
         case EbtInt:
         case EbtUint:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+        case EbtUint16:
+#endif
         case EbtFloat:
 #ifdef AMD_EXTENSIONS
         case EbtFloat16:
@@ -920,8 +1140,12 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
     case EbtUint:
         switch (from) {
         case EbtInt:
-            return version >= 400;
+            return version >= 400 || (source == EShSourceHlsl);
         case EbtUint:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+        case EbtUint16:
+#endif
             return true;
         case EbtBool:
             return (source == EShSourceHlsl);
@@ -931,6 +1155,9 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
     case EbtInt:
         switch (from) {
         case EbtInt:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+#endif
             return true;
         case EbtBool:
             return (source == EShSourceHlsl);
@@ -943,6 +1170,10 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
         case EbtUint:
         case EbtInt64:
         case EbtUint64:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+        case EbtUint16:
+#endif
             return true;
         default:
             return false;
@@ -951,10 +1182,32 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
         switch (from) {
         case EbtInt:
         case EbtInt64:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+#endif
+            return true;
+        default:
+            return false;
+        }
+#ifdef AMD_EXTENSIONS
+    case EbtFloat16:
+        switch (from) {
+        case EbtInt16:
+        case EbtUint16:
+        case EbtFloat16:
             return true;
         default:
             return false;
         }
+    case EbtUint16:
+        switch (from) {
+        case EbtInt16:
+        case EbtUint16:
+            return true;
+        default:
+            return false;
+        }
+#endif
     default:
         return false;
     }
@@ -1094,21 +1347,79 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
         break;
 #endif
     case EbtInt:
-        switch(type.getVectorSize()) {
-        case 1: op = EOpConstructInt;   break;
-        case 2: op = EOpConstructIVec2; break;
-        case 3: op = EOpConstructIVec3; break;
-        case 4: op = EOpConstructIVec4; break;
-        default: break; // some compilers want this
+        if (type.getMatrixCols()) {
+            switch (type.getMatrixCols()) {
+            case 2:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructIMat2x2; break;
+                case 3: op = EOpConstructIMat2x3; break;
+                case 4: op = EOpConstructIMat2x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            case 3:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructIMat3x2; break;
+                case 3: op = EOpConstructIMat3x3; break;
+                case 4: op = EOpConstructIMat3x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            case 4:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructIMat4x2; break;
+                case 3: op = EOpConstructIMat4x3; break;
+                case 4: op = EOpConstructIMat4x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            }
+        } else {
+            switch(type.getVectorSize()) {
+            case 1: op = EOpConstructInt;   break;
+            case 2: op = EOpConstructIVec2; break;
+            case 3: op = EOpConstructIVec3; break;
+            case 4: op = EOpConstructIVec4; break;
+            default: break; // some compilers want this
+            }
         }
         break;
     case EbtUint:
-        switch(type.getVectorSize()) {
-        case 1: op = EOpConstructUint;  break;
-        case 2: op = EOpConstructUVec2; break;
-        case 3: op = EOpConstructUVec3; break;
-        case 4: op = EOpConstructUVec4; break;
-        default: break; // some compilers want this
+        if (type.getMatrixCols()) {
+            switch (type.getMatrixCols()) {
+            case 2:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructUMat2x2; break;
+                case 3: op = EOpConstructUMat2x3; break;
+                case 4: op = EOpConstructUMat2x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            case 3:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructUMat3x2; break;
+                case 3: op = EOpConstructUMat3x3; break;
+                case 4: op = EOpConstructUMat3x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            case 4:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructUMat4x2; break;
+                case 3: op = EOpConstructUMat4x3; break;
+                case 4: op = EOpConstructUMat4x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            }
+        } else {
+            switch(type.getVectorSize()) {
+            case 1: op = EOpConstructUint;  break;
+            case 2: op = EOpConstructUVec2; break;
+            case 3: op = EOpConstructUVec3; break;
+            case 4: op = EOpConstructUVec4; break;
+            default: break; // some compilers want this
+            }
         }
         break;
     case EbtInt64:
@@ -1129,15 +1440,64 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
         default: break; // some compilers want this
         }
         break;
-    case EbtBool:
+#ifdef AMD_EXTENSIONS
+    case EbtInt16:
         switch(type.getVectorSize()) {
-        case 1:  op = EOpConstructBool;  break;
-        case 2:  op = EOpConstructBVec2; break;
-        case 3:  op = EOpConstructBVec3; break;
-        case 4:  op = EOpConstructBVec4; break;
+        case 1: op = EOpConstructInt16;   break;
+        case 2: op = EOpConstructI16Vec2; break;
+        case 3: op = EOpConstructI16Vec3; break;
+        case 4: op = EOpConstructI16Vec4; break;
         default: break; // some compilers want this
         }
         break;
+    case EbtUint16:
+        switch(type.getVectorSize()) {
+        case 1: op = EOpConstructUint16;  break;
+        case 2: op = EOpConstructU16Vec2; break;
+        case 3: op = EOpConstructU16Vec3; break;
+        case 4: op = EOpConstructU16Vec4; break;
+        default: break; // some compilers want this
+        }
+        break;
+#endif
+    case EbtBool:
+        if (type.getMatrixCols()) {
+            switch (type.getMatrixCols()) {
+            case 2:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructBMat2x2; break;
+                case 3: op = EOpConstructBMat2x3; break;
+                case 4: op = EOpConstructBMat2x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            case 3:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructBMat3x2; break;
+                case 3: op = EOpConstructBMat3x3; break;
+                case 4: op = EOpConstructBMat3x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            case 4:
+                switch (type.getMatrixRows()) {
+                case 2: op = EOpConstructBMat4x2; break;
+                case 3: op = EOpConstructBMat4x3; break;
+                case 4: op = EOpConstructBMat4x4; break;
+                default: break; // some compilers want this
+                }
+                break;
+            }
+        } else {
+            switch(type.getVectorSize()) {
+            case 1:  op = EOpConstructBool;  break;
+            case 2:  op = EOpConstructBVec2; break;
+            case 3:  op = EOpConstructBVec3; break;
+            case 4:  op = EOpConstructBVec4; break;
+            default: break; // some compilers want this
+            }
+        }
+        break;
     default:
         break;
     }
@@ -1158,15 +1518,15 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r
         return nullptr;
 
     TIntermAggregate* aggNode = nullptr;
-    if (left)
+    if (left != nullptr)
         aggNode = left->getAsAggregate();
-    if (! aggNode || aggNode->getOp() != EOpNull) {
+    if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
         aggNode = new TIntermAggregate;
-        if (left)
+        if (left != nullptr)
             aggNode->getSequence().push_back(left);
     }
 
-    if (right)
+    if (right != nullptr)
         aggNode->getSequence().push_back(right);
 
     return aggNode;
@@ -1271,7 +1631,8 @@ TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type,
 //
 // For "?:" test nodes.  There are three children; a condition,
 // a true path, and a false path.  The two paths are specified
-// as separate parameters.
+// as separate parameters. For vector 'cond', the true and false
+// are not paths, but vectors to mix.
 //
 // Specialization constant operations include
 //     - The ternary operator ( ? : )
@@ -1300,14 +1661,39 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
             return nullptr;
     }
 
+    // Handle a vector condition as a mix
+    if (!cond->getType().isScalarOrVec1()) {
+        TType targetVectorType(trueBlock->getType().getBasicType(), EvqTemporary,
+                               cond->getType().getVectorSize());
+        // smear true/false operands as needed
+        trueBlock = addUniShapeConversion(EOpMix, targetVectorType, trueBlock);
+        falseBlock = addUniShapeConversion(EOpMix, targetVectorType, falseBlock);
+
+        // After conversion, types have to match.
+        if (falseBlock->getType() != trueBlock->getType())
+            return nullptr;
+
+        // make the mix operation
+        TIntermAggregate* mix = makeAggregate(loc);
+        mix = growAggregate(mix, falseBlock);
+        mix = growAggregate(mix, trueBlock);
+        mix = growAggregate(mix, cond);
+        mix->setType(targetVectorType);
+        mix->setOp(EOpMix);
+
+        return mix;
+    }
+
+    // Now have a scalar condition...
+
+    // Convert true and false expressions to matching types
+    addBiShapeConversion(EOpMix, trueBlock, falseBlock);
+
     // After conversion, types have to match.
     if (falseBlock->getType() != trueBlock->getType())
         return nullptr;
 
-    //
-    // See if all the operands are constant, then fold it otherwise not.
-    //
-
+    // Eliminate the selection when the condition is a scalar and all operands are constant.
     if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
         if (cond->getAsConstantUnion()->getConstArray()[0].getBConst())
             return trueBlock;
@@ -1381,6 +1767,24 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, co
     return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal);
 }
 
+#ifdef AMD_EXTENSIONS
+TIntermConstantUnion* TIntermediate::addConstantUnion(short i16, const TSourceLoc& loc, bool literal) const
+{
+    TConstUnionArray unionArray(1);
+    unionArray[0].setIConst(i16);
+
+    return addConstantUnion(unionArray, TType(EbtInt16, EvqConst), loc, literal);
+}
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned short u16, const TSourceLoc& loc, bool literal) const
+{
+    TConstUnionArray unionArray(1);
+    unionArray[0].setUConst(u16);
+
+    return addConstantUnion(unionArray, TType(EbtUint16, EvqConst), loc, literal);
+}
+#endif
+
 TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const
 {
     TConstUnionArray unionArray(1);
@@ -1478,10 +1882,11 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
 //
 // Create while and do-while loop nodes.
 //
-TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
+TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
 {
     TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
     node->setLoc(loc);
+    node->setLoopControl(control);
 
     return node;
 }
@@ -1489,13 +1894,19 @@ TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TInte
 //
 // Create a for-loop sequence.
 //
-TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
+TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TLoopControl control)
 {
     TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
     node->setLoc(loc);
-
-    // make a sequence of the initializer and statement
-    TIntermAggregate* loopSequence = makeAggregate(initializer, loc);
+    node->setLoopControl(control);
+
+    // make a sequence of the initializer and statement, but try to reuse the
+    // aggregate already created for whatever is in the initializer, if there is one
+    TIntermAggregate* loopSequence = (initializer == nullptr ||
+                                      initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc)
+                                                                                : initializer->getAsAggregate();
+    if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence)
+        loopSequence->setOp(EOpNull);
     loopSequence = growAggregate(loopSequence, node);
     loopSequence->setOperator(EOpSequence);
 
@@ -1535,6 +1946,14 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
     // Propagate 'noContraction' label in backward from 'precise' variables.
     glslang::PropagateNoContraction(*this);
 
+    switch (textureSamplerTransformMode) {
+    case EShTexSampTransKeep:
+        break;
+    case EShTexSampTransUpgradeTextureRemoveSampler:
+        performTextureUpgradeAndSamplerRemovalTransformation(root);
+        break;
+    }
+
     return true;
 }
 
@@ -1725,6 +2144,30 @@ bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const
     case EOpConvUintToInt64:
     case EOpConvUint64ToInt:
     case EOpConvIntToUint64:
+#ifdef AMD_EXTENSIONS
+    case EOpConvInt16ToBool:
+    case EOpConvBoolToInt16:
+    case EOpConvInt16ToInt:
+    case EOpConvIntToInt16:
+    case EOpConvInt16ToUint:
+    case EOpConvUintToInt16:
+    case EOpConvInt16ToInt64:
+    case EOpConvInt64ToInt16:
+    case EOpConvInt16ToUint64:
+    case EOpConvUint64ToInt16:
+    case EOpConvUint16ToBool:
+    case EOpConvBoolToUint16:
+    case EOpConvUint16ToInt:
+    case EOpConvIntToUint16:
+    case EOpConvUint16ToUint:
+    case EOpConvUintToUint16:
+    case EOpConvUint16ToInt64:
+    case EOpConvInt64ToUint16:
+    case EOpConvUint16ToUint64:
+    case EOpConvUint64ToUint16:
+    case EOpConvInt16ToUint16:
+    case EOpConvUint16ToInt16:
+#endif
 
     // unary operations
     case EOpNegative:
@@ -1853,6 +2296,10 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
     case EOpBitwiseNot:
         if (operand->getBasicType() != EbtInt &&
             operand->getBasicType() != EbtUint &&
+#ifdef AMD_EXTENSIONS
+            operand->getBasicType() != EbtInt16 &&
+            operand->getBasicType() != EbtUint16 &&
+#endif
             operand->getBasicType() != EbtInt64 &&
             operand->getBasicType() != EbtUint64)
 
@@ -1867,6 +2314,10 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
             operand->getBasicType() != EbtUint &&
             operand->getBasicType() != EbtInt64 &&
             operand->getBasicType() != EbtUint64 &&
+#ifdef AMD_EXTENSIONS
+            operand->getBasicType() != EbtInt16 &&
+            operand->getBasicType() != EbtUint16 &&
+#endif
             operand->getBasicType() != EbtFloat &&
 #ifdef AMD_EXTENSIONS
             operand->getBasicType() != EbtFloat16 &&
@@ -1967,6 +2418,42 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
     // We now have only scalars, vectors, and matrices to worry about.
     //
 
+    // HLSL implicitly promotes bool -> int for numeric operations.
+    // (Implicit conversions to make the operands match each other's types were already done.)
+    if (getSource() == EShSourceHlsl &&
+        (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)) {
+        switch (op) {
+        case EOpLessThan:
+        case EOpGreaterThan:
+        case EOpLessThanEqual:
+        case EOpGreaterThanEqual:
+
+        case EOpRightShift:
+        case EOpLeftShift:
+
+        case EOpMod:
+
+        case EOpAnd:
+        case EOpInclusiveOr:
+        case EOpExclusiveOr:
+
+        case EOpAdd:
+        case EOpSub:
+        case EOpDiv:
+        case EOpMul:
+            left = addConversion(op, TType(EbtInt, EvqTemporary, left->getVectorSize()), left);
+            right = addConversion(op, TType(EbtInt, EvqTemporary, right->getVectorSize()), right);
+            if (left == nullptr || right == nullptr)
+                return false;
+            node.setLeft(left);
+            node.setRight(right);
+            break;
+
+        default:
+            break;
+        }
+    }
+
     // Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that)
     switch (op) {
     case EOpLessThan:
@@ -2037,8 +2524,14 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
 
         // Check for integer-only operands.
         if ((left->getBasicType() != EbtInt &&  left->getBasicType() != EbtUint &&
-             left->getBasicType() != EbtInt64 &&  left->getBasicType() != EbtUint64) ||
+#ifdef AMD_EXTENSIONS
+             left->getBasicType() != EbtInt16 && left->getBasicType() != EbtUint16 &&
+#endif
+             left->getBasicType() != EbtInt64 && left->getBasicType() != EbtUint64) ||
             (right->getBasicType() != EbtInt && right->getBasicType() != EbtUint &&
+#ifdef AMD_EXTENSIONS
+             right->getBasicType() != EbtInt16 && right->getBasicType() != EbtUint16 &&
+#endif
              right->getBasicType() != EbtInt64 && right->getBasicType() != EbtUint64))
             return false;
         if (left->isMatrix() || right->isMatrix())
@@ -2079,8 +2572,6 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
     case EOpLogicalXor:
         return left->getType() == right->getType();
 
-    // no shifts: they can mix types (scalar int can shift a vector uint, etc.)
-
     case EOpMod:
     case EOpModAssign:
 
@@ -2094,6 +2585,7 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
     case EOpAdd:
     case EOpSub:
     case EOpDiv:
+
     case EOpAddAssign:
     case EOpSubAssign:
     case EOpDivAssign:
@@ -2118,7 +2610,7 @@ bool TIntermediate::promoteBinary(TIntermBinary& node)
         return true;
 
     // Finish handling the case, for all ops, where there are two vectors of different sizes
-    if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize())
+    if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1)
         return false;
 
     //
@@ -2667,4 +3159,41 @@ bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TInt
            (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant());
 }
 
+struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
+    bool visitAggregate(TVisit, TIntermAggregate* ag) override {
+        using namespace std;
+        TIntermSequence& seq = ag->getSequence();
+        // remove pure sampler variables
+        TIntermSequence::iterator newEnd = remove_if(seq.begin(), seq.end(), [](TIntermNode* node) {
+            TIntermSymbol* symbol = node->getAsSymbolNode();
+            if (!symbol)
+                return false;
+
+            return (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler());
+        });
+        seq.erase(newEnd, seq.end());
+        // replace constructors with sampler/textures
+        // update textures into sampled textures
+        for_each(seq.begin(), seq.end(), [](TIntermNode*& node) {
+            TIntermSymbol* symbol = node->getAsSymbolNode();
+            if (!symbol) {
+                TIntermAggregate *constructor = node->getAsAggregate();
+                if (constructor && constructor->getOp() == EOpConstructTextureSampler) {
+                    if (!constructor->getSequence().empty())
+                        node = constructor->getSequence()[0];
+                }
+            } else if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) {
+                symbol->getWritableType().getSampler().combined = true;
+            }
+        });
+        return true;
+    }
+};
+
+void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root)
+{
+    TextureUpgradeAndSamplerRemovalTransform transform;
+    root->traverse(&transform);
+}
+
 } // end namespace glslang

+ 2 - 0
src/libraries/glslang/glslang/MachineIndependent/LiveTraverser.h

@@ -33,6 +33,8 @@
 // POSSIBILITY OF SUCH DAMAGE.
 //
 
+#pragma once
+
 #include "../Include/Common.h"
 #include "reflection.h"
 #include "localintermediate.h"

+ 15 - 31
src/libraries/glslang/glslang/MachineIndependent/ParseContextBase.cpp

@@ -226,7 +226,8 @@ void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op,
 // Add 'symbol' to the list of deferred linkage symbols, which
 // are later processed in finish(), at which point the symbol
 // must still be valid.
-// It is okay if the symbol's type will be subsequently edited.
+// It is okay if the symbol's type will be subsequently edited;
+// the modifications will be tracked.
 void TParseContextBase::trackLinkage(TSymbol& symbol)
 {
     if (!parsingBuiltins)
@@ -530,21 +531,20 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
 // Make the passed-in variable information become a member of the
 // global uniform block.  If this doesn't exist yet, make it.
 //
-void TParseContextBase::growGlobalUniformBlock(TSourceLoc& loc, TType& memberType, TString& memberName, TTypeList* typeList)
+void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
 {
-    // make the global block, if not yet made
+    // Make the global block, if not yet made.
     if (globalUniformBlock == nullptr) {
-        TString& blockName = *NewPoolTString(getGlobalUniformBlockName());
         TQualifier blockQualifier;
         blockQualifier.clear();
         blockQualifier.storage = EvqUniform;
-        TType blockType(new TTypeList, blockName, blockQualifier);
-        TString* instanceName = NewPoolTString("");
-        globalUniformBlock = new TVariable(instanceName, blockType, true);
+        TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier);
+        setUniformBlockDefaults(blockType);
+        globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true);
         firstNewMember = 0;
     }
 
-    // add the requested member as a member to the block
+    // Add the requested member as a member to the global block.
     TType* type = new TType;
     type->shallowCopy(memberType);
     type->setFieldName(memberName);
@@ -552,36 +552,20 @@ void TParseContextBase::growGlobalUniformBlock(TSourceLoc& loc, TType& memberTyp
         type->setStruct(typeList);
     TTypeLoc typeLoc = {type, loc};
     globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc);
-}
-
-//
-// Insert into the symbol table the global uniform block created in
-// growGlobalUniformBlock(). The variables added as members won't be
-// found unless this is done.
-//
-bool TParseContextBase::insertGlobalUniformBlock()
-{
-    if (globalUniformBlock == nullptr)
-        return true;
 
-    int numMembers = (int)globalUniformBlock->getType().getStruct()->size();
-    bool inserted = false;
+    // Insert into the symbol table.
     if (firstNewMember == 0) {
         // This is the first request; we need a normal symbol table insert
-        inserted = symbolTable.insert(*globalUniformBlock);
-        if (inserted)
+        if (symbolTable.insert(*globalUniformBlock))
             trackLinkage(*globalUniformBlock);
-    } else if (firstNewMember <= numMembers) {
+        else
+            error(loc, "failed to insert the global constant buffer", "uniform", "");
+    } else {
         // This is a follow-on request; we need to amend the first insert
-        inserted = symbolTable.amend(*globalUniformBlock, firstNewMember);
-    }
-
-    if (inserted) {
-        finalizeGlobalUniformBlockLayout(*globalUniformBlock);
-        firstNewMember = numMembers;
+        symbolTable.amend(*globalUniformBlock, firstNewMember);
     }
 
-    return inserted;
+    ++firstNewMember;
 }
 
 void TParseContextBase::finish()

+ 179 - 36
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -51,8 +51,8 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
                              int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
                              TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) :
             TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
-            contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0),
-            inMain(false), postMainReturn(false), currentFunctionType(nullptr), blockName(nullptr),
+            inMain(false),
+            blockName(nullptr),
             limits(resources.limits),
             atomicUintOffsets(nullptr), anyIndexLimits(false)
 {
@@ -255,6 +255,10 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector<TString>&
             error(loc, "\")\" expected to end 'debug' pragma", "#pragma", "");
             return;
         }
+    } else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) {
+        if (tokens.size() != 1)
+            error(loc, "extra tokens", "#pragma", "");
+        intermediate.setUseStorageBuffer();
     }
 }
 
@@ -342,10 +346,8 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
     TIntermTyped* result = nullptr;
 
     int indexValue = 0;
-    if (index->getQualifier().isFrontEndConstant()) {
+    if (index->getQualifier().isFrontEndConstant())
         indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst();
-        checkIndex(loc, base->getType(), indexValue);
-    }
 
     variableCheck(base);
     if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) {
@@ -353,10 +355,12 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
             error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), "");
         else
             error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", "");
-    } else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant())
+    } else if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) {
+        // both base and index are front-end constants
+        checkIndex(loc, base->getType(), indexValue);
         return intermediate.foldDereference(base, indexValue, loc);
-    else {
-        // at least one of base and index is variable...
+    } else {
+        // at least one of base and index is not a front-end constant variable...
 
         if (base->getAsSymbolNode() && isIoResizeArray(base->getType()))
             handleIoResizeArrayAccess(loc, base);
@@ -364,6 +368,8 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
         if (index->getQualifier().isFrontEndConstant()) {
             if (base->getType().isImplicitlySizedArray())
                 updateImplicitArraySize(loc, base, indexValue);
+            else
+                checkIndex(loc, base->getType(), indexValue);
             result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
         } else {
             if (base->getType().isImplicitlySizedArray()) {
@@ -906,7 +912,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc,
     loopNestingLevel = 0;
     statementNestingLevel = 0;
     controlFlowNestingLevel = 0;
-    postMainReturn = false;
+    postEntryPointReturn = false;
 
     return paramNodes;
 }
@@ -1187,7 +1193,7 @@ void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op)
                 error(loc, "tessellation control barrier() cannot be placed within flow control", "", "");
             if (! inMain)
                 error(loc, "tessellation control barrier() must be in main()", "", "");
-            else if (postMainReturn)
+            else if (postEntryPointReturn)
                 error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
         }
         break;
@@ -1436,9 +1442,56 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
                 error(loc, "must be a compile-time constant:", feature, "component argument");
         }
 
+#ifdef AMD_EXTENSIONS
+        bool bias = false;
+        if (callNode.getOp() == EOpTextureGather)
+            bias = fnCandidate.getParamCount() > 3;
+        else if (callNode.getOp() == EOpTextureGatherOffset ||
+                 callNode.getOp() == EOpTextureGatherOffsets)
+            bias = fnCandidate.getParamCount() > 4;
+
+        if (bias) {
+            TString biasFeatureString = fnCandidate.getName() + "with bias argument";
+            const char* feature = biasFeatureString.c_str();
+            profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
+            requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
+        }
+#endif
+
         break;
     }
 
+#ifdef AMD_EXTENSIONS
+    case EOpSparseTextureGather:
+    case EOpSparseTextureGatherOffset:
+    case EOpSparseTextureGatherOffsets:
+    {
+        bool bias = false;
+        if (callNode.getOp() == EOpSparseTextureGather)
+            bias = fnCandidate.getParamCount() > 4;
+        else if (callNode.getOp() == EOpSparseTextureGatherOffset ||
+                 callNode.getOp() == EOpSparseTextureGatherOffsets)
+            bias = fnCandidate.getParamCount() > 5;
+
+        if (bias) {
+            TString featureString = fnCandidate.getName() + "with bias argument";
+            const char* feature = featureString.c_str();
+            profileRequires(loc, ~EEsProfile, 450, nullptr, feature);
+            requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature);
+        }
+
+        break;
+    }
+
+    case EOpSparseTextureGatherLod:
+    case EOpSparseTextureGatherLodOffset:
+    case EOpSparseTextureGatherLodOffsets:
+    {
+        requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str());
+        break;
+    }
+#endif
+
     case EOpTextureOffset:
     case EOpTextureFetchOffset:
     case EOpTextureProjOffset:
@@ -2096,6 +2149,17 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
     case EOpConstructDMat4x2:
     case EOpConstructDMat4x3:
     case EOpConstructDMat4x4:
+#ifdef AMD_EXTENSIONS
+    case EOpConstructF16Mat2x2:
+    case EOpConstructF16Mat2x3:
+    case EOpConstructF16Mat2x4:
+    case EOpConstructF16Mat3x2:
+    case EOpConstructF16Mat3x3:
+    case EOpConstructF16Mat3x4:
+    case EOpConstructF16Mat4x2:
+    case EOpConstructF16Mat4x3:
+    case EOpConstructF16Mat4x4:
+#endif
         constructingMatrix = true;
         break;
     default:
@@ -2156,6 +2220,10 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
             case EOpConstructUint:
             case EOpConstructInt64:
             case EOpConstructUint64:
+#ifdef AMD_EXTENSIONS
+            case EOpConstructInt16:
+            case EOpConstructUint16:
+#endif
             case EOpConstructBool:
             case EOpConstructBVec2:
             case EOpConstructBVec3:
@@ -2172,6 +2240,14 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T
             case EOpConstructU64Vec2:
             case EOpConstructU64Vec3:
             case EOpConstructU64Vec4:
+#ifdef AMD_EXTENSIONS
+            case EOpConstructI16Vec2:
+            case EOpConstructI16Vec3:
+            case EOpConstructI16Vec4:
+            case EOpConstructU16Vec2:
+            case EOpConstructU16Vec3:
+            case EOpConstructU16Vec4:
+#endif
                 // This was the list of valid ones, if they aren't converting from float
                 // and aren't making an array.
                 makeSpecConst = ! floatArgument && ! type.isArray();
@@ -2464,6 +2540,9 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
     }
 
     if (publicType.basicType == EbtInt   || publicType.basicType == EbtUint   ||
+#ifdef AMD_EXTENSIONS
+        publicType.basicType == EbtInt16 || publicType.basicType == EbtUint16 ||
+#endif
         publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64 ||
         publicType.basicType == EbtDouble)
         profileRequires(loc, EEsProfile, 300, nullptr, "shader input/output");
@@ -2474,6 +2553,9 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
     if (!qualifier.flat) {
 #endif
         if (publicType.basicType == EbtInt    || publicType.basicType == EbtUint   ||
+#ifdef AMD_EXTENSIONS
+            publicType.basicType == EbtInt16  || publicType.basicType == EbtUint16 ||
+#endif
             publicType.basicType == EbtInt64  || publicType.basicType == EbtUint64 ||
             publicType.basicType == EbtDouble ||
             (publicType.userDef && (publicType.userDef->containsBasicType(EbtInt)    ||
@@ -2894,7 +2976,7 @@ void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& typ
     }
 }
 
-void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember)
+void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TArraySizes* arraySizes, bool initializer, bool lastMember)
 {
     assert(arraySizes);
 
@@ -2906,10 +2988,13 @@ void TParseContext::arrayUnsizedCheck(const TSourceLoc& loc, const TQualifier& q
     if (initializer)
         return;
 
-    // No environment lets any non-outer-dimension that's to be implicitly sized
+    // No environment allows any non-outer-dimension to be implicitly sized
     if (arraySizes->isInnerImplicit())
         error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", "");
 
+    if (arraySizes->isInnerSpecialization())
+        error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", "");
+
     // desktop always allows outer-dimension-unsized variable arrays,
     if (profile != EEsProfile)
         return;
@@ -2990,7 +3075,7 @@ void TParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes)
 // Do all the semantic checking for declaring or redeclaring an array, with and
 // without a size, and make the right changes to the symbol table.
 //
-void TParseContext::declareArray(const TSourceLoc& loc, TString& identifier, const TType& type, TSymbol*& symbol)
+void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol)
 {
     if (symbol == nullptr) {
         bool currentScope;
@@ -4196,6 +4281,10 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
         if (id.compare(0, 11, "local_size_") == 0) {
             profileRequires(loc, EEsProfile, 310, 0, "gl_WorkGroupSize");
             profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize");
+            if (id.size() == 12 && value == 0) {
+                error(loc, "must be at least 1", id.c_str(), "");
+                return;
+            }
             if (id == "local_size_x") {
                 publicType.shaderQualifiers.localSize[0] = value;
                 return;
@@ -4246,7 +4335,6 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
 // This is also true for overriding layout-qualifier-names, where one
 // overrides the other (e.g., row_major vs. column_major); only the last
 // occurrence has any effect."
-//
 void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly)
 {
     if (src.hasMatrix())
@@ -4328,6 +4416,25 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
         }
     }
 
+    // user-variable location check, which are required for SPIR-V in/out:
+    //  - variables have it directly,
+    //  - blocks have it on each member (already enforced), so check first one
+    if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone &&
+        !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) {
+
+        switch (qualifier.storage) {
+        case EvqVaryingIn:
+        case EvqVaryingOut:
+            if (type.getBasicType() != EbtBlock || 
+                (!(*type.getStruct())[0].type->getQualifier().hasLocation() && 
+                  (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))
+                error(loc, "SPIR-V requires location for user input/output", "location", "");
+            break;
+        default:
+            break;
+        }
+    }
+
     // Check packing and matrix
     if (qualifier.hasUniformLayout()) {
         switch (qualifier.storage) {
@@ -4355,6 +4462,22 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
     }
 }
 
+// "For some blocks declared as arrays, the location can only be applied at the block level:
+// When a block is declared as an array where additional locations are needed for each member
+// for each block array element, it is a compile-time error to specify locations on the block
+// members.  That is, when locations would be under specified by applying them on block members,
+// they are not allowed on block members.  For arrayed interfaces (those generally having an
+// extra level of arrayness due to interface expansion), the outer array is stripped before
+// applying this rule."
+void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation, TArraySizes* arraySizes)
+{
+    if (memberWithLocation && arraySizes != nullptr) {
+        if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0))
+            error(loc, "cannot use in a block array where new locations are needed for each block element",
+                       "location", "");
+    }
+}
+
 // Do layout error checking with respect to a type.
 void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
 {
@@ -4500,7 +4623,7 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
             }
         }
     } else if (type.isImage() && ! qualifier.writeonly) {
-        const char *explanation = "image variables declared 'writeonly' without a format layout qualifier";
+        const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier";
         requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation);
         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation);
     }
@@ -4529,6 +4652,10 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type)
         case EbtUint:
         case EbtInt64:
         case EbtUint64:
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+        case EbtUint16:
+#endif
         case EbtBool:
         case EbtFloat:
         case EbtDouble:
@@ -4692,12 +4819,8 @@ void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol)
                 if (symbol.getType().isExplicitlySizedArray())
                     numOffsets *= symbol.getType().getCumulativeArraySize();
                 else {
-                    // TODO: functionality: implicitly-sized atomic_uint arrays.
-                    // We don't know the full size until later.  This might
-                    // be a specification problem, will report to Khronos.  For the
-                    // cases that is not true, the rest of the checking would need
-                    // to be done at link time instead of compile time.
-                    warn(loc, "implicitly sized atomic_uint array treated as having one element for tracking the default offset", "atomic_uint", "");
+                    // "It is a compile-time error to declare an unsized array of atomic_uint."
+                    error(loc, "array must be explicitly sized", "atomic_uint", "");
                 }
             }
             int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets);
@@ -4983,7 +5106,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
         arrayDimMerge(type, arraySizes);
 
         // Check that implicit sizing is only where allowed.
-        arrayUnsizedCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false);
+        arraySizesCheck(loc, type.getQualifier(), &type.getArraySizes(), initializer != nullptr, false);
 
         if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type))
             declareArray(loc, identifier, type, symbol);
@@ -5016,6 +5139,8 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
 
     // look for errors in layout qualifier use
     layoutObjectCheck(loc, *symbol);
+
+    // fix up
     fixOffset(loc, *symbol);
 
     return initNode;
@@ -5053,7 +5178,7 @@ TVariable* TParseContext::makeInternalVariable(const char* name, const TType& ty
 //
 // Return the successfully declared variable.
 //
-TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, TString& identifier, TType& type)
+TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type)
 {
     // make a new variable
     TVariable* variable = new TVariable(&identifier, type);
@@ -5477,6 +5602,22 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
         basicOp = EOpConstructUint64;
         break;
 
+#ifdef AMD_EXTENSIONS
+    case EOpConstructI16Vec2:
+    case EOpConstructI16Vec3:
+    case EOpConstructI16Vec4:
+    case EOpConstructInt16:
+        basicOp = EOpConstructInt16;
+        break;
+
+    case EOpConstructU16Vec2:
+    case EOpConstructU16Vec3:
+    case EOpConstructU16Vec4:
+    case EOpConstructUint16:
+        basicOp = EOpConstructUint16;
+        break;
+#endif
+
     case EOpConstructBVec2:
     case EOpConstructBVec3:
     case EOpConstructBVec4:
@@ -5533,7 +5674,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     blockStageIoCheck(loc, currentBlockQualifier);
     blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr);
     if (arraySizes) {
-        arrayUnsizedCheck(loc, currentBlockQualifier, arraySizes, false, false);
+        arraySizesCheck(loc, currentBlockQualifier, arraySizes, false, false);
         arrayDimCheck(loc, arraySizes, 0);
         if (arraySizes->getNumDims() > 1)
             requireProfile(loc, ~EEsProfile, "array-of-array of block");
@@ -5551,7 +5692,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
         if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
             error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
         if (memberType.isArray())
-            arrayUnsizedCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, member == typeList.size() - 1);
+            arraySizesCheck(memberLoc, currentBlockQualifier, &memberType.getArraySizes(), false, member == typeList.size() - 1);
         if (memberQualifier.hasOffset()) {
             if (spvVersion.spv == 0) {
                 requireProfile(memberLoc, ~EEsProfile, "offset on block member");
@@ -5597,11 +5738,10 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
 
     mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true);
 
-    // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
     // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
-    if (currentBlockQualifier.hasAlign() || currentBlockQualifier.hasAlign()) {
+    if (currentBlockQualifier.hasAlign()) {
         if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430) {
-            error(loc, "can only be used with std140 or std430 layout packing", "offset/align", "");
+            error(loc, "can only be used with std140 or std430 layout packing", "align", "");
             defaultQualification.layoutAlign = -1;
         }
     }
@@ -5643,9 +5783,12 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
             }
         } else
             memberWithoutLocation = true;
-        if (memberQualifier.hasAlign()) {
+
+        // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts."
+        // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts."
+        if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) {
             if (defaultQualification.layoutPacking != ElpStd140 && defaultQualification.layoutPacking != ElpStd430)
-                error(memberLoc, "can only be used with std140 or std430 layout packing", "align", "");
+                error(memberLoc, "can only be used with std140 or std430 layout packing", "offset/align", "");
         }
 
         TQualifier newMemberQualification = defaultQualification;
@@ -5653,6 +5796,8 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
         memberQualifier = newMemberQualification;
     }
 
+    layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes);
+
     // Process the members
     fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation);
     fixBlockXfbOffsets(currentBlockQualifier, typeList);
@@ -5720,6 +5865,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     // Check for general layout qualifier errors
     layoutObjectCheck(loc, variable);
 
+    // fix up
     if (isIoResizeArray(blockType)) {
         ioArraySymbolResizeList.push_back(&variable);
         checkIoArraysConsistency(loc, true);
@@ -5768,7 +5914,7 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q
 }
 
 // Do all block-declaration checking regarding its qualifiers.
-void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool instanceName)
+void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/)
 {
     // The 4.5 specification says:
     //
@@ -5795,11 +5941,8 @@ void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier&
         error(loc, "cannot use sample qualifier on an interface block", "sample", "");
     if (qualifier.invariant)
         error(loc, "cannot use invariant qualifier on an interface block", "invariant", "");
-    if (qualifier.layoutPushConstant) {
+    if (qualifier.layoutPushConstant)
         intermediate.addPushConstantCount();
-        if (! instanceName)
-            error(loc, "requires an instance name", "push_constant", "");
-    }
 }
 
 //
@@ -5837,7 +5980,7 @@ void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifi
                     if (nextLocation >= (int)TQualifier::layoutLocationEnd)
                         error(memberLoc, "location is too large", "location", "");
                     memberQualifier.layoutLocation = nextLocation;
-                    memberQualifier.layoutComponent = 0;
+                    memberQualifier.layoutComponent = TQualifier::layoutComponentEnd;
                 }
                 nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize(*typeList[member].type);
             }

+ 32 - 21
src/libraries/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -77,6 +77,10 @@ public:
                       TInfoSink& infoSink, bool forwardCompatible, EShMessages messages)
           : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
             symbolTable(symbolTable),
+            statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
+            postEntryPointReturn(false),
+            contextPragma(true, false),
+            limits(resources.limits),
             parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
             globalUniformBlock(nullptr)
     { }
@@ -133,18 +137,31 @@ public:
             extensionCallback(line, extension, behavior);
     }
 
-    TSymbolTable& symbolTable;   // symbol table that goes with the current language, version, and profile
-
     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
-    // TODO: This could perhaps get its own object, but the current design doesn't work
-    // yet when new uniform variables are declared between function definitions, so
-    // this is pending getting a fully functional design.
-    virtual void growGlobalUniformBlock(TSourceLoc&, TType&, TString& memberName, TTypeList* typeList = nullptr);
-    virtual bool insertGlobalUniformBlock();
+    virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
 
     virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
     virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
 
+    const char* const scopeMangler = "::";
+
+    // Basic parsing state, easily accessible to the grammar
+
+    TSymbolTable& symbolTable;        // symbol table that goes with the current language, version, and profile
+    int statementNestingLevel;        // 0 if outside all flow control or compound statements
+    int loopNestingLevel;             // 0 if outside all loops
+    int structNestingLevel;           // 0 if outside blocks and structures
+    int controlFlowNestingLevel;      // 0 if outside all flow control
+    const TType* currentFunctionType; // the return type of the function that's currently being parsed
+    bool functionReturnsValue;        // true if a non-void function has a return
+    // if inside a function, true if the function is the entry point and this is after a return statement
+    bool postEntryPointReturn;
+    // case, node, case, case, node, ...; ensure only one node between cases;   stack of them for nesting
+    TList<TIntermSequence*> switchSequenceStack;
+    // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
+    TList<int> switchLevel;
+    struct TPragma contextPragma;
+
 protected:
     TParseContextBase(TParseContextBase&);
     TParseContextBase& operator=(TParseContextBase&);
@@ -153,6 +170,8 @@ protected:
     TVector<TSymbol*> linkageSymbols; // these need to be transferred to 'linkage', after all editing is done
     TScanContext* scanContext;
     TPpContext* ppContext;
+    TBuiltInResource resources;
+    TLimits& limits;
 
     // These, if set, will be called when a line, pragma ... is preprocessed.
     // They will be called with any parameters to the original directive.
@@ -175,7 +194,8 @@ protected:
     TVariable* globalUniformBlock;   // the actual block, inserted into the symbol table
     int firstNewMember;              // the index of the first member not yet inserted into the symbol table
     // override this to set the language-specific name
-    virtual const char* getGlobalUniformBlockName() { return ""; }
+    virtual const char* getGlobalUniformBlockName() const { return ""; }
+    virtual void setUniformBlockDefaults(TType&) const { }
     virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
     virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
                                const char* szExtraInfoFormat, TPrefixType prefix,
@@ -297,7 +317,7 @@ public:
     bool arrayError(const TSourceLoc&, const TType&);
     void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
     void structArrayCheck(const TSourceLoc&, const TType& structure);
-    void arrayUnsizedCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer, bool lastMember);
+    void arraySizesCheck(const TSourceLoc&, const TQualifier&, const TArraySizes*, bool initializer, bool lastMember);
     void arrayOfArrayVersionCheck(const TSourceLoc&);
     void arrayDimCheck(const TSourceLoc&, const TArraySizes* sizes1, const TArraySizes* sizes2);
     void arrayDimCheck(const TSourceLoc&, const TType*, const TArraySizes*);
@@ -339,6 +359,7 @@ public:
     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
     void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
     void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
+    void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes);
     void layoutTypeCheck(const TSourceLoc&, const TType&);
     void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
     void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
@@ -372,8 +393,8 @@ protected:
     void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
     void inheritGlobalDefaults(TQualifier& dst) const;
     TVariable* makeInternalVariable(const char* name, const TType&) const;
-    TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&);
-    void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&);
+    TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
+    void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
     TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
     void finish() override;
@@ -384,17 +405,7 @@ public:
     //
 
     // Current state of parsing
-    struct TPragma contextPragma;
-    int loopNestingLevel;        // 0 if outside all loops
-    int structNestingLevel;      // 0 if outside blocks and structures
-    int controlFlowNestingLevel; // 0 if outside all flow control
-    int statementNestingLevel;   // 0 if outside all flow control or compound statements
-    TList<TIntermSequence*> switchSequenceStack;  // case, node, case, case, node, ...; ensure only one node between cases;   stack of them for nesting
-    TList<int> switchLevel;      // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
     bool inMain;                 // if inside a function, true if the function is main
-    bool postMainReturn;         // if inside a function, true if the function is main and this is after a return statement
-    const TType* currentFunctionType;  // the return type of the function that's currently being parsed
-    bool functionReturnsValue;   // true if a non-void function has a return
     const TString* blockName;
     TQualifier currentBlockQualifier;
     TPrecisionQualifier defaultPrecision[EbtNumTypes];

+ 2 - 0
src/libraries/glslang/glslang/MachineIndependent/RemoveTree.h

@@ -32,6 +32,8 @@
 // POSSIBILITY OF SUCH DAMAGE.
 //
 
+#pragma once
+
 namespace glslang {
 
 void RemoveAllTreeNodes(TIntermNode*);

+ 33 - 1
src/libraries/glslang/glslang/MachineIndependent/Scan.cpp

@@ -175,7 +175,7 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
 
     bool versionNotFirst = false;  // means not first WRT comments and white space, nothing more
     notFirstToken = false;         // means not first WRT to real tokens
-    version = 0;  // means not found
+    version = 0;                   // means not found
     profile = ENoProfile;
 
     bool foundNonSpaceTab = false;
@@ -464,6 +464,15 @@ void TScanContext::fillInKeywordMap()
     (*KeywordMap)["u64vec4"] =                 U64VEC4;
 
 #ifdef AMD_EXTENSIONS
+    (*KeywordMap)["int16_t"] =                 INT16_T;
+    (*KeywordMap)["uint16_t"] =                UINT16_T;
+    (*KeywordMap)["i16vec2"] =                 I16VEC2;
+    (*KeywordMap)["i16vec3"] =                 I16VEC3;
+    (*KeywordMap)["i16vec4"] =                 I16VEC4;
+    (*KeywordMap)["u16vec2"] =                 U16VEC2;
+    (*KeywordMap)["u16vec3"] =                 U16VEC3;
+    (*KeywordMap)["u16vec4"] =                 U16VEC4;
+
     (*KeywordMap)["float16_t"] =               FLOAT16_T;
     (*KeywordMap)["f16vec2"] =                 F16VEC2;
     (*KeywordMap)["f16vec3"] =                 F16VEC3;
@@ -701,10 +710,18 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
         case PpAtomDecrement:          return DEC_OP;
         case PpAtomIncrement:          return INC_OP;
 
+        case PpAtomColonColon:
+            parseContext.error(loc, "not supported", "::", "");
+            break;
+
         case PpAtomConstInt:           parserToken->sType.lex.i   = ppToken.ival;       return INTCONSTANT;
         case PpAtomConstUint:          parserToken->sType.lex.i   = ppToken.ival;       return UINTCONSTANT;
         case PpAtomConstInt64:         parserToken->sType.lex.i64 = ppToken.i64val;     return INT64CONSTANT;
         case PpAtomConstUint64:        parserToken->sType.lex.i64 = ppToken.i64val;     return UINT64CONSTANT;
+#ifdef AMD_EXTENSIONS
+        case PpAtomConstInt16:         parserToken->sType.lex.i   = ppToken.ival;       return INT16CONSTANT;
+        case PpAtomConstUint16:        parserToken->sType.lex.i   = ppToken.ival;       return UINT16CONSTANT;
+#endif
         case PpAtomConstFloat:         parserToken->sType.lex.d   = ppToken.dval;       return FLOATCONSTANT;
         case PpAtomConstDouble:        parserToken->sType.lex.d   = ppToken.dval;       return DOUBLECONSTANT;
 #ifdef AMD_EXTENSIONS
@@ -969,6 +986,21 @@ int TScanContext::tokenizeIdentifier()
         return identifierOrType();
 
 #ifdef AMD_EXTENSIONS
+    case INT16_T:
+    case UINT16_T:
+    case I16VEC2:
+    case I16VEC3:
+    case I16VEC4:
+    case U16VEC2:
+    case U16VEC3:
+    case U16VEC4:
+        afterType = true;
+        if (parseContext.symbolTable.atBuiltInLevel() ||
+            (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) &&
+             parseContext.profile != EEsProfile && parseContext.version >= 450))
+            return keyword;
+        return identifierOrType();
+
     case FLOAT16_T:
     case F16VEC2:
     case F16VEC3:

+ 2 - 0
src/libraries/glslang/glslang/MachineIndependent/ScanContext.h

@@ -38,6 +38,8 @@
 // sits between the preprocessor scanner and parser.
 //
 
+#pragma once
+
 #include "ParseHelper.h"
 
 namespace glslang {

+ 32 - 46
src/libraries/glslang/glslang/MachineIndependent/ShaderLang.cpp

@@ -442,7 +442,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
     bool correct = true;
 
     if (source == EShSourceHlsl) {
-        version = 450;          // TODO: GLSL parser is still used for builtins.
+        version = 500;          // shader model; currently a characteristic of glslang, not the input
         profile = ECoreProfile; // allow doubles in prototype parsing
         return correct;
     }
@@ -566,41 +566,6 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         }
     }
 
-    // A meta check on the condition of the compiler itself...
-    switch (version) {
-
-    // ES versions
-    case 100:
-    case 300:
-        // versions are complete
-        break;
-
-    // Desktop versions
-    case 110:
-    case 120:
-    case 130:
-    case 140:
-    case 150:
-    case 330:
-        // versions are complete
-        break;
-
-    case 310:
-    case 400:
-    case 410:
-    case 420:
-    case 430:
-    case 440:
-    case 450:
-        infoSink.info << "Warning, version " << version << " is not yet complete; most version-specific features are present, but some are missing.\n";
-        break;
-
-    default:
-        infoSink.info << "Warning, version " << version << " is unknown.\n";
-        break;
-
-    }
-
     return correct;
 }
 
@@ -679,13 +644,13 @@ bool ProcessDeferred(
     // First, without using the preprocessor or parser, find the #version, so we know what
     // symbol tables, processing rules, etc. to set up.  This does not need the extra strings
     // outlined above, just the user shader.
-    int version;
-    EProfile profile;
     glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]);  // no preamble
-    bool versionNotFirstToken;
-    bool versionNotFirst = userInput.scanVersion(version, profile, versionNotFirstToken);
+    int version = 0;
+    EProfile profile = ENoProfile;
+    bool versionNotFirstToken = false;
+    bool versionNotFirst = (messages & EShMsgReadHlsl) ? true : userInput.scanVersion(version, profile, versionNotFirstToken);
     bool versionNotFound = version == 0;
-    if (forceDefaultVersionAndProfile) {
+    if (forceDefaultVersionAndProfile && (messages & EShMsgReadHlsl) == 0) {
         if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
             (version != defaultVersion || profile != defaultProfile)) {
             compiler->infoSink.info << "Warning, (version, profile) forced to be ("
@@ -726,6 +691,13 @@ bool ProcessDeferred(
     intermediate.setSpv(spvVersion);
     if (spvVersion.vulkan >= 100)
         intermediate.setOriginUpperLeft();
+    if ((messages & EShMsgHlslOffsets) || (messages & EShMsgReadHlsl))
+        intermediate.setHlslOffsets();
+    if (messages & EShMsgDebugInfo) {
+        intermediate.setSourceFile(names[numPre]);
+        for (int s = 0; s < numStrings; ++s)
+            intermediate.addSourceText(strings[numPre]);
+    }
     SetupBuiltinSymbolTable(version, profile, spvVersion, source);
 
     TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
@@ -1553,13 +1525,30 @@ void TShader::setSourceEntryPoint(const char* name)
     sourceEntryPointName = name;
 }
 
+// Set binding base for sampler types
 void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); }
+// Set binding base for texture types (SRV)
 void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
+// Set binding base for image types
 void TShader::setShiftImageBinding(unsigned int base)   { intermediate->setShiftImageBinding(base); }
+// Set binding base for uniform buffer objects (CBV)
 void TShader::setShiftUboBinding(unsigned int base)     { intermediate->setShiftUboBinding(base); }
+// Synonym for setShiftUboBinding, to match HLSL language.
+void TShader::setShiftCbufferBinding(unsigned int base) { intermediate->setShiftUboBinding(base); }
+// Set binding base for UAV (unordered access view)
+void TShader::setShiftUavBinding(unsigned int base)     { intermediate->setShiftUavBinding(base); }
+// Set binding base for SSBOs
+void TShader::setShiftSsboBinding(unsigned int base)    { intermediate->setShiftSsboBinding(base); }
+// Enables binding automapping using TIoMapper
 void TShader::setAutoMapBindings(bool map)              { intermediate->setAutoMapBindings(map); }
+// Fragile: currently within one stage: simple auto-assignment of location
+void TShader::setAutoMapLocations(bool map)              { intermediate->setAutoMapLocations(map); }
+// See comment above TDefaultHlslIoMapper in iomapper.cpp:
+void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
 void TShader::setFlattenUniformArrays(bool flatten)     { intermediate->setFlattenUniformArrays(flatten); }
 void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); }
+void TShader::setResourceSetBinding(const std::vector<std::string>& base)   { intermediate->setResourceSetBinding(base); }
+void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
 
 //
 // Turn the shader strings into a parse tree in the TIntermediate.
@@ -1583,11 +1572,6 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
                            forwardCompatible, messages, *intermediate, includer, sourceEntryPointName);
 }
 
-bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
-{
-    return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
-}
-
 // Fill in a string with the result of preprocessing ShaderStrings
 // Returns true if all extensions, pragmas and version strings were valid.
 bool TShader::preprocess(const TBuiltInResource* builtInResources,
@@ -1775,6 +1759,7 @@ const char* TProgram::getUniformBlockName(int index) const   { return reflection
 int TProgram::getUniformBlockSize(int index) const           { return reflection->getUniformBlock(index).size; }
 int TProgram::getUniformIndex(const char* name) const        { return reflection->getIndex(name); }
 int TProgram::getUniformBlockIndex(int index) const          { return reflection->getUniform(index).index; }
+int TProgram::getUniformBlockCounterIndex(int index) const   { return reflection->getUniformBlock(index).counterIndex; }
 int TProgram::getUniformType(int index) const                { return reflection->getUniform(index).glDefineType; }
 int TProgram::getUniformBufferOffset(int index) const        { return reflection->getUniform(index).offset; }
 int TProgram::getUniformArraySize(int index) const           { return reflection->getUniform(index).size; }
@@ -1784,6 +1769,7 @@ int TProgram::getAttributeType(int index) const              { return reflection
 const TType* TProgram::getAttributeTType(int index) const    { return reflection->getAttribute(index).getType(); }
 const TType* TProgram::getUniformTType(int index) const      { return reflection->getUniform(index).getType(); }
 const TType* TProgram::getUniformBlockTType(int index) const { return reflection->getUniformBlock(index).getType(); }
+unsigned TProgram::getLocalSize(int dim) const               { return reflection->getLocalSize(dim); }
 
 void TProgram::dumpReflection()                      { reflection->dump(); }
 

+ 21 - 2
src/libraries/glslang/glslang/MachineIndependent/SymbolTable.cpp

@@ -50,7 +50,7 @@ namespace glslang {
 //
 // Recursively generate mangled names.
 //
-void TType::buildMangledName(TString& mangledName)
+void TType::buildMangledName(TString& mangledName) const
 {
     if (isMatrix())
         mangledName += 'm';
@@ -67,6 +67,10 @@ void TType::buildMangledName(TString& mangledName)
     case EbtUint:               mangledName += 'u';      break;
     case EbtInt64:              mangledName += "i64";    break;
     case EbtUint64:             mangledName += "u64";    break;
+#ifdef AMD_EXTENSIONS
+    case EbtInt16:              mangledName += "i16";    break;
+    case EbtUint16:             mangledName += "u16";    break;
+#endif
     case EbtBool:               mangledName += 'b';      break;
     case EbtAtomicUint:         mangledName += "au";     break;
     case EbtSampler:
@@ -99,11 +103,23 @@ void TType::buildMangledName(TString& mangledName)
         case EsdSubpass:  mangledName += "P";  break;
         default: break; // some compilers want this
         }
+
+        switch (sampler.vectorSize) {
+        case 1: mangledName += "1"; break;
+        case 2: mangledName += "2"; break;
+        case 3: mangledName += "3"; break;
+        case 4: break; // default to prior name mangle behavior
+        }
+
         if (sampler.ms)
             mangledName += "M";
         break;
     case EbtStruct:
-        mangledName += "struct-";
+    case EbtBlock:
+        if (basicType == EbtStruct)
+            mangledName += "struct-";
+        else
+            mangledName += "block-";
         if (typeName)
             mangledName += *typeName;
         for (unsigned int i = 0; i < structure->size(); ++i) {
@@ -295,6 +311,8 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
     op = copyOf.op;
     defined = copyOf.defined;
     prototyped = copyOf.prototyped;
+    implicitThis = copyOf.implicitThis;
+    illegalImplicitThis = copyOf.illegalImplicitThis;
     defaultParamCount = copyOf.defaultParamCount;
 }
 
@@ -319,6 +337,7 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
 {
     TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
     symTableLevel->anonId = anonId;
+    symTableLevel->thisLevel = thisLevel;
     std::vector<bool> containerCopied(anonId, false);
     tLevel::const_iterator iter;
     for (iter = level.begin(); iter != level.end(); ++iter) {

+ 91 - 15
src/libraries/glslang/glslang/MachineIndependent/SymbolTable.h

@@ -198,7 +198,6 @@ struct TParameter {
     TString *name;
     TType* type;
     TIntermTyped* defaultValue;
-    TBuiltInVariable declaredBuiltIn;
     void copyParam(const TParameter& param)
     {
         if (param.name)
@@ -207,8 +206,8 @@ struct TParameter {
             name = 0;
         type = param.type->clone();
         defaultValue = param.defaultValue;
-        declaredBuiltIn = param.declaredBuiltIn;
     }
+    TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
 };
 
 //
@@ -219,48 +218,70 @@ public:
     explicit TFunction(TOperator o) :
         TSymbol(0),
         op(o),
-        defined(false), prototyped(false), defaultParamCount(0) { }
+        defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { }
     TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
         TSymbol(name),
         mangledName(*name + '('),
         op(tOp),
-        defined(false), prototyped(false), defaultParamCount(0)
+        defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0)
     {
         returnType.shallowCopy(retType);
         declaredBuiltIn = retType.getQualifier().builtIn;
     }
-    virtual TFunction* clone() const;
+    virtual TFunction* clone() const override;
     virtual ~TFunction();
 
-    virtual TFunction* getAsFunction() { return this; }
-    virtual const TFunction* getAsFunction() const { return this; }
+    virtual TFunction* getAsFunction() override { return this; }
+    virtual const TFunction* getAsFunction() const override { return this; }
 
+    // Install 'p' as the (non-'this') last parameter.
+    // Non-'this' parameters are reflected in both the list of parameters and the
+    // mangled name.
     virtual void addParameter(TParameter& p)
     {
         assert(writable);
-        p.declaredBuiltIn = p.type->getQualifier().builtIn;
         parameters.push_back(p);
         p.type->appendMangledName(mangledName);
 
         if (p.defaultValue != nullptr)
             defaultParamCount++;
     }
+
+    // Install 'this' as the first parameter.
+    // 'this' is reflected in the list of parameters, but not the mangled name.
+    virtual void addThisParameter(TType& type, const char* name)
+    {
+        TParameter p = { NewPoolTString(name), new TType, nullptr };
+        p.type->shallowCopy(type);
+        parameters.insert(parameters.begin(), p);
+    }
+
     virtual void addPrefix(const char* prefix) override
     {
         TSymbol::addPrefix(prefix);
         mangledName.insert(0, prefix);
     }
 
-    virtual const TString& getMangledName() const { return mangledName; }
-    virtual const TType& getType() const { return returnType; }
+    virtual void removePrefix(const TString& prefix)
+    {
+        assert(mangledName.compare(0, prefix.size(), prefix) == 0);
+        mangledName.erase(0, prefix.size());
+    }
+
+    virtual const TString& getMangledName() const override { return mangledName; }
+    virtual const TType& getType() const override { return returnType; }
     virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
-    virtual TType& getWritableType() { return returnType; }
+    virtual TType& getWritableType() override { return returnType; }
     virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
     virtual TOperator getBuiltInOp() const { return op; }
     virtual void setDefined() { assert(writable); defined = true; }
     virtual bool isDefined() const { return defined; }
     virtual void setPrototyped() { assert(writable); prototyped = true; }
     virtual bool isPrototyped() const { return prototyped; }
+    virtual void setImplicitThis() { assert(writable); implicitThis = true; }
+    virtual bool hasImplicitThis() const { return implicitThis; }
+    virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
+    virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
 
     // Return total number of parameters
     virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
@@ -272,7 +293,7 @@ public:
     virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
     virtual const TParameter& operator[](int i) const { return parameters[i]; }
 
-    virtual void dump(TInfoSink &infoSink) const;
+    virtual void dump(TInfoSink &infoSink) const override;
 
 protected:
     explicit TFunction(const TFunction&);
@@ -287,6 +308,11 @@ protected:
     TOperator op;
     bool defined;
     bool prototyped;
+    bool implicitThis;         // True if this function is allowed to see all members of 'this'
+    bool illegalImplicitThis;  // True if this function is not supposed to have access to dynamic members of 'this',
+                               // even if it finds member variables in the symbol table.
+                               // This is important for a static member function that has member variables in scope,
+                               // but is not allowed to use them, or see hidden symbols instead.
     int  defaultParamCount;
 };
 
@@ -334,7 +360,7 @@ protected:
 class TSymbolTableLevel {
 public:
     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
-    TSymbolTableLevel() : defaultPrecision(0), anonId(0) { }
+    TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
     ~TSymbolTableLevel();
 
     bool insert(TSymbol& symbol, bool separateNameSpaces)
@@ -492,6 +518,9 @@ public:
     TSymbolTableLevel* clone() const;
     void readOnly();
 
+    void setThisLevel() { thisLevel = true; }
+    bool isThisLevel() const { return thisLevel; }
+
 protected:
     explicit TSymbolTableLevel(TSymbolTableLevel&);
     TSymbolTableLevel& operator=(TSymbolTableLevel&);
@@ -503,6 +532,8 @@ protected:
     tLevel level;  // named mappings
     TPrecisionQualifier *defaultPrecision;
     int anonId;
+    bool thisLevel;  // True if this level of the symbol table is a structure scope containing member function
+                     // that are supposed to see anonymous access to member variables.
 };
 
 class TSymbolTable {
@@ -559,6 +590,20 @@ public:
         table.push_back(new TSymbolTableLevel);
     }
 
+    // Make a new symbol-table level to represent the scope introduced by a structure
+    // containing member functions, such that the member functions can find anonymous
+    // references to member variables.
+    //
+    // 'thisSymbol' should have a name of "" to trigger anonymous structure-member
+    // symbol finds.
+    void pushThis(TSymbol& thisSymbol)
+    {
+        assert(thisSymbol.getName().size() == 0);
+        table.push_back(new TSymbolTableLevel);
+        table.back()->setThisLevel();
+        insert(thisSymbol);
+    }
+
     void pop(TPrecisionQualifier *p)
     {
         table[currentLevel()]->getPreviousDefaultPrecisions(p);
@@ -645,19 +690,50 @@ public:
         }
     }
 
-    TSymbol* find(const TString& name, bool* builtIn = 0, bool *currentScope = 0)
+    // Normal find of a symbol, that can optionally say whether the symbol was found
+    // at a built-in level or the current top-scope level.
+    TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0)
     {
         int level = currentLevel();
         TSymbol* symbol;
+        int thisDepth = 0;
         do {
+            if (table[level]->isThisLevel())
+                ++thisDepth;
             symbol = table[level]->find(name);
             --level;
-        } while (symbol == 0 && level >= 0);
+        } while (symbol == nullptr && level >= 0);
         level++;
         if (builtIn)
             *builtIn = isBuiltInLevel(level);
         if (currentScope)
             *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel();  // consider shared levels as "current scope" WRT user globals
+        if (thisDepthP != nullptr) {
+            if (! table[level]->isThisLevel())
+                thisDepth = 0;
+            *thisDepthP = thisDepth;
+        }
+
+        return symbol;
+    }
+
+    // Find of a symbol that returns how many layers deep of nested
+    // structures-with-member-functions ('this' scopes) deep the symbol was
+    // found in.
+    TSymbol* find(const TString& name, int& thisDepth)
+    {
+        int level = currentLevel();
+        TSymbol* symbol;
+        thisDepth = 0;
+        do {
+            if (table[level]->isThisLevel())
+                ++thisDepth;
+            symbol = table[level]->find(name);
+            --level;
+        } while (symbol == 0 && level >= 0);
+
+        if (! table[level + 1]->isThisLevel())
+            thisDepth = 0;
 
         return symbol;
     }

+ 41 - 1
src/libraries/glslang/glslang/MachineIndependent/Versions.cpp

@@ -195,6 +195,8 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_AMD_shader_explicit_vertex_parameter]     = EBhDisable;
     extensionBehavior[E_GL_AMD_gcn_shader]                           = EBhDisable;
     extensionBehavior[E_GL_AMD_gpu_shader_half_float]                = EBhDisable;
+    extensionBehavior[E_GL_AMD_texture_gather_bias_lod]              = EBhDisable;
+    extensionBehavior[E_GL_AMD_gpu_shader_int16]                     = EBhDisable;
 #endif
 
 #ifdef NV_EXTENSIONS
@@ -233,6 +235,10 @@ void TParseVersions::initializeExtensionBehavior()
     extensionBehavior[E_GL_OES_tessellation_point_size]  = EBhDisable;
     extensionBehavior[E_GL_OES_texture_buffer]           = EBhDisable;
     extensionBehavior[E_GL_OES_texture_cube_map_array]   = EBhDisable;
+
+    // EXT extensions
+    extensionBehavior[E_GL_EXT_device_group]             = EBhDisable;
+    extensionBehavior[E_GL_EXT_multiview]                = EBhDisable;
 }
 
 // Get code that is not part of a shared symbol table, is specific to this shader,
@@ -315,6 +321,8 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_AMD_shader_explicit_vertex_parameter 1\n"
             "#define GL_AMD_gcn_shader 1\n"
             "#define GL_AMD_gpu_shader_half_float 1\n"
+            "#define GL_AMD_texture_gather_bias_lod 1\n"
+            "#define GL_AMD_gpu_shader_int16 1\n"
 #endif
 
 #ifdef NV_EXTENSIONS
@@ -323,6 +331,22 @@ void TParseVersions::getPreamble(std::string& preamble)
             "#define GL_NV_viewport_array2 1\n"
 #endif
             ;
+
+        if (version >= 150) {
+            // define GL_core_profile and GL_compatibility_profile
+            preamble += "#define GL_core_profile 1\n";
+
+            if (profile == ECompatibilityProfile)
+                preamble += "#define GL_compatibility_profile 1\n";
+        }
+    }
+
+    if ((profile != EEsProfile && version >= 140) ||
+        (profile == EEsProfile && version >= 310)) {
+        preamble += 
+            "#define GL_EXT_device_group 1\n"
+            "#define GL_EXT_multiview 1\n"
+            ;
     }
 
     // #line and #include
@@ -481,6 +505,11 @@ void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, i
     }
 }
 
+void TParseVersions::unimplemented(const TSourceLoc& loc, const char* featureDesc)
+{
+    error(loc, "feature not yet implemented", featureDesc, "");
+}
+
 // Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false.
 // Warns appropriately if the requested behavior of an extension is "warn".
 bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc)
@@ -686,10 +715,21 @@ void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
 }
 
 #ifdef AMD_EXTENSIONS
+// Call for any operation needing GLSL 16-bit integer data-type support.
+void TParseVersions::int16Check(const TSourceLoc& loc, const char* op, bool builtIn)
+{
+    if (! builtIn) {
+        requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_int16, "shader int16");
+        requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
+        profileRequires(loc, ECoreProfile, 450, nullptr, op);
+        profileRequires(loc, ECompatibilityProfile, 450, nullptr, op);
+    }
+}
+
 // Call for any operation needing GLSL float16 data-type support.
 void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn)
 {
-    if (!builtIn) {
+    if (! builtIn) {
         requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float, "shader half float");
         requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
         profileRequires(loc, ECoreProfile, 450, nullptr, op);

+ 7 - 0
src/libraries/glslang/glslang/MachineIndependent/Versions.h

@@ -133,6 +133,10 @@ const char* const E_GL_ARB_sparse_texture_clamp         = "GL_ARB_sparse_texture
 const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
 const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
 
+// EXT extensions
+const char* const E_GL_EXT_device_group                 = "GL_EXT_device_group";
+const char* const E_GL_EXT_multiview                    = "GL_EXT_multiview";
+
 // #line and #include
 const char* const E_GL_GOOGLE_cpp_style_line_directive          = "GL_GOOGLE_cpp_style_line_directive";
 const char* const E_GL_GOOGLE_include_directive                 = "GL_GOOGLE_include_directive";
@@ -143,7 +147,10 @@ const char* const E_GL_AMD_shader_trinary_minmax                = "GL_AMD_shader
 const char* const E_GL_AMD_shader_explicit_vertex_parameter     = "GL_AMD_shader_explicit_vertex_parameter";
 const char* const E_GL_AMD_gcn_shader                           = "GL_AMD_gcn_shader";
 const char* const E_GL_AMD_gpu_shader_half_float                = "GL_AMD_gpu_shader_half_float";
+const char* const E_GL_AMD_texture_gather_bias_lod              = "GL_AMD_texture_gather_bias_lod";
+const char* const E_GL_AMD_gpu_shader_int16                     = "GL_AMD_gpu_shader_int16";
 #endif
+
 #ifdef NV_EXTENSIONS
 
 const char* const E_GL_NV_sample_mask_override_coverage         = "GL_NV_sample_mask_override_coverage";

+ 2 - 0
src/libraries/glslang/glslang/MachineIndependent/gl_types.h

@@ -21,6 +21,8 @@
 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */
 
+#pragma once
+
 #define GL_FLOAT                          0x1406
 #define GL_FLOAT_VEC2                     0x8B50
 #define GL_FLOAT_VEC3                     0x8B51

File diff suppressed because it is too large
+ 480 - 625
src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp


+ 318 - 321
src/libraries/glslang/glslang/MachineIndependent/glslang_tab.cpp.h

@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.7.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison interface for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -26,13 +26,13 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
-# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
-/* Enabling traces.  */
+#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
+/* Debug traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 1
 #endif
@@ -40,306 +40,315 @@
 extern int yydebug;
 #endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ATTRIBUTE = 258,
-     VARYING = 259,
-     CONST = 260,
-     BOOL = 261,
-     FLOAT = 262,
-     DOUBLE = 263,
-     INT = 264,
-     UINT = 265,
-     INT64_T = 266,
-     UINT64_T = 267,
-     FLOAT16_T = 268,
-     BREAK = 269,
-     CONTINUE = 270,
-     DO = 271,
-     ELSE = 272,
-     FOR = 273,
-     IF = 274,
-     DISCARD = 275,
-     RETURN = 276,
-     SWITCH = 277,
-     CASE = 278,
-     DEFAULT = 279,
-     SUBROUTINE = 280,
-     BVEC2 = 281,
-     BVEC3 = 282,
-     BVEC4 = 283,
-     IVEC2 = 284,
-     IVEC3 = 285,
-     IVEC4 = 286,
-     I64VEC2 = 287,
-     I64VEC3 = 288,
-     I64VEC4 = 289,
-     UVEC2 = 290,
-     UVEC3 = 291,
-     UVEC4 = 292,
-     U64VEC2 = 293,
-     U64VEC3 = 294,
-     U64VEC4 = 295,
-     VEC2 = 296,
-     VEC3 = 297,
-     VEC4 = 298,
-     MAT2 = 299,
-     MAT3 = 300,
-     MAT4 = 301,
-     CENTROID = 302,
-     IN = 303,
-     OUT = 304,
-     INOUT = 305,
-     UNIFORM = 306,
-     PATCH = 307,
-     SAMPLE = 308,
-     BUFFER = 309,
-     SHARED = 310,
-     COHERENT = 311,
-     VOLATILE = 312,
-     RESTRICT = 313,
-     READONLY = 314,
-     WRITEONLY = 315,
-     DVEC2 = 316,
-     DVEC3 = 317,
-     DVEC4 = 318,
-     DMAT2 = 319,
-     DMAT3 = 320,
-     DMAT4 = 321,
-     F16VEC2 = 322,
-     F16VEC3 = 323,
-     F16VEC4 = 324,
-     F16MAT2 = 325,
-     F16MAT3 = 326,
-     F16MAT4 = 327,
-     NOPERSPECTIVE = 328,
-     FLAT = 329,
-     SMOOTH = 330,
-     LAYOUT = 331,
-     __EXPLICITINTERPAMD = 332,
-     MAT2X2 = 333,
-     MAT2X3 = 334,
-     MAT2X4 = 335,
-     MAT3X2 = 336,
-     MAT3X3 = 337,
-     MAT3X4 = 338,
-     MAT4X2 = 339,
-     MAT4X3 = 340,
-     MAT4X4 = 341,
-     DMAT2X2 = 342,
-     DMAT2X3 = 343,
-     DMAT2X4 = 344,
-     DMAT3X2 = 345,
-     DMAT3X3 = 346,
-     DMAT3X4 = 347,
-     DMAT4X2 = 348,
-     DMAT4X3 = 349,
-     DMAT4X4 = 350,
-     F16MAT2X2 = 351,
-     F16MAT2X3 = 352,
-     F16MAT2X4 = 353,
-     F16MAT3X2 = 354,
-     F16MAT3X3 = 355,
-     F16MAT3X4 = 356,
-     F16MAT4X2 = 357,
-     F16MAT4X3 = 358,
-     F16MAT4X4 = 359,
-     ATOMIC_UINT = 360,
-     SAMPLER1D = 361,
-     SAMPLER2D = 362,
-     SAMPLER3D = 363,
-     SAMPLERCUBE = 364,
-     SAMPLER1DSHADOW = 365,
-     SAMPLER2DSHADOW = 366,
-     SAMPLERCUBESHADOW = 367,
-     SAMPLER1DARRAY = 368,
-     SAMPLER2DARRAY = 369,
-     SAMPLER1DARRAYSHADOW = 370,
-     SAMPLER2DARRAYSHADOW = 371,
-     ISAMPLER1D = 372,
-     ISAMPLER2D = 373,
-     ISAMPLER3D = 374,
-     ISAMPLERCUBE = 375,
-     ISAMPLER1DARRAY = 376,
-     ISAMPLER2DARRAY = 377,
-     USAMPLER1D = 378,
-     USAMPLER2D = 379,
-     USAMPLER3D = 380,
-     USAMPLERCUBE = 381,
-     USAMPLER1DARRAY = 382,
-     USAMPLER2DARRAY = 383,
-     SAMPLER2DRECT = 384,
-     SAMPLER2DRECTSHADOW = 385,
-     ISAMPLER2DRECT = 386,
-     USAMPLER2DRECT = 387,
-     SAMPLERBUFFER = 388,
-     ISAMPLERBUFFER = 389,
-     USAMPLERBUFFER = 390,
-     SAMPLERCUBEARRAY = 391,
-     SAMPLERCUBEARRAYSHADOW = 392,
-     ISAMPLERCUBEARRAY = 393,
-     USAMPLERCUBEARRAY = 394,
-     SAMPLER2DMS = 395,
-     ISAMPLER2DMS = 396,
-     USAMPLER2DMS = 397,
-     SAMPLER2DMSARRAY = 398,
-     ISAMPLER2DMSARRAY = 399,
-     USAMPLER2DMSARRAY = 400,
-     SAMPLEREXTERNALOES = 401,
-     SAMPLER = 402,
-     SAMPLERSHADOW = 403,
-     TEXTURE1D = 404,
-     TEXTURE2D = 405,
-     TEXTURE3D = 406,
-     TEXTURECUBE = 407,
-     TEXTURE1DARRAY = 408,
-     TEXTURE2DARRAY = 409,
-     ITEXTURE1D = 410,
-     ITEXTURE2D = 411,
-     ITEXTURE3D = 412,
-     ITEXTURECUBE = 413,
-     ITEXTURE1DARRAY = 414,
-     ITEXTURE2DARRAY = 415,
-     UTEXTURE1D = 416,
-     UTEXTURE2D = 417,
-     UTEXTURE3D = 418,
-     UTEXTURECUBE = 419,
-     UTEXTURE1DARRAY = 420,
-     UTEXTURE2DARRAY = 421,
-     TEXTURE2DRECT = 422,
-     ITEXTURE2DRECT = 423,
-     UTEXTURE2DRECT = 424,
-     TEXTUREBUFFER = 425,
-     ITEXTUREBUFFER = 426,
-     UTEXTUREBUFFER = 427,
-     TEXTURECUBEARRAY = 428,
-     ITEXTURECUBEARRAY = 429,
-     UTEXTURECUBEARRAY = 430,
-     TEXTURE2DMS = 431,
-     ITEXTURE2DMS = 432,
-     UTEXTURE2DMS = 433,
-     TEXTURE2DMSARRAY = 434,
-     ITEXTURE2DMSARRAY = 435,
-     UTEXTURE2DMSARRAY = 436,
-     SUBPASSINPUT = 437,
-     SUBPASSINPUTMS = 438,
-     ISUBPASSINPUT = 439,
-     ISUBPASSINPUTMS = 440,
-     USUBPASSINPUT = 441,
-     USUBPASSINPUTMS = 442,
-     IMAGE1D = 443,
-     IIMAGE1D = 444,
-     UIMAGE1D = 445,
-     IMAGE2D = 446,
-     IIMAGE2D = 447,
-     UIMAGE2D = 448,
-     IMAGE3D = 449,
-     IIMAGE3D = 450,
-     UIMAGE3D = 451,
-     IMAGE2DRECT = 452,
-     IIMAGE2DRECT = 453,
-     UIMAGE2DRECT = 454,
-     IMAGECUBE = 455,
-     IIMAGECUBE = 456,
-     UIMAGECUBE = 457,
-     IMAGEBUFFER = 458,
-     IIMAGEBUFFER = 459,
-     UIMAGEBUFFER = 460,
-     IMAGE1DARRAY = 461,
-     IIMAGE1DARRAY = 462,
-     UIMAGE1DARRAY = 463,
-     IMAGE2DARRAY = 464,
-     IIMAGE2DARRAY = 465,
-     UIMAGE2DARRAY = 466,
-     IMAGECUBEARRAY = 467,
-     IIMAGECUBEARRAY = 468,
-     UIMAGECUBEARRAY = 469,
-     IMAGE2DMS = 470,
-     IIMAGE2DMS = 471,
-     UIMAGE2DMS = 472,
-     IMAGE2DMSARRAY = 473,
-     IIMAGE2DMSARRAY = 474,
-     UIMAGE2DMSARRAY = 475,
-     STRUCT = 476,
-     VOID = 477,
-     WHILE = 478,
-     IDENTIFIER = 479,
-     TYPE_NAME = 480,
-     FLOATCONSTANT = 481,
-     DOUBLECONSTANT = 482,
-     INTCONSTANT = 483,
-     UINTCONSTANT = 484,
-     INT64CONSTANT = 485,
-     UINT64CONSTANT = 486,
-     BOOLCONSTANT = 487,
-     FLOAT16CONSTANT = 488,
-     LEFT_OP = 489,
-     RIGHT_OP = 490,
-     INC_OP = 491,
-     DEC_OP = 492,
-     LE_OP = 493,
-     GE_OP = 494,
-     EQ_OP = 495,
-     NE_OP = 496,
-     AND_OP = 497,
-     OR_OP = 498,
-     XOR_OP = 499,
-     MUL_ASSIGN = 500,
-     DIV_ASSIGN = 501,
-     ADD_ASSIGN = 502,
-     MOD_ASSIGN = 503,
-     LEFT_ASSIGN = 504,
-     RIGHT_ASSIGN = 505,
-     AND_ASSIGN = 506,
-     XOR_ASSIGN = 507,
-     OR_ASSIGN = 508,
-     SUB_ASSIGN = 509,
-     LEFT_PAREN = 510,
-     RIGHT_PAREN = 511,
-     LEFT_BRACKET = 512,
-     RIGHT_BRACKET = 513,
-     LEFT_BRACE = 514,
-     RIGHT_BRACE = 515,
-     DOT = 516,
-     COMMA = 517,
-     COLON = 518,
-     EQUAL = 519,
-     SEMICOLON = 520,
-     BANG = 521,
-     DASH = 522,
-     TILDE = 523,
-     PLUS = 524,
-     STAR = 525,
-     SLASH = 526,
-     PERCENT = 527,
-     LEFT_ANGLE = 528,
-     RIGHT_ANGLE = 529,
-     VERTICAL_BAR = 530,
-     CARET = 531,
-     AMPERSAND = 532,
-     QUESTION = 533,
-     INVARIANT = 534,
-     PRECISE = 535,
-     HIGH_PRECISION = 536,
-     MEDIUM_PRECISION = 537,
-     LOW_PRECISION = 538,
-     PRECISION = 539,
-     PACKED = 540,
-     RESOURCE = 541,
-     SUPERP = 542
-   };
+  enum yytokentype
+  {
+    ATTRIBUTE = 258,
+    VARYING = 259,
+    CONST = 260,
+    BOOL = 261,
+    FLOAT = 262,
+    DOUBLE = 263,
+    INT = 264,
+    UINT = 265,
+    INT64_T = 266,
+    UINT64_T = 267,
+    INT16_T = 268,
+    UINT16_T = 269,
+    FLOAT16_T = 270,
+    BREAK = 271,
+    CONTINUE = 272,
+    DO = 273,
+    ELSE = 274,
+    FOR = 275,
+    IF = 276,
+    DISCARD = 277,
+    RETURN = 278,
+    SWITCH = 279,
+    CASE = 280,
+    DEFAULT = 281,
+    SUBROUTINE = 282,
+    BVEC2 = 283,
+    BVEC3 = 284,
+    BVEC4 = 285,
+    IVEC2 = 286,
+    IVEC3 = 287,
+    IVEC4 = 288,
+    I64VEC2 = 289,
+    I64VEC3 = 290,
+    I64VEC4 = 291,
+    UVEC2 = 292,
+    UVEC3 = 293,
+    UVEC4 = 294,
+    U64VEC2 = 295,
+    U64VEC3 = 296,
+    U64VEC4 = 297,
+    VEC2 = 298,
+    VEC3 = 299,
+    VEC4 = 300,
+    MAT2 = 301,
+    MAT3 = 302,
+    MAT4 = 303,
+    CENTROID = 304,
+    IN = 305,
+    OUT = 306,
+    INOUT = 307,
+    UNIFORM = 308,
+    PATCH = 309,
+    SAMPLE = 310,
+    BUFFER = 311,
+    SHARED = 312,
+    COHERENT = 313,
+    VOLATILE = 314,
+    RESTRICT = 315,
+    READONLY = 316,
+    WRITEONLY = 317,
+    DVEC2 = 318,
+    DVEC3 = 319,
+    DVEC4 = 320,
+    DMAT2 = 321,
+    DMAT3 = 322,
+    DMAT4 = 323,
+    F16VEC2 = 324,
+    F16VEC3 = 325,
+    F16VEC4 = 326,
+    F16MAT2 = 327,
+    F16MAT3 = 328,
+    F16MAT4 = 329,
+    I16VEC2 = 330,
+    I16VEC3 = 331,
+    I16VEC4 = 332,
+    U16VEC2 = 333,
+    U16VEC3 = 334,
+    U16VEC4 = 335,
+    NOPERSPECTIVE = 336,
+    FLAT = 337,
+    SMOOTH = 338,
+    LAYOUT = 339,
+    __EXPLICITINTERPAMD = 340,
+    MAT2X2 = 341,
+    MAT2X3 = 342,
+    MAT2X4 = 343,
+    MAT3X2 = 344,
+    MAT3X3 = 345,
+    MAT3X4 = 346,
+    MAT4X2 = 347,
+    MAT4X3 = 348,
+    MAT4X4 = 349,
+    DMAT2X2 = 350,
+    DMAT2X3 = 351,
+    DMAT2X4 = 352,
+    DMAT3X2 = 353,
+    DMAT3X3 = 354,
+    DMAT3X4 = 355,
+    DMAT4X2 = 356,
+    DMAT4X3 = 357,
+    DMAT4X4 = 358,
+    F16MAT2X2 = 359,
+    F16MAT2X3 = 360,
+    F16MAT2X4 = 361,
+    F16MAT3X2 = 362,
+    F16MAT3X3 = 363,
+    F16MAT3X4 = 364,
+    F16MAT4X2 = 365,
+    F16MAT4X3 = 366,
+    F16MAT4X4 = 367,
+    ATOMIC_UINT = 368,
+    SAMPLER1D = 369,
+    SAMPLER2D = 370,
+    SAMPLER3D = 371,
+    SAMPLERCUBE = 372,
+    SAMPLER1DSHADOW = 373,
+    SAMPLER2DSHADOW = 374,
+    SAMPLERCUBESHADOW = 375,
+    SAMPLER1DARRAY = 376,
+    SAMPLER2DARRAY = 377,
+    SAMPLER1DARRAYSHADOW = 378,
+    SAMPLER2DARRAYSHADOW = 379,
+    ISAMPLER1D = 380,
+    ISAMPLER2D = 381,
+    ISAMPLER3D = 382,
+    ISAMPLERCUBE = 383,
+    ISAMPLER1DARRAY = 384,
+    ISAMPLER2DARRAY = 385,
+    USAMPLER1D = 386,
+    USAMPLER2D = 387,
+    USAMPLER3D = 388,
+    USAMPLERCUBE = 389,
+    USAMPLER1DARRAY = 390,
+    USAMPLER2DARRAY = 391,
+    SAMPLER2DRECT = 392,
+    SAMPLER2DRECTSHADOW = 393,
+    ISAMPLER2DRECT = 394,
+    USAMPLER2DRECT = 395,
+    SAMPLERBUFFER = 396,
+    ISAMPLERBUFFER = 397,
+    USAMPLERBUFFER = 398,
+    SAMPLERCUBEARRAY = 399,
+    SAMPLERCUBEARRAYSHADOW = 400,
+    ISAMPLERCUBEARRAY = 401,
+    USAMPLERCUBEARRAY = 402,
+    SAMPLER2DMS = 403,
+    ISAMPLER2DMS = 404,
+    USAMPLER2DMS = 405,
+    SAMPLER2DMSARRAY = 406,
+    ISAMPLER2DMSARRAY = 407,
+    USAMPLER2DMSARRAY = 408,
+    SAMPLEREXTERNALOES = 409,
+    SAMPLER = 410,
+    SAMPLERSHADOW = 411,
+    TEXTURE1D = 412,
+    TEXTURE2D = 413,
+    TEXTURE3D = 414,
+    TEXTURECUBE = 415,
+    TEXTURE1DARRAY = 416,
+    TEXTURE2DARRAY = 417,
+    ITEXTURE1D = 418,
+    ITEXTURE2D = 419,
+    ITEXTURE3D = 420,
+    ITEXTURECUBE = 421,
+    ITEXTURE1DARRAY = 422,
+    ITEXTURE2DARRAY = 423,
+    UTEXTURE1D = 424,
+    UTEXTURE2D = 425,
+    UTEXTURE3D = 426,
+    UTEXTURECUBE = 427,
+    UTEXTURE1DARRAY = 428,
+    UTEXTURE2DARRAY = 429,
+    TEXTURE2DRECT = 430,
+    ITEXTURE2DRECT = 431,
+    UTEXTURE2DRECT = 432,
+    TEXTUREBUFFER = 433,
+    ITEXTUREBUFFER = 434,
+    UTEXTUREBUFFER = 435,
+    TEXTURECUBEARRAY = 436,
+    ITEXTURECUBEARRAY = 437,
+    UTEXTURECUBEARRAY = 438,
+    TEXTURE2DMS = 439,
+    ITEXTURE2DMS = 440,
+    UTEXTURE2DMS = 441,
+    TEXTURE2DMSARRAY = 442,
+    ITEXTURE2DMSARRAY = 443,
+    UTEXTURE2DMSARRAY = 444,
+    SUBPASSINPUT = 445,
+    SUBPASSINPUTMS = 446,
+    ISUBPASSINPUT = 447,
+    ISUBPASSINPUTMS = 448,
+    USUBPASSINPUT = 449,
+    USUBPASSINPUTMS = 450,
+    IMAGE1D = 451,
+    IIMAGE1D = 452,
+    UIMAGE1D = 453,
+    IMAGE2D = 454,
+    IIMAGE2D = 455,
+    UIMAGE2D = 456,
+    IMAGE3D = 457,
+    IIMAGE3D = 458,
+    UIMAGE3D = 459,
+    IMAGE2DRECT = 460,
+    IIMAGE2DRECT = 461,
+    UIMAGE2DRECT = 462,
+    IMAGECUBE = 463,
+    IIMAGECUBE = 464,
+    UIMAGECUBE = 465,
+    IMAGEBUFFER = 466,
+    IIMAGEBUFFER = 467,
+    UIMAGEBUFFER = 468,
+    IMAGE1DARRAY = 469,
+    IIMAGE1DARRAY = 470,
+    UIMAGE1DARRAY = 471,
+    IMAGE2DARRAY = 472,
+    IIMAGE2DARRAY = 473,
+    UIMAGE2DARRAY = 474,
+    IMAGECUBEARRAY = 475,
+    IIMAGECUBEARRAY = 476,
+    UIMAGECUBEARRAY = 477,
+    IMAGE2DMS = 478,
+    IIMAGE2DMS = 479,
+    UIMAGE2DMS = 480,
+    IMAGE2DMSARRAY = 481,
+    IIMAGE2DMSARRAY = 482,
+    UIMAGE2DMSARRAY = 483,
+    STRUCT = 484,
+    VOID = 485,
+    WHILE = 486,
+    IDENTIFIER = 487,
+    TYPE_NAME = 488,
+    FLOATCONSTANT = 489,
+    DOUBLECONSTANT = 490,
+    INTCONSTANT = 491,
+    UINTCONSTANT = 492,
+    INT64CONSTANT = 493,
+    UINT64CONSTANT = 494,
+    INT16CONSTANT = 495,
+    UINT16CONSTANT = 496,
+    BOOLCONSTANT = 497,
+    FLOAT16CONSTANT = 498,
+    LEFT_OP = 499,
+    RIGHT_OP = 500,
+    INC_OP = 501,
+    DEC_OP = 502,
+    LE_OP = 503,
+    GE_OP = 504,
+    EQ_OP = 505,
+    NE_OP = 506,
+    AND_OP = 507,
+    OR_OP = 508,
+    XOR_OP = 509,
+    MUL_ASSIGN = 510,
+    DIV_ASSIGN = 511,
+    ADD_ASSIGN = 512,
+    MOD_ASSIGN = 513,
+    LEFT_ASSIGN = 514,
+    RIGHT_ASSIGN = 515,
+    AND_ASSIGN = 516,
+    XOR_ASSIGN = 517,
+    OR_ASSIGN = 518,
+    SUB_ASSIGN = 519,
+    LEFT_PAREN = 520,
+    RIGHT_PAREN = 521,
+    LEFT_BRACKET = 522,
+    RIGHT_BRACKET = 523,
+    LEFT_BRACE = 524,
+    RIGHT_BRACE = 525,
+    DOT = 526,
+    COMMA = 527,
+    COLON = 528,
+    EQUAL = 529,
+    SEMICOLON = 530,
+    BANG = 531,
+    DASH = 532,
+    TILDE = 533,
+    PLUS = 534,
+    STAR = 535,
+    SLASH = 536,
+    PERCENT = 537,
+    LEFT_ANGLE = 538,
+    RIGHT_ANGLE = 539,
+    VERTICAL_BAR = 540,
+    CARET = 541,
+    AMPERSAND = 542,
+    QUESTION = 543,
+    INVARIANT = 544,
+    PRECISE = 545,
+    HIGH_PRECISION = 546,
+    MEDIUM_PRECISION = 547,
+    LOW_PRECISION = 548,
+    PRECISION = 549,
+    PACKED = 550,
+    RESOURCE = 551,
+    SUPERP = 552
+  };
 #endif
 
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
+
+union YYSTYPE
 {
-/* Line 2058 of yacc.c  */
-#line 66 "glslang.y"
+#line 68 "MachineIndependent/glslang.y" /* yacc.c:1909  */
 
     struct {
         glslang::TSourceLoc loc;
@@ -373,28 +382,16 @@ typedef union YYSTYPE
         };
     } interm;
 
+#line 386 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909  */
+};
 
-/* Line 2058 of yacc.c  */
-#line 379 "glslang_tab.cpp.h"
-} YYSTYPE;
+typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
+
 int yyparse (glslang::TParseContext* pParseContext);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
-#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED  */
+#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED  */

+ 185 - 8
src/libraries/glslang/glslang/MachineIndependent/intermOut.cpp

@@ -45,11 +45,31 @@
 
 namespace {
 
-bool is_positive_infinity(double x) {
+bool IsInfinity(double x) {
 #ifdef _MSC_VER
-  return _fpclass(x) == _FPCLASS_PINF;
+    switch (_fpclass(x)) {
+    case _FPCLASS_NINF:
+    case _FPCLASS_PINF:
+        return true;
+    default:
+        return false;
+    }
+#else
+    return std::isinf(x);
+#endif
+}
+
+bool IsNan(double x) {
+#ifdef _MSC_VER
+    switch (_fpclass(x)) {
+    case _FPCLASS_SNAN:
+    case _FPCLASS_QNAN:
+        return true;
+    default:
+        return false;
+    }
 #else
-  return std::isinf(x) && (x >= 0);
+  return std::isnan(x);
 #endif
 }
 
@@ -288,6 +308,13 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break;
     case EOpInt64BitsToDouble:  out.debug << "int64BitsToDouble";  break;
     case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break;
+#ifdef AMD_EXTENSIONS
+    case EOpFloat16BitsToInt16:  out.debug << "float16BitsToInt16";  break;
+    case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break;
+    case EOpInt16BitsToFloat16:  out.debug << "int16BitsToFloat16";  break;
+    case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break;
+#endif
+
     case EOpPackSnorm2x16:  out.debug << "packSnorm2x16";        break;
     case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16";      break;
     case EOpPackUnorm2x16:  out.debug << "packUnorm2x16";        break;
@@ -308,6 +335,16 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpUnpackUint2x32:   out.debug << "unpackUint2x32";     break;
 
 #ifdef AMD_EXTENSIONS
+    case EOpPackInt2x16:      out.debug << "packInt2x16";        break;
+    case EOpUnpackInt2x16:    out.debug << "unpackInt2x16";      break;
+    case EOpPackUint2x16:     out.debug << "packUint2x16";       break;
+    case EOpUnpackUint2x16:   out.debug << "unpackUint2x16";     break;
+
+    case EOpPackInt4x16:      out.debug << "packInt4x16";        break;
+    case EOpUnpackInt4x16:    out.debug << "unpackInt4x16";      break;
+    case EOpPackUint4x16:     out.debug << "packUint4x16";       break;
+    case EOpUnpackUint4x16:   out.debug << "unpackUint4x16";     break;
+
     case EOpPackFloat2x16:    out.debug << "packFloat2x16";      break;
     case EOpUnpackFloat2x16:  out.debug << "unpackFloat2x16";    break;
 #endif
@@ -370,6 +407,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpRcp:                    out.debug << "rcp";                   break;
     case EOpSaturate:               out.debug << "saturate";              break;
 
+    case EOpSparseTexelsResident:   out.debug << "sparseTexelsResident";  break;
+
 #ifdef AMD_EXTENSIONS
     case EOpMinInvocations:             out.debug << "minInvocations";              break;
     case EOpMaxInvocations:             out.debug << "maxInvocations";              break;
@@ -411,6 +450,42 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
     case EOpConvFloat16ToDouble:    out.debug << "Convert float16 to double";   break;
     case EOpConvFloat16ToInt64:     out.debug << "Convert float16 to int64";    break;
     case EOpConvFloat16ToUint64:    out.debug << "Convert float16 to uint64";   break;
+
+    case EOpConvBoolToInt16:        out.debug << "Convert bool to int16";       break;
+    case EOpConvIntToInt16:         out.debug << "Convert int to int16";        break;
+    case EOpConvUintToInt16:        out.debug << "Convert uint to int16";       break;
+    case EOpConvFloatToInt16:       out.debug << "Convert float to int16";      break;
+    case EOpConvDoubleToInt16:      out.debug << "Convert double to int16";     break;
+    case EOpConvFloat16ToInt16:     out.debug << "Convert float16 to int16";    break;
+    case EOpConvInt64ToInt16:       out.debug << "Convert int64 to int16";      break;
+    case EOpConvUint64ToInt16:      out.debug << "Convert uint64 to int16";     break;
+    case EOpConvUint16ToInt16:      out.debug << "Convert uint16 to int16";     break;
+    case EOpConvInt16ToBool:        out.debug << "Convert int16 to bool";       break;
+    case EOpConvInt16ToInt:         out.debug << "Convert int16 to int";        break;
+    case EOpConvInt16ToUint:        out.debug << "Convert int16 to uint";       break;
+    case EOpConvInt16ToFloat:       out.debug << "Convert int16 to float";      break;
+    case EOpConvInt16ToDouble:      out.debug << "Convert int16 to double";     break;
+    case EOpConvInt16ToFloat16:     out.debug << "Convert int16 to float16";    break;
+    case EOpConvInt16ToInt64:       out.debug << "Convert int16 to int64";      break;
+    case EOpConvInt16ToUint64:      out.debug << "Convert int16 to uint64";     break;
+
+    case EOpConvBoolToUint16:       out.debug << "Convert bool to uint16";      break;
+    case EOpConvIntToUint16:        out.debug << "Convert int to uint16";       break;
+    case EOpConvUintToUint16:       out.debug << "Convert uint to uint16";      break;
+    case EOpConvFloatToUint16:      out.debug << "Convert float to uint16";     break;
+    case EOpConvDoubleToUint16:     out.debug << "Convert double to uint16";    break;
+    case EOpConvFloat16ToUint16:    out.debug << "Convert float16 to uint16";   break;
+    case EOpConvInt64ToUint16:      out.debug << "Convert int64 to uint16";     break;
+    case EOpConvUint64ToUint16:     out.debug << "Convert uint64 to uint16";    break;
+    case EOpConvInt16ToUint16:      out.debug << "Convert int16 to uint16";     break;
+    case EOpConvUint16ToBool:       out.debug << "Convert uint16 to bool";      break;
+    case EOpConvUint16ToInt:        out.debug << "Convert uint16 to int";       break;
+    case EOpConvUint16ToUint:       out.debug << "Convert uint16 to uint";      break;
+    case EOpConvUint16ToFloat:      out.debug << "Convert uint16 to float";     break;
+    case EOpConvUint16ToDouble:     out.debug << "Convert uint16 to double";    break;
+    case EOpConvUint16ToFloat16:    out.debug << "Convert uint16 to float16";   break;
+    case EOpConvUint16ToInt64:      out.debug << "Convert uint16 to int64";     break;
+    case EOpConvUint16ToUint64:     out.debug << "Convert uint16 to uint64";    break;
 #endif
 
     default: out.debug.message(EPrefixError, "Bad unary op");
@@ -444,9 +519,13 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
 
     case EOpConstructFloat: out.debug << "Construct float"; break;
     case EOpConstructDouble:out.debug << "Construct double"; break;
+
     case EOpConstructVec2:  out.debug << "Construct vec2";  break;
     case EOpConstructVec3:  out.debug << "Construct vec3";  break;
     case EOpConstructVec4:  out.debug << "Construct vec4";  break;
+    case EOpConstructDVec2: out.debug << "Construct dvec2";  break;
+    case EOpConstructDVec3: out.debug << "Construct dvec3";  break;
+    case EOpConstructDVec4: out.debug << "Construct dvec4";  break;
     case EOpConstructBool:  out.debug << "Construct bool";  break;
     case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
     case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
@@ -467,6 +546,16 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break;
     case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break;
     case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break;
+#ifdef AMD_EXTENSIONS
+    case EOpConstructInt16:   out.debug << "Construct int16_t"; break;
+    case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break;
+    case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break;
+    case EOpConstructI16Vec4: out.debug << "Construct i16vec4"; break;
+    case EOpConstructUint16:  out.debug << "Construct uint16_t"; break;
+    case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break;
+    case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break;
+    case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break;
+#endif
     case EOpConstructMat2x2:  out.debug << "Construct mat2";    break;
     case EOpConstructMat2x3:  out.debug << "Construct mat2x3";  break;
     case EOpConstructMat2x4:  out.debug << "Construct mat2x4";  break;
@@ -485,6 +574,33 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpConstructDMat4x2: out.debug << "Construct dmat4x2"; break;
     case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break;
     case EOpConstructDMat4x4: out.debug << "Construct dmat4";   break;
+    case EOpConstructIMat2x2: out.debug << "Construct imat2";   break;
+    case EOpConstructIMat2x3: out.debug << "Construct imat2x3"; break;
+    case EOpConstructIMat2x4: out.debug << "Construct imat2x4"; break;
+    case EOpConstructIMat3x2: out.debug << "Construct imat3x2"; break;
+    case EOpConstructIMat3x3: out.debug << "Construct imat3";   break;
+    case EOpConstructIMat3x4: out.debug << "Construct imat3x4"; break;
+    case EOpConstructIMat4x2: out.debug << "Construct imat4x2"; break;
+    case EOpConstructIMat4x3: out.debug << "Construct imat4x3"; break;
+    case EOpConstructIMat4x4: out.debug << "Construct imat4";   break;
+    case EOpConstructUMat2x2: out.debug << "Construct umat2";   break;
+    case EOpConstructUMat2x3: out.debug << "Construct umat2x3"; break;
+    case EOpConstructUMat2x4: out.debug << "Construct umat2x4"; break;
+    case EOpConstructUMat3x2: out.debug << "Construct umat3x2"; break;
+    case EOpConstructUMat3x3: out.debug << "Construct umat3";   break;
+    case EOpConstructUMat3x4: out.debug << "Construct umat3x4"; break;
+    case EOpConstructUMat4x2: out.debug << "Construct umat4x2"; break;
+    case EOpConstructUMat4x3: out.debug << "Construct umat4x3"; break;
+    case EOpConstructUMat4x4: out.debug << "Construct umat4";   break;
+    case EOpConstructBMat2x2: out.debug << "Construct bmat2";   break;
+    case EOpConstructBMat2x3: out.debug << "Construct bmat2x3"; break;
+    case EOpConstructBMat2x4: out.debug << "Construct bmat2x4"; break;
+    case EOpConstructBMat3x2: out.debug << "Construct bmat3x2"; break;
+    case EOpConstructBMat3x3: out.debug << "Construct bmat3";   break;
+    case EOpConstructBMat3x4: out.debug << "Construct bmat3x4"; break;
+    case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break;
+    case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break;
+    case EOpConstructBMat4x4: out.debug << "Construct bmat4";   break;
 #ifdef AMD_EXTENSIONS
     case EOpConstructFloat16:   out.debug << "Construct float16_t"; break;
     case EOpConstructF16Vec2:   out.debug << "Construct f16vec2";   break;
@@ -600,6 +716,37 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
     case EOpTextureGather:              out.debug << "textureGather";         break;
     case EOpTextureGatherOffset:        out.debug << "textureGatherOffset";   break;
     case EOpTextureGatherOffsets:       out.debug << "textureGatherOffsets";  break;
+    case EOpTextureClamp:               out.debug << "textureClamp";          break;
+    case EOpTextureOffsetClamp:         out.debug << "textureOffsetClamp";    break;
+    case EOpTextureGradClamp:           out.debug << "textureGradClamp";      break;
+    case EOpTextureGradOffsetClamp:     out.debug << "textureGradOffsetClamp";  break;
+#ifdef AMD_EXTENSIONS
+    case EOpTextureGatherLod:           out.debug << "textureGatherLod";        break;
+    case EOpTextureGatherLodOffset:     out.debug << "textureGatherLodOffset";  break;
+    case EOpTextureGatherLodOffsets:    out.debug << "textureGatherLodOffsets"; break;
+#endif
+
+    case EOpSparseTexture:                  out.debug << "sparseTexture";                   break;
+    case EOpSparseTextureOffset:            out.debug << "sparseTextureOffset";             break;
+    case EOpSparseTextureLod:               out.debug << "sparseTextureLod";                break;
+    case EOpSparseTextureLodOffset:         out.debug << "sparseTextureLodOffset";          break;
+    case EOpSparseTextureFetch:             out.debug << "sparseTexelFetch";                break;
+    case EOpSparseTextureFetchOffset:       out.debug << "sparseTexelFetchOffset";          break;
+    case EOpSparseTextureGrad:              out.debug << "sparseTextureGrad";               break;
+    case EOpSparseTextureGradOffset:        out.debug << "sparseTextureGradOffset";         break;
+    case EOpSparseTextureGather:            out.debug << "sparseTextureGather";             break;
+    case EOpSparseTextureGatherOffset:      out.debug << "sparseTextureGatherOffset";       break;
+    case EOpSparseTextureGatherOffsets:     out.debug << "sparseTextureGatherOffsets";      break;
+    case EOpSparseImageLoad:                out.debug << "sparseImageLoad";                 break;
+    case EOpSparseTextureClamp:             out.debug << "sparseTextureClamp";              break;
+    case EOpSparseTextureOffsetClamp:       out.debug << "sparseTextureOffsetClamp";        break;
+    case EOpSparseTextureGradClamp:         out.debug << "sparseTextureGradClamp";          break;
+    case EOpSparseTextureGradOffsetClamp:   out.debug << "sparseTextureGradOffsetClam";     break;
+#ifdef AMD_EXTENSIONS
+    case EOpSparseTextureGatherLod:         out.debug << "sparseTextureGatherLod";          break;
+    case EOpSparseTextureGatherLodOffset:   out.debug << "sparseTextureGatherLodOffset";    break;
+    case EOpSparseTextureGatherLodOffsets:  out.debug << "sparseTextureGatherLodOffsets";   break;
+#endif
 
     case EOpAddCarry:                   out.debug << "addCarry";              break;
     case EOpSubBorrow:                  out.debug << "subBorrow";             break;
@@ -694,11 +841,14 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
 #endif
             {
                 const double value = constUnion[i].getDConst();
-                // Print infinity in a portable way, for test stability.
-                // Other cases may be needed in the future: negative infinity,
-                // and NaNs.
-                if (is_positive_infinity(value))
-                    out.debug << "inf\n";
+                // Print infinities and NaNs in a portable way.
+                if (IsInfinity(value)) {
+                    if (value < 0)
+                        out.debug << "-1.#INF\n";
+                    else
+                        out.debug << "+1.#INF\n";
+                } else if (IsNan(value))
+                    out.debug << "1.#IND\n";
                 else {
                     const int maxSize = 300;
                     char buf[maxSize];
@@ -744,6 +894,26 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
                 out.debug << buf << "\n";
             }
             break;
+#ifdef AMD_EXTENSIONS
+        case EbtInt16:
+            {
+                const int maxSize = 300;
+                char buf[maxSize];
+                snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int16_t");
+
+                out.debug << buf << "\n";
+            }
+            break;
+        case EbtUint16:
+            {
+                const int maxSize = 300;
+                char buf[maxSize];
+                snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint16_t");
+
+                out.debug << buf << "\n";
+            }
+            break;
+#endif
         default:
             out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
             break;
@@ -884,6 +1054,13 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
 
     case EShLangTessControl:
         infoSink.debug << "vertices = " << vertices << "\n";
+
+        if (inputPrimitive != ElgNone)
+            infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
+        if (vertexSpacing != EvsNone)
+            infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
+        if (vertexOrder != EvoNone)
+            infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
         break;
 
     case EShLangTessEvaluation:

+ 410 - 92
src/libraries/glslang/glslang/MachineIndependent/iomapper.cpp

@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2016 LunarG, Inc.
+// Copyright (C) 2016-2017 LunarG, Inc.
 //
 // All rights reserved.
 //
@@ -66,11 +66,14 @@ namespace glslang {
 
 struct TVarEntryInfo
 {
-    int             id;
-    TIntermSymbol*  symbol;
-    bool            live;
-    int             newBinding;
-    int             newSet;
+    int               id;
+    TIntermSymbol*    symbol;
+    bool              live;
+    int               newBinding;
+    int               newSet;
+    int               newLocation;
+    int               newComponent;
+    int               newIndex;
 
     struct TOrderById
     {
@@ -113,70 +116,143 @@ typedef std::vector<TVarEntryInfo> TVarLiveMap;
 class TVarGatherTraverser : public TLiveTraverser
 {
 public:
-    TVarGatherTraverser(const TIntermediate& i, TVarLiveMap& vars, bool traverseDeadCode)
+    TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList)
       : TLiveTraverser(i, traverseDeadCode, true, true, false)
-      , varLiveList(vars)
+      , inputList(inList)
+      , outputList(outList)
+      , uniformList(uniformList)
     {
     }
 
 
     virtual void visitSymbol(TIntermSymbol* base)
     {
-        if (base->getQualifier().storage == EvqUniform) {
+        TVarLiveMap* target = nullptr;
+        if (base->getQualifier().storage == EvqVaryingIn)
+            target = &inputList;
+        else if (base->getQualifier().storage == EvqVaryingOut)
+            target = &outputList;
+        else if (base->getQualifier().isUniformOrBuffer())
+            target = &uniformList;
+
+        if (target) {
             TVarEntryInfo ent = { base->getId(), base, !traverseAll };
-            TVarLiveMap::iterator at = std::lower_bound(varLiveList.begin(), varLiveList.end(), ent, TVarEntryInfo::TOrderById());
-            if (at != varLiveList.end() && at->id == ent.id)
+            TVarLiveMap::iterator at = std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById());
+            if (at != target->end() && at->id == ent.id)
               at->live = at->live || !traverseAll; // update live state
             else
-              varLiveList.insert(at, ent);
+              target->insert(at, ent);
         }
     }
 
 private:
-    TVarLiveMap&    varLiveList;
+    TVarLiveMap&    inputList;
+    TVarLiveMap&    outputList;
+    TVarLiveMap&    uniformList;
 };
 
 class TVarSetTraverser : public TLiveTraverser
 {
 public:
-    TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& vars)
+    TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& inList, const TVarLiveMap& outList, const TVarLiveMap& uniformList)
       : TLiveTraverser(i, true, true, true, false)
-      , varLiveList(vars)
+      , inputList(inList)
+      , outputList(outList)
+      , uniformList(uniformList)
     {
     }
 
 
     virtual void visitSymbol(TIntermSymbol* base)
     {
+        const TVarLiveMap* source;
+        if (base->getQualifier().storage == EvqVaryingIn)
+            source = &inputList;
+        else if (base->getQualifier().storage == EvqVaryingOut)
+            source = &outputList;
+        else if (base->getQualifier().isUniformOrBuffer())
+            source = &uniformList;
+        else
+            return;
+
         TVarEntryInfo ent = { base->getId() };
-        TVarLiveMap::const_iterator at = std::lower_bound(varLiveList.begin(), varLiveList.end(), ent, TVarEntryInfo::TOrderById());
-        if (at == varLiveList.end())
+        TVarLiveMap::const_iterator at = std::lower_bound(source->begin(), source->end(), ent, TVarEntryInfo::TOrderById());
+        if (at == source->end())
             return;
-        if (!(at->id == ent.id))
+
+        if (at->id != ent.id)
             return;
 
         if (at->newBinding != -1)
             base->getWritableType().getQualifier().layoutBinding = at->newBinding;
         if (at->newSet != -1)
             base->getWritableType().getQualifier().layoutSet = at->newSet;
+        if (at->newLocation != -1)
+            base->getWritableType().getQualifier().layoutLocation = at->newLocation;
+        if (at->newComponent != -1)
+            base->getWritableType().getQualifier().layoutComponent = at->newComponent;
+        if (at->newIndex != -1)
+            base->getWritableType().getQualifier().layoutIndex = at->newIndex;
     }
 
   private:
-    const TVarLiveMap&    varLiveList;
+    const TVarLiveMap&    inputList;
+    const TVarLiveMap&    outputList;
+    const TVarLiveMap&    uniformList;
 };
 
-struct TResolverAdaptor
+struct TNotifyUniformAdaptor
 {
-    TResolverAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e)
+    EShLanguage stage;
+    TIoMapResolver& resolver;
+    inline TNotifyUniformAdaptor(EShLanguage s, TIoMapResolver& r)
+      : stage(s)
+      , resolver(r)
+    {
+    }
+    inline void operator()(TVarEntryInfo& ent)
+    {
+        resolver.notifyBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
+    }
+private:
+    TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&);
+};
+
+struct TNotifyInOutAdaptor
+{
+    EShLanguage stage;
+    TIoMapResolver& resolver;
+    inline TNotifyInOutAdaptor(EShLanguage s, TIoMapResolver& r)
+      : stage(s)
+      , resolver(r)
+    {
+    }
+    inline void operator()(TVarEntryInfo& ent)
+    {
+        resolver.notifyInOut(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
+    }
+private:
+    TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&);
+};
+
+struct TResolverUniformAdaptor
+{
+    TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm)
       : stage(s)
       , resolver(r)
       , infoSink(i)
       , error(e)
+      , intermediate(interm)
     {
     }
 
     inline void operator()(TVarEntryInfo& ent)
     {
+        ent.newLocation = -1;
+        ent.newComponent = -1;
+        ent.newBinding = -1;
+        ent.newSet = -1;
+        ent.newIndex = -1;
         const bool isValid = resolver.validateBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
         if (isValid) {
             ent.newBinding = resolver.resolveBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
@@ -209,25 +285,77 @@ struct TResolverAdaptor
     TIoMapResolver& resolver;
     TInfoSink&      infoSink;
     bool&           error;
+    TIntermediate&  intermediate;
 
 private:
-    TResolverAdaptor& operator=(TResolverAdaptor&);
+    TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&);
 };
 
-/*
- * Basic implementation of glslang::TIoMapResolver that replaces the
- * previous offset behaviour.
- * It does the same, uses the offsets for th corresponding uniform
- * types. Also respects the EOptionAutoMapBindings flag and binds
- * them if needed.
- */
-struct TDefaultIoResolver : public glslang::TIoMapResolver
+struct TResolverInOutAdaptor
+{
+    TResolverInOutAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e, TIntermediate& interm)
+      : stage(s)
+      , resolver(r)
+      , infoSink(i)
+      , error(e)
+      , intermediate(interm)
+    {
+    }
+
+    inline void operator()(TVarEntryInfo& ent)
+    {
+        ent.newLocation = -1;
+        ent.newComponent = -1;
+        ent.newBinding = -1;
+        ent.newSet = -1;
+        ent.newIndex = -1;
+        const bool isValid = resolver.validateInOut(stage,
+                                                    ent.symbol->getName().c_str(),
+                                                    ent.symbol->getType(),
+                                                    ent.live);
+        if (isValid) {
+            ent.newLocation = resolver.resolveInOutLocation(stage,
+                                                            ent.symbol->getName().c_str(),
+                                                            ent.symbol->getType(),
+                                                            ent.live);
+            ent.newComponent = resolver.resolveInOutComponent(stage,
+                                                              ent.symbol->getName().c_str(),
+                                                              ent.symbol->getType(),
+                                                              ent.live);
+            ent.newIndex = resolver.resolveInOutIndex(stage,
+                                                      ent.symbol->getName().c_str(),
+                                                      ent.symbol->getType(),
+                                                      ent.live);
+        } else {
+            TString errorMsg = "Invalid shader In/Out variable semantic: ";
+            errorMsg += ent.symbol->getType().getQualifier().semanticName;
+            infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
+            error = true;
+        }
+    }
+
+    EShLanguage     stage;
+    TIoMapResolver& resolver;
+    TInfoSink&      infoSink;
+    bool&           error;
+    TIntermediate&  intermediate;
+
+private:
+    TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&);
+};
+
+// Base class for shared TIoMapResolver services, used by several derivations.
+struct TDefaultIoResolverBase : public glslang::TIoMapResolver
 {
     int baseSamplerBinding;
     int baseTextureBinding;
     int baseImageBinding;
     int baseUboBinding;
-    bool doAutoMapping;
+    int baseSsboBinding;
+    int baseUavBinding;
+    std::vector<std::string> baseResourceSetBinding;
+    bool doAutoBindingMapping;
+    bool doAutoLocationMapping;
     typedef std::vector<int> TSlotSet;
     typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
     TSlotSetMap slots;
@@ -246,7 +374,12 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver
     int reserveSlot(int set, int slot)
     {
         TSlotSet::iterator at = findSlot(set, slot);
-        slots[set].insert(at, slot);
+
+        // tolerate aliasing, by not double-recording aliases
+        // (policy about appropriateness of the alias is higher up)
+        if (at == slots[set].end() || *at != slot)
+            slots[set].insert(at, slot);
+
         return slot;
     }
 
@@ -263,83 +396,241 @@ struct TDefaultIoResolver : public glslang::TIoMapResolver
         return reserveSlot(set, base);
     }
 
-    bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
+    virtual bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override = 0;
+
+    virtual int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override = 0;
+
+    int resolveSet(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
+    {
+        if (type.getQualifier().hasSet())
+            return type.getQualifier().layoutSet;
+        return 0;
+    }
+
+    bool validateInOut(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
+    {
+        return true;
+    }
+    int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override
+    {
+        if (!doAutoLocationMapping || type.getQualifier().hasLocation())
+            return -1;
+
+        // Placeholder.
+        // TODO: It would be nice to flesh this out using 
+        // intermediate->computeTypeLocationSize(type), or functions that call it like
+        // intermediate->addUsedLocation()
+        // These in turn would want the intermediate, which is not available here, but
+        // is available in many places, and a lot of copying from it could be saved if
+        // it were just available.
+        return 0;
+    }
+    int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
+    {
+        return -1;
+    }
+    int resolveInOutIndex(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
+    {
+        return -1;
+    }
+
+    void notifyBinding(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
+    void notifyInOut(EShLanguage, const char* /*name*/, const TType&, bool /*is_live*/) override {}
+    void endNotifications() override {}
+
+protected:
+    static int getLayoutSet(const glslang::TType& type) {
+        if (type.getQualifier().hasSet())
+            return type.getQualifier().layoutSet;
+        else
+            return 0;
+    }
+
+    static bool isSamplerType(const glslang::TType& type) {
+        return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler();
+    }
+
+    static bool isTextureType(const glslang::TType& type) {
+        return type.getBasicType() == glslang::EbtSampler && type.getSampler().isTexture();
+    }
+
+    static bool isUboType(const glslang::TType& type) {
+        return type.getQualifier().storage == EvqUniform;
+    }
+};
+
+/*
+ * Basic implementation of glslang::TIoMapResolver that replaces the
+ * previous offset behavior.
+ * It does the same, uses the offsets for the corresponding uniform
+ * types. Also respects the EOptionAutoMapBindings flag and binds
+ * them if needed.
+ */
+/*
+ * Default resolver
+ */
+struct TDefaultIoResolver : public TDefaultIoResolverBase
+{
+    bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
     {
+        return true;
+    }
+
+    int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
+    {
+        const int set = getLayoutSet(type);
+
         if (type.getQualifier().hasBinding()) {
-            int set;
-            if (type.getQualifier().hasSet())
-                set = type.getQualifier().layoutSet;
-            else
-                set = 0;
+            if (isImageType(type))
+                return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding);
 
-            if (type.getBasicType() == glslang::EbtSampler) {
-                const glslang::TSampler& sampler = type.getSampler();
-                if (sampler.isPureSampler())
-                    return checkEmpty(set, baseSamplerBinding + type.getQualifier().layoutBinding);
+            if (isTextureType(type))
+                return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
 
-                if (sampler.isTexture())
-                    return checkEmpty(set, baseTextureBinding + type.getQualifier().layoutBinding);
-            }
+            if (isSsboType(type))
+                return reserveSlot(set, baseSsboBinding + type.getQualifier().layoutBinding);
 
-            if (type.getQualifier().isUniformOrBuffer())
-                return checkEmpty(set, baseUboBinding + type.getQualifier().layoutBinding);
+            if (isSamplerType(type))
+                return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
+
+            if (isUboType(type))
+                return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
+        } else if (is_live && doAutoBindingMapping) {
+            // find free slot, the caller did make sure it passes all vars with binding
+            // first and now all are passed that do not have a binding and needs one
+
+            if (isImageType(type))
+                return getFreeSlot(set, baseImageBinding);
+
+            if (isTextureType(type))
+                return getFreeSlot(set, baseTextureBinding);
+
+            if (isSsboType(type))
+                return getFreeSlot(set, baseSsboBinding);
+
+            if (isSamplerType(type))
+                return getFreeSlot(set, baseSamplerBinding);
+
+            if (isUboType(type))
+                return getFreeSlot(set, baseUboBinding);
         }
+
+        return -1;
+    }
+
+protected:
+    static bool isImageType(const glslang::TType& type) {
+        return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage();
+    }
+
+    static bool isSsboType(const glslang::TType& type) {
+        return type.getQualifier().storage == EvqBuffer;
+    }
+};
+
+/********************************************************************************
+The following IO resolver maps types in HLSL register space, as follows:
+
+t – for shader resource views (SRV)
+   TEXTURE1D
+   TEXTURE1DARRAY
+   TEXTURE2D
+   TEXTURE2DARRAY
+   TEXTURE3D
+   TEXTURECUBE
+   TEXTURECUBEARRAY
+   TEXTURE2DMS
+   TEXTURE2DMSARRAY
+   STRUCTUREDBUFFER
+   BYTEADDRESSBUFFER
+   BUFFER
+   TBUFFER
+    
+s – for samplers
+   SAMPLER
+   SAMPLER1D
+   SAMPLER2D
+   SAMPLER3D
+   SAMPLERCUBE
+   SAMPLERSTATE
+   SAMPLERCOMPARISONSTATE
+
+u – for unordered access views (UAV)
+   RWBYTEADDRESSBUFFER
+   RWSTRUCTUREDBUFFER
+   APPENDSTRUCTUREDBUFFER
+   CONSUMESTRUCTUREDBUFFER
+   RWBUFFER
+   RWTEXTURE1D
+   RWTEXTURE1DARRAY
+   RWTEXTURE2D
+   RWTEXTURE2DARRAY
+   RWTEXTURE3D
+
+b – for constant buffer views (CBV)
+   CBUFFER
+   CONSTANTBUFFER
+ ********************************************************************************/
+struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
+{
+    bool validateBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& /*type*/, bool /*is_live*/) override
+    {
         return true;
     }
 
     int resolveBinding(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool is_live) override
     {
-        int set;
-        if (type.getQualifier().hasSet())
-            set = type.getQualifier().layoutSet;
-        else
-            set = 0;
+        const int set = getLayoutSet(type);
 
         if (type.getQualifier().hasBinding()) {
-            if (type.getBasicType() == glslang::EbtSampler) {
-                const glslang::TSampler& sampler = type.getSampler();
-                if (sampler.isImage())
-                    return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding);
+            if (isUavType(type))
+                return reserveSlot(set, baseUavBinding + type.getQualifier().layoutBinding);
 
-                if (sampler.isPureSampler())
-                    return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
+            if (isSrvType(type))
+                return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
 
-                if (sampler.isTexture())
-                    return reserveSlot(set, baseTextureBinding + type.getQualifier().layoutBinding);
-            }
+            if (isSamplerType(type))
+                return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
 
-            if (type.getQualifier().isUniformOrBuffer())
+            if (isUboType(type))
                 return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
-        } else if (is_live && doAutoMapping) {
+        } else if (is_live && doAutoBindingMapping) {
             // find free slot, the caller did make sure it passes all vars with binding
             // first and now all are passed that do not have a binding and needs one
-            if (type.getBasicType() == glslang::EbtSampler) {
-                const glslang::TSampler& sampler = type.getSampler();
-                if (sampler.isImage())
-                    return getFreeSlot(set, baseImageBinding);
 
-                if (sampler.isPureSampler())
-                    return getFreeSlot(set, baseSamplerBinding);
+            if (isUavType(type))
+                return getFreeSlot(set, baseUavBinding);
 
-                if (sampler.isTexture())
-                    return getFreeSlot(set, baseTextureBinding);
-            }
+            if (isSrvType(type))
+                return getFreeSlot(set, baseTextureBinding);
+
+            if (isSamplerType(type))
+                return getFreeSlot(set, baseSamplerBinding);
 
-            if (type.getQualifier().isUniformOrBuffer())
+            if (isUboType(type))
                 return getFreeSlot(set, baseUboBinding);
         }
 
         return -1;
     }
 
-    int resolveSet(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override
-    {
-        if (type.getQualifier().hasSet())
-            return type.getQualifier().layoutSet;
-        return 0;
+protected:
+    // Return true if this is a SRV (shader resource view) type:
+    static bool isSrvType(const glslang::TType& type) {
+        return isTextureType(type) || type.getQualifier().storage == EvqBuffer;
+    }
+
+    // Return true if this is a UAV (unordered access view) type:
+    static bool isUavType(const glslang::TType& type) {
+        if (type.getQualifier().readonly)
+            return false;
+
+        return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) ||
+            (type.getQualifier().storage == EvqBuffer);
     }
 };
 
+
 // Map I/O variables to provided offsets, and make bindings for
 // unbound but live variables.
 //
@@ -351,7 +642,11 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
         intermediate.getShiftTextureBinding() == 0 &&
         intermediate.getShiftImageBinding() == 0 &&
         intermediate.getShiftUboBinding() == 0 &&
+        intermediate.getShiftSsboBinding() == 0 &&
+        intermediate.getShiftUavBinding() == 0 &&
+        intermediate.getResourceSetBinding().empty() &&
         intermediate.getAutoMapBindings() == false &&
+        intermediate.getAutoMapLocations() == false &&
         resolver == nullptr)
         return true;
 
@@ -364,19 +659,33 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
 
     // if no resolver is provided, use the default resolver with the given shifts and auto map settings
     TDefaultIoResolver defaultResolver;
+    TDefaultHlslIoResolver defaultHlslResolver;
+
     if (resolver == nullptr) {
-        defaultResolver.baseSamplerBinding = intermediate.getShiftSamplerBinding();
-        defaultResolver.baseTextureBinding = intermediate.getShiftTextureBinding();
-        defaultResolver.baseImageBinding = intermediate.getShiftImageBinding();
-        defaultResolver.baseUboBinding = intermediate.getShiftUboBinding();
-        defaultResolver.doAutoMapping = intermediate.getAutoMapBindings();
+        TDefaultIoResolverBase* resolverBase;
 
-        resolver = &defaultResolver;
+        // TODO: use a passed in IO mapper for this
+        if (intermediate.usingHlslIoMapping())
+            resolverBase = &defaultHlslResolver;
+        else
+            resolverBase = &defaultResolver;
+
+        resolverBase->baseSamplerBinding = intermediate.getShiftSamplerBinding();
+        resolverBase->baseTextureBinding = intermediate.getShiftTextureBinding();
+        resolverBase->baseImageBinding = intermediate.getShiftImageBinding();
+        resolverBase->baseUboBinding = intermediate.getShiftUboBinding();
+        resolverBase->baseSsboBinding = intermediate.getShiftSsboBinding();
+        resolverBase->baseUavBinding = intermediate.getShiftUavBinding();
+        resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding();
+        resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
+        resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
+
+        resolver = resolverBase;
     }
 
-    TVarLiveMap varMap;
-    TVarGatherTraverser iter_binding_all(intermediate, varMap, true);
-    TVarGatherTraverser iter_binding_live(intermediate, varMap, false);
+    TVarLiveMap inVarMap, outVarMap, uniformVarMap;
+    TVarGatherTraverser iter_binding_all(intermediate, true, inVarMap, outVarMap, uniformVarMap);
+    TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap);
 
     root->traverse(&iter_binding_all);
     iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str());
@@ -388,16 +697,25 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
     }
 
     // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info.
-    std::sort(varMap.begin(), varMap.end(), TVarEntryInfo::TOrderByPriority());
+    std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderByPriority());
 
     bool hadError = false;
-    TResolverAdaptor doResolve(stage, *resolver, infoSink, hadError);
-    std::for_each(varMap.begin(), varMap.end(), doResolve);
+    TNotifyInOutAdaptor inOutNotify(stage, *resolver);
+    TNotifyUniformAdaptor uniformNotify(stage, *resolver);
+    TResolverUniformAdaptor uniformResolve(stage, *resolver, infoSink, hadError, intermediate);
+    TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError, intermediate);
+    std::for_each(inVarMap.begin(), inVarMap.end(), inOutNotify);
+    std::for_each(outVarMap.begin(), outVarMap.end(), inOutNotify);
+    std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformNotify);
+    resolver->endNotifications();
+    std::for_each(inVarMap.begin(), inVarMap.end(), inOutResolve);
+    std::for_each(outVarMap.begin(), outVarMap.end(), inOutResolve);
+    std::for_each(uniformVarMap.begin(), uniformVarMap.end(), uniformResolve);
 
     if (!hadError) {
         // sort by id again, so we can use lower bound to find entries
-        std::sort(varMap.begin(), varMap.end(), TVarEntryInfo::TOrderById());
-        TVarSetTraverser iter_iomap(intermediate, varMap);
+        std::sort(uniformVarMap.begin(), uniformVarMap.end(), TVarEntryInfo::TOrderById());
+        TVarSetTraverser iter_iomap(intermediate, inVarMap, outVarMap, uniformVarMap);
         root->traverse(&iter_iomap);
     }
 

+ 21 - 7
src/libraries/glslang/glslang/MachineIndependent/linkValidate.cpp

@@ -461,10 +461,12 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
     case EShLangTessEvaluation:
         if (inputPrimitive == ElgNone)
             error(infoSink, "At least one shader must specify an input layout primitive");
-        if (vertexSpacing == EvsNone)
-            vertexSpacing = EvsEqual;
-        if (vertexOrder == EvoNone)
-            vertexOrder = EvoCcw;
+        if (source == EShSourceGlsl) {
+            if (vertexSpacing == EvsNone)
+                vertexSpacing = EvsEqual;
+            if (vertexOrder == EvoNone)
+                vertexOrder = EvoCcw;
+        }
         break;
     case EShLangGeometry:
         if (inputPrimitive == ElgNone)
@@ -858,7 +860,7 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp
     return -1; // no collision
 }
 
-// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
+// Accumulate bindings and offsets, and check for collisions
 // as the accumulation is done.
 //
 // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.
@@ -1045,9 +1047,9 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
 
 const int baseAlignmentVec4Std140 = 16;
 
-// Return the size and alignment of a scalar.
+// Return the size and alignment of a component of the given type.
 // The size is returned in the 'size' parameter
-// Return value is the alignment of the type.
+// Return value is the alignment..
 int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
 {
     switch (type.getBasicType()) {
@@ -1055,6 +1057,8 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
     case EbtUint64:
     case EbtDouble:  size = 8; return 8;
 #ifdef AMD_EXTENSIONS
+    case EbtInt16:
+    case EbtUint16:
     case EbtFloat16: size = 2; return 2;
 #endif
     default:         size = 4; return 4;
@@ -1217,4 +1221,14 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
     return baseAlignmentVec4Std140;
 }
 
+// To aid the basic HLSL rule about crossing vec4 boundaries.
+bool TIntermediate::improperStraddle(const TType& type, int size, int offset)
+{
+    if (! type.isVector() || type.isArray())
+        return false;
+
+    return size <= 16 ? offset / 16 != (offset + size - 1) / 16
+                      : offset % 16 != 0;
+}
+
 } // end namespace glslang

+ 64 - 7
src/libraries/glslang/glslang/MachineIndependent/localintermediate.h

@@ -174,9 +174,16 @@ public:
         shiftTextureBinding(0),
         shiftImageBinding(0),
         shiftUboBinding(0),
+        shiftSsboBinding(0),
+        shiftUavBinding(0),
         autoMapBindings(false),
+        autoMapLocations(false),
         flattenUniformArrays(false),
-        useUnknownFormat(false)
+        useUnknownFormat(false),
+        hlslOffsets(false),
+        useStorageBuffer(false),
+        hlslIoMapping(false),
+        textureSamplerTransformMode(EShTexSampTransKeep)
     {
         localSize[0] = 1;
         localSize[1] = 1;
@@ -207,12 +214,27 @@ public:
     unsigned int getShiftImageBinding() const { return shiftImageBinding; }
     void setShiftUboBinding(unsigned int shift)     { shiftUboBinding = shift; }
     unsigned int getShiftUboBinding()     const { return shiftUboBinding; }
-    void setAutoMapBindings(bool map)               { autoMapBindings = map; }
+    void setShiftSsboBinding(unsigned int shift)     { shiftSsboBinding = shift; }
+    unsigned int getShiftSsboBinding()  const { return shiftSsboBinding; }
+    void setShiftUavBinding(unsigned int shift) { shiftUavBinding = shift; }
+    unsigned int getShiftUavBinding()  const { return shiftUavBinding; }
+    void setResourceSetBinding(const std::vector<std::string>& shift) { resourceSetBinding = shift; }
+    const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
+    void setAutoMapBindings(bool map)           { autoMapBindings = map; }
     bool getAutoMapBindings()             const { return autoMapBindings; }
-    void setFlattenUniformArrays(bool flatten)      { flattenUniformArrays = flatten; }
+    void setAutoMapLocations(bool map)          { autoMapLocations = map; }
+    bool getAutoMapLocations()            const { return autoMapLocations; }
+    void setFlattenUniformArrays(bool flatten)  { flattenUniformArrays = flatten; }
     bool getFlattenUniformArrays()        const { return flattenUniformArrays; }
     void setNoStorageFormat(bool b)             { useUnknownFormat = b; }
     bool getNoStorageFormat()             const { return useUnknownFormat; }
+    void setHlslOffsets()         { hlslOffsets = true; }
+    bool usingHlslOFfsets() const { return hlslOffsets; }
+    void setUseStorageBuffer() { useStorageBuffer = true; }
+    bool usingStorageBuffer() const { return useStorageBuffer; }
+    void setHlslIoMapping(bool b) { hlslIoMapping = b; }
+    bool usingHlslIoMapping()     { return hlslIoMapping; }
+    void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; }
 
     void setVersion(int v) { version = v; }
     int getVersion() const { return version; }
@@ -237,7 +259,9 @@ public:
     TIntermSymbol* addSymbol(const TType&, const TSourceLoc&);
     TIntermSymbol* addSymbol(const TIntermSymbol&);
     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
-    TIntermTyped* addShapeConversion(TOperator, const TType&, TIntermTyped*);
+    TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*);
+    void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode);
+    TIntermTyped* addShapeConversion(const TType&, TIntermTyped*);
     TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
     TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
     TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
@@ -261,13 +285,18 @@ public:
     TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const;
+#ifdef AMD_EXTENSIONS
+    TIntermConstantUnion* addConstantUnion(short, const TSourceLoc&, bool literal = false) const;
+    TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const;
+    
+#endif
     TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const;
     TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const;
     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
-    TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
-    TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
+    TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
+    TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&, TLoopControl = ELoopControlNone);
     TIntermBranch* addBranch(TOperator, const TSourceLoc&);
     TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
     template<typename selectorType> TIntermTyped* addSwizzle(TSwizzleSelectors<selectorType>&, const TSourceLoc&);
@@ -410,7 +439,9 @@ public:
     }
     int addXfbBufferOffset(const TType&);
     unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
+    static int getBaseAlignmentScalar(const TType&, int& size);
     static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor);
+    static bool improperStraddle(const TType& type, int size, int offset);
     bool promote(TIntermOperator*);
 
 #ifdef NV_EXTENSIONS
@@ -420,6 +451,18 @@ public:
     bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
 #endif
 
+    const char* addSemanticName(const TString& name)
+    {
+        return semanticNameSet.insert(name).first->c_str();
+    }
+
+    void setSourceFile(const char* file) { sourceFile = file; }
+    const std::string& getSourceFile() const { return sourceFile; }
+    void addSourceText(const char* text) { sourceText = sourceText + text; }
+    const std::string& getSourceText() const { return sourceText; }
+
+    const char* const implicitThisName = "@this";
+
 protected:
     TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
     void error(TInfoSink& infoSink, const char*);
@@ -433,7 +476,6 @@ protected:
     void inOutLocationCheck(TInfoSink&);
     TIntermSequence& findLinkerObjects() const;
     bool userOutputUsed() const;
-    static int getBaseAlignmentScalar(const TType&, int& size);
     bool isSpecializationOperation(const TIntermOperator&) const;
     bool promoteUnary(TIntermUnary&);
     bool promoteBinary(TIntermBinary&);
@@ -442,6 +484,7 @@ protected:
     void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&);
     void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&);
     bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
+    void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
 
     const EShLanguage language;  // stage, known at construction time
     EShSource source;            // source language, known a bit later
@@ -485,9 +528,16 @@ protected:
     unsigned int shiftTextureBinding;
     unsigned int shiftImageBinding;
     unsigned int shiftUboBinding;
+    unsigned int shiftSsboBinding;
+    unsigned int shiftUavBinding;
+    std::vector<std::string> resourceSetBinding;
     bool autoMapBindings;
+    bool autoMapLocations;
     bool flattenUniformArrays;
     bool useUnknownFormat;
+    bool hlslOffsets;
+    bool useStorageBuffer;
+    bool hlslIoMapping;
 
     typedef std::list<TCall> TGraph;
     TGraph callGraph;
@@ -497,6 +547,13 @@ protected:
     std::vector<TOffsetRange> usedAtomics;  // sets of bindings used by atomic counters
     std::vector<TXfbBuffer> xfbBuffers;     // all the data we need to track per xfb buffer
     std::unordered_set<int> usedConstantId; // specialization constant ids used
+    std::set<TString> semanticNameSet;
+
+    EShTextureSamplerTransformMode textureSamplerTransformMode;
+
+    // source code of shader, useful as part of debug information
+    std::string sourceFile;
+    std::string sourceText;
 
 private:
     void operator=(TIntermediate&); // prevent assignments

+ 0 - 6
src/libraries/glslang/glslang/MachineIndependent/parseConst.cpp

@@ -76,12 +76,6 @@ bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
         return false;
     }
 
-    if (node->getSequence().size() == 0) {
-        error = true;
-
-        return false;
-    }
-
     bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
     if (flag) {
         singleConstantParam = true;

+ 2 - 0
src/libraries/glslang/glslang/MachineIndependent/parseVersions.h

@@ -68,6 +68,7 @@ public:
     virtual void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
     virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
     virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
+    virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
     virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
     virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
     virtual TExtensionBehavior getExtensionBehavior(const char*);
@@ -77,6 +78,7 @@ public:
     virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
     virtual void doubleCheck(const TSourceLoc&, const char* op);
 #ifdef AMD_EXTENSIONS
+    virtual void int16Check(const TSourceLoc& loc, const char* op, bool builtIn = false);
     virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
 #endif
     virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);

+ 29 - 8
src/libraries/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp

@@ -76,7 +76,9 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 \****************************************************************************/
 
+#ifndef _CRT_SECURE_NO_WARNINGS
 #define _CRT_SECURE_NO_WARNINGS
+#endif
 
 #include <sstream>
 #include <cstdlib>
@@ -391,6 +393,14 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
     TSourceLoc loc = ppToken->loc;  // because we sometimes read the newline before reporting the error
     if (token == PpAtomIdentifier) {
         if (strcmp("defined", ppToken->name) == 0) {
+            if (! parseContext.isReadingHLSL() && isMacroInput()) {
+                if (parseContext.relaxedErrors())
+                    parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression",
+                                                      "defined", "");
+                else
+                    parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros",
+                                                       "defined", "");
+            }
             bool needclose = 0;
             token = scanToken(ppToken);
             if (token == '(') {
@@ -611,14 +621,14 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
     TShader::Includer::IncludeResult* res = nullptr;
     if (startWithLocalSearch)
         res = includer.includeLocal(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1);
-    if (! res || res->headerName.empty()) {
+    if (res == nullptr || res->headerName.empty()) {
         includer.releaseInclude(res);
         res = includer.includeSystem(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1);
     }
 
     // Process the results
-    if (res && !res->headerName.empty()) {
-        if (res->headerData && res->headerLength) {
+    if (res != nullptr && !res->headerName.empty()) {
+        if (res->headerData != nullptr && res->headerLength > 0) {
             // path for processing one or more tokens from an included header, hand off 'res'
             const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine();
             std::ostringstream prologue;
@@ -636,8 +646,8 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
     } else {
         // error path, clean up
         std::string message =
-            res ? std::string(res->headerData, res->headerLength)
-                : std::string("Could not process include directive");
+            res != nullptr ? std::string(res->headerData, res->headerLength)
+                           : std::string("Could not process include directive");
         parseContext.ppError(directiveLoc, message.c_str(), "#include", "for header name: %s", filename.c_str());
         includer.releaseInclude(res);
     }
@@ -714,6 +724,7 @@ int TPpContext::CPPerror(TPpToken* ppToken)
         if (token == PpAtomConstInt   || token == PpAtomConstUint   ||
             token == PpAtomConstInt64 || token == PpAtomConstUint64 ||
 #ifdef AMD_EXTENSIONS
+            token == PpAtomConstInt16 || token == PpAtomConstUint16 ||
             token == PpAtomConstFloat16 ||
 #endif
             token == PpAtomConstFloat || token == PpAtomConstDouble) {
@@ -748,6 +759,10 @@ int TPpContext::CPPpragma(TPpToken* ppToken)
         case PpAtomConstUint:
         case PpAtomConstInt64:
         case PpAtomConstUint64:
+#ifdef AMD_EXTENSIONS
+        case PpAtomConstInt16:
+        case PpAtomConstUint16:
+#endif
         case PpAtomConstFloat:
         case PpAtomConstDouble:
 #ifdef AMD_EXTENSIONS
@@ -776,8 +791,12 @@ int TPpContext::CPPversion(TPpToken* ppToken)
 {
     int token = scanToken(ppToken);
 
-    if (errorOnVersion || versionSeen)
-        parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", "");
+    if (errorOnVersion || versionSeen) {
+        if (parseContext.isReadingHLSL())
+            parseContext.ppError(ppToken->loc, "invalid preprocessor command", "#version", "");
+        else
+            parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", "");
+    }
     versionSeen = true;
 
     if (token == '\n') {
@@ -986,6 +1005,8 @@ TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream& arg, TPpToken*
     int token;
     while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) {
         token = tokenPaste(token, *ppToken);
+        if (token == tMarkerInput::marker || token == EndOfInput)
+            break;
         if (token == PpAtomIdentifier && MacroExpand(ppToken, false, newLineOkay) != 0)
             continue;
         expandedArg->putToken(token, ppToken);
@@ -1050,7 +1071,7 @@ int TPpContext::tMacroInput::scan(TPpToken* ppToken)
     // TODO: preprocessor:  properly handle whitespace (or lack of it) between tokens when expanding
     if (token == PpAtomIdentifier) {
         int i;
-        for (i = mac->args.size() - 1; i >= 0; i--)
+        for (i = (int)mac->args.size() - 1; i >= 0; i--)
             if (strcmp(pp->atomStrings.getString(mac->args[i]), ppToken->name) == 0)
                 break;
         if (i >= 0) {

+ 4 - 0
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp

@@ -76,7 +76,9 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 \****************************************************************************/
 
+#ifndef _CRT_SECURE_NO_WARNINGS
 #define _CRT_SECURE_NO_WARNINGS
+#endif
 
 #include <cassert>
 #include <cstdlib>
@@ -120,6 +122,8 @@ const struct {
     { PpAtomDecrement,      "--" },
     { PpAtomIncrement,      "++" },
 
+    { PpAtomColonColon,     "::" },
+
     { PpAtomDefine,         "define" },
     { PpAtomUndef,          "undef" },
     { PpAtomIf,             "if" },

+ 14 - 6
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpContext.h

@@ -92,7 +92,7 @@ namespace glslang {
 
 class TPpToken {
 public:
-    TPpToken() : space(false), ival(0), dval(0.0), i64val(0)
+    TPpToken() : space(false), i64val(0)
     {
         loc.init();
         name[0] = 0;
@@ -108,10 +108,14 @@ public:
     bool operator!=(const TPpToken& right) { return ! operator==(right); }
 
     TSourceLoc loc;
-    bool   space;  // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
-    int    ival;
-    double dval;
-    long long i64val;
+    bool space;  // true if a space (for white space or a removed comment) should also be recognized, in front of the token returned
+
+    union {
+        int ival;
+        double dval;
+        long long i64val;
+    };
+
     char   name[MaxTokenLength + 1];
 };
 
@@ -196,6 +200,7 @@ public:
         virtual void ungetch() = 0;
         virtual bool peekPasting() { return false; }          // true when about to see ##
         virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
+        virtual bool isMacroInput() { return false; }
 
         // Will be called when we start reading tokens from this instance
         virtual void notifyActivated() {}
@@ -236,7 +241,7 @@ public:
         void reset() { current = 0; }
 
     protected:
-        void putSubtoken(int);
+        void putSubtoken(char);
         int getSubtoken();
         void ungetSubtoken();
 
@@ -302,6 +307,7 @@ protected:
     void ungetChar() { inputStack.back()->ungetch(); }
     bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
     bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
+    bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
 
     static const int maxIfNesting = 64;
 
@@ -325,6 +331,7 @@ protected:
         virtual void ungetch() override { assert(0); }
         bool peekPasting() override { return prepaste; }
         bool endOfReplacementList() override { return mac->body.atEnd(); }
+        bool isMacroInput() override { return true; }
 
         MacroSymbol *mac;
         TVector<TokenStream*> args;
@@ -584,6 +591,7 @@ protected:
     int ScanFromString(char* s);
     void missingEndifCheck();
     int lFloatConst(int len, int ch, TPpToken* ppToken);
+    int characterLiteral(TPpToken* ppToken);
 
     void push_include(TShader::Includer::IncludeResult* result)
     {

+ 0 - 81
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpMemory.cpp

@@ -1,81 +0,0 @@
-//
-// Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
-// Copyright (C) 2013 LunarG, Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-//    Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-//
-//    Redistributions in binary form must reproduce the above
-//    copyright notice, this list of conditions and the following
-//    disclaimer in the documentation and/or other materials provided
-//    with the distribution.
-//
-//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
-//    contributors may be used to endorse or promote products derived
-//    from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-/****************************************************************************\
-Copyright (c) 2002, NVIDIA Corporation.
-
-NVIDIA Corporation("NVIDIA") supplies this software to you in
-consideration of your agreement to the following terms, and your use,
-installation, modification or redistribution of this NVIDIA software
-constitutes acceptance of these terms.  If you do not agree with these
-terms, please do not use, install, modify or redistribute this NVIDIA
-software.
-
-In consideration of your agreement to abide by the following terms, and
-subject to these terms, NVIDIA grants you a personal, non-exclusive
-license, under NVIDIA's copyrights in this original NVIDIA software (the
-"NVIDIA Software"), to use, reproduce, modify and redistribute the
-NVIDIA Software, with or without modifications, in source and/or binary
-forms; provided that if you redistribute the NVIDIA Software, you must
-retain the copyright notice of NVIDIA, this notice and the following
-text and disclaimers in all such redistributions of the NVIDIA Software.
-Neither the name, trademarks, service marks nor logos of NVIDIA
-Corporation may be used to endorse or promote products derived from the
-NVIDIA Software without specific prior written permission from NVIDIA.
-Except as expressly stated in this notice, no other rights or licenses
-express or implied, are granted by NVIDIA herein, including but not
-limited to any patent rights that may be infringed by your derivative
-works or by other works in which the NVIDIA Software may be
-incorporated. No hardware is licensed hereunder.
-
-THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
-INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
-ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
-PRODUCTS.
-
-IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
-INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
-OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
-NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
-TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
-NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-\****************************************************************************/
-
-namespace glslang {
-
-} // end namespace glslang

+ 261 - 24
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp

@@ -76,7 +76,9 @@ TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
 NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 \****************************************************************************/
 
+#ifndef _CRT_SECURE_NO_WARNINGS
 #define _CRT_SECURE_NO_WARNINGS
+#endif
 
 #include <cstdlib>
 #include <cstring>
@@ -101,9 +103,16 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
 {
     bool HasDecimalOrExponent = false;
     int isDouble = 0;
+    bool generateFloat16 = false;
+    bool acceptFloat16 = parseContext.intermediate.getSource() == EShSourceHlsl;
+    bool isFloat16 = false;
+    bool requireHF = false;
 #ifdef AMD_EXTENSIONS
-    int isFloat16 = 0;
-    bool enableFloat16 = parseContext.version >= 450 && parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float);
+    if (parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float)) {
+        acceptFloat16 = true;
+        generateFloat16 = true;
+        requireHF = true;
+    }
 #endif
 
     const auto saveName = [&](int ch) {
@@ -117,6 +126,35 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
         HasDecimalOrExponent = true;
         saveName(ch);
         ch = getChar();
+
+        // 1.#INF or -1.#INF
+        if (ch == '#') {
+            if ((len <  2) ||
+                (len == 2 && ppToken->name[0] != '1') ||
+                (len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) ||
+                (len >  3))
+                parseContext.ppError(ppToken->loc, "unexpected use of", "#", "");
+            else {
+                // we have 1.# or -1.# or +1.#, check for 'INF'
+                if ((ch = getChar()) != 'I' ||
+                    (ch = getChar()) != 'N' ||
+                    (ch = getChar()) != 'F')
+                    parseContext.ppError(ppToken->loc, "expected 'INF'", "#", "");
+                else {
+                    // we have [+-].#INF, and we are targeting IEEE 754, so wrap it up:
+                    saveName('I');
+                    saveName('N');
+                    saveName('F');
+                    ppToken->name[len] = '\0';
+                    if (ppToken->name[0] == '-')
+                        ppToken->i64val = 0xfff0000000000000; // -Infinity
+                    else
+                        ppToken->i64val = 0x7ff0000000000000; // +Infinity
+                    return PpAtomConstFloat;
+                }
+            }
+        }
+
         while (ch >= '0' && ch <= '9') {
             saveName(ch);
             ch = getChar();
@@ -158,21 +196,27 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
             saveName(ch2);
             isDouble = 1;
         }
+    } else if (acceptFloat16 && (ch == 'h' || ch == 'H')) {
 #ifdef AMD_EXTENSIONS
-    } else if (enableFloat16 && (ch == 'h' || ch == 'H')) {
-        parseContext.float16Check(ppToken->loc, "half floating-point suffix");
+        if (generateFloat16)
+            parseContext.float16Check(ppToken->loc, "half floating-point suffix");
+#endif
         if (!HasDecimalOrExponent)
             parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", "");
-        int ch2 = getChar();
-        if (ch2 != 'f' && ch2 != 'F') {
-            ungetChar();
-            ungetChar();
+        if (requireHF) {
+            int ch2 = getChar();
+            if (ch2 != 'f' && ch2 != 'F') {
+                ungetChar();
+                ungetChar();
+            } else {
+                saveName(ch);
+                saveName(ch2);
+                isFloat16 = generateFloat16;
+            }
         } else {
             saveName(ch);
-            saveName(ch2);
-            isFloat16 = 1;
+            isFloat16 = generateFloat16;
         }
-#endif
     } else if (ch == 'f' || ch == 'F') {
         parseContext.profileRequires(ppToken->loc,  EEsProfile, 300, nullptr, "floating-point suffix");
         if (! parseContext.relaxedErrors())
@@ -197,14 +241,88 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
     // Return the right token type
     if (isDouble)
         return PpAtomConstDouble;
-#ifdef AMD_EXTENSIONS
     else if (isFloat16)
         return PpAtomConstFloat16;
-#endif
     else
         return PpAtomConstFloat;
 }
 
+// Recognize a character literal.
+//
+// The first ' has already been accepted, read the rest, through the closing '.
+//
+// Always returns PpAtomConstInt.
+//
+int TPpContext::characterLiteral(TPpToken* ppToken)
+{
+    ppToken->name[0] = 0;
+    ppToken->ival = 0;
+
+    if (parseContext.intermediate.getSource() != EShSourceHlsl) {
+        // illegal, except in macro definition, for which case we report the character
+        return '\'';
+    }
+
+    int ch = getChar();
+    switch (ch) {
+    case '\'':
+        // As empty sequence:  ''
+        parseContext.ppError(ppToken->loc, "unexpected", "\'", "");
+        return PpAtomConstInt;
+    case '\\':
+        // As escape sequence:  '\XXX'
+        switch (ch = getChar()) {
+        case 'a':
+            ppToken->ival = 7;
+            break;
+        case 'b':
+            ppToken->ival = 8;
+            break;
+        case 't':
+            ppToken->ival = 9;
+            break;
+        case 'n':
+            ppToken->ival = 10;
+            break;
+        case 'v':
+            ppToken->ival = 11;
+            break;
+        case 'f':
+            ppToken->ival = 12;
+            break;
+        case 'r':
+            ppToken->ival = 13;
+            break;
+        case 'x':
+        case '0':
+            parseContext.ppError(ppToken->loc, "octal and hex sequences not supported", "\\", "");
+            break;
+        default:
+            // This catches '\'', '\"', '\?', etc.
+            // Also, things like '\C' mean the same thing as 'C'
+            // (after the above cases are filtered out).
+            ppToken->ival = ch;
+            break;
+        }
+        break;
+    default:
+        ppToken->ival = ch;
+        break;
+    }
+    ppToken->name[0] = (char)ppToken->ival;
+    ppToken->name[1] = '\0';
+    ch = getChar();
+    if (ch != '\'') {
+        parseContext.ppError(ppToken->loc, "expected", "\'", "");
+        // Look ahead for a closing '
+        do {
+            ch = getChar();
+        } while (ch != '\'' && ch != EndOfInput && ch != '\n');
+    }
+
+    return PpAtomConstInt;
+}
+
 //
 // Scanner used to tokenize source stream.
 //
@@ -216,6 +334,18 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
     int ii = 0;
     unsigned long long ival = 0;
     bool enableInt64 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64);
+#ifdef AMD_EXTENSIONS
+    bool enableInt16 = pp->parseContext.version >= 450 && pp->parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16);
+#endif
+    bool acceptHalf = pp->parseContext.intermediate.getSource() == EShSourceHlsl;
+#ifdef AMD_EXTENSIONS
+    if (pp->parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float))
+        acceptHalf = true;
+#endif
+
+    const auto floatingPointChar = [&](int ch) { return ch == '.' || ch == 'e' || ch == 'E' ||
+                                                                     ch == 'f' || ch == 'F' ||
+                                                     (acceptHalf && (ch == 'h' || ch == 'H')); };
 
     ppToken->ival = 0;
     ppToken->i64val = 0;
@@ -279,6 +409,9 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
 
                 bool isUnsigned = false;
                 bool isInt64 = false;
+#ifdef AMD_EXTENSIONS
+                bool isInt16 = false;
+#endif
                 ppToken->name[len++] = (char)ch;
                 ch = getch();
                 if ((ch >= '0' && ch <= '9') ||
@@ -287,7 +420,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
 
                     ival = 0;
                     do {
-                        if (ival <= 0x0fffffff || (enableInt64 && ival <= 0x0fffffffffffffffull)) {
+                        if (ival <= 0x0fffffffu || (enableInt64 && ival <= 0x0fffffffffffffffull)) {
                             ppToken->name[len++] = (char)ch;
                             if (ch >= '0' && ch <= '9') {
                                 ii = ch - '0';
@@ -326,11 +459,28 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         } else
                             ungetch();
                     }
-                }
-                else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+
+#ifdef AMD_EXTENSIONS
+                    if (enableInt16) {
+                        int nextCh = getch();
+                        if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
+                            if (len < MaxTokenLength)
+                                ppToken->name[len++] = (char)nextCh;
+                            isInt16 = true;
+                        } else
+                            ungetch();
+                    }
+#endif
+                } else if (enableInt64 && (ch == 'l' || ch == 'L')) {
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                     isInt64 = true;
+#ifdef AMD_EXTENSIONS
+                } else if (enableInt16 && (ch == 's' || ch == 'S')) {
+                    if (len < MaxTokenLength)
+                        ppToken->name[len++] = (char)ch;
+                    isInt16 = true;
+#endif
                 } else
                     ungetch();
                 ppToken->name[len] = '\0';
@@ -338,6 +488,11 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 if (isInt64) {
                     ppToken->i64val = ival;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+#ifdef AMD_EXTENSIONS
+                } else if (isInt16) {
+                    ppToken->ival = (int)ival;
+                    return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
+#endif
                 } else {
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -347,6 +502,9 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
 
                 bool isUnsigned = false;
                 bool isInt64 = false;
+#ifdef AMD_EXTENSIONS
+                bool isInt16 = false;
+#endif
                 bool octalOverflow = false;
                 bool nonOctal = false;
                 ival = 0;
@@ -359,7 +517,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", "");
                         AlreadyComplained = 1;
                     }
-                    if (ival <= 0x1fffffff || (enableInt64 && ival <= 0x1fffffffffffffffull)) {
+                    if (ival <= 0x1fffffffu || (enableInt64 && ival <= 0x1fffffffffffffffull)) {
                         ii = ch - '0';
                         ival = (ival << 3) | ii;
                     } else
@@ -380,7 +538,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         ch = getch();
                     } while (ch >= '0' && ch <= '9');
                 }
-                if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F')
+                if (floatingPointChar(ch))
                     return pp->lFloatConst(len, ch, ppToken);
 
                 // wasn't a float, so must be octal...
@@ -401,11 +559,28 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         } else
                             ungetch();
                     }
-                }
-                else if (enableInt64 && (ch == 'l' || ch == 'L')) {
+
+#ifdef AMD_EXTENSIONS
+                    if (enableInt16) {
+                        int nextCh = getch();
+                        if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
+                            if (len < MaxTokenLength)
+                                ppToken->name[len++] = (char)nextCh;
+                            isInt16 = true;
+                        } else
+                            ungetch();
+                    }
+#endif
+                } else if (enableInt64 && (ch == 'l' || ch == 'L')) {
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                     isInt64 = true;
+#ifdef AMD_EXTENSIONS
+                } else if (enableInt16 && (ch == 's' || ch == 'S')) {
+                    if (len < MaxTokenLength)
+                        ppToken->name[len++] = (char)ch;
+                    isInt16 = true;
+#endif
                 } else
                     ungetch();
                 ppToken->name[len] = '\0';
@@ -416,6 +591,11 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 if (isInt64) {
                     ppToken->i64val = ival;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+#ifdef AMD_EXTENSIONS
+                } else if (isInt16) {
+                    ppToken->ival = (int)ival;
+                    return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
+#endif
                 } else {
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -435,13 +615,16 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 }
                 ch = getch();
             } while (ch >= '0' && ch <= '9');
-            if (ch == '.' || ch == 'e' || ch == 'f' || ch == 'E' || ch == 'F') {
+            if (floatingPointChar(ch))
                 return pp->lFloatConst(len, ch, ppToken);
-            } else {
+            else {
                 // Finish handling signed and unsigned integers
                 int numericLen = len;
                 bool isUnsigned = false;
                 bool isInt64 = false;
+#ifdef AMD_EXTENSIONS
+                bool isInt16 = false;
+#endif
                 if (ch == 'u' || ch == 'U') {
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
@@ -456,10 +639,28 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                         } else
                             ungetch();
                     }
+
+#ifdef AMD_EXTENSIONS
+                    if (enableInt16) {
+                        int nextCh = getch();
+                        if ((ch == 'u' && nextCh == 's') || (ch == 'U' && nextCh == 'S')) {
+                            if (len < MaxTokenLength)
+                                ppToken->name[len++] = (char)nextCh;
+                            isInt16 = true;
+                        } else
+                            ungetch();
+                    }
+#endif
                 } else if (enableInt64 && (ch == 'l' || ch == 'L')) {
                     if (len < MaxTokenLength)
                         ppToken->name[len++] = (char)ch;
                     isInt64 = true;
+#ifdef AMD_EXTENSIONS
+                } else if (enableInt16 && (ch == 's' || ch == 'S')) {
+                    if (len < MaxTokenLength)
+                        ppToken->name[len++] = (char)ch;
+                    isInt16 = true;
+#endif
                 } else
                     ungetch();
 
@@ -469,10 +670,22 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt;
                 const unsigned long long oneTenthMaxInt64  = 0xFFFFFFFFFFFFFFFFull / 10;
                 const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64;
+#ifdef AMD_EXTENSIONS
+                const unsigned short oneTenthMaxInt16  = 0xFFFFu / 10;
+                const unsigned short remainderMaxInt16 = 0xFFFFu - 10 * oneTenthMaxInt16;
+#endif
                 for (int i = 0; i < numericLen; i++) {
                     ch = ppToken->name[i] - '0';
-                    if ((enableInt64 == false && ((ival > oneTenthMaxInt) || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt))) ||
-                        (enableInt64 && ((ival > oneTenthMaxInt64) || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64)))) {
+                    bool overflow = false;
+                    if (isInt64)
+                        overflow = (ival > oneTenthMaxInt64 || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64));
+#ifdef AMD_EXTENSIONS
+                    else if (isInt16)
+                        overflow = (ival > oneTenthMaxInt16 || (ival == oneTenthMaxInt16 && (unsigned short)ch > remainderMaxInt16));
+#endif
+                    else
+                        overflow = (ival > oneTenthMaxInt || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt));
+                    if (overflow) {
                         pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", "");
                         ival = 0xFFFFFFFFFFFFFFFFull;
                         break;
@@ -483,6 +696,11 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 if (isInt64) {
                     ppToken->i64val = ival;
                     return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64;
+#ifdef AMD_EXTENSIONS
+                } else if (isInt16) {
+                    ppToken->ival = (int)ival;
+                    return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16;
+#endif
                 } else {
                     ppToken->ival = (int)ival;
                     return isUnsigned ? PpAtomConstUint : PpAtomConstInt;
@@ -652,6 +870,8 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 return '/';
             }
             break;
+        case '\'':
+            return pp->characterLiteral(ppToken);
         case '"':
             // TODO: If this gets enhanced to handle escape sequences, or
             // anything that is different than what #include needs, then
@@ -671,6 +891,12 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
                 pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", "");
             }
             return PpAtomConstString;
+        case ':':
+            ch = getch();
+            if (ch == ':')
+                return PpAtomColonColon;
+            ungetch();
+            return ':';
         }
 
         ch = getch();
@@ -724,6 +950,10 @@ int TPpContext::tokenize(TPpToken& ppToken)
         case PpAtomConstFloat:
         case PpAtomConstInt64:
         case PpAtomConstUint64:
+#ifdef AMD_EXTENSIONS
+        case PpAtomConstInt16:
+        case PpAtomConstUint16:
+#endif
         case PpAtomConstDouble:
 #ifdef AMD_EXTENSIONS
         case PpAtomConstFloat16:
@@ -773,6 +1003,7 @@ int TPpContext::tokenPaste(int token, TPpToken& ppToken)
         token = scanToken(&pastedPpToken);
         assert(token == PpAtomPaste);
 
+        // This covers end of macro expansion
         if (endOfReplacementList()) {
             parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", "");
             break;
@@ -781,6 +1012,12 @@ int TPpContext::tokenPaste(int token, TPpToken& ppToken)
         // get the token after the ##
         token = scanToken(&pastedPpToken);
 
+        // This covers end of argument expansion
+        if (token == tMarkerInput::marker) {
+            parseContext.ppError(ppToken.loc, "unexpected location; end of argument", "##", "");
+            break;
+        }
+
         // get the token text
         switch (resultToken) {
         case PpAtomIdentifier:

+ 0 - 77
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpSymbols.cpp

@@ -1,77 +0,0 @@
-//
-// Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
-// Copyright (C) 2013 LunarG, Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-//    Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-//
-//    Redistributions in binary form must reproduce the above
-//    copyright notice, this list of conditions and the following
-//    disclaimer in the documentation and/or other materials provided
-//    with the distribution.
-//
-//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
-//    contributors may be used to endorse or promote products derived
-//    from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-//
-/****************************************************************************\
-Copyright (c) 2002, NVIDIA Corporation.
-
-NVIDIA Corporation("NVIDIA") supplies this software to you in
-consideration of your agreement to the following terms, and your use,
-installation, modification or redistribution of this NVIDIA software
-constitutes acceptance of these terms.  If you do not agree with these
-terms, please do not use, install, modify or redistribute this NVIDIA
-software.
-
-In consideration of your agreement to abide by the following terms, and
-subject to these terms, NVIDIA grants you a personal, non-exclusive
-license, under NVIDIA's copyrights in this original NVIDIA software (the
-"NVIDIA Software"), to use, reproduce, modify and redistribute the
-NVIDIA Software, with or without modifications, in source and/or binary
-forms; provided that if you redistribute the NVIDIA Software, you must
-retain the copyright notice of NVIDIA, this notice and the following
-text and disclaimers in all such redistributions of the NVIDIA Software.
-Neither the name, trademarks, service marks nor logos of NVIDIA
-Corporation may be used to endorse or promote products derived from the
-NVIDIA Software without specific prior written permission from NVIDIA.
-Except as expressly stated in this notice, no other rights or licenses
-express or implied, are granted by NVIDIA herein, including but not
-limited to any patent rights that may be infringed by your derivative
-works or by other works in which the NVIDIA Software may be
-incorporated. No hardware is licensed hereunder.
-
-THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
-WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
-INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
-ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
-PRODUCTS.
-
-IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
-INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
-OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
-NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
-TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
-NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-\****************************************************************************/

+ 20 - 4
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp

@@ -80,8 +80,10 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // For recording and playing back the stream of tokens in a macro definition.
 //
 
-#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
+#ifndef _CRT_SECURE_NO_WARNINGS
 #define _CRT_SECURE_NO_WARNINGS
+#endif
+#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/)
 #define snprintf sprintf_s
 #endif
 
@@ -96,9 +98,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace glslang {
 
 // push onto back of stream
-void TPpContext::TokenStream::putSubtoken(int subtoken)
+void TPpContext::TokenStream::putSubtoken(char subtoken)
 {
-    assert((subtoken & ~0xff) == 0);
     data.push_back(static_cast<unsigned char>(subtoken));
 }
 
@@ -125,7 +126,8 @@ void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken)
     const char* s;
     char* str = NULL;
 
-    putSubtoken(token);
+    assert((token & ~0xff) == 0);
+    putSubtoken(static_cast<char>(token));
 
     switch (token) {
     case PpAtomIdentifier:
@@ -139,6 +141,10 @@ void TPpContext::TokenStream::putToken(int token, TPpToken* ppToken)
     case PpAtomConstUint:
     case PpAtomConstInt64:
     case PpAtomConstUint64:
+#ifdef AMD_EXTENSIONS
+    case PpAtomConstInt16:
+    case PpAtomConstUint16:
+#endif
     case PpAtomConstFloat:
     case PpAtomConstDouble:
 #ifdef AMD_EXTENSIONS
@@ -188,6 +194,10 @@ int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken
     case PpAtomConstUint:
     case PpAtomConstInt64:
     case PpAtomConstUint64:
+#ifdef AMD_EXTENSIONS
+    case PpAtomConstInt16:
+    case PpAtomConstUint16:
+#endif
         len = 0;
         ch = getSubtoken();
         while (ch != 0 && ch != EndOfInput) {
@@ -215,6 +225,9 @@ int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken
             ppToken->dval = atof(ppToken->name);
             break;
         case PpAtomConstInt:
+#ifdef AMD_EXTENSIONS
+        case PpAtomConstInt16:
+#endif
             if (len > 0 && ppToken->name[0] == '0') {
                 if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
                     ppToken->ival = (int)strtol(ppToken->name, 0, 16);
@@ -224,6 +237,9 @@ int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken
                 ppToken->ival = atoi(ppToken->name);
             break;
         case PpAtomConstUint:
+#ifdef AMD_EXTENSIONS
+        case PpAtomConstUint16:
+#endif
             if (len > 0 && ppToken->name[0] == '0') {
                 if (len > 1 && (ppToken->name[1] == 'x' || ppToken->name[1] == 'X'))
                     ppToken->ival = (int)strtoul(ppToken->name, 0, 16);

+ 6 - 2
src/libraries/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h

@@ -117,6 +117,8 @@ enum EFixedAtoms {
     PpAtomDecrement,
     PpAtomIncrement,
 
+    PpAtomColonColon,
+
     PpAtomPaste,
 
     // Constants
@@ -125,11 +127,13 @@ enum EFixedAtoms {
     PpAtomConstUint,
     PpAtomConstInt64,
     PpAtomConstUint64,
+#ifdef AMD_EXTENSIONS
+    PpAtomConstInt16,
+    PpAtomConstUint16,
+#endif
     PpAtomConstFloat,
     PpAtomConstDouble,
-#ifdef AMD_EXTENSIONS
     PpAtomConstFloat16,
-#endif
     PpAtomConstString,
 
     // Identifiers

+ 2 - 0
src/libraries/glslang/glslang/MachineIndependent/propagateNoContraction.h

@@ -37,6 +37,8 @@
 // propagate 'noContraction' qualifier.
 //
 
+#pragma once
+
 #include "../Include/intermediate.h"
 
 namespace glslang {

+ 39 - 1
src/libraries/glslang/glslang/MachineIndependent/reflection.cpp

@@ -696,14 +696,40 @@ void TReflectionTraverser::visitSymbol(TIntermSymbol* base)
 // Implement TReflection methods.
 //
 
+// Track any required attribute reflection, such as compute shader numthreads.
+//
+void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediate& intermediate)
+{
+    if (stage == EShLangCompute) {
+        // Remember thread dimensions
+        for (int dim=0; dim<3; ++dim)
+            localSize[dim] = intermediate.getLocalSize(dim);
+    }
+}
+
+// build counter block index associations for buffers
+void TReflection::buildCounterIndices()
+{
+    // search for ones that have counters
+    for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
+        const TString counterName(indexToUniformBlock[i].name + "@count");
+        const int index = getIndex(counterName);
+
+        if (index >= 0)
+            indexToUniformBlock[i].counterIndex = index;
+    }
+}
+
 // Merge live symbols from 'intermediate' into the existing reflection database.
 //
 // Returns false if the input is too malformed to do this.
-bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
+bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate)
 {
     if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
         return false;
 
+    buildAttributeReflection(stage, intermediate);
+
     TReflectionTraverser it(intermediate, *this);
 
     // put the entry point on the list of functions to process
@@ -716,6 +742,8 @@ bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
         function->traverse(&it);
     }
 
+    buildCounterIndices();
+
     return true;
 }
 
@@ -736,6 +764,16 @@ void TReflection::dump()
         indexToAttribute[i].dump();
     printf("\n");
 
+    if (getLocalSize(0) > 1) {
+        static const char* axis[] = { "X", "Y", "Z" };
+
+        for (int dim=0; dim<3; ++dim)
+            if (getLocalSize(dim) > 1)
+                printf("Local size %s: %d\n", axis[dim], getLocalSize(dim));
+
+        printf("\n");
+    }
+
     // printf("Live names\n");
     // for (TNameToIndex::const_iterator it = nameToIndex.begin(); it != nameToIndex.end(); ++it)
     //    printf("%s: %d\n", it->first.c_str(), it->second);

+ 25 - 3
src/libraries/glslang/glslang/MachineIndependent/reflection.h

@@ -57,11 +57,16 @@ class TObjectReflection {
 public:
     TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) :
         name(pName), offset(pOffset),
-        glDefineType(pGLDefineType), size(pSize), index(pIndex), type(pType.clone()) { }
+        glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), type(pType.clone()) { }
 
     void dump() const {
-        printf("%s: offset %d, type %x, size %d, index %d, binding %d\n",
+        printf("%s: offset %d, type %x, size %d, index %d, binding %d",
                name.c_str(), offset, glDefineType, size, index, getBinding() );
+
+        if (counterIndex != -1)
+            printf(", counter %d", counterIndex);
+
+        printf("\n");
     }
 
     const TType* const getType() const { return type; }
@@ -71,6 +76,7 @@ public:
     int glDefineType;
     int size;         // data size in bytes for a block, array size for a (non-block) object that's an array
     int index;
+    int counterIndex;
 
     static TObjectReflection badReflection() { return TObjectReflection(); }
 
@@ -89,7 +95,12 @@ protected:
 // The full reflection database
 class TReflection {
 public:
-    TReflection() : badReflection(TObjectReflection::badReflection()) { }
+    TReflection() : badReflection(TObjectReflection::badReflection())
+    { 
+        for (int dim=0; dim<3; ++dim)
+            localSize[dim] = 0;
+    }
+
     virtual ~TReflection() {}
 
     // grow the reflection stage by stage
@@ -135,11 +146,20 @@ public:
             return it->second;
     }
 
+    // see getIndex(const char*)
+    int getIndex(const TString& name) const { return getIndex(name.c_str()); }
+
+    // Thread local size
+    unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; }
+
     void dump();
 
 protected:
     friend class glslang::TReflectionTraverser;
 
+    void buildCounterIndices();
+    void buildAttributeReflection(EShLanguage, const TIntermediate&);
+
     // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
     typedef std::map<TString, int> TNameToIndex;
     typedef std::vector<TObjectReflection> TMapIndexToReflection;
@@ -149,6 +169,8 @@ protected:
     TMapIndexToReflection indexToUniform;
     TMapIndexToReflection indexToUniformBlock;
     TMapIndexToReflection indexToAttribute;
+
+    unsigned int localSize[3];
 };
 
 } // end namespace glslang

+ 0 - 14
src/libraries/glslang/glslang/OSDependent/Unix/ossource.cpp

@@ -184,20 +184,6 @@ void ReleaseGlobalLock()
   pthread_mutex_unlock(&gMutex);
 }
 
-// TODO: non-windows: if we need these on linux, flesh them out
-void* OS_CreateThread(TThreadEntrypoint /*entry*/)
-{
-    return 0;
-}
-
-void OS_WaitForAllThreads(void* /*threads*/, int /*numThreads*/)
-{
-}
-
-void OS_Sleep(int /*milliseconds*/)
-{
-}
-
 void OS_DumpMemoryCounters()
 {
 }

+ 0 - 15
src/libraries/glslang/glslang/OSDependent/Windows/ossource.cpp

@@ -131,21 +131,6 @@ unsigned int __stdcall EnterGenericThread (void* entry)
     return ((TThreadEntrypoint)entry)(0);
 }
 
-void* OS_CreateThread(TThreadEntrypoint entry)
-{
-    return (void*)_beginthreadex(0, 0, EnterGenericThread, (void*)entry, 0, 0);
-}
-
-void OS_WaitForAllThreads(void* threads, int numThreads)
-{
-    WaitForMultipleObjects(numThreads, (HANDLE*)threads, true, INFINITE);
-}
-
-void OS_Sleep(int milliseconds)
-{
-    Sleep(milliseconds);
-}
-
 //#define DUMP_COUNTERS
 
 void OS_DumpMemoryCounters()

+ 0 - 3
src/libraries/glslang/glslang/OSDependent/osinclude.h

@@ -53,11 +53,8 @@ void GetGlobalLock();
 void ReleaseGlobalLock();
 
 typedef unsigned int (*TThreadEntrypoint)(void*);
-void* OS_CreateThread(TThreadEntrypoint);
-void OS_WaitForAllThreads(void* threads, int numThreads);
 
 void OS_CleanupThreadData(void);
-void OS_Sleep(int milliseconds);
 
 void OS_DumpMemoryCounters();
 

+ 67 - 19
src/libraries/glslang/glslang/Public/ShaderLang.h

@@ -40,6 +40,7 @@
 #include "../MachineIndependent/Versions.h"
 
 #include <cstring>
+#include <vector>
 
 #ifdef _WIN32
 #define C_DECL __cdecl
@@ -133,6 +134,14 @@ typedef enum {
     EShOptFull,         // Optimizations that will take more time
 } EShOptimizationLevel;
 
+//
+// Texture and Sampler transformation mode.
+//
+typedef enum {
+    EShTexSampTransKeep,   // keep textures and samplers as is (default)
+    EShTexSampTransUpgradeTextureRemoveSampler,  // change texture w/o embeded sampler into sampled texture and throw away all samplers
+} EShTextureSamplerTransformMode;
+
 //
 // Message choices for what errors and warnings are given.
 //
@@ -147,6 +156,8 @@ enum EShMessages {
     EShMsgReadHlsl         = (1 << 6),  // use HLSL parsing rules and semantics
     EShMsgCascadingErrors  = (1 << 7),  // get cascading errors; risks error-recovery issues, instead of an early exit
     EShMsgKeepUncalled     = (1 << 8),  // for testing, don't eliminate uncalled functions
+    EShMsgHlslOffsets      = (1 << 9),  // allow block offsets to follow HLSL rules instead of GLSL rules
+    EShMsgDebugInfo        = (1 << 10), // save debug information
 };
 
 //
@@ -203,14 +214,6 @@ SH_IMPORT_EXPORT int ShCompile(
     EShMessages messages = EShMsgDefault // warnings and errors
     );
 
-SH_IMPORT_EXPORT int ShLink(
-    const ShHandle,               // linker object
-    const ShHandle h[],           // compiler objects to link together
-    const int numHandles,
-    ShHandle uniformMap,          // updated with new uniforms
-    short int** uniformsAccessed,  // returned with indexes of uniforms accessed
-    int* numUniformsAccessed);
-
 SH_IMPORT_EXPORT int ShLinkExt(
     const ShHandle,               // linker object
     const ShHandle h[],           // compiler objects to link together
@@ -310,9 +313,16 @@ public:
     void setShiftTextureBinding(unsigned int base);
     void setShiftImageBinding(unsigned int base);
     void setShiftUboBinding(unsigned int base);
+    void setShiftUavBinding(unsigned int base);
+    void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding
+    void setShiftSsboBinding(unsigned int base);
+    void setResourceSetBinding(const std::vector<std::string>& base);
     void setAutoMapBindings(bool map);
+    void setAutoMapLocations(bool map);
+    void setHlslIoMapping(bool hlslIoMap);
     void setFlattenUniformArrays(bool flatten);
     void setNoStorageFormat(bool useUnknownFormat);
+    void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode);
 
     // Interface to #include handlers.
     //
@@ -397,6 +407,9 @@ public:
         virtual void releaseInclude(IncludeResult*) override { }
     };
 
+    bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
+               bool forwardCompatible, EShMessages, Includer&);
+
     bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
                bool forwardCompatible, EShMessages messages)
     {
@@ -404,12 +417,18 @@ public:
         return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer);
     }
 
-    bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
-               bool forwardCompatible, EShMessages, Includer&);
-
     // Equivalent to parse() without a default profile and without forcing defaults.
-    // Provided for backwards compatibility.
-    bool parse(const TBuiltInResource*, int defaultVersion, bool forwardCompatible, EShMessages);
+    bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)
+    {
+        return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages);
+    }
+
+    bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages,
+               Includer& includer)
+    {
+        return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer);
+    }
+
     bool preprocess(const TBuiltInResource* builtInResources,
                     int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
                     bool forwardCompatible, EShMessages message, std::string* outputString,
@@ -459,10 +478,19 @@ class TIoMapper;
 // and resolveSet are invoked to resolve the binding and descriptor
 // set index respectively.
 // Invocations happen in a particular order:
-// 1) var with binding and set already defined
-// 2) var with binding but no set defined
-// 3) var with set but no binding defined
-// 4) var with no binding and no set defined
+// 1) all shader inputs
+// 2) all shader outputs
+// 3) all uniforms with binding and set already defined
+// 4) all uniforms with binding but no set defined
+// 5) all uniforms with set but no binding defined
+// 6) all uniforms with no binding and no set defined
+//
+// mapIO will use this resolver in two phases. The first
+// phase is a notification phase, calling the corresponging
+// notifiy callbacks, this phase ends with a call to endNotifications.
+// Phase two starts directly after the call to endNotifications
+// and calls all other callbacks to validate and to get the
+// bindings, sets, locations, component and color indices. 
 //
 // NOTE: that still limit checks are applied to bindings and sets
 // and may result in an error.
@@ -471,15 +499,33 @@ class TIoMapResolver
 public:
   virtual ~TIoMapResolver() {}
 
-  // Should return true if the resulting/current binding would be ok.
+  // Should return true if the resulting/current binding would be okay.
   // Basic idea is to do aliasing binding checks with this.
   virtual bool validateBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
   // Should return a value >= 0 if the current binding should be overridden.
   // Return -1 if the current binding (including no binding) should be kept.
   virtual int resolveBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
-  // Should return a value >= 0 if the current set should be overriden.
+  // Should return a value >= 0 if the current set should be overridden.
   // Return -1 if the current set (including no set) should be kept.
   virtual int resolveSet(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Should return true if the resulting/current setup would be okay.
+  // Basic idea is to do aliasing checks and reject invalid semantic names.
+  virtual bool validateInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Should return a value >= 0 if the current location should be overridden.
+  // Return -1 if the current location (including no location) should be kept.
+  virtual int resolveInOutLocation(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Should return a value >= 0 if the current component index should be overridden.
+  // Return -1 if the current component index (including no index) should be kept.
+  virtual int resolveInOutComponent(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Should return a value >= 0 if the current color index should be overridden.
+  // Return -1 if the current color index (including no index) should be kept.
+  virtual int resolveInOutIndex(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Notification of a uniform variable
+  virtual void notifyBinding(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Notification of a in or out variable
+  virtual void notifyInOut(EShLanguage stage, const char* name, const TType& type, bool is_live) = 0;
+  // Called by mapIO when it has finished the notify pass
+  virtual void endNotifications() = 0;
 };
 
 // Make one TProgram per set of shaders that will get linked together.  Add all
@@ -510,10 +556,12 @@ public:
     int getUniformBlockSize(int blockIndex) const;         // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
     int getUniformIndex(const char* name) const;           // can be used for glGetUniformIndices()
     int getUniformBlockIndex(int index) const;             // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
+    int getUniformBlockCounterIndex(int index) const;      // returns block index of associated counter.
     int getUniformType(int index) const;                   // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)
     int getUniformBufferOffset(int index) const;           // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET)
     int getUniformArraySize(int index) const;              // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE)
     int getNumLiveAttributes() const;                      // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES)
+    unsigned getLocalSize(int dim) const;                  // return dim'th local size
     const char *getAttributeName(int index) const;         // can be used for glGetActiveAttrib()
     int getAttributeType(int index) const;                 // can be used for glGetActiveAttrib()
     const TType* getUniformTType(int index) const;         // returns a TType*

Some files were not shown because too many files changed in this diff